Dynamically starting children to Demux Mp4 tracks
I want to convert this to take arbitrary user uploaded Mp4 files where the tracks can have different indexes:
I tried converting the above to:
but now the demuxer doesn't run, because there are no outputs to pull data..
How do I add dynamic children, based on the track types?
structure = [
child(:video_source, %Membrane.File.Source{
location: @input_file
})
|> child(:demuxer, Membrane.MP4.Demuxer.ISOM)
# Video
|> via_out(Pad.ref(:output, 1))
|> child(:vido_tmp, %Membrane.H264.Parser{
output_stream_structure: :annexb
})
|> do_video()
|> child(:video_out, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {25, 1}},
output_stream_structure: :avc1
}),
# Audio
get_child(:demuxer)
|> via_out(Pad.ref(:output, 2))
|> do_audio(),
# Mux
child(:muxer, Membrane.MP4.Muxer.ISOM)
|> child(:sink, %Membrane.File.Sink{location: @out_file})
get_child(:video_out) |> get_child(:muxer),
get_child(:audio_out) |> get_child(:muxer)
] structure = [
child(:video_source, %Membrane.File.Source{
location: @input_file
})
|> child(:demuxer, Membrane.MP4.Demuxer.ISOM)
# Video
|> via_out(Pad.ref(:output, 1))
|> child(:vido_tmp, %Membrane.H264.Parser{
output_stream_structure: :annexb
})
|> do_video()
|> child(:video_out, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {25, 1}},
output_stream_structure: :avc1
}),
# Audio
get_child(:demuxer)
|> via_out(Pad.ref(:output, 2))
|> do_audio(),
# Mux
child(:muxer, Membrane.MP4.Muxer.ISOM)
|> child(:sink, %Membrane.File.Sink{location: @out_file})
get_child(:video_out) |> get_child(:muxer),
get_child(:audio_out) |> get_child(:muxer)
]I tried converting the above to:
@impl true
def handle_init(_ctx, _path) do
structure = [
child(:video_source, %Membrane.File.Source{
location: @input_file
})
|> child(:demuxer, Membrane.MP4.Demuxer.ISOM),
# Mux
child(:muxer, Membrane.MP4.Muxer.ISOM)
|> child(:sink, %Membrane.File.Sink{location: @out_file})
]
{[spec: structure], %{}}
end
@impl true
def handle_child_notification({:new_tracks, tracks}, :demuxer, _ctx, state) do
spec =
tracks
|> Enum.map(fn
{track_id, %Membrane.H264{}} ->
get_child(:demuxer)
|> via_out(Pad.ref(:output, track_id))
|> do_video()
{track_id, %Membrane.AAC{}} ->
get_child(:demuxer)
|> via_out(Pad.ref(:output, track_id))
|> do_audio()
end)
{[spec: spec], state}
end @impl true
def handle_init(_ctx, _path) do
structure = [
child(:video_source, %Membrane.File.Source{
location: @input_file
})
|> child(:demuxer, Membrane.MP4.Demuxer.ISOM),
# Mux
child(:muxer, Membrane.MP4.Muxer.ISOM)
|> child(:sink, %Membrane.File.Sink{location: @out_file})
]
{[spec: structure], %{}}
end
@impl true
def handle_child_notification({:new_tracks, tracks}, :demuxer, _ctx, state) do
spec =
tracks
|> Enum.map(fn
{track_id, %Membrane.H264{}} ->
get_child(:demuxer)
|> via_out(Pad.ref(:output, track_id))
|> do_video()
{track_id, %Membrane.AAC{}} ->
get_child(:demuxer)
|> via_out(Pad.ref(:output, track_id))
|> do_audio()
end)
{[spec: spec], state}
endbut now the demuxer doesn't run, because there are no outputs to pull data..
How do I add dynamic children, based on the track types?