Understanding ffmpeg map option - ffmpeg

I came across the following command in a blog post which creates different quality video streams that are packaged into DASH format via the dash muxer.
ffmpeg -i $VIDEO_IN \
-preset $PRESET_P -keyint_min $GOP_SIZE -g $GOP_SIZE -sc_threshold 0 \
-r $FPS -c:v libx264 -pix_fmt yuv420p -c:a aac -b:a 128k -ac 1 -ar 44100 \
-map v:0 -s:0 $V_SIZE_1 -b:v:0 2M -maxrate:0 2.14M -bufsize:0 3.5M \
-map v:0 -s:1 $V_SIZE_2 -b:v:1 145k -maxrate:1 155k -bufsize:1 220k \
-map v:0 -s:2 $V_SIZE_3 -b:v:2 365k -maxrate:2 390k -bufsize:2 640k \
-map v:0 -s:3 $V_SIZE_4 -b:v:3 730k -maxrate:3 781k -bufsize:3 1278k \
-map v:0 -s:4 $V_SIZE_4 -b:v:4 1.1M -maxrate:4 1.17M -bufsize:4 2M \
-map v:0 -s:5 $V_SIZE_5 -b:v:5 3M -maxrate:5 3.21M -bufsize:5 5.5M \
-map v:0 -s:6 $V_SIZE_5 -b:v:6 4.5M -maxrate:6 4.8M -bufsize:6 8M \
-map v:0 -s:7 $V_SIZE_6 -b:v:7 6M -maxrate:7 6.42M -bufsize:7 11M \
-map v:0 -s:8 $V_SIZE_6 -b:v:8 7.8M -maxrate:8 8.3M -bufsize:8 14M \
-map 0:a \
-init_seg_name init\$RepresentationID\$.\$ext\$ -media_seg_name chunk\$RepresentationID\$-\$Number%05d\$.\$ext\$ \
-use_template 1 -use_timeline 1 \
-seg_duration 4 -adaptation_sets "id=0,streams=v id=1,streams=a" \
-f dash Dash/dash.mpd
The thing I'm struggling to understand is how the maps work. I've read the Map docs but they don't seem to have a comparable example.
Why is -map v:0 used for every video stream?
Why does the first map line operate on stream 0 (e.g. -b:v:0) and the next map line operates on stream 1 (e.g. -b:v:1), etc.
Would really appreciate a breakdown.

Why is -map v:0 used for every video stream?
The correct string should be -map 0:v:0. The file index was omitted and thus implicitly interpreted as file index 0. Such syntax is best avoided.
Why does the first map line operate on stream 0 (e.g. -b:v:0)
Don't think in terms of lines or proximity of options in relation to a map. The 0 in -b:v:0 is part of a stream specifier and targets which output stream to target.
See
What the different between -b:v <target bitrate> and -b <target bitrate> FFmpeg flags?
https://superuser.com/q/1219784/

Related

How do I enable gpu acceleration in ffmpeg?

my code:
sudo ffmpeg -i rtsp://rtsp.stream/pattern \
-map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
-c:v h264_cuvid -crf 22 -c:a aac -ar 48000 \
-filter:v:0 scale=w=480:h=360 -maxrate:v:0 600k -b:a:0 500k \
-filter:v:1 scale=w=640:h=480 -maxrate:v:1 1500k -b:a:1 1000k \
-filter:v:2 scale=w=1280:h=720 -maxrate:v:2 3000k -b:a:2 2000k \
-var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p" \
-preset fast -hls_list_size 10 -threads 0 -f hls \
-hls_time 3 -hls_flags independent_segments \
-master_pl_name "livestream.m3u8" \
-y -vsync 0 -hwaccel cuda "/var/www/livestream-%v.m3u8"
Option hwaccel (use HW accelerated decoding) cannot be applied to output url /var/www/livestream-%v.m3u8 -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to.
Error parsing options for output file /var/www/livestream-%v.m3u8.
It doesn't work with the above error.
working cpu code:
sudo ffmpeg -i rtsp://rtsp.stream/pattern \
-map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
-c:v libx264 -crf 22 -c:a aac -ar 48000 \
-filter:v:0 scale=w=480:h=360 -maxrate:v:0 600k -b:a:0 500k \
-filter:v:1 scale=w=640:h=480 -maxrate:v:1 1500k -b:a:1 1000k \
-filter:v:2 scale=w=1280:h=720 -maxrate:v:2 3000k -b:a:2 2000k \
-var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p" \
-preset fast -hls_list_size 10 -threads 0 -f hls \
-hls_time 3 -hls_flags independent_segments \
-master_pl_name "livestream.m3u8" \
-y "/var/www/livestream-%v.m3u8"
The above operates as a cpu and annoys my cpu. I don't know how to write the command.=
Any ideas?

Video captured from x11grab is not playable in HLS format on Firefox/Safari

I'm trying to produce an HLS playlist from a video file.
It's a file captured from a virtual screen with ffmpeg and x11grab module:
ffmpeg -y -t 10 -copyts -draw_mouse 0 -framerate 24 -f x11grab -thread_queue_size 1024 -i :0 -f pulse -i default -acodec copy /tmp/test_preprocessed.mkv
But when I'm trying to produce HLS from this file, the output seems not correct, as it doesn't play in Firefox/Safari, but does play in Chrome (using hls.js or https://www.hlsplayer.net/ for example)
Original file: https://transfer.sh/y1a6Fv/735171b9-42a1-461a-a118-981119bdf74e_preprocessed.mkv
HLS Playlist generated from this file: https://video-staging-bucket.ams3.digitaloceanspaces.com/c08584ca-4731-4820-b5c7-71f12955c0b2/stackoverflow/playlist.m3u8
(Works in https://www.hlsplayer.net/ with chrome, doesn't works with Firefox/Safari)
How I'm producing the HLS:
ffmpeg -y \
-t 10 \
-i 735171b9-42a1-461a-a118-981119bdf74e_preprocessed.mkv \
-r 24 \
-filter_complex '[0:v]split=3[v1][v2][v3]; [v1]scale=w=1280:h=720[v1out]; [v2]scale=w=854:h=480[v2out]; [v3]scale=w=640:h=360[v3out]' \
-map '[v1out]' -c:v:0 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:0 3200k -maxrate:v:0 3200k -minrate:v:0 2500k -bufsize:v:0 3200k -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map '[v2out]' -c:v:1 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:1 1600k -maxrate:v:1 1600k -minrate:v:1 1250k -bufsize:v:1 1600k -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map '[v3out]' -c:v:2 libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v:2 900k -maxrate:v:2 900k -minrate:v:2 700k -bufsize:v:2 900k -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map a:0 -c:a:0 aac -b:a:0 96k \
-map a:0 -c:a:1 aac -b:a:1 128k \
-map a:0 -c:a:2 aac -b:a:2 128k \
-f hls \
-hls_time 4 \
-hls_playlist_type vod \
-hls_flags independent_segments \
-hls_segment_type mpegts \
-hls_segment_filename 'hls'/stream_%v_data%02d.ts \
-master_pl_name playlist.m3u8 \
-var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2" \
-t 10 \
'hls'/stream_%v.m3u8
Is there something I missed ? Maybe a standard ? Or maybe problem is related to PTS/DTS of my file ?
Thanks !

Multiple bitrates/resolutions and creating HLS playlist issue

When I run the command below, only the 1280x720 line works. The other two lines do not work. Where am I missing?
ffmpeg -i test.mp4 -s:v:0 1280x720 -c:a aac -c:v:0 libx264 -b:v:0 2000k \
-s:v:1 640x480 -c:a aac -c:v:1 libx264 -b:v:1 1000k \
-s:v:2 320x240 -c:a aac -c:v:2 libx264 -b:v:2 600k \
-f hls -hls_playlist_type vod -master_pl_name test.m3u8 \
-hls_segment_filename test_%v/test%06d.ts -use_localtime_mkdir 1 stream_%v.m3u8
You need to map the input video stream for each output video stream explicitly like this:
ffmpeg -i test.mp4 \
-map 0:v:0 -s:v:0 1280x720 -c:v:0 libx264 -b:v:0 2000k \
-map 0:v:0 -s:v:1 640x480 -c:v:1 libx264 -b:v:1 1000k \
-map 0:v:0 -s:v:2 320x240 -c:v:2 libx264 -b:v:2 600k \
-c:a aac \
-f hls -hls_playlist_type vod -master_pl_name test.m3u8 \
-hls_segment_filename test_%v/test%06d.ts -use_localtime_mkdir 1 stream_%v.m3u8

How to convert mkv video to hls using compiled ffmpeg

With the following commands converting the mkv video into HLS master playlist based video streams is not working correctly.
ffmpeg -i input.mkv \
-y -vsync 0 -c:v h264_cuvid -c:v h264_nvenc -c:a copy \
-map 0:v:0 -map 0:a:0 -vf fade,hwupload_cuda,scale_npp=854:358 -b:v:0 1M -b:a:0 128k \
-map 0:v:0 -map 0:a:0 -vf fade,hwupload_cuda,scale_npp=1280:536 -b:v:1 3M -b:a:1 192k \
-var_stream_map "v:0,a:0,name:480p v:1,a:1,name:720p" \
-hls_time 10 -hls_list_size 0 -hls_time 3 -hls_flags independent_segments -f hls -hls_playlist_type event -master_pl_name "master-pl.m3u8" output-%v.m3u8
And it is generating the output as follows which is wrong.
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-STREAM-INF:BANDWIDTH=1240800,RESOLUTION=1280x536,CODECS="avc1.4d401f,ac-3"
output-480p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3511200,RESOLUTION=1280x536,CODECS="avc1.4d401f,ac-3"
output-720p.m3u8
Question
How to generate master playlist with ffmpeg (which was compiled to work with nvidia GPU)
GPU compile configurations
--enable-nonfree --disable-shared --enable-gpl --enable-libx264 --enable-cuda --enable-nvenc --enable-cuvid --enable-cuda-nvcc --enable-openssl --enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64
I have copied the multiple resolution based video generating based on following commands which works well, but it works with CPU I would like to convert it into GPU.
ffmpeg -i input.mkv \
-map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
-c:v libx264 -crf 22 -c:a aac -ar 48000 \
-filter:v:0 scale=w=480:h=360 -maxrate:v:0 600k -b:a:0 64k \
-filter:v:1 scale=w=640:h=480 -maxrate:v:1 900k -b:a:1 128k \
-filter:v:2 scale=w=1280:h=720 -maxrate:v:2 900k -b:a:2 128k \
-var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p" \
-preset slow -hls_list_size 0 -threads 0 -f hls -hls_playlist_type event -hls_time 3 \
-hls_flags independent_segments -master_pl_name "name-pl.m3u8" \
"name-%v.m3u8"

How can I generate a multiple period DASH manifest with ffmpeg?

I am looking to encode a file and generate multiple periods rather than just one period. When I try to run ffmpeg with the below command, the result is a single period with multiple adaptation sets so clearly that is the wrong approach. I had thought by breaking the files by time this might work but apparently not. Any advice would be appreciated:
ffmpeg -i ~/Downloads/turkish-horses.mp4 \
-map 0:v:0 -b:v:1 1000k -ss 0 -t 5 -c:v:1 libx264 -filter:v:1 "scale=640:-1" \
-map 0:v:0 -b:v:2 1000k -ss 5 -c:v:2 libx264 -filter:v:2 "scale=640:-1" \
-map 0:v:0 -b:v:3 3000k -ss 0 -t 5 -c:v:3 libx264 -filter:v:3 "scale=1280:-1" \
-map 0:v:0 -b:v:4 3000k -ss 5 -c:v:4 libx264 -filter:v:4 "scale=1280:-1" \
-map 0:a\?:0 -ss 0 -t 5 -c:a aac -b:a 192k \
-map 0:a\?:0 -ss 5 -c:a aac -b:a 192k \
-use_timeline 1 -use_template 0 \
-adaptation_sets "id=0,streams=0,2 id=1,streams=4 id=2,streams=1,3 id=3,streams=5" \
-f dash output.mpd

Resources