Skip to content

Instantly share code, notes, and snippets.

@sk22
Last active April 17, 2024 13:08
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save sk22/d97a15638256a785fa3ca4cde29024e2 to your computer and use it in GitHub Desktop.
Save sk22/d97a15638256a785fa3ca4cde29024e2 to your computer and use it in GitHub Desktop.

ffmpeg command cheat sheet

ts + vtt subtitles + jpeg thumbnail

ffmpeg -i *.ts -i *.vtt -attach *.jpeg \
  -c copy \
  -metadata title="insert title here" \
  -metadata description="insert description here" \
  -metadata date_released=2020 \
  -metadata:s:t:0 mimetype=image/jpeg -metadata:s:t:0 filename=cover_land.jpg \
  -metadata:s:a:0 language=ger -metadata:s:s:0 language=ger \
  output.mkv
  -c:v libx265 # re-encode as hevc

attach cover.jpg to mkv

ffmpeg -i video.mkv -attach cover.jpg -attach small_cover.jpg -map 0 -c copy \
  -metadata:s:t mimetype=image/jpg \
  -metadata:s:t:0 filename=cover.jpg \
  -metadata:s:t:1 filename=small_cover.jpg \
  out.mkv

scale (e.g.) cover image

ffmpeg -i vert-cover-original.jpg -vf scale=600:-1 cover.jpg
ffmpeg -i vert-cover-original.jpg -vf scale=120:-1 small_cover.jpg
ffmpeg -i land-cover-original.jpg -vf scale=-1:600 cover_land.jpg
ffmpeg -i land-cover-original.jpg -vf scale=-1:120 small_cover_land.jpg

extract cover image

ffmpeg -i movie.mkv -map 0:v -map -0:V -c copy cover.jpg

mapping: include video streams, exclude all normal video streams

convert to hevc, keep all metadata and other streams, re-add cover image

ffmpeg -i input-x264.mkv -attach cover.jpg -c copy -c:v libx265 \
  -map 0 -map -0:v:m:filename \
  -metadata:s:t:0 mimetype=image/jpeg -metadata:s:t:0 filename=cover.jpg \
  output-x265.mkv
  • doesn't properly copy input's cover images, apparently? hence re-adding manually
  • codecs: copy all, use libx265 for video streams
  • mapping:
    1. include all streams from input 0
    2. exclude the video stream with metadata filename (which only the cover art video stream has)

subtitles offset (in seconds; hh:mm:ss.mmm)

if subtitles are too early

ffmpeg -itsoffset 22 -i f.mkv -c copy subtitles.vtt

if subtitles come too late (there's a gap at the beginning)

ffmpeg -itsoffset -22 -i f.mkv -c copy subtitles.vtt

concat videos

https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg

file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

to quickly generate a list of all (matching) files, use this bash script line:

find -type f -name '*.mp4' | sed "s/.*/file \'&\'/" | tee files.txt
ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4

trim video

  • starting at 0:30, ending 10 seconds later (0:40)
ffmpeg -ss 00:00:30.0 -i input.mp4 -c copy -t 00:00:10.0 output.mp4
# or:
ffmpeg -ss 00:00:30.0 -i input.mp4 -c copy -to 00:00:40.0 output.mp4

“Note that -t is an output option and always needs to be specified after -i.” – https://superuser.com/questions/138331/using-ffmpeg-to-cut-up-video

make a gif

https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality

ffmpeg -ss 30 -t 3 -i input.mp4 -vf "fps=15,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output.gif

re-encode, add cover, add metadata for episodes

ffmpeg -i Angekommen*.mp4 \
  -filter:v "crop=in_w:in_h-64:0:32" \
  -c:v libx265 \
  -attach cover.jpg -attach small_cover.jpg \
  -metadata language="deu" \
  -metadata description="Juana, a 17-year-old wheelchair user, aims to explore her sexuality but is ashamed of her body. Trying to find her place in a new high school, she will go through failure, friendship, fear and politics until she builds her own pride." \
  -metadata:s:v:0 language="deu" \
  -metadata:s:a:0 language="spa" \
  -metadata:s:t mimetype=image/jpg \
  -metadata:s:t:0 filename=cover.jpg \
  -metadata:s:t:1 filename=small_cover.jpg \
  -metadata show="1 Meter 20" \
  -metadata release_date=2021 \
  -metadata season_number=1 \
  -metadata title="Angekommen" \
  -metadata episode_sort=1 \
  "1 Meter 20 - S01E01 - Angekommen.mkv"

mkvpropedit

https://mkvtoolnix.download/doc/mkvpropedit.html

mkvinfo movie.mkv

set title

mkvpropedit movie.mkv --set title="The Movie"

get attachments

mkvextract movie.mkv attachments 1:cover.jpg

set attachment

mkvpropedit movie.mkv --add-attachment movie-cover.jpg \
  --attachment-name cover.jpg --attachment-mime-type "image/jpeg"

add subtitles

https://superuser.com/questions/609113/how-to-add-and-remove-subtitles-in-an-mkv-file

mkvmerge -o output.mkv --language 0:ger \
  input.mkv subs.srt

list languages

mkvmerge --list-languages | grep German

random snippets

let convTime = (h, m, s, ms) => ms + s * 1000 + m * 1000 * 60 + h * 1000 * 60 * 60
let convText = text => convTime(...Array.from(text.split(/:|\./)).map(t => Number(t)))

['00:55:08.54', ..., '00:03:10.44'].forEach(t => console.log(convText))
// => [3341000, ..., 3308054]

// array of chapter lengths
[3341000, ..., 3308054].reduce((pre, cur) => { console.log(pre, pre + cur - 1); return pre + cur }, 0)

let toTime = m => `${Math.floor(m % (1000 * 60 * 60 * 60) / 1000 / 60 / 60)}:${Math.floor(m % (1000 * 60 * 60) / 1000 / 60)}:${Math.floor(m % (1000 * 60) / 1000)}.${m % 1000}`
# get current titles from mkv files and write them to titles.txt
for f in **/*.mkv; do echo $f >> titles.txt; mkvinfo $f | grep Title >> titles.txt; done
# then i used visual studio code to change titles and format the lines to form this command:
mkvpropedit "videofile1.mkv" -s title="video title 1"

concat seperate audio/video segment and merge them

find -name 'seg-*-f1-a*' | sort -V | while read f; do cat $f >> audio.ts; done
find -name 'seg-*-f9-v*' | sort -V | while read f; do cat $f >> video.ts; done
ffmpeg -i video.ts -i audio.ts -map 0:v -map 1:a -c copy output.mp4

get all filenames excluding extension

yes, this has nothing to do with ffmpeg

for f in *.mkv; do echo "${f%.*}"; done

extract/convert srt files from mkv files

for f in *.mkv; do n="${f%.mkv}"; ffmpeg -i "$f" "$n.eng.srt"; done

or even this, so i can log out of the ssh session while it completes its task

nohup bash -c 'for f in *.mkv; do n="${f%.mkv}"; ffmpeg -i "$f" "$n.eng.srt"; done' &

rename episode subtitle files according to number

renames

One Piece Temporada 5 Episodio 381.ass
381 - A New Crewmate! The Musician, Humming Brook!.mkv

to

381 - A New Crewmate! The Musician, Humming Brook!.spa.ass
381 - A New Crewmate! The Musician, Humming Brook!.mkv
for i in {351..381}; do vid=($i*.mkv); sub=(*$i.ass); name="${vid%.*}"; mv "$sub" "$name.spa.ass"; done

convert *.ass to *.srt

for f in *.ass; do ffmpeg -i "$f" "${f%.*}.srt"; done

to be continued

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment