Редактиране на видео под Линукс
[video
linux
software
]
Съвети за редактиране на видео под Линукс
Въведение
Тук ще споделя моя опит с приложения и команди за обработка на видео под Линукс. Част от резултатите можете да видите тук: Different ways to improve video using free software in Linux - add telemetry, enhance colors, stabilize video.
Docker
Docker е много удобен инструмент, когато трябва да се работи със сложни взаимовръзки между библиотеките. Препоръчителният начин за инсталация е описан на https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker ВАШИЯТ–ПОТРЕБИТЕЛ
ffmpeg
За определяне на качеството при прекодиране се ползват параметрите -codec:v libx264 -crf 18 -preset slower
- За повече информация https://stackoverflow.com/questions/20435420/ffmpeg-how-to-apply-filters-without-losing-quality, https://stackoverflow.com/questions/17793150/default-ffmpeg-codec-when-nothing-is-specified#:~:text=ffmpeg%20will%20re-encode%20each,then%20mpeg4%20will%20be%20used
Стабилизиране на видео
Резултатът от стабилизирането може да се види тук:
- резултат
- сравнение половин екран, без допълнителна обработка
- сравнение цял екран, без допълнителна обработка
- оригинално видео
Плъгинът vid.stab не е компилиран стандартно в Ubuntu 18.04 и за това командите се изпълняват в докер.
Прави се на две стъпки - в първата се установява на къде е отместено (векторът на отместването) видеото във всеки един момент от време (симулира жироскоп), а на втората стъпка се променя самото видео (прилага се трансформация с обратния вектор).
- един файл
docker run --rm -v "$(pwd)":/data jrottenberg/ffmpeg -i /data/ВИДЕО.MP4 -vf vidstabdetect=accuracy=15:shakiness=10:mincontrast=0.3:show=0:result=/data/transforms.trf -an -f null -
docker run --rm -v "$(pwd)":/data jrottenberg/ffmpeg -i /data/ВИДЕО.MP4 -vf vidstabtransform=smoothing=20:input="/data/transforms.trf:optzoom=0,unsharp" /data/РЕЗУЛТАТ.mp4
- всички файлове в директория
#!/bin/bash
set -e
relativeFolder="${1}"
folder=$(cd "${relativeFolder}"; pwd)
for relativeFile in "${folder}"/*.MP4; do
[ -e "${relativeFile}" ] || continue
filename="${relativeFile##*/}"
docker run --rm -v "${folder}":/data jrottenberg/ffmpeg -i "/data/${filename}" -vf vidstabdetect=accuracy=15:shakiness=10:mincontrast=0.3:show=0:result=/data/transforms.trf -an -f null -
docker run --rm -v "${folder}":/data jrottenberg/ffmpeg -i "/data/${filename}" -vf vidstabtransform=smoothing=20:input="/data/transforms.trf:optzoom=0,unsharp" "/data/output-${filename}"
done
rm -rf "${folder}"/transforms.trf
sudo chown "$(whoami)":"$(whoami)" output-*.MP4
- за ползване на GPU (добавя се
:vaapi
)
docker run (...) jrottenberg/ffmpeg:vaapi (...)
-
допълнителна информация: https://dashcamtalk.com/forum/threads/how-to-stabilizing-your-video.19189/, Stabilize Scuba Diving
-
за съжаление тази обработка отнема доста време и за това бъдете търпеливи (може да го пуснете през нощта)
Телеметрия към видео (Picture in Picture)
-
[GoPro Dashboard Overlay]https://github.com/time4tea/gopro-dashboard-overlay
-
venv/bin/gopro-dashboard.py --profile highquality --layout xml --layout-xml ~/.gopro-graphics/layout.xml --gpx recordedgpx.gpx recordedvideo.MP4 result.MP4
-
~/.gopro-graphics/ffmpeg-profiles.json
{
"highquality": {
"input": [],
"output": ["-vcodec", "libx264", "-acodec", "copy","-preset", "slower","-crf", "18"]
}
}
~/.gopro-graphics/layout.xml
<layout>
<composite x="260" y="30" name="date_and_time">
<component type="datetime" x="0" y="0" format="%Y/%m/%d" size="16" align="right"/>
<component type="datetime" x="0" y="24" format="%H:%M:%S.%f" truncate="5" size="32" align="right"/>
</composite>
<composite x="1644" y="36" name="gps_info">
<component type="text" x="256" y="0" size="16" align="right">GPS INFO</component>
<component type="text" x="0" y="24" size="16" align="left">Lat: </component>
<component type="text" x="128" y="24" size="16" align="left">Lon: </component>
<component type="metric" x="118" y="24" metric="lat" dp="6" size="16" align="right" cache="False"/>
<component type="metric" x="256" y="24" metric="lon" dp="6" size="16" align="right" cache="False"/>
</composite>
<composite x="16" y="800" name="big_mph">
<component type="text" x="0" y="0" size="16">MPH</component>
<component type="metric" x="0" y="0" metric="speed" units="mph" dp="0" size="160" />
</composite>
<component type="gradient_chart" name="gradient_chart" x="400" y="980"/>
<composite x="220" y="980" name="gradient">
<component type="text" x="70" y="0" size="16">SLOPE(%)</component>
<component type="icon" x="0" y="0" file="slope-triangle.png" size="64"/>
<component type="metric" x="70" y="18" metric="gradient" dp="1" size="32" />
</composite>
<composite x="16" y="980" name="altitude">
<component type="text" x="70" y="0" size="16">ALT(m)</component>
<component type="icon" x="0" y="0" file="mountain.png" size="64"/>
<component type="metric" x="70" y="18" metric="alt" dp="1" size="32" />
</composite>
<composite x="1900" y="820" name="temperature">
<component type="text" x="-70" y="0" size="16" align="right">TEMP(C)</component>
<component type="icon" x="-64" y="0" file="thermometer.png" size="64"/>
<component type="metric" x="-70" y="18" metric="temp" dp="0" size="32" align="right"/>
</composite>
<composite x="1900" y="900" name="cadence">
<component type="text" x="-70" y="0" size="16" align="right">RPM</component>
<component type="icon" x="-64" y="0" file="gauge.png" size="64"/>
<component type="metric" x="-70" y="18" metric="cadence" dp="0" size="32" align="right"/>
</composite>
<composite x="1900" y="980" name="heartbeat">
<component type="text" x="-70" y="0" size="16" align="right">BPM</component>
<component type="icon" x="-64" y="0" file="heartbeat.png" size="64"/>
<component type="metric" x="-70" y="18" metric="hr" dp="0" size="32" align="right"/>
</composite>
<frame x="1644" y="100" width="256" height="256" fo="50" cr="35">
<component type="journey_map" name="moving_map" x="0" y="0" size="256" zoom="16"/>
</frame>
<frame x="1644" y="376" width="256" height="256" fo="50" cr="128">
<component type="journey_map" name="journey_map" x="0" y="0" size="256" />
</frame>
<frame x="1644" y="676" width="256" height="256" fo="50">
<component type="journey_map" name="journey_map" x="0" y="0" size="256" />
</frame>
<frame x="1644" y="976" width="256" height="256" fo="20" opacity="0.6" >
<component type="journey_map" name="journey_map" x="0" y="0" size="256" />
</frame>
<frame x="1044" y="100" width="256" height="256">
<component type="journey_map" name="moving_map" x="0" y="0" size="256" zoom="16" corner_radius="35"/>
</frame>
<frame x="1044" y="376" width="256" height="256">
<component type="journey_map" name="journey_map" x="0" y="0" size="256" corner_radius="70"/>
</frame>
<frame x="1044" y="676" width="256" height="256">
<component type="journey_map" name="journey_map" x="0" y="0" size="256" />
</frame>
<frame x="1044" y="976" width="256" height="256" opacity="0.6" >
<component type="journey_map" name="journey_map" x="0" y="0" size="256" opacity="0.6" />
</frame>
<frame x="1044" y="976" width="256" height="256" opacity="0.6" >
<component type="journey_map" name="journey_map" x="0" y="0" size="256" opacity="0.6" />
</frame>
<frame x="1344" y="976" width="256" height="256">
<component type="journey_map" name="journey_map" x="0" y="0" size="256" opacity="0.6" />
</frame>
</layout>
Телеметрия към видео (Picture in Picture), сложния начин
Резултатът от добавянето на телеметрия може да се види тук:
Съществуват множество приложения за добавяне на телеметрични данни (локация, скорост, посока и други) към видео, но те са платени, за Windows, за конкретен модел камера или резултатът не е особено сполучлив. За това тук ще опиша един друг вариант. При него използвам gpx файл от GPS, който качвам на ayvri и записвам видеото посредством SimpleScreenRecorder. Резултатът може да видите тук: резултат, базиран на оригинално видео и телеметрия.
- добавям gpx файла в ayvri (може и през интеграцията със страва)
- отварям създаденото видео, преди да зареди натискам пауза, намалявам скоростта до х1, натискам
STATS
за да се покажат всички телеметрични данни - в конзолата на Chromе (
Ctrl+Shift+I
илиF12
) изпълнявамdocument.getElementById('StatsPanelContainer').style = "padding-right: 750px; padding-top: 337px;";document.getElementById("StatsPanelContainer").childNodes[0].childNodes[1].remove();document.getElementById("StatsPanelContainer").childNodes[0].childNodes[0].childNodes[3].remove();
- имайте предвид че това маха някои от метриките, а тъй като те зависят от зададения тип на записа (туризъм, ски, парапланер) може да се наложи да се промени скрипта по-горе в зависимост от типа на активността
- по-принцип избягвайте да изпълнявате такива скриптове в браузъра си без да ги разбирате напълно, защото това може да доведе до големи неприятности (открадване на акаунт и други) - в случая (както се вижда -
.style = ...; .remove();
) само местя и трия разни компоненти, но скриптът може да прави доста повече неща за това бъдете внимателни!
- пускам SimpleScreenRecorder, настройвам го да записва цял екран, размерите на резултатното видеото да е 0.6 от реалните размери (така или иначе го намаляваме за да се вижда само в края на екрана), отказвам записът на аудио, избирам добро качество
- пускам видеото на цял екран (от бутона долу-дясно)
- избирам правилната гледна точка в ayvri така че маршрутът да е някъде в средата на екрана (и да не се закрива от насрещни възвишения/върхове), пускам запис в SimpleScreenRecorder посредством
Ctrl+R
и натискам Play след това го спирам след края на видеото в ayvri. ffmpeg -i "ВИДЕО.MP4" -i "ТЕЛЕМЕТРИЯ.mkv" -filter_complex "[1]trim=31,setpts=PTS-STARTPTS[telemetry];color=c=white,vignette=angle=PI/2:aspect=4/3:x0=w/2+30:y0=h/2-10[mask];[mask][telemetry]scale2ref[scaledmask][scaledtelemetry];[scaledtelemetry][scaledmask]alphamerge,crop=exact=1:x=0:y=ih/2:w=iw/2+245:h=ih-410[pip]; [0][pip] overlay=main_w-overlay_w:0:eof_action=endall,format=yuv420p" -codec:v libx264 -crf 18 -preset slower -acodec copy РЕЗУЛТАТ.mp4
- в зависимост от размерите на монитора/прозореца ще трябва да промените
w=iw/2+245:h=ih-410
за да позиционирате телеметрията горе-дясно - в зависимост от отместването във времето между телеметрията и видеото ще трябва да промените колко да изрежете от началото на телеметрията (
trim=31
) - ако искате телеметрията да избледнява повече или по-малко към краищата променете
angle=PI/2:aspect=4/3:x0=w/2+30:y0=h/2-10
, къдетоPI/2
контролира колко бързо да избледнява,4/3
- в коя посока колко да избледнява,x0=w/2+30:y0=h/2-10
от къде да започне избледняването - в случая не е от центъра и по този начин се контролира колко да е избледняло към краищата
- в зависимост от размерите на монитора/прозореца ще трябва да промените
- допълнителна информация: https://www.oodlestechnologies.com/blogs/PICTURE-IN-PICTURE-effect-using-FFMPEG/
- може да промените изглежда от ayvri като ползвате Chrome и натиснете с десния клавиш на мишката върху елемента и след това
Inspect
и изтриване/промяна на съответния HTML елемент, това може да стане и с javascript, например:document.getElementById('StatsPanelContainer').style = "padding-right: 750px; padding-top: 337px;";document.getElementById("StatsPanelContainer").childNodes[0].childNodes[1].remove();document.getElementById("StatsPanelContainer").childNodes[0].childNodes[0].childNodes[3].remove();
- имайте предвид че това маха някои от метриките, а тъй като те зависят от зададения тип на записа (туризъм, ски, парапланер) може да се наложи да се промени скрипта по-горе в зависимост от типа на активността
- по-принцип избягвайте да изпълнявате такива скриптове в браузъра си без да ги разбирате напълно, защото това може да доведе до големи неприятности (открадване на акаунт и други) - в случая (както се вижда -
.style = ...; .remove();
) само местя и трия разни компоненти, но скриптът може да прави доста повече неща за това бъдете внимателни!
- за проба може да се генерира видео с по-лошо качество, но по-бързо и по този начин да се ориентирате дали видеото и телеметрията са синхронизирани:
ffmpeg -i "ВИДЕО.MP4" -i "ТЕЛЕМЕТРИЯ.mkv" -filter_complex "[1]copy [pip]; [0][pip] overlay=main_w-overlay_w:0" -profile:v main -preset ultrafast -level 3.1 -b:v 140k -ar 44100 -ab 128k -s 720x400 -vcodec h264 -acodec copy РЕЗУЛТАТ.mp4
илиffmpeg -i "ВИДЕО.MP4" -i "ТЕЛЕМЕТРИЯ.mkv" -filter_complex "[1]copy [pip]; [0][pip] overlay=main_w-overlay_w:0" -vcodec h264 -preset ultrafast -acodec copy РЕЗУЛТАТ.mp4
- не е нужно да изчакате генерирането до край - в началото го пуснете за няколко секунди с добро качество (спира се с еднократно натискане на
Ctrl+C
) за да проверите дали всичко е наред (телеметрията дали е на правилното място и дали видеото е в синхрон с телеметрията) - най-добре да ползвате
.mkv
формат за да можете да видите резултатът без да спирате процесът (mp4
поставяmoov atom
накрая, докато вmkv
това не е така и можете да гледате резултатът докато ffmpeg работи):ffmpeg -i "ВИДЕО.MP4" -i "ТЕЛЕМЕТРИЯ.mkv" -filter_complex "[1]trim=31,setpts=PTS-STARTPTS[telemetry];[telemetry]crop=exact=1:x=900+200:y=ih/2-250:w=iw/2+245-900-200:h=ih-1000,scale=w=3*iw:h=3*ih[pip]; [0:v:0][pip] overlay=main_w-overlay_w:0:eof_action=endall" -profile:v main -preset ultrafast -level 3.1 -b:v 2140k -s 1024x768 -vcodec h264 -y ПРОБА.mkv
- може да се ползва
ffmplay
вместоffmpeg
- не е нужно да изчакате генерирането до край - в началото го пуснете за няколко секунди с добро качество (спира се с еднократно натискане на
- за съжаление тази обработка отнема доста време и за това бъдете търпеливи (може да го пуснете през нощта)
Подобряване на цветовете
Резултатът от подобряването на цветовете може да се види тук:
Повечето хора съветват, когато видеото се записва това да се прави с Flat профил и ръчни настройки за да може то да се подобри по-лесно на втори етап. Като цяло настройките по време на заснемане са от особено значение - прегледайте следните видеа: общи съвети, вкл. за GoPro, настройки, YI 4K+ или потърсете нещо конкретно за вашата камера. С две думи - fps трябва да е кратна на честотата на електрическата мрежа в страната (страните в Европа 50 Hz, САЩ - 60 Hz) за да не се получават хоризонтални плуващи черти при снимане на изкуствено осветление (това е и една от причината да има разлика между стандартите PAL/SECAM). Останалите настройки - FOV: (Ultra) Wide, Metering mode: Average, Quality: най-висока, White Balance зависи от светлината - облачно/сняг/6500K+, изгрев/залез/нажежаема крушка/3000K, дневна светлина/5500K, Color: Flat, ISO Max: на светло 400, иначе max 1600 (зависи от камерата), EV: зависи от камерата, стабилизация: включена, Sharpness: low.
Много добри съвети за обработка можете да видите тук: DaVinci Resolve, GIMP/ffmpeg.
За мен ffmpeg вариантът ми е най-удобен: print screen на кадър с най-много цветове. В GIMP>Colors>Levels>Auto и след това копираме съответните min/max стойности за Red/Green/Blue и използваме (заместваме RED_MIN и останалите) ffmpeg -i "ВИДЕО.MP4" -filter_complex "colorlevels=rimin=RED_MIN/255:rimax=RED_MAX/255:gimin=GREEN_MIN/255:gimax=GREEN_MAX/255:bimin=BLUE_MIN/255:bimax=BLUE_MAX/255,format=yuv420p" -codec:v libx264 -crf 18 -preset slower -acodec copy РЕЗУЛТАТ.mp4
. Друг вариант (повече възможности, но не толкова автоматичен) е използвайки GIMP>Colors>Curves… или GIMP>Colors>Levels>Auto и бутон “Edit these Settings as Curves”, експорт до файл (Manage presets > Export Current Settings to File) и след това docker run -v "$(pwd):/data" --rm python:2 bash -c "wget https://raw.githubusercontent.com/fehlfarbe/gimp2acv/master/acv.py && wget https://raw.githubusercontent.com/fehlfarbe/gimp2acv/master/gimp2acv.py && pip install numpy && python /gimp2acv.py /data/curves"
и ffmpeg -i "ВИДЕО.MP4" -filter_complex "curves=psfile=curves.acv,format=yuv420p" -codec:v libx264 -crf 18 -preset slower -acodec copy РЕЗУЛТАТ.mp4
.
Погледнете още и следните филтри и линкове: Color Correct Scuba Diving, colorbalance, manupilation of video colors, GIMP 2.10 Curves, GIMP 2.10 Shadows and Highlights.
Телеметрия, стабилизиране, цветове
Описаните по-горе подобрения могат да бъдат обединени, ето и резултатът:
docker run --rm -v "$(pwd)":/data jrottenberg/ffmpeg -i /data/ВИДЕО.MP4 -vf vidstabdetect=accuracy=15:shakiness=10:mincontrast=0.3:show=0:result=/data/transforms.trf -an -f null -
docker run --rm -v "$(pwd)":/data jrottenberg/ffmpeg -i "/data/ВИДЕО.MP4" -i "/data/ТЕЛЕМЕТРИЯ.mkv" -filter_complex "[0]vidstabtransform=smoothing=20:input=/data/transforms.trf:optzoom=0,unsharp,colorlevels=rimin=RED_MIN/255:rimax=RED_MAX/255:gimin=GREEN_MIN/255:gimax=GREEN_MAX/255:bimin=BLUE_MIN/255:bimax=BLUE_MAX/255 [stabilized];[1]trim=31,setpts=PTS-STARTPTS[telemetry];color=c=white,vignette=angle=PI/2:aspect=4/3:x0=w/2+30:y0=h/2-10[mask];[mask][telemetry]scale2ref[scaledmask][scaledtelemetry];[scaledtelemetry][scaledmask]alphamerge,crop=exact=1:x=0:y=ih/2:w=iw/2+245:h=ih-410[pip]; [stabilized][pip] overlay=main_w-overlay_w:0:eof_action=endall,format=yuv420p" -codec:v libx264 -crf 18 -preset slower -acodec copy /data/РЕЗУЛТАТ.mp4
- сравненията са генериране посредством
- половин екран:
docker run --rm -v "$(pwd)":/data jrottenberg/ffmpeg -i "/data/ВИДЕО.MP4" -i "/data/ТЕЛЕМЕТРИЯ.mkv" -i "/data/СЪЩОТОВИДЕОВТОРИПЪТ.MP4" -filter_complex "[0]vidstabtransform=smoothing=20:input=/data/transforms.trf:optzoom=0,unsharp,colorlevels=rimin=RED_MIN/255:rimax=RED_MAX/255:gimin=GREEN_MIN/255:gimax=GREEN_MAX/255:bimin=BLUE_MIN/255:bimax=BLUE_MAX/255 [stabilized];[1]trim=ОФСЕТ,setpts=PTS-STARTPTS[telemetry];color=c=white,vignette=angle=PI/2:aspect=4/3:x0=w/2+30:y0=h/2-10[mask];[mask][telemetry]scale2ref[scaledmask][scaledtelemetry];[scaledtelemetry][scaledmask]alphamerge,crop=exact=1:x=0:y=ih/2:w=iw/2+245:h=ih-410[pip]; [stabilized][pip] overlay=main_w-overlay_w:0:eof_action=endall,crop=exact=1:x=iw/2:y=0:w=iw/2:h=ih[right];[2:v:0][right]overlay=main_w/2:0" -vcodec h264 -acodec copy /data/РЕЗУЛТАТ.mp4
- цял екран:
docker run --rm -v "$(pwd)":/data jrottenberg/ffmpeg -i "/data/ВИДЕО.MP4" -i "/data/ТЕЛЕМЕТРИЯ.mkv" -i "/data/СЪЩОТОВИДЕОВТОРИПЪТ.MP4" -filter_complex "[0]vidstabtransform=smoothing=20:input=/data/transforms.trf:optzoom=0,unsharp,colorlevels=rimin=RED_MIN/255:rimax=RED_MAX/255:gimin=GREEN_MIN/255:gimax=GREEN_MAX/255:bimin=BLUE_MIN/255:bimax=BLUE_MAX/255 [stabilized];[1]trim=ОФСЕТ,setpts=PTS-STARTPTS[telemetry];color=c=white,vignette=angle=PI/2:aspect=4/3:x0=w/2+30:y0=h/2-10[mask];[mask][telemetry]scale2ref[scaledmask][scaledtelemetry];[scaledtelemetry][scaledmask]alphamerge,crop=exact=1:x=0:y=ih/2:w=iw/2+245:h=ih-410[pip]; [stabilized][pip] overlay=main_w-overlay_w:0:eof_action=endall[right];[2:v:0]pad=iw*2:ih[original];[original][right]overlay=w" -vcodec h264 -acodec copy /data/РЕЗУЛТАТ.mp4
- вместо
СЪЩОТОВИДЕОВТОРИПЪТ
може да се ползва split
- половин екран:
- за съжаление тази обработка отнема доста време и за това бъдете търпеливи (може да го пуснете през нощта)
Добавяне на музика за фон
- безплатна музика за фон: pixabay, mixkit, besound, Youtube AudioLibrary, tunetank, uppbeat
- обединяване на няколко аудиофайла до необходимата дължина
ffmpeg -f concat -safe 0 -i <(printf "file '$(pwd)/music1.mp3'\nfile '$(pwd)/music2.mp3'\nfile '$(pwd)/music3.mp3'") -c copy output.mp3
- подменяне на цялото аудио:
ffmpeg -i video.mp4 -i output.mp3 -c copy -map 0:v -map 1:a -shortest output-different-autio.mp4
- микс между аудиото от видеото и музиката на фон:
- 0.7 е константа за заглушаване на аудиото от видеото (да е малко притъпено), https://stackoverflow.com/questions/14498539/how-to-overlay-downmix-two-audio-files-using-ffmpeg, https://superuser.com/questions/1347946/ffmpeg-merge-audio-with-video-and-lower-volume, https://trac.ffmpeg.org/wiki/AudioChannelManipulation
- ако аудиото започне да се разминава -
"[0:a]aresample=async=1000,volume=0.7,apad[V];[1:a]volume=1[A];[A][V]amix[out]"
, https://stackoverflow.com/questions/35416110/ffmpeg-concat-video-and-audio-out-of-sync
ffmpeg -i video.mp4 -i output.mp3 -filter_complex "[0:a]volume=0.7,apad[V];[1:a][V]amix[out]" -c:v copy -map 0:v -map [out] -shortest output-final.mp4
Добавяне на снимки към видео
- https://stackoverflow.com/questions/43958438/merge-videos-and-images-using-ffmpeg
- аудиото е необходимо, защото ако искаме да вмъкнем в началото на видеото - аудиото ще изчезне: https://superuser.com/questions/1096921/concatenating-videos-with-ffmpeg-produces-silent-video-when-the-first-video-has
ffmpeg -loop 1 -framerate 50 -t 2 -i image1.png \
-loop 1 -framerate 50 -t 2 -i image2.png \
-f lavfi -i anullsrc=cl=stereo:r=48000 -map 2:a \
-filter_complex "[0][1]concat=n=2:v=1:a=0,format=yuv420p" \
-codec:v libx264 -crf 18 -preset slow \
-ar 48000 -ab 128k \
-y -shortest images.mp4
- след което го добавяме посредством
ffmpeg -f concat ...
както е показано в Взимане на определени моменти от клип и обединяването им
Разделяне на отделни клипове
ffmpeg -ss 593.3 -i ГОЛЯМФАЙЛ.mp4 -t 551.64 -c copy РЕЗУЛТАТ.mp4
, където 551.64 е продължителността:duration=$(bc <<< "(${endSeconds} + 0.01) - ${startSeconds}" | awk '{ printf "%.4f", $0 }')
ffmpeg -i ГОЛЯМФАЙЛ.mp4 -ss 00:10:00 -to 00:20:00 -c copy РЕЗУЛТАТ.mp4
ffmpeg -i ГОЛЯМФАЙЛ.mp4 -c copy -map 0 -segment_time 00:20:00 -f segment -reset_timestamps 1 РЕЗУЛТАТ%03d.mp4
ffmpeg -i input.mp4 -threads 3 -vcodec copy -acodec copy -f segment -segment_time 00:15 result_%02d.mp4
- За повече информация https://unix.stackexchange.com/questions/1670/how-can-i-use-ffmpeg-to-split-mpeg-video-into-10-minute-chunks
MP4Box -split 15 GX010024.MP4
(apt install gpac
)- За повече информация https://github.com/gpac/gpac/wiki/MP4Box, https://askubuntu.com/questions/35605/splitting-an-mp4-file
Взимане на определени моменти от клип и обединяването им
- необходими са името на файла, от който ще вземем частите (ВИДЕО.mp4) и моментите, които трябва да останат (начало-край, в променливата INCLUDE)
- записвам си такъв файл за всяко видео
set -xe
INPUT="${INPUT:-ВИДЕО.mp4}"
INCLUDE="${INCLUDE:-
${INPUT}
00:00:17 00:01:22
00:04:10 00:05:10
# if you want to add images to video here or at the beginning:
images.mp4
00:00:00 00:00:04
}"
# тук обикновено слагам като коментар всички команди, които съм изпълнил за стабилизация, телеметрия, цветове, curve и т.н.
#https://ayvri.com/scene/.../...
#ffmpeg -i "/media/....MP4" -i "ayvri.mkv" -filter_complex "[1]trim=42,setpts=PTS-STARTPTS[telemetry];[telemetry]crop=exact=1:x=900:y=ih/2-100:w=iw/2+245-900:h=ih-900[pip]; [0:v:0][pip] overlay=main_w-overlay_w:0:eof_action=endall" -profile:v main -preset ultrafast -level 3.1 -b:v 2140k -s 1024x768 -vcodec h264 -y result.mkv
#docker run --rm -v "/media/....MP4":"/....MP4" -v "$(pwd)":/data jrottenberg/ffmpeg -i "/media/....MP4" -vf vidstabdetect=accuracy=15:shakiness=10:mincontrast=0.3:show=0:result=/data/transforms.trf -an -f null -
#docker run --rm -v "/media/....MP4":"/media/....MP4" -v "$(pwd)":/data jrottenberg/ffmpeg -i "/media/....MP4" -i "/data/ayvri.mkv" -filter_complex "[0]vidstabtransform=smoothing=20:input=/data/transforms.trf:optzoom=0,unsharp,colorlevels=rimin=1/255:rimax=172/255:gimin=1/255:gimax=169/255:bimin=4/255:bimax=167/255 [stabilized];[1]trim=42,setpts=PTS-STARTPTS[telemetry];color=c=white,vignette=angle=PI/2:aspect=4/3:x0=w/2+30:y0=h/2-10[mask];[mask][telemetry]scale2ref[scaledmask][scaledtelemetry];[scaledtelemetry][scaledmask]alphamerge,crop=exact=1:x=0:y=ih/2:w=iw/2+245:h=ih-410[pip]; [stabilized][pip] overlay=main_w-overlay_w:0:eof_action=endall,format=yuv420p" -codec:v libx264 -crf 18 -preset slower -acodec copy /data/last.mp4
CURRENT_FILE="${INPUT}"
CONCAT_LIST=""
function extract() {
# based on https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg
function toSeconds() {
awk -F: 'NF==3 { print ($1 * 3600) + ($2 * 60) + $3 } NF==2 { print ($1 * 60) + $2 } NF==1 { print 0 + $1 }' <<< ${1}
}
local start="${1}"
local end="${2}"
local inputFile="$(realpath "${3:-${CURRENT_FILE}}")"
local startSeconds=$(toSeconds "${start}")
local endSeconds=$(toSeconds "${end}")
CONCAT_LIST="$(printf "%s\nfile '%s'\ninpoint %s\noutpoint %s" "${CONCAT_LIST}" "${inputFile}" "${startSeconds}" "${endSeconds}")"
}
IFS=$'\n'
for next in ${INCLUDE}; do
if [[ "${next}" =~ [A-Za-z_] ]]; then
CURRENT_FILE="${next}"
continue
fi
extract "${next% *}" "${next##* }"
done
# if you want to add images to video - put images.mp4 and 00:00:00 00:00:04 to INCLUDE on line 5
# https://stackoverflow.com/questions/43958438/merge-videos-and-images-using-ffmpeg
# https://superuser.com/questions/1096921/concatenating-videos-with-ffmpeg-produces-silent-video-when-the-first-video-has
ffmpeg -loop 1 -framerate 50 -t 2 -i image1.png \
-loop 1 -framerate 50 -t 2 -i image2.png \
-f lavfi -i anullsrc=cl=stereo:r=48000 -map 2:a \
-filter_complex "[0][1]concat=n=2:v=1:a=0,format=yuv420p" \
-codec:v libx264 -crf 18 -preset slow \
-ar 48000 -ab 128k \
-y -shortest images.mp4
# check https://superuser.com/questions/1059245/ffmpeg-join-two-mp4-files-with-ffmpeg-on-command-line and https://stackoverflow.com/questions/7333232/how-to-concatenate-two-mp4-files-using-ffmpeg
ffmpeg -f concat -safe 0 -fflags +discardcorrupt -fflags +fastseek -fflags +genpts -avoid_negative_ts 1 -i <(echo "${CONCAT_LIST}") -c copy "${INPUT%.*}-final.${INPUT##*.}"
# even if there are some squelch in video in vlc, it will be overcome by players like youtube or mpv
rm images.mp4
# background music to video:
curl https://assets.mixkit.co/music/download/mixkit-deep-urban-623.mp3 -o background.mp3
ffmpeg -f concat -safe 0 -i <(printf "file '$(pwd)/background.mp3'\nfile '$(pwd)/background.mp3'") -c copy background-full.mp3
# aresample is because of https://stackoverflow.com/questions/35416110/ffmpeg-concat-video-and-audio-out-of-sync
ffmpeg -i "${INPUT%.*}-final.${INPUT##*.}" -i background-full.mp3 -filter_complex "[0:a]aresample=async=1000,volume=0.7,apad[V];[1:a]volume=1[A];[A][V]amix[out]" -c:v copy -c:a aac -map 0:v -map [out] -ar 48000 -ab 128k -shortest "${INPUT%.*}-final-background.${INPUT##*.}"
rm background-full.mp3
Преглед frame-by-frame
mpv ВИДЕО.mp4
и след това.
и,
- между 10 и 15 (вкл.) фрейм към файл:
ffmpeg -i ВИДЕО.mp4 -vf select='between(n\,10\,15)' -vsync 0 frames%d.png
Сваляне на видео от youtube
docker run -it --rm -v "$(pwd):/data" vimagick/youtube-dl -i -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]' -i --audio-format=mp3 -o "%(title)s.%(ext)s" 'https://www.youtube.com/watch?v=(...)'
-
сваляне само на аудио:
docker run -it --rm -v "$(pwd):/data" vimagick/youtube-dl -i -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]' -x -i --audio-format=mp3 -o "%(title)s.%(ext)s" 'https://www.youtube.com/watch?v=(...)'
- ако не работи - обновете до най-новата версия:
docker pull vimagick/youtube-dl
Забързване на видео
ffmpeg -i ВИДЕО.MP4 -filter:v "setpts=0.1*PTS" -an РЕЗУЛТАТ-fast.MP4
Завъртане на видео portrait landscape, lanscape video in instagram
Използвам https://humanpoint.eu/images/giphy.gif (взето от тук: https://www.youtube.com/watch?v=vr8c_TsaYPc). Добавям го за 1 секунда в началото на клипа заедно със следния ефект:
<effectgroup id="rotatephone" parentIn="0">
<effect id="mirror">
<property name="reverse">0</property>
<property name="mirror">flip</property>
</effect>
<effect id="fade_to_black">
<property name="out">30</property>
<property name="level
alpha">1
0=1;31=0.537313</property>
<property name="in">0</property>
</effect>
<effect id="qtblend">
<property name="rotate_center">1</property>
<property name="distort">0</property>
<property name="compositing">0</property>
<property name="rotation">0=0</property>
<property name="rect">0=480 270 2880 1620 1.000000</property>
</effect>
</effectgroup>
ffmpeg -i "sourc.mp4" -metadata:s:v rotate="-90" -codec copy "destination.mp4"
#not working: exiftool -rotation=0 -api largefilesupport=1 $INPUTVIDEO
Филтър за определен период от време
Ако искаме да приложим различна корекция на цветовете в различни периоди от клипчето:
- split/trim/concat, https://superuser.com/questions/977743/ffmpeg-possible-to-apply-filter-to-only-part-of-a-video-file-while-transcoding
- Timeline editing, https://superuser.com/questions/977743/ffmpeg-possible-to-apply-filter-to-only-part-of-a-video-file-while-transcoding, https://ffmpeg.org/ffmpeg-filters.html#Timeline-editing
Графичен интерфейс
Повечето от нещата тук могат да се направят и през графични програми като kdenlive - например Overlay Video Picture in Picture и Stabilize Shaky Videos Using Kdenlive Free Editing Software, shotcut, pitivi, DaVinci Resolve, изрязване на видео - LosslessCut
KDEnlive
Понякога файлът се разваля, за това обикновено пускам while true; do git add .; git commit --no-gpg-sign -m wip; sleep 10; done
, а в последствие git rebase -i origin/master
с f
на всеки ред.
Аудио обработка
Натиснете бутона "watch" в github или се абонирайте с RSS четец ако искате да научавате за обновления или нови статии.