= ffmpeg
in=... ; out=... # or eg. out="${in/%.mov/-small.mov}"
ffmpeg -i "$in"
==webm to mp4
Example:
ffmpeg -i "$in" -tune film -crf 20 -preset slow -b:a 192k -movflags +faststart "${in%%.webm}.mp4"
==h264
-c:v libx264 -pix_fmt yuv420p -tune film -crf 20 -g 50
-preset slow # (veryfast fast medium slow slower veryslow)
===Limit bitrate
Can be used with ''-crf''
-maxrate 6M -bufsize 6M
Or set an average bitrate, without using ''-crf'' (see [[https://trac.ffmpeg.org/wiki/Limiting%20the%20output%20bitrate|Limiting the output bitrate]])
-b:v 4M -maxrate 6M -bufsize 10M
==prores
* Prores proxy: -profile:v 0
* Prores LT: -profile:v 1
* Prores SQ: -profile:v 2
* Prores HQ: -profile:v 3
-c:v prores_ks -profile:v 1 -vendor apl0
-c:a pcm_s16le
==resize
See https://trac.ffmpeg.org/wiki/Scaling for details.
If using ''-s WxH'', you need to calculate the right sizes to preserve the aspect ratio. It's easier and generally better to use ''-vf scale=...'', which offers various shortcuts, and allows selecting the resizing algorithm.
Examples:
-vf "scale=hd1080"
-vf "scale=hd1080:flags=lanczos" # same, but with lanczos algorithm instead of default bilinear
-vf scale=640:-2 # width 640px, height as needed but divisible by 2
-vf "scale=iw/2:ih/2" # half width and height of original
-vf "scale=iw/2:-2" # same (half width and height), but height divisible by 2
etc.
==Deinterlace
See https://ffmpeg.org/ffmpeg-filters.html#yadif :
> yadif=mode:parity:deint
> defaults: 0(send_frame=one frame for each frame) : -1(auto=auto detection of field order) : 0(all=all frames)
-vf "yadif=0:-1:0"
==Extract part
start=00:05:12.000 # or just seconds: start=312
duration=00:01:05.000 # or just seconds: duration=65
ffmpeg -i "$in" -ss $start -t $duration -c:v copy ...
If ''-ss $start'' is before the ''-i'' input, it may be faster in some cases. But with codecs like h264, the resulting output may also miss the needed keyframes at the start, and the beginning of the video may be corrupted.
==Extract single frames
All frames as .png:
in="file.mov"; out="${in%.*}.%06d.png"
ffmpeg -i "$in" -f image2 "$out"
Here a frame at 5 seconds, and a frame at 300 seconds from the start
in="file.mov"
for start in 5 300; do ffmpeg -ss $start -i "$in" -r 1 -vframes 1 -f image2 "${in/%.mov/}-at-$start-sec.png"; done
Output one image for every I-frame:
ffmpeg -i input.flv -vf "select='eq(pict_type,PICT_TYPE_I)'" -vsync vfr thumb%04d.png
Find all .mov files under some directory, and extract a single Jpeg:
pos=2 # get frame at $pos seconds from start of file
search_in=/mnt/x/y
ext="mov"
find "$search_in" -type f -name "*.$ext" -not -name ".*" \
| while read f; do
n=$(basename "$f")
[ -f "$n" ] && n="$n-$RANDOM"
ffmpeg -nostdin -hide_banner -loglevel error -ss $pos -i "$f" \
-r 1 -vframes 1 -f image2 "$n.jpg" \
&& echo "OK $n.jpg"
done
Output all frames for a given duration (in seconds):
in="file.mkv"
start=00:09:38.000
duration=20
out="${in%%.mkv}-$start.%04d.png"
ffmpeg -ss $start -i "$in" -t $duration -f image2 "$out"
See also ffmpeg's [[https://trac.ffmpeg.org/wiki/Create%20a%20thumbnail%20image%20every%20X%20seconds%20of%20the%20video|Create a thumbnail image every X seconds of the video]].
==Images to video
With numbered frames, the numbering must start at 0: "frame0000.png", "frame0001.png", "frame0002.png", ...
===Animated webp
Frames to animated .webp :
in="test-tiff%08d.tif"; out="tiff-2.webp"
ffmpeg -r 25 -i "$in" -c:v libwebp_anim -lossless 1 -loop 0 -preset default -an -vsync 0 -s 480x270 "$out"
Animated .gif to .webp (copied from [[https://ozzyczech.cz/bash/convert-gif-to-web-m-with-ffmpeg/|Convert GIF to WebM with ffmpeg]])
ffmpeg -i my-animation.gif -c vp9 -b:v 0 -crf 41 my-animation.webm
===Jpegs to mp4
1 .jpg image = 1 frame :
in="image%03d.jpg" # image000.jpg to image999.jpg
out="image-to-video.mp4"
ffmpeg -framerate 25 -i "$in" -c:v libx264 -crf 18 -pix_fmt yuv420p "$out"
To start on a specific numbered frame, use ''-start_number''. Example staring at "image150.jpg":
in="image%03d.jpg" # image000.jpg to image999.jpg
out="image-to-video.mp4"
ffmpeg -start_number 150 framerate 25 -i "$in" -c:v libx264 -crf 18 -pix_fmt yuv420p "$out"
Slideshow with 1 .jpg = 1 second :
fps=25
out="slideshow-glob.mp4"
ffmpeg -framerate 1 -pattern_type glob -i '*.jpeg' -c:v libx264 -crf 20 -g $fps -pix_fmt yuv420p -r $fps "$out"
If the size of the frames is uneven (eg. 512x459), it needs to be set to an even size, or there will be this error:
> ''height not divisible by 2 (512x459)''
> ''Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height''
In this case, specify the size. For example: ''-s 512x460''
==Audio
===Audio AAC
-c:a aac -b:a 192k
===AC3 5.1 to Stereo
Using defaults:
ffmpeg -i input.ac3 -ac 2 output.ac3
Or manual:
... -af "pan=stereo|FL < 1.0*FL + 0.707*FC + 0.707*BL|FR < 1.0*FR + 0.707*FC + 0.707*BR" ...
See also: https://forum.videohelp.com/threads/404278-Ac3-5-1-audio-track-convert-to-stereo
===Remap 2 mono audio to stereo
I think that since ''-map'' is used, ''-map:v'' must be added too or the output is without video.
-filter_complex "[0:a:0][0:a:1]amerge,channelmap=channel_layout=stereo[st]" -map 0:v -map "[st]"
=== FLAC
==== FLAC to MP3
dir="/path/to/output_dir"; mkdir -p "$dir"
for f in *.flac; do
f2=$(basename "${f%.flac}.mp3"); \
out="$dir/$f2"; \
ffmpeg -i "$f" -c:a libmp3lame -q:a 0 -c:v copy "$out"
done
''-q:a 0'' with ''libmp3lame'' makes it use best quality VBR. See https://trac.ffmpeg.org/wiki/Encode/MP3
''-c:v copy'' makes it copy album art if there is any (instead of converting it to .png)
The metadata from FLAC is preserved by default, and written to a ID3v2.4 header. To write an ID3v2.3 header instead, add the ''-id3v2_version 3'' option.
==== WAV to FLAC
Can be done with ''flac'' instead of ffmpeg:
for f in *.wav; do
flac "$f" --keep-foreign-metadata -V -o "${f%%wav}.flac"
done
=== Detect silence
==== volumedetect
This was slow? 330 mn. for a 167 mn. / 600GB file with 16 audio channels. Not slow on 30GB 16channels quicktime. But doesn't separate channels!
time ffmpeg -i "$in" -map 0:a -af "volumedetect" -f null - 2>&1 | tee "$in-volumedetect.txt"
==== astats
ffmpeg -i "$in" -vn -sn -dn -map 0:a -af "astats=measure_overall=none" -f null - 2>&1
See also https://ffmpeg.org/ffmpeg-filters.html#toc-ebur128-1
==== EBU stats
For a file with 12 mono audio tracks:
for t in {0..11}; do ffmpeg -nostats -i "$in" -map 0:a:$t -filter_complex ebur128 -f null - > $(printf "ebur-$in-a%02d.txt" $t) 2>&1 ; done
==faststart
Move "moov" atom to start of file (https://ffmpeg.org/ffmpeg-formats.html#Options-8). (Implies file copy after encoding)
-movflags faststart
==Change framerate
''-r 25'' or ''-vf "fps=fps=25"''
Example to check what it does:
ffmpeg -f lavfi -i testsrc=duration=10:size=854x480:rate=60 \
-vf "drawtext=text=%{n}:fontsize=72:r=60:x=(w-tw)/2: y=h-(2*lh):fontcolor=white:box=1:boxcolor=0x00000099" test.mp4
== Add pseudo-timecode
Example with Fuji .MOV files, to add the "Create Date" time as a timecode:
* Check file extensions
find . -type f | perl -ple 's/^.*\.(\w+)/$1/' | sort -u
* Prepare destination
dest=/mnt/share/temp
mkdir -p "$dest"
* Extract time, add as TC, preserve original file date
find . -type f -name "*.MOV" \
| while read f; do \
b=$(basename "$f");
t=$(exiftool -CreateDate "$f" | awk '{print $NF}');
tc="$t:00";
echo "====== $f $tc";
ffmpeg -loglevel warning -i "$f" -codec copy -map_metadata 0 -movflags use_metadata_tags -timecode "$tc" -f mov "$dest/$b"
If the exiftool command gives the error "End of processing at large atom (LargeFileSupport not enabled)", add the ''-api largefilesupport=1'' option so the exiftool line becomes:
t=$(exiftool -api largefilesupport=1 -CreateDate "$f" | awk '{print $NF}');
==Diff
From https://reto.ch/training/2017/201706/FFmpeg.html
f1=... # file 1
f2=... # file 2
t="-t 60" # limit time
out=delta.mp4
ffmpeg -i "$f1" -i "$f2" $t \
-filter_complex "[1]format=yuva444p,lut=c3=128,negate[1_with_alpha_channel];[0][1_with_alpha_channel]overlay" "$out"
How to add resize? How to add different start times for input files?
Or see https://stackoverflow.com/questions/25774996/how-to-compare-show-the-difference-between-2-videos-in-ffmpeg :
ffmpeg -i "$f1" -i "$f2" $t \
-filter_complex "blend=all_mode=difference" \
-c:v libx264 -crf 18 -c:a none "$out"
And [[https://trac.ffmpeg.org/wiki/FilteringGuide|FFmpeg Filtering Guide]]
Or http://dericed.com/2012/display-video-difference-with-ffmpegs-overlay-filter/
ffmpeg "$f1" -i "$f2" $t \
-filter_complex '[1:v]format=yuva444p,lut=c3=128,negate[video2withAlpha],[0:v][video2withAlpha]overlay[out]' \
-map [out] "$out"
==Stream MD5
$ ffmpeg -i "$filename" -map 0:a -codec copy -f md5 "$filename.md5"
$ ffmpeg -i "$filename" -map 0:a -codec copy -hide_banner -loglevel warning -f md5 -
$ ffmpeg -i "$filename" -map 0 -c copy -f streamhash -hash md5 -
...
0,v,MD5=50224fec84bc6dfde90d742bcf1d2e01
1,a,MD5=1d2a32ed72798d66e0110bd02df2be65
$ ffmpeg -i "$f" -map 0 -c copy -f streamhash -hash md5 "$f.stream.md5"
See also:
* http://ffmpeg.org/ffmpeg-formats.html#hash
* https://trac.ffmpeg.org/wiki/framemd5%20Intro%20and%20HowTo
* https://stackoverflow.com/a/897594/111036
* https://stackoverflow.com/questions/63608312/how-to-md5-the-video-track-only-in-ffmpeg
==Other options
-nostdin
Verbosity:
-hide_banner -loglevel warning -stats
# or
-hide_banner -loglevel info -stats
===Edit metadata===
See [[https://superuser.com/questions/834244/how-do-i-name-an-audio-track-with-ffmpeg/835069|How do I name an audio track with ffmpeg]]:
ffmpeg -i input.mp4 -map 0 -c copy -metadata:s:a:0 title="One" -metadata:s:a:1 title="Two" -metadata:s:a:0 language=eng -metadata:s:a:1 language=spa output.mp4
==Examples
===Audio + still image to video
ffmpeg -loop 1 -r 1 -i "$in_img" -i "$in_a" \
-c:v libx264 -pix_fmt yuv420p -crf 22 -preset veryfast -tune stillimage \
-c:a copy -shortest "$out"
===Resize, remap audio, change fps
Source is 4K (3840x2160), 50fps progressive, 8 mono tracks.
Wanted output : HD 1920x1080, 25 fps, 1 stereo audio from source tracks 1 + 2.
ffmpeg -i "$in" -vf "scale=hd1080" -r 25 \
-c:v libx264 -pix_fmt yuv420p -tune film -crf 20 -g 50 \
-filter_complex "[0:a:0][0:a:1]amerge,channelmap=channel_layout=stereo[st]" \
-map 0:v -map "[st]" \
-c:a aac -b:a 192k \
"$out"
Sample output:
ffmpeg -i "$in" -t 300 -vf "scale=hd1080" -r 25 -c:v libx264 -pix_fmt yuv420p -tune film -preset fast -crf 20 -g 50 -filter_complex "[0:a:0][0:a:1]amerge,channelmap=channel_layout=stereo[st]" -map 0:v -map "[st]" -c:a aac -b:a 192k "$out"
ffmpeg version 4.2.1-static https://johnvansickle.com/ffmpeg/ Copyright (c) 2000-2019 the FFmpeg developers
...
[mxf @ 0x6225a40] decoding for stream 0 failed
Guessed Channel Layout for Input Stream #0.1 : mono
Guessed Channel Layout for Input Stream #0.2 : mono
...
Guessed Channel Layout for Input Stream #0.16 : mono
Input #0, mxf, from 'fdv20190808pgm.mxf':
Metadata:
operational_pattern_ul: 060e2b34.04010101.0d010201.01010900
uid : bd7136e0-ba0f-11e9-8fed-ac1f6b48c8ac
generation_uid : bd7136e0-ba0f-11e9-8fee-ac1f6b48c8ac
company_name : oc
product_name : OCtk
product_version : 2.10
product_uid : 3a4fe380-0d01-11e4-869f-3cd92b5c1dfc
modification_date: 2019-08-08T21:07:17.708000Z
material_package_umid: 0x060A2B340101010501010D2013000000BD6EECF0BA0F11E98FB2AC1F6B48C8AC
timecode : 21:07:16:08
Duration: 02:47:16.24, start: 0.000000, bitrate: 524301 kb/s
Stream #0:0: Video: h264 (High 4:2:2 Intra), yuv422p10le(progressive), 3840x2160 [SAR 1:1 DAR 16:9], 50 fps, 50 tbr, 50 tbn, 100 tbc
Metadata:
file_package_umid: 0x060A2B340101010501010D2013000000BD6AF550BA0F11E98F81AC1F6B48C8AC
Stream #0:1: Audio: pcm_s24le, 48000 Hz, mono, s32 (24 bit), 1152 kb/s
Metadata:
file_package_umid: 0x060A2B340101010501010D2013000000BD6AF550BA0F11E98F81AC1F6B48C8AC
Stream #0:2: Audio: pcm_s24le, 48000 Hz, mono, s32 (24 bit), 1152 kb/s
...
Metadata:
file_package_umid: 0x060A2B340101010501010D2013000000BD6AF550BA0F11E98F81AC1F6B48C8AC
Stream #0:16: Audio: pcm_s24le, 48000 Hz, mono, s32 (24 bit), 1152 kb/s
Metadata:
file_package_umid: 0x060A2B340101010501010D2013000000BD6AF550BA0F11E98F81AC1F6B48C8AC
Stream #0:17: Data: none
Metadata:
file_package_umid: 0x060A2B340101010501010D2013000000BD6AF550BA0F11E98F81AC1F6B48C8AC
data_type : vbi_vanc_smpte_436M
Stream mapping:
Stream #0:1 (pcm_s24le) -> amerge:in0 (graph 0)
Stream #0:2 (pcm_s24le) -> amerge:in1 (graph 0)
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
channelmap (graph 0) -> Stream #0:1 (aac)
...
{{tag>public ffmpeg}}