Zend certified PHP/Magento developer

Complex ffmpeg multi-encode/streamcopy/muxing scenario: is this actually doable?

I’m trying to do multiple muxing/re-encode/copy operations on an input video with ffmpeg and have run into roadblocks with the methods I’ve tried; before I continue testing, I want to confirm whether this is actually even possible with the software. (This is for a live streaming setup that takes in one live stream from another PC on my LAN, and archives/restreams it to multiple RTMP targets, hence the -re flag and needing to do everything in one operation.)

The input video has one high-bitrate h.264 video stream and four PCM audio tracks.

The three outputs I need:

  • one h.246 encode at 8Mbps, aac encode of audio track 1 only
  • one h.264 encode at 12Mbps, aac encode of audio track 1 only (ideally
    using the same encode as the first output, i.e. only having to encode
    audio once)
  • one pure streamcopy of the whole input to .mkv

(These commands may be full of errors and bad practices, just a general idea of the direction I’m going.)

I’ve tried using the split/asplit filters in combination with the tee muxer along these lines, which seems like it would work in theory except that using filters disallows streamcopy/codec passthrough (ironically no actual filtering is being done to the video stream in this case, other than passing it through).

ffmpeg -re -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i $INPUT 
-filter_complex "[0:v]split=3[twitch][youtube][passv];[0:a]asplit[stream][passa]" 
-map:v "[twitch]" -map:v "[youtube]" -map:v "[passv]" -map:a "[stream]:0" -map:a "[passa]" 
-c:v:0 h264_qsv -profile:v:0 high -preset:v:0 medium -g 120 -b:v:0 8M -maxrate:v:0 8M -bufsize:v:0 4M 
-c:v:1 h264_qsv -profile:v:1 high -preset:v:0 medium -g 120 -b:v:1 12M -maxrate:v:1 12M -bufsize:v:1 6M 
-c:v:2 copy 
-c:a:0 aac -b:a:0 320k 
-c:a:1 copy 
-f tee "[select='v:0,a:0']8mbps.mkv|[select='v:1,a:0']12mbps.mkv|[select='v:2,a:1']copy.mkv"

I also played around with simple stream mapping to multiple outputs, but it seems like it only actually processes one video and audio output each, and I’m not sure stream mapping can even be used this way so this one is likely a mess.

ffmpeg -re -init_hw_device qsv=hw -filter_hw_device hw -hwaccel qsv -hwaccel_output_format qsv -c:v h264_qsv -i $INPUT 
-map 0:0 -c h264_qsv -profile high -preset medium -g 120 -b 8M -maxrate 8M -bufsize 4M 
-map 0:0 -c h264_qsv -profile high -preset medium -g 120 -b 12M -maxrate 12M -bufsize 6M 
-map 0:1 -c aac -b 320k 
-map 0:a -c copy 
-f tee "[select='v:0,a:0']8mbps.mkv|[select='v:1,a:1']12mbps.mkv|[select='v:2,a:1']copy.mkv"

To further complicate things, I’m using Quick Sync hardware encoding here and would want to apply -vf hwupload=extra_hw_frames=64,format=qsv to each re-encode if possible, but in my initial testing it was unclear if two sets of filters is possible, even on different encodes.

At any rate, is this even achievable with ffmpeg, and how if so?