0

I would like to stream a single MP4 to multiple streaming sites at once. The easiest way I could think to do this was to simply run four concurrent ffmpeg instances at once, and send the stream individually. I wish I had stuck to this.

Unfortunately I remembered the tee filter and had hoped it would save a few CPU cycles. Instead I have wasted hours getting nowhere.

I realise these sorts of questions have been asked before, hundreds of times, and with them hundreds of answers. None of them have helped me.

To get the “banner” out of the way:

ffmpeg version 4.2.2-static https://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-6)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100

Note that I have tried static and linked builds (no change) as well as older versions of ffmpeg (worse).

Now, for the first command:

[h264 @ 0x6f8f1c0] Reinit context to 1280x720, pix_fmt: yuv420p
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'huuge.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.20.100
  Duration: 00:23:18.37, start: 0.000000, bitrate: 2104 kb/s
    Stream #0:0(eng): Video: h264 (High), 1 reference frame (avc1 / 0x31637661), yuv420p(left), 1280x720 [SAR 1:1 DAR 16:9], 1900 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandle
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 192 kb/s (default)
    Metadata:
      handler_name    : SoundHandle
[tcp @ 0x6fbc6c0] Starting connection attempt to 35.176.16.102 port 1935
[tcp @ 0x6fbc6c0] Successfully connected to 35.176.16.102 port 1935
[flv @ 0x6ff1240] Tag avc1 incompatible with output codec id '27' ([7][0][0][0])
[tee @ 0x6fb6900] Slave '[f=flv:onfail=ignore]rtmp://stream.dlive.tv/live/<snip>': error writing header: Invalid data found when processing input
[AVIOContext @ 0x6ff09c0] Statistics: 0 seeks, 0 writeouts
[tee @ 0x6fb6900] Slave muxer #0 failed: Invalid data found when processing input, continuing with 2/3 slaves.
[tcp @ 0x6fbc380] Starting connection attempt to 99.181.67.204 port 1935
[tcp @ 0x6fbc380] Successfully connected to 99.181.67.204 port 1935
[flv @ 0x7026a80] Tag avc1 incompatible with output codec id '27' ([7][0][0][0])
[tee @ 0x6fb6900] Slave '[f=flv:onfail=ignore]rtmp://live-lhr04.twitch.tv/app/<snip>': error writing header: Invalid data found when processing input
[AVIOContext @ 0x70260c0] Statistics: 0 seeks, 0 writeouts
[tee @ 0x6fb6900] Slave muxer #1 failed: Invalid data found when processing input, continuing with 1/3 slaves.
[flv @ 0x6f99880] Tag avc1 incompatible with output codec id '27' ([7][0][0][0])
[tee @ 0x6f969c0] Slave '[f=flv:onfail=ignore]rtmp://a.rtmp.youtube.com/live2/<snip>': error writing header: Invalid data found when processing input
[tee @ 0x6fb6900] All tee outputs failed.
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
    Last message repeated 1 times
[AVIOContext @ 0x6f96400] Statistics: 2123151 bytes read, 0 seeks

I tried adding -vtag avc1 which made no difference.

And simply out of curiosity I tried using the -use_fifo 1 switch:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'huuge.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.20.100
  Duration: 00:23:18.37, start: 0.000000, bitrate: 2104 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1900 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandle
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 192 kb/s (default)
    Metadata:
      handler_name    : SoundHandle
Output #0, tee, to '[f=flv:onfail=ignore]rtmp://stream.dlive.tv/live/<snip>|[f=flv:onfail=ignore]rtmps://homeserver:1936/rtmp/<snip>|[f=flv:onfail=ignore]rtmp://live-lhr04.twitch.tv/app/<snip>|[f=flv:onfail=ignore]rtmp://a.rtmp.youtube.com/live2/<snip>':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.29.100
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 1900 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc (default)
    Metadata:
      handler_name    : VideoHandle
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 192 kb/s (default)ffmpeg: malloc.c:2404: sysmalloc: Assertion `(unsigned long) (old_size) < (unsigned long) (nb + MINSIZE)' failed.

    Metadata:
      handler_name    : SoundHandleffmpeg: malloc.c:2401: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.

Aborted                 (core dumped) ffmpeg -hide_banner -re -i "$1" -flags +global_header -map 0 -c copy -f tee -use_fifo 1 "[f=flv:onfail=ignore]rtmp://stream.dlive.tv/live/<snip>|[f=flv:onfail=ignore]rtmps://homeserver:1936/rtmp/<snip>|[f=flv:onfail=ignore]rtmp://live-lhr04.twitch.tv/app/<snip>|[f=flv:onfail=ignore]rtmp://a.rtmp.youtube.com/live2/<snip>"

I can do nothing with a segfault.

So now I'm hoping someone else may have tried this, but done so successfully. One file to four outputs doesn't seem to be that big a deal, but I cannot get it to work!

For reference, four separate ffmpeg instances work fine, including through stunnel. And the whitespace between the pipes make no difference.

I have tried -flags +global_header and bsfs/v=dump_extra=freq=keyframe both separate and together, which are no help. I have no idea what the latter does.

1

I'll need to debug when I have time to see why this occurs during tee and not mormally, but for now, add -vtag 7 to get ffmpeg working when streamcopying H.264/AVC video. Do check and confirm that your recipients can decode the output.

-flags +global_header only applies when encoding the video.
bsfs/v=dump_extra=freq=keyframe is not relevant and in fact, counterproductive for FLV output, although it does not intersect with your issue.
-use_fifo 1 also does not intersect, and it's orthogonal here.

1
  • That did it! Because I was using aac I also had to add -atag 10, but I wasn't told that until your solution got me that far. Thank you!
    – Ken Sharp
    Mar 9 '20 at 14:25
0

Perhaps you could try a different approach, instead of getting FFMPEG to stream to different IP's use something else.

I.e. Capture what you need and encode with FFMPEG, then pass that to something else to pass it on the the multiple locations.

This guide might help you (providing you are in the nginx enviro).

I've spent a lot of time running into brick walls recently with streaming related stuff, and found it is frequently easier to use two or three specialist things, rather than trying to force one to do it all.

Hope this helps.

3
  • The videos are re-encoded with ffmpeg before they are streamed. Encoding them again will achieve nothing as the result is always going to be the same. I have used Nginx in the past but it is not suitable for this either, and is no different to using separate ffmpeg invocations, but with added hassle and complexity (and resource waste).
    – Ken Sharp
    Mar 4 '20 at 21:44
  • I am not suggesting encoding them multiple times. You should be able to get ffmpeg to end code, the pipe/broadcast this to something else that will then simply broadcast it to the multiple points you need it sent to (assuming all points support the same format). IMO this should not need a 2nd lot of encoding, simply pass it on.
    – Netspud2K
    Mar 5 '20 at 1:39
  • That's already what is being done. You are complicating a very simple issue.
    – Ken Sharp
    Mar 6 '20 at 3:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.