FFmpeg

Share on:

FFmpeg - konverzija i titlovi



:left
FFmpeg je moćno parče softvera sposobno da dekodira, enkodira, transkodira, strimuje, filtrira i pušta skoro sve poznate formate medijskih fajlova, počev od onih zastarelih pa do savrmenih tek uvedenih u primenu.

  • Instalacija je jednostavna:
1sudo apt install ffmpeg
2ffmpeg -formats # formati koje podržava
3ffmpeg -codecs  # lista kodeka koje se instaliraju sa njim

Ja ću se ovde fokusirati na 2 slučaja zanimljiva običnim korisnicima:

  • Konverziju video i audio fajlova u smislu promene formata, bitrejta, rezolucije, tipa kompresije itd. , što smanjuje izlaznu veličinu ali uz gubitak kvaliteta prikaza.
  • Ugrađivanje titlova u video fajlove, kao i lepljenje (hardcoding) titlova prvenstveno srpske latinice i ćirilice. TITLOVI
  • Svuda u daljem tekstu CP1250 je oznaka za latinicu, a ako imamo ćirilični titl oznaka je CP1251.

KONVERZIJA


Da li vam se desilo da dođete u posed video ili audio snimka koji za svoju dužinu ima neverovatnu veličinu.
Običnom korisniku nije potreban preterani kvalitet klipa od 7 minuta koji ima 1 GB ili više.
Treba naći kompromisno rešenje, a za to su nam potrebni parametri video fajla.
U paketu sa FFmpeg instalira se i FFplay (jednostavni medijski plejer) i FFprobe (alat za analizu parametara multimedijskih fajlova).
Evo kako pomoću FFprobe možemo dobiti parametre našeg testnog fajla:

  • Rezoluciju:
1ffprobe -v error -select_streams v:0 -show_entries stream=height,width -of csv=s=x:p=0 https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4
  • Broj frejmova u sekundi - Frame Rate:
1ffprobe -v error -select_streams v:0 -show_entries stream=avg_frame_rate -of default=noprint_wrappers=1:nokey=1 https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4
2# 30000/1001 je 30 fps
  • Veličinu fajla:
1ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1 https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4
2# dobijena vrednost je bajtima (za iznos u MB treba podeliti sa 1048576)

Kao što vidimo komande su dugačke i mada daju sliku o upotrebljivosti, njihova primena nije baš praktična. Mnogo jednostavnije je instalirati neki GUI program, kao što je mediaInfo-gui:
1sudo apt update && sudo apt upgrade
2sudo apt install mediainfo-gui

Dakle naš fajl ima ~58 MB, rezoluciju 3840x2160 i Bitrate 22 Mb/s

napomena:
Podatke o parametrima video fajla možemo da dobijemo i iz komandne linije:

1sudo apt install mediainfo
2mediainfo --Inform="Video;rezolucija = %Width%x%Height% Px, dijagonala = %DisplayAspectRatio/String%, bitrejt = %BitRate/String%, frejmrejt = %FrameRate% fps, dužina = %Duration/String1%, %InternetMediaType%" https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4

odgovor:
rezolucija = 3840x2160 Px, dijagonala = 16:9, bitrejt = 22.0 Mb/s, frejmrejt = 29.970 fps, dužina = 23 s 123 ms, video/H264

Možemo da uradimo sledeće:

  • Možemo da ga smanjimo kompresijom uz pomoć H265 kodeka:
1ffmpeg -i https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4 -c:v libx265 -crf 28 output.mp4

Ovde koristimo CRF (Constant Rate Factor) kao default podešavanje kvaliteta i bitrate-a. Više o tome ovde.
Test fajl smo smanjili: sa 57.8 na 48.6 MB, odnosno nekih ~20%:

  • Obzirom da naš fajl ima Bitrate 22 Mb/s, smanjimo ga na 10:
1ffmpeg -i https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4 -b:v 10M -minrate 10M -maxrate 10M output.mp4


Smanjili smo veličinu fajla na 26 MB, ali po cenu vidljive degradacije kvaliteta.

  • Možemo da smanjimo rezoluciju na FullHD (1920x1080):
1ffmpeg -i https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4 -vf scale=1920:1080,setsar=1:1 output.mp4

Dobijamo sledeće parametre:


Evo tabele sa preporučenim rezolucijama za dijagonalu 16:9

Best Choice: 2nd Best: 3rd Best:
Multiples of 16 Multiples of 8 Multiples of 4
1920 x 1080 1792 x 1008 1856 x 1044
1280 x 720 1152 x 648 1216 x 684
1024 x 576 896 x 504 1088 x 612
768 x 432 640 x 360 960 x 540
512 x 288 384 x 216 832 x 468
256 x 144 128 x 72 704 x 396
576 x 324
448 x 252
320 x 180
192 x 108

Zaključak:

Na svakom od nas je da proceni koliki gubitak kvaliteta mu je prihvatljiv kad zadaje izlazne parametre.
Evo predloga kako bi to moglo da se uradi kombinujući više operacija u istoj komandi.

1ffmpeg -i https://www.countryvetclinic.com/wp-content/uploads/2019/05/Pexels-Videos-1321208.mp4 -vf scale=1920:1080,setsar=1:1 -b:v 15M -minrate 13M -maxrate 16M -c:v libx265 -crf 28 output.mp4


Dovođenje video fajla na zadatu veličinu


  • Hajde da razmotrimo scenario u kome nam je zadato da veličinu fajla svedemo na određenu vrednost i to promenom bitrejta.
    Naš fajl Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 ima bitrejt 2150 kb/s , dužinu 5 min 8 s = 308 s i veličinu ~84 MB.
    Zadatak je da fajl ne pređe 80 MB.

1 byte = 0.008192 kb # jedan bajt je jednak 8192 milionita dela kilobita.
1 MB = 1000000 byte = 1000000 x 0.008192 = 8192 kb (kilobita)

Formula je: bitrejt (kb/s) = veličina fajla (kb)/ vreme trajanja (s)

Konvertujemo megabajte u kilobite (MB u kb):
80 MB x 8192 = 655360 kb

Ukupni bitrejt (video + audio) = 655360/308 = 2127 kb/s
2127 - 128 = 1999 kb/s # kad oduzmemo 128 za audio strim, za video ostaje 1999

Sad ide transkodiranje u 2 prolaza:

1ffmpeg -y -i Auntie.Edna.2018.1080p.BluRay.x264-\[YTS.AM\].mp4 -c:v libx264 -b:v 1999k -pass 1 -an -f null /dev/null && ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-\[YTS.AM\].mp4 -c:v libx264 -b:v 1999k -pass 2 -c:a aac -b:a 128k Auntie.Edna.80MB.mp4

Rezultat: fajl veličine 78,5 MB


Limitiranje broja jezgara-tredova pri precesiranju


  • FFmppeg je program koji simultano koristi više procesorskih jezgara, odnosno tredova (paralelnih operacija).
    Kako naći koliko jezgara i tredova poržava naš procesor:
1grep ^cpu\\scores /proc/cpuinfo | uniq |  awk '{print $4}'  # broj fizičkih jezgara
2grep -c ^processor /proc/cpuinfo # broj tredova (number of threads)

Prva komanda mi daje broj 4, a druga broj 8, što znači da moj procesor Intel i7-3770 ima 4 jezgra i 8 tredova.

Kad pokrenem neko grupno enkodiranje (batch process), svih 8 tredova se aktiviraju dovodeći do zauzeća procesora od 100%.
Treba ograničiti broj tredova koje će koristiti FFmpeg kako bi rasteretili procesor za nešto drugo.

  • Za enkodiranje u H.264:
1ffmpeg -i imput.mp4 -c:v libx264 -crf 23 -threads 4 output.mp4

​ gde smo sa -threads 4 zadali FFmpeg-u da komandu izvršava sa 4 treda.

​ Za grupno (batch) enkodiranje ista komanda bi bila:

1for i in *.mp4; do ffmpeg -i "$i" -c:v libx264 -crf 23 -threads 4 "${i%.mp4}-H.264.mp4"; done

​ dobijamo enkodirane istoimene fajlove samo sa sufiksom -H.264

  • Za enkodiranje u H.265:
1ffmpeg -i imput.mp4 -c:v libx265 -crf 23 -x265-params pools=6 output.mp4

​ gde smo sa -x265-params pools=6 zadali FFmpeg-u da komandu izvršava sa 6 tredova. ​ Za grupno (batch) enkodiranje ista komanda bi bila:

1for i in *.mp4; do ffmpeg -i "$i" -c:v libx265 -crf 23 -x265-params pools=4 "${i%.mp4}-H.265.mp4"; done


TITLOVI



Neka nam testni fajl bude Auntie Edna.
Ako još niste instalirali/ažurirali youtube-dl evo komande:

1sudo apt-get remove -y youtube-dl && sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl && sudo chmod a+rx /usr/local/bin/youtube-dl

daunlodujmo Ednu u maksimalnoj ponuđenoj rezoluciji (1728x1080):

1cd /folder/gde/vrsimo/konverziju
2youtube-dl -F https://vimeo.com/311038206

Dobićemo ovako nešto:

Izaberemo jednu od ponuđenih opcija sa najvećom rezolucijom (ja sam uzeo poslednju):

1youtube-dl -f dash-fastly_skyfire-video-1197402664 https://vimeo.com/311038206

Sad skinimo titl odavde.

Imamo video fajl (Auntie Edna-311038206.mp4) i titl (Auntie.Edna.2018.720p.BluRay.x264-[YTS.AM].srt) koje ćemo preimenovati u Auntie_Edna.mp4 i titl.srt.

1mv 'Auntie Edna-311038206.mp4' Auntie_Edna.mp4
2mv Auntie.Edna.2018.720p.BluRay.x264-[YTS.AM].srt titl.srt

Ugradićemo titl u fajl kao njegov sastavni deo bez re-enkodiranja:

1ffmpeg -i Auntie_Edna.mp4 -sub_charenc CP1250 -i titl.srt -map 0:v -map 0:a -c copy -map 1 -c:s:0 mov_text -metadata:s:s:0 language=srp Auntie_Edna_sa_titlom.mp4

  1. U fajl Auntie_Edna_sa_titlom.mp4 je ugrađen titl uz audio i video komponentu:
    mediainfo-gui

  2. Ugrađivanje titla u mkv fajl:

    1ffmpeg -i input.mkv -sub_charenc CP1250 -i subtitle.srt -map 0:v -map 0:a -c copy -map 1 -c:s:0 srt -metadata:s:s:0 language=srp output.mkv
    
  3. Ili ugrađivanje više titlova u mkv fajl:

    1ffmpeg -i input.mp4       -i subtitle_eng.srt -i subtitle_fre.srt \
    2       -map 0:v -map 0:a  -map 1              -map 2              \
    3       -c:v copy -c:a copy -c:s copy                              \
    4       -metadata:s:s:0 language=eng -metadata:s:s:1 language=fre  \
    5  output.mkv
    

Nalepićemo titl na video kao sastavni deo slike uz re-enkodiranje:

  1. Titl žute boje,sa transparentnom pozadinom, font Arial 24, testni fajl promenjen u Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -vf "subtitles=titl.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=24,OutlineColour=&H100000000,Outline=1,Alignment=2,Shadow=1,PrimaryColour=&H0000FFFF'" Auntie-Edna.mp4
    

  2. Titl isti kao u prethodnom slučaju ali sa crnom pozadinom:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -vf "subtitles=titl.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=24,OutlineColour=&H100000000,Outline=1,BorderStyle=3,Alignment=2,Shadow=1,PrimaryColour=&H0000FFFF'" Auntie--Edna.mp4
    

  3. Crna boja je u redu ako je na fajl već nalepljen neki strani titl koji odvlači pažnju. Obično to nije tako drastično, pa vizuelno više prija polutransparentna pozadina:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -vf "subtitles=titl.srt:charenc=CP1250:force_style='BackColour=&H80000000,Fontname=Arial,Fontsize=22,OutlineColour=&H100000000,Outline=1,BorderStyle=4,Alignment=2,Shadow=1,PrimaryColour=&H0000FFFF'" Auntie__Edna.mp4
    

  4. Transparentna pozadina titlova + enkodirano -crf 28 u x265;
    fajl smanjen sa 84 na 29 MB:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -vf "subtitles=titl.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=24,OutlineColour=&H100000000,Outline=1,Alignment=2,Shadow=1,PrimaryColour=&H0000FFFF'" -c:v libx265 -crf 28 Auntie---Edna.mp4
    

  5. Prethodne operacije smo obavljali ostavljajući nepromenjenu rezoluciju 1920x808 što odgovara dijagonali (Aspect Ratio) od 2,4:1.
    Vidimo iz predloženih rezolucija da FFmpeg "voli" standardni odnos 16:9.
    Evo kako bi smo skalirali naš video fajl sa 1920x808 [A.R - 2.40:1] na 1280:720 [A.R. - 16:9] uz zadržavanje proporcija slike, dakle popunjavanje praznog prostora crnim trakama:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1" Auntie.-.Edna.mp4
    

  6. Ako skaliranje na različitu rezoluciju iskombinujemo sa lepljenjem titlova, dobićemo:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -filter_complex "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:-1:-1,setsar=1,subtitles=titl.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=20,OutlineColour=&H100000000,Outline=1,Alignment=2,Shadow=1,PrimaryColour=&H0000FFFF'[v]" -map "[v]" -map 0:a -c:a copy Auntie-.-Edna.mp4
    

  7. Ima tu još prostora ispod titla, hajde da maksimalno iskoristimo crnu traku:

    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -filter_complex "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:-1:-1,setsar=1,subtitles=titl.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=20,OutlineColour=&H100000000,Outline=1,Alignment=2,MarginV=1,Shadow=1,PrimaryColour=&H0000FFFF'[v]" -map "[v]" -map 0:a -c:a copy Auntie-..-Edna.mp4
    

  1. Ako bi uz sve iz prethodne tačke dodali re-enkodiranje u H265 da bi smanjili veličinu fajla:
    1ffmpeg -i Auntie.Edna.2018.1080p.BluRay.x264-[YTS.AM].mp4 -filter_complex "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:-1:-1,setsar=1,subtitles=titl.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=20,OutlineColour=&H100000000,Outline=1,Alignment=2,MarginV=1,Shadow=1,PrimaryColour=&H0000FFFF'[v]" -map "[v]" -map 0:a -c:a copy -c:v libx265 -crf 28 Auntie-Edna.mp4
    

  1. Kako bi recimo isekli deo fajla i na njega nalepili titl.
    Evo primera kako iz desete epizode šeste sezone Game of Thrones izrenderovati titl na segment od 00:57:14 do 01:01:51 u kome Lyanna Mormont drži istorijski govor Severnjacima:

    1ffmpeg -ss 00:57:14 -to 01:01:51 -copyts -i GoT.S06E10.mkv -vf "subtitles=GoT.S06E10.srt:charenc=CP1250:force_style='Fontname=Arial,Fontsize=24,OutlineColour=&H100000000,Outline=1,Alignment=2,Shadow=1,PrimaryColour=&H0000FFFF'" -c:a copy -ss 00:57:14 -y king_in_the_north.mp4
    

I to bi bilo to...