Membrane.AAC.Parser - Not enough information provided to parse the stream.

Hello, I am receiving audio via my reolink camera and I am trying to send it to an RTMP server. Here is the info from my camera using ffmpeg:
Duration: N/A, start: 0.000250, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p(progressive), 2560x1920, 30 fps, 30 tbr, 90k tbn
Stream #0:1: Audio: aac (LC), 16000 Hz, mono, fltp
Duration: N/A, start: 0.000250, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p(progressive), 2560x1920, 30 fps, 30 tbr, 90k tbn
Stream #0:1: Audio: aac (LC), 16000 Hz, mono, fltp
Here are the relevant parts of the pipeline:
def handle_init(_ctx, _opts) do
spec = [
child(:source, %Membrane.RTSP.Source{
transport: :tcp,
allowed_media_types: [:video, :audio],
stream_uri: @rtsp_url
}),

child(:rtmp_sink, %Membrane.RTMP.Sink{rtmp_url: @rtmp_url, tracks: [:video, :audio]}),

child(:audio_depayloader, %Membrane.RTP.AAC.Depayloader{
mode: :lbr
}),
child(:audio_parser, %Membrane.AAC.Parser{
#out_encapsulation: :none
}),
child(:audio_realtimer, Membrane.Realtimer),

get_child(:source)
|> via_out(Pad.ref(:output, "track2"))
|> get_child(:audio_depayloader)
|> get_child(:audio_parser)
|> get_child(:audio_realtimer)
|> via_in(Pad.ref(:audio, 0))
|> get_child(:rtmp_sink)
]

{[spec: spec], %{}}
end
def handle_init(_ctx, _opts) do
spec = [
child(:source, %Membrane.RTSP.Source{
transport: :tcp,
allowed_media_types: [:video, :audio],
stream_uri: @rtsp_url
}),

child(:rtmp_sink, %Membrane.RTMP.Sink{rtmp_url: @rtmp_url, tracks: [:video, :audio]}),

child(:audio_depayloader, %Membrane.RTP.AAC.Depayloader{
mode: :lbr
}),
child(:audio_parser, %Membrane.AAC.Parser{
#out_encapsulation: :none
}),
child(:audio_realtimer, Membrane.Realtimer),

get_child(:source)
|> via_out(Pad.ref(:output, "track2"))
|> get_child(:audio_depayloader)
|> get_child(:audio_parser)
|> get_child(:audio_realtimer)
|> via_in(Pad.ref(:audio, 0))
|> get_child(:rtmp_sink)
]

{[spec: spec], %{}}
end
When I run it, I get the following error message:
Evaluation process terminated - {:membrane_child_crash, :audio_parser, {%RuntimeError{message: "Not enough information provided to parse the stream. \nProfile, channels and sample rate need to be provided in one of the following ways:\n - ADTS encapsulation\n - Stream format, either explicitly or through `:config` field\n - `:audio_specific_config` option of this element\nHowever they evaluated to: \n - Profile: nil\n - Channels: nil\n - Sample rate: nil\n"}, [{Membrane.AAC.Parser, :handle_stream_format, 4, [file: ~c"lib/membrane/aac/parser.ex", line: 139, error_info: %{module: Exception}]}, ...
Evaluation process terminated - {:membrane_child_crash, :audio_parser, {%RuntimeError{message: "Not enough information provided to parse the stream. \nProfile, channels and sample rate need to be provided in one of the following ways:\n - ADTS encapsulation\n - Stream format, either explicitly or through `:config` field\n - `:audio_specific_config` option of this element\nHowever they evaluated to: \n - Profile: nil\n - Channels: nil\n - Sample rate: nil\n"}, [{Membrane.AAC.Parser, :handle_stream_format, 4, [file: ~c"lib/membrane/aac/parser.ex", line: 139, error_info: %{module: Exception}]}, ...
How do I properly pass the information to the audio parser?
9 Replies
phillipp
phillippOP5mo ago
I went and asked ChatGPT and it suggest to use :hbr for the :audio_depayloader and audio_specific_config: <<0x12, 0x08>> for the aac parser. Now the stream is working but I can't hear any audio. There surely is audio as I am able to hear birds and cars over the reolink app. Any ideas?
varsill
varsill5mo ago
Hello @phillipp ! I would say that the Membrane.RTSP.Source (which is a bin, meaning that it "wraps" some elements under the hood) should spawn the appropriate depayloader and parser on its own, and pass to them information like audio_specific_config read from the exchanged RTSP messages. Have you tried removing the audio_depayloader from your pipeline? (the parser might still be needed to change the encapsulation so that it matches RTMP capabilities)
phillipp
phillippOP5mo ago
@varsill I messed around a bit more with ChatGPT and it suggested me to resample the audio and that did the trick. The below pipeline is working for me.
spec = [
child(:source, %Membrane.RTSP.Source{
transport: :tcp,
allowed_media_types: [:video, :audio],
stream_uri: @rtsp_url
}),
child(:video_parser, %Membrane.H264.Parser{
output_stream_structure: :avc3,
}),
child(:video_realtimer, Membrane.Realtimer),
child(:rtmp_sink, %Membrane.RTMP.Sink{rtmp_url: @rtmp_url, tracks: [:video, :audio]}),

child(:audio_depayloader, %Membrane.RTP.AAC.Depayloader{
mode: :hbr
}),
child(:audio_parser, %Membrane.AAC.Parser{
out_encapsulation: :ADTS,
audio_specific_config: AACConfigHelper.generate(:aac_lc, 16000, 1)
}),
child(:aac_decoder, Membrane.AAC.FDK.Decoder),
child(:audio_resampler, %Membrane.FFmpeg.SWResample.Converter{
output_stream_format: %Membrane.RawAudio{channels: 2, sample_format: :s16le, sample_rate: 44_100}
}),
child(:aac_encoder, Membrane.AAC.FDK.Encoder),
child(:audio_realtimer, Membrane.Realtimer),

get_child(:source)
|> via_out(Pad.ref(:output, "track1"))
|> get_child(:video_parser)
|> get_child(:video_realtimer)
|> via_in(Pad.ref(:video, 0))
|> get_child(:rtmp_sink),

get_child(:source)
|> via_out(Pad.ref(:output, "track2"))
|> get_child(:audio_depayloader)
|> get_child(:audio_parser)
|> get_child(:aac_decoder)
|> get_child(:audio_resampler)
|> get_child(:aac_encoder)
|> get_child(:audio_realtimer)
|> via_in(Pad.ref(:audio, 0))
|> get_child(:rtmp_sink)
]
spec = [
child(:source, %Membrane.RTSP.Source{
transport: :tcp,
allowed_media_types: [:video, :audio],
stream_uri: @rtsp_url
}),
child(:video_parser, %Membrane.H264.Parser{
output_stream_structure: :avc3,
}),
child(:video_realtimer, Membrane.Realtimer),
child(:rtmp_sink, %Membrane.RTMP.Sink{rtmp_url: @rtmp_url, tracks: [:video, :audio]}),

child(:audio_depayloader, %Membrane.RTP.AAC.Depayloader{
mode: :hbr
}),
child(:audio_parser, %Membrane.AAC.Parser{
out_encapsulation: :ADTS,
audio_specific_config: AACConfigHelper.generate(:aac_lc, 16000, 1)
}),
child(:aac_decoder, Membrane.AAC.FDK.Decoder),
child(:audio_resampler, %Membrane.FFmpeg.SWResample.Converter{
output_stream_format: %Membrane.RawAudio{channels: 2, sample_format: :s16le, sample_rate: 44_100}
}),
child(:aac_encoder, Membrane.AAC.FDK.Encoder),
child(:audio_realtimer, Membrane.Realtimer),

get_child(:source)
|> via_out(Pad.ref(:output, "track1"))
|> get_child(:video_parser)
|> get_child(:video_realtimer)
|> via_in(Pad.ref(:video, 0))
|> get_child(:rtmp_sink),

get_child(:source)
|> via_out(Pad.ref(:output, "track2"))
|> get_child(:audio_depayloader)
|> get_child(:audio_parser)
|> get_child(:aac_decoder)
|> get_child(:audio_resampler)
|> get_child(:aac_encoder)
|> get_child(:audio_realtimer)
|> via_in(Pad.ref(:audio, 0))
|> get_child(:rtmp_sink)
]
varsill
varsill5mo ago
Good to hear that it's working for you! If you have time, you can try removing that depayloader though (and the resampling part too) as it's possible that the stream can be properly handled with its native sampling frequency etc. - a benefit coming with such an approach is that it would be less resource-consuming.
phillipp
phillippOP5mo ago
@varsill So, I left out the depayloader and the resampling part. The audio pipeline looks like this now:
get_child(:source)
|> via_out(Pad.ref(:output, "track2"))
|> get_child(:audio_parser)
|> get_child(:audio_realtimer)
|> via_in(Pad.ref(:audio, 0))
|> get_child(:rtmp_sink)
get_child(:source)
|> via_out(Pad.ref(:output, "track2"))
|> get_child(:audio_parser)
|> get_child(:audio_realtimer)
|> via_in(Pad.ref(:audio, 0))
|> get_child(:rtmp_sink)
and i am getting:
Evaluation process terminated - {:membrane_child_crash, :audio_parser, {%Membrane.StreamFormatError{message: "Stream format: %Membrane.RTP{payload_format: nil} is not matching accepted format pattern `AAC` or `Membrane.RemoteStream` in def_input_pad for pad :input in Membrane.AAC.Parser. Beware that stream format is forwarded by the default implemetation of handle_stream_format in filters.\n"}, [{Membrane.Core.Element.StreamFormatController, :"-validate_stream_format!/3-fun-1-", 4, [file: ~c"lib/membrane/core/element/stream_format_controller.ex", line: 120]}, {Enum, :"-reduce/3-lists^foldl/2-0-", 3, [file: ~c"lib/enum.ex", line: 2546]}, {Membrane.Core.Element.StreamFormatController, :validate_stream_format!, 3, [file: ~c"lib/membrane/core/element/stream_format_controller.ex", line: 105]}, {Membrane.Core.Element.StreamFormatController, :exec_handle_stream_format, 4, [file: ~c"lib/membrane/core/element/stream_format_controller.ex", line: 77]}, {Membrane.Core.Element, :handle_info, 2, [file: ~c"lib/membrane/core/element.ex", line: 235]}, {:gen_server, :try_handle_info, 3, [file: ~c"gen_server.erl", line: 2345]}, {:gen_server, :handle_msg, 6, [file: ~c"gen_server.erl", line: 2433]}, {:proc_lib, :init_p_do_apply, 3, [file: ~c"proc_lib.erl", line: 329]}]}}
Evaluation process terminated - {:membrane_child_crash, :audio_parser, {%Membrane.StreamFormatError{message: "Stream format: %Membrane.RTP{payload_format: nil} is not matching accepted format pattern `AAC` or `Membrane.RemoteStream` in def_input_pad for pad :input in Membrane.AAC.Parser. Beware that stream format is forwarded by the default implemetation of handle_stream_format in filters.\n"}, [{Membrane.Core.Element.StreamFormatController, :"-validate_stream_format!/3-fun-1-", 4, [file: ~c"lib/membrane/core/element/stream_format_controller.ex", line: 120]}, {Enum, :"-reduce/3-lists^foldl/2-0-", 3, [file: ~c"lib/enum.ex", line: 2546]}, {Membrane.Core.Element.StreamFormatController, :validate_stream_format!, 3, [file: ~c"lib/membrane/core/element/stream_format_controller.ex", line: 105]}, {Membrane.Core.Element.StreamFormatController, :exec_handle_stream_format, 4, [file: ~c"lib/membrane/core/element/stream_format_controller.ex", line: 77]}, {Membrane.Core.Element, :handle_info, 2, [file: ~c"lib/membrane/core/element.ex", line: 235]}, {:gen_server, :try_handle_info, 3, [file: ~c"gen_server.erl", line: 2345]}, {:gen_server, :handle_msg, 6, [file: ~c"gen_server.erl", line: 2433]}, {:proc_lib, :init_p_do_apply, 3, [file: ~c"proc_lib.erl", line: 329]}]}}
Billal
Billal5mo ago
Hi @phillipp What do you get as tracks when you receive this message {:set_up_tracks, tracks} ?
phillipp
phillippOP5mo ago
@Billal this are the tracks: audio:
[
%{
type: :audio,
rtpmap: %ExSDP.Attribute.RTPMapping{
payload_type: 97,
encoding: "MPEG4-GENERIC",
clock_rate: 16000,
params: 1
},
fmtp: %ExSDP.Attribute.FMTP{
pt: 97,
profile_level_id: 1,
level_asymmetry_allowed: nil,
packetization_mode: nil,
max_mbps: nil,
max_smbps: nil,
max_fs: nil,
max_dpb: nil,
max_br: nil,
sprop_parameter_sets: nil,
profile_space: nil,
profile_id: nil,
tier_flag: nil,
level_id: nil,
interop_constraints: nil,
sprop_vps: nil,
sprop_sps: nil,
sprop_pps: nil,
maxaveragebitrate: nil,
maxplaybackrate: nil,
sprop_maxcapturerate: nil,
maxptime: nil,
ptime: nil,
minptime: nil,
stereo: nil,
cbr: nil,
useinbandfec: nil,
usedtx: nil,
max_fr: nil,
profile: nil,
level_idx: nil,
tier: nil,
apt: nil,
rtx_time: nil,
repair_window: nil,
dtmf_tones: nil,
redundant_payloads: nil,
bitrate: nil,
streamtype: 5,
config: <<20, 8>>,
mode: :AAC_hbr,
objecttype: nil,
constantsize: nil,
constantduration: nil,
maxdisplacement: nil,
de_interleavebuffersize: nil,
...
},
control_path: "track2",
framerate: nil
}
]
[
%{
type: :audio,
rtpmap: %ExSDP.Attribute.RTPMapping{
payload_type: 97,
encoding: "MPEG4-GENERIC",
clock_rate: 16000,
params: 1
},
fmtp: %ExSDP.Attribute.FMTP{
pt: 97,
profile_level_id: 1,
level_asymmetry_allowed: nil,
packetization_mode: nil,
max_mbps: nil,
max_smbps: nil,
max_fs: nil,
max_dpb: nil,
max_br: nil,
sprop_parameter_sets: nil,
profile_space: nil,
profile_id: nil,
tier_flag: nil,
level_id: nil,
interop_constraints: nil,
sprop_vps: nil,
sprop_sps: nil,
sprop_pps: nil,
maxaveragebitrate: nil,
maxplaybackrate: nil,
sprop_maxcapturerate: nil,
maxptime: nil,
ptime: nil,
minptime: nil,
stereo: nil,
cbr: nil,
useinbandfec: nil,
usedtx: nil,
max_fr: nil,
profile: nil,
level_idx: nil,
tier: nil,
apt: nil,
rtx_time: nil,
repair_window: nil,
dtmf_tones: nil,
redundant_payloads: nil,
bitrate: nil,
streamtype: 5,
config: <<20, 8>>,
mode: :AAC_hbr,
objecttype: nil,
constantsize: nil,
constantduration: nil,
maxdisplacement: nil,
de_interleavebuffersize: nil,
...
},
control_path: "track2",
framerate: nil
}
]
video:
[
%{
type: :video,
rtpmap: %ExSDP.Attribute.RTPMapping{
payload_type: 96,
encoding: "H264",
clock_rate: 90000,
params: nil
},
fmtp: %ExSDP.Attribute.FMTP{
pt: 96,
profile_level_id: 6553650,
level_asymmetry_allowed: nil,
packetization_mode: 1,
max_mbps: nil,
max_smbps: nil,
max_fs: nil,
max_dpb: nil,
max_br: nil,
sprop_parameter_sets: %{
sps: <<103, 100, 0, 50, 172, 210, 0, 160, 3, 198, 132, 0, 0, 15, 164, 0,
3, 170, 112, 16>>,
pps: <<104, 234, 143, 44>>
},
profile_space: nil,
profile_id: nil,
tier_flag: nil,
level_id: nil,
interop_constraints: nil,
sprop_vps: nil,
sprop_sps: nil,
sprop_pps: nil,
maxaveragebitrate: nil,
maxplaybackrate: nil,
sprop_maxcapturerate: nil,
maxptime: nil,
ptime: nil,
minptime: nil,
stereo: nil,
cbr: nil,
useinbandfec: nil,
usedtx: nil,
max_fr: nil,
profile: nil,
level_idx: nil,
tier: nil,
apt: nil,
rtx_time: nil,
repair_window: nil,
dtmf_tones: nil,
redundant_payloads: nil,
bitrate: nil,
streamtype: nil,
config: nil,
mode: nil,
objecttype: nil,
constantsize: nil,
constantduration: nil,
maxdisplacement: nil,
...
},
control_path: "track1",
framerate: nil
}
]
[
%{
type: :video,
rtpmap: %ExSDP.Attribute.RTPMapping{
payload_type: 96,
encoding: "H264",
clock_rate: 90000,
params: nil
},
fmtp: %ExSDP.Attribute.FMTP{
pt: 96,
profile_level_id: 6553650,
level_asymmetry_allowed: nil,
packetization_mode: 1,
max_mbps: nil,
max_smbps: nil,
max_fs: nil,
max_dpb: nil,
max_br: nil,
sprop_parameter_sets: %{
sps: <<103, 100, 0, 50, 172, 210, 0, 160, 3, 198, 132, 0, 0, 15, 164, 0,
3, 170, 112, 16>>,
pps: <<104, 234, 143, 44>>
},
profile_space: nil,
profile_id: nil,
tier_flag: nil,
level_id: nil,
interop_constraints: nil,
sprop_vps: nil,
sprop_sps: nil,
sprop_pps: nil,
maxaveragebitrate: nil,
maxplaybackrate: nil,
sprop_maxcapturerate: nil,
maxptime: nil,
ptime: nil,
minptime: nil,
stereo: nil,
cbr: nil,
useinbandfec: nil,
usedtx: nil,
max_fr: nil,
profile: nil,
level_idx: nil,
tier: nil,
apt: nil,
rtx_time: nil,
repair_window: nil,
dtmf_tones: nil,
redundant_payloads: nil,
bitrate: nil,
streamtype: nil,
config: nil,
mode: nil,
objecttype: nil,
constantsize: nil,
constantduration: nil,
maxdisplacement: nil,
...
},
control_path: "track1",
framerate: nil
}
]
had to split it up because of discord character limit
Billal
Billal5mo ago
Ok, I see the issue. I'll try to fix it and create a new release by tomorrow @phillipp try the new version
phillipp
phillippOP5mo ago
@Billal yeah, now it works. thanks!

Did you find this page helpful?