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
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?
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 !
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
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"
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