ffmpeg
documentation says that we can use dash muxer to create dash segments and manifest file with just a single command, like:
ffmpeg -re -i <input> -map 0 -map 0 -c:a libfdk_aac -c:v libx264
-b:v:0 800k -b:v:1 300k -s:v:1 320x170 -profile:v:1 baseline
-profile:v:0 main -bf 1 -keyint_min 120 -g 120 -sc_threshold 0
-b_strategy 0 -ar:a:1 22050 -use_timeline 1 -use_template 1
-window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a"
-f dash /path/to/out.mpd
Saying I have some HD video file and I want this video to be available through DASH in different bit rates, so that clients can automatically select from the alternatives based on current network conditions. Can all these be done with a single ffmpeg
command, like given above?
I know there is a solution with using ffmpeg + mp4box, but i'm interested if it could be done with ffmpeg
only.
Ok, so this is how I resolved my problem. Following commands are useful for implementing pseudo-live dash content (it's when you want to stream existing video file as if it were a live video) but also the same approach could be used for on-demand video. First, we transform an input video file (sample.divx) into another, well prepared for dash streaming video file - sample_dash.mp4:
ffmpeg -y -i sample.divx ^
-c:v libx264 -x264opts "keyint=24:min-keyint=24:no-scenecut" -r 24 ^
-c:a aac -b:a 128k ^
-bf 1 -b_strategy 0 -sc_threshold 0 -pix_fmt yuv420p ^
-map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 ^
-b:v:0 250k -filter:v:0 "scale=-2:240" -profile:v:0 baseline ^
-b:v:1 750k -filter:v:1 "scale=-2:480" -profile:v:1 main ^
-b:v:2 1500k -filter:v:2 "scale=-2:720" -profile:v:2 high ^
sample_dash.mp4
I'm saying sample_dash.mp4 is well prepared because it's encoded in a good for dash format - H264/ACC and it's containing multiple (3) video streams with different qualities (baseline, main, high). ffmpeg dash muxer will translate these 3 video streams into relevant alternative video quality deash segment files. Here is how:
ffmpeg -y -re -i sample_dash.mp4 ^
-map 0 ^
-use_timeline 1 -use_template 1 -window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a" ^
-f dash sample.mpd
-re
flags tells ffmpeg to process the input video in a realtime manner, which is useful for pseudo-live streaming.
With the help of this answer and documentation, Following is the way to do this in single command:
ffmpeg -i $inputFile \
-map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 -map 0:v:0 -map 0:a\?:0 \
-b:v:0 350k -c:v:0 libx264 -filter:v:0 "scale=320:-1" \
-b:v:1 1000k -c:v:1 libx264 -filter:v:1 "scale=640:-1" \
-b:v:2 3000k -c:v:2 libx264 -filter:v:2 "scale=1280:-1" \
-b:v:3 245k -c:v:3 libvpx-vp9 -filter:v:3 "scale=320:-1" \
-b:v:4 700k -c:v:4 libvpx-vp9 -filter:v:4 "scale=640:-1" \
-b:v:5 2100k -c:v:5 libvpx-vp9 -filter:v:5 "scale=1280:-1" \
-use_timeline 1 -use_template 1 -window_size 6 -adaptation_sets "id=0,streams=v id=1,streams=a" \
-hls_playlist true -f dash output/output.mpd