ffmpeg

Costas

Administrator
Staff member
old years ffmpeg distribute only the source code and there are many people made webpages and spreading the binaries.

now days is only one site.



show video information
ffmpeg.exe -i "input.mp4"

convert 4:3 video to 16:9

by default if nothing specified on cmd line, uses libx264 (h264) codec.
  • CBR (Constant Bit Rate) - Target specific filesize (aka bitrate)
ffmpeg.exe -i "input.mp4" -b:v 376k -maxrate 376k -bufsize 700k -vf "scale=854x480,setsar=1" -c:a aac -b:a 96k "output.mp4"
  • Constrained encoding (VBV / maximum bit rate)
ffmpeg.exe -i "input.mp4" -crf 30 -maxrate 450k -bufsize 800k -vf "scale=854x480,setsar=1" -c:a aac -b:a 96k "output.mp4"

crf = where 0 is lossless, 23 is default, and 51 is worst possible. A lower value is a higher quality (src)
  • Constrained encoding with libx265 (h265) codec
ffmpeg.exe -i "input.mp4" -crf 30 -vcodec libx265 -vf "scale=854x480,setsar=1" -c:a aac -b:a 96k "output.mp4"

You can use -crf or -b:v with a maximum bit rate by specifying both -maxrate and -bufsize. (src)

convert to 480p - avoid "height not divisible by 2"
//normal : ffmpeg.exe -i "input.mp4" -crf 27 -vf scale=-1:480 "output.mp4" -- "height not divisible by 2"

//fix - https://dtbaker.net/blog/ffmpeg-width-or-height-not-divisible-by-2/
ffmpeg.exe -i "input.mp4" -crf 27 -vf scale=-2:480 "output.mp4"


  • Target specific filesize (aka bitrate) - how to calculate
//this will show the movie length in seconds
ffprobe.exe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "input.mp4"

//source - https://trac.ffmpeg.org/wiki/Encode/H.264#twopass
//you can achieve the same result at https://www.3ivx.com/support/calculator/
Assuming you have a video is 1h 40m and you would like to trim down to 350mb with audio 96kbits, the calculation is (8192 is constant) ;
targetSize * 8192 / ffprobe result
350 * 8192 / 6071,72 = 472kBit/s (total bitrate)
472 - 96 (desired audio bitrate) = 376kBit/s video bitrate
  • Two-pass
It's recommended to use a two-pass encoding mode if you want to target specific filesize (aka bitrate).​
On 2022, using 2 passes with libx265 not recommended, nothing changes. (src)​
Nevertheless, the use is :​
construct the needed cmd line, and add -pass 1, these will generate a log file, then use the same cmd line but now with -pass 2 to do the actual conversion.



Make a batch file to drag & drop the video file

JavaScript:
@echo off

if [%1]==[] goto usage

:: filepath of ffmpeg
set ffmpeg="c:\tools\ffmpeg.exe"
set ffprobe="c:\tools\ffprobe.exe"

set dd=%~1h265.mp4

%ffmpeg% -i "%~1" -crf 30 -vcodec libx265 -vf "scale=854x480,setsar=1" -c:a aac -b:a 96k "%dd%"
::%ffmpeg% -i "%~1" -crf 30 -maxrate 450k -bufsize 800k -vf "scale=854x480,setsar=1" -c:a aac -b:a 96k "%dd%"
::%ffmpeg% -i "%~1" -b:v 376k -maxrate 376k -bufsize 700k -vf "scale=854x480,setsar=1" -c:a aac -b:a 96k "%dd%"
::%ffmpeg% -i "%1"
::%ffprobe% -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "%~1"

pause

exit

:usage
@echo please drag and drop a file
pause
exit

bufsize
Based on the -bufsize option, ffmpeg will calculate and correct the average bit rate produced. If we didn't specify -bufsize, these intervals could be significantly longer than we would want. This would cause the current bit rate to frequently jump a lot over and below the specified average bit rate and would cause an unsteady output bit rate.

If we specify a smaller -bufsize, ffmpeg will more frequently check for the output bit rate and constrain it to the specified average bit rate from the command line. Hence, lowering -bufsize lowers the bitrate variation that the encoder can produce.

Specifying too small -bufsize would cause ffmpeg to degrade the output image quality, because it would have to (frequently) conform to the limitations and would not have enough of a free space to use some optimizations (for example, optimizations based on the frame repetitions and similar), because the buffer would not contain enough frames for the optimizations to be effective. (src)

crf
Use this rate control mode if you want to keep the best quality and care less about the file size. This is the recommended rate control mode for most uses.

This method allows the encoder to attempt to achieve a certain output quality for the whole file when output file size is of less importance. This provides maximum compression efficiency with a single pass. By adjusting the so-called quantizer for each frame, it gets the bitrate it needs to keep the requested quality level. The downside is that you can't tell it to get a specific filesize or not go over a specific size or bitrate, which means that this method is not recommended for encoding videos for streaming. (src)

16:9 resolutions :
  • 640 x 360 (nHD)
  • 854 x 480 (FWVGA)
  • 960 x 540 (qHD)
  • 1024 x 576 (WSVGA)
  • 1280 x 720 (HD/WXGA)
  • 1366 x 768 (FWXGA)
  • 1600 x 900 (HD+)
  • 1920 x 1080 (FHD)
  • 2048 x 1152 (QWXGA)
  • 2560 x 1440 (QHD)
  • 3200 x 1800 (WQXGA+)
  • 3840 x 2160 (UHD)
  • 5120 x 2880 (UHD+)
  • 7680 x 4320 (FUHD)
  • 15360 x 8640 (QUHD)
  • 30720 x 17280 (HHD)
  • 61440 x 34560 (FHHD)
  • 122880 x 69120 (QHHD)


references :
ffmpeg - H.264 Video Encoding Guide
ffmpeg - Scale Filter
ffmpeg - Codecs
Doing 2 pass encoding with FFmpeg
@tigefa4u/personal quick ffmpeg cheat sheet
Limit output filesize - no other switches can be used, when the encoding reaches the excepted filesize stops, so the result can be the half movie
16:9 <> 4:3
libx265
ffmpeg -ss and -t for cutting for video / mp3
Avidemux Tutorial for fixing 4:3 to 16:9
Change CPU Priority
 
Last edited:

Costas

Administrator
Staff member
remove metadata (exif) from images/mp4

https://exiftool.org/

JavaScript:
//https://www.funkyspacemonkey.com/how-to-remove-exif-metadata

exiftool -all= "c:\1.mp4"

maybe there is also another way for the same.

this removing the metadata fields only, no video/audio channel descriptions.
 

Costas

Administrator
Staff member
convert video to 480p and remove video default audio
ffmpeg.exe -i "input.avi" -vcodec libx264 -b:v 1000k -an -vf scale=854:-1,fps=25 "output.mp4"
--if you getting 'height not divisible by 2' use : -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2,fps=25"

convert video to 480p and add repeatable audio track that dont extend the video
--https://stackoverflow.com/a/37706813
ffmpeg.exe -i "input.avi" -stream_loop -1 -i audio.mp3 -shortest -b:v 1000k -c:a aac -b:a 96k -vf scale=854:-1,fps=25 -vcodec libx264 "output.mp4"

--

adding audio ( without re-encode )
source
* video.mp4 is 1:23
* audio.aac audio is 8:20

//the length of output.mp4 will be 8:20
ffmpeg -i video.mp4 -i audio.aac -c copy -map 0:v -map 1:a output.mp4

//the length of output.mp4 will be 1:23 ( because of -t 83 switch ) 83 = (1m = 60 sec) + 23sec
ffmpeg -i video.mp4 -i audio6.aac -c copy -map 0:v -map 1:a -t 83 output.mp4

//the length of the output.mp4 will be equal as when the shortest output stream ends (video or audio), in this case 1:23 -- https://ffmpeg.org/ffmpeg.html
ffmpeg -i video.mp4 -i audio6.aac -c copy -map 0:v -map 1:a -shortest output.mp4


source
* video.mp4 is 1:23
* audio.aac audio is 0:27

//the length of output.mp4 will be 1:23 with the audio repeatable
ffmpeg -i video.mp4 -stream_loop -1 -i audio.mp3 -c copy -map 0:v -map 1:a -shortest output.mp4
 

Costas

Administrator
Staff member
metadata title used on every application, adjust with
ffmpeg -i input.mp4 -metadata title="The video titile" -c copy output.mp4

ref - https://write.corbpie.com/adding-metadata-to-a-video-or-audio-file-with-ffmpeg/

increasing volume in video
ffmpeg -i input.mkv -filter:a "volume=4.0" output.mkv;

ref - https://bytefreaks.net/uncategorized/increase-volume-in-video-using-ffmpeg (ffmpeg)

normalize all sound duration to the one max (if the video volume is low, is not gain)
1st
ffmpeg -i input.mp4 -af "volumedetect" -vn -sn -dn -f null NUL

[Parsed_volumedetect_0 @ 00000270226e1ec0] n_samples: 114395136
[Parsed_volumedetect_0 @ 00000270226e1ec0] mean_volume: -28.1 dB
[Parsed_volumedetect_0 @ 00000270226e1ec0] max_volume: -7.6 dB
[Parsed_volumedetect_0 @ 00000270226e1ec0] histogram_7db: 19
[Parsed_volumedetect_0 @ 00000270226e1ec0] histogram_8db: 183

get the max_volume value

2nd
ffmpeg -i input.mp4 -filter:a "volume=7.6dB" output.mkv
ref - https://superuser.com/a/323127

Loudness Normalization
1st
ffmpeg -i input.mp4 -filter:a loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json -f null NUL
{
"input_i" : "-24.49",
"input_tp" : "-7.54",
"input_lra" : "4.70",
"input_thresh" : "-35.30",
"output_i" : "-16.13",
"output_tp" : "-1.50",
"output_lra" : "4.60",
"output_thresh" : "-26.92",
"normalization_type" : "dynamic",
"target_offset" : "0.13"
}

2nd
ffmpeg -i input.mp4 -filter:a loudnorm=I=-16:TP=-1.5:LRA=11:measured_I=-24.49:measured_LRA=4.70:measured_TP=-7.54:measured_thresh=-35.30:eek:ffset=0.13:linear=true:print_format=summary output.mp4

Speeding up/slowing down video
//https://trac.ffmpeg.org/wiki/How%20to%20speed%20up%20/%20slow%20down%20a%20video

ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" output.mp4

Cutting (aka split)
//this will create aa the new video from 5:20 + 10minutes. with the -t is not declared goes till the end of the video.
ffmpeg -i input.mp4 -ss 00:05:20 -t 00:10:00 -c:v copy -c:a copy output1.mp4

//this will make the cut depending on video times
ffmpeg -i a.mp4 -ss 00:17:42 -to 00:19:28 -c:v copy -c:a copy output1.mp4

//this hardcode also the subs
ffmpeg -i "a.mkv" -ss 00:12:40 -to 00:29:09 -vf "subtitles='a.srt'" -c:v libx264 -c:a aac -strict experimental output1.mp4

//this hardcode the subs and also resize to 640p
ffmpeg -i "a.mkv" -ss 01:27:57 -to 01:28:53 -vf "scale=640:-1,subtitles='a.srt'" -c:v libx264 -c:a aac -strict experimental output1.mp4

Merge (aka concat)
there is a file called merge.txt is like that
file output1.mp4
file output2.mp4
file output3.mp4

using the following to merge to one file
ffmpeg -f concat -safe 0 -i merge.txt -c copy merged_output.mp4


ref
https://trac.ffmpeg.org/wiki/AudioVolume
http://k.ylo.ph/2016/04/04/loudnorm.html (mirror)
https://superuser.com/a/1637581
 

Costas

Administrator
Staff member
add hardcode subtitles

ffmpeg -i video.mp4-vf subtitles=subtitle.srt out.mp4

*1*//consider to add quality factor parameter and even parameterize the encoder -- https://video.stackexchange.com/a/17549
ffmpeg -i gradedFinal.mov -vf subtitles=portSbs.srt -crf 18 -c:a copy gradedFinalwithSubs.mov

*2*//set the font & fontsize (Arial 24 is the normal as VHS) -- https://stackoverflow.com/a/34644126
ffmpeg -i "C:\Users\test.mkv" -vf "subtitles=sub.srt:force_style='FontName=Arial,FontSize=24'" -vcodec libx264 -acodec copy -q:v 0 -q:a 0 output.mp4

//extended version of *2* by using crf and veryfast preset as advised here -- https://superuser.com/a/1259172
ffmpeg -i "C:\Users\test.mkv" -crf 21 -vf "subtitles=sub.srt:force_style='FontName=Arial,FontSize=24'" -vcodec libx264 -preset veryfast -acodec copy -q:v 0 -q:a 0 output.mp4

apparently this will reencode the video... source

I think the best alternative is to convert the subtitles to images (vobsub), see here...

add soft subtitles to container

ffmpeg -i input.mp4 -i subtitle.en.srt -c copy -c:s mov_text -metadata:s:s:0 language=eng ouptut_english.mp4

//specify multiple .srt files
ffmpeg -i input.mp4 -i subtitle.en.srt -i subtitle.chi.srt -map 0 -map 1 -map 2 -c copy -c:s mov_text -metadata:s:s:0 language=eng -metadata:s:s:1 language=chi output_eng_chi.mp4

-c copy specifies that the video is not to be re-encoded.
-c:s mov_text sets the SRT file to MOV_TEXT format.
-metadata:s:s:0 means to set the metadata for Stream:Subtitle:Number of stream, starting with 0.
language=eng sets the subtitle language to English. The value for this option uses the ISO 639 language code which consists of 3 letters for every language. source

extract subtitles by container
ffmpeg -i Movie.mkv -map 0:s:0 subs.srt -- https://superuser.com/a/1649387

(linux only) Capture a region around cursor (aka follow mouse / trackmouse)
//https://ffmpeg.org/ffmpeg-devices.html#Options-20
ffmpeg -f x11grab -follow_mouse centered -framerate 25 -video_size cif -i :0.0 out.mpg

How Can I make bookmarks/chapters for a video?
 
Top