Изменения

Перейти к: навигация, поиск
м
Новая страница: «Прикольная фишка консольного ffmpeg’а — его можно использовать вместе с '''именованными кан...»
Прикольная фишка консольного ffmpeg’а — его можно использовать вместе с '''именованными каналами''' (named pipes) для нарезки и слияния видео.

'''Шаг первый''': создаём именованные каналы. А допустим, у нас ещё и аудиодорожек несколько.

{{note}} Сначала я хотел написать, как завещал великий [http://ffmpeg.org/faq.html#TOC29 FAQ] — по одному файлу на каждую дорожку, то есть целую кучу: <tt>file1.v file1.a1 file1.a2 file2.v file2.a1 file2.a2 file.v file.a1 file.a2</tt>. Однако обнаружил, что AVI-контейнер прекрасно переживает конкатенацию и что в этом случае результат получается даже лучше — на мгновении, когда Балу дёргает Багиру за хвост в процессе пения [[rupedia:The_Bare_Necessities|Bare Necessities]], не возникает никакого затупа. А в случае с кучей raw-файлов — возникало. Так что попробуем AVI.

<source lang="bash">
mkfifo file1.avi
mkfifo file2.avi
mkfifo file.avi
</source>

'''Шаг второй''': запускаем декодирующие в сырые форматы ffmpeg’и и конкатенирующий потоки cat в фоновом режиме — пускай ждут, пока им разрешат писать в каналы. Пусть входные файлы у нас — это грёбаные DVD’шные VOB’ы с тремя аудиодорожками, дискретизированными на 48 KHz, первые две — 5.1, последняя — моно.

Кстати 1: <tt>-ss</tt> нужно указывать время либо в секундах, либо в формате HH:MM:SS[.mmm]. Именно в таком, то есть просто MM:SS не прокатит.

{{note}} Командная строка FFmpeg’а некоммутативна :) от перемены аргументов местами меняется смысл. Например, если указать <tt>-ss</tt> ''после'' <tt>-i файл</tt>, вы задолбаетесь ждать, пока оно перейдёт к нужному месту в файле, потому что будет seek’ать на уровне кодека. А если указать <tt>-ss</tt> ''до'' <tt>-i файл</tt>, seek’ать оно будет на уровне контейнера и сделает это быстро.

Кстати 2: для сырых аудиоформатов обязательно указывать параметры <tt>-ac -ar</tt> и <tt>-f</tt> (например <tt>s16le</tt>) либо <tt>-acodec</tt> (например <tt>pcm_s16le</tt>), как при кодировании, так и при декодировании, иначе как же оно узнает, какой raw формат мы хотим? При чтении raw формата эти параметры нужно указывать ''до'' <tt>-i входного_файла</tt>.

{{note}} А <tt>-newaudio</tt>, например, нужно указывать ''после'' имени выходного файла. А опции для добавляемой -newaudio аудиодорожки — непосредственно перед <tt>-newaudio</tt>.

Кстати 3: <tt>-y</tt> поможет нам избежать предупреждений.

Кстати 4: запуск ffmpeg’ов с «выпуском» в именованный канал нормально не удавался под непривилигерованным юзером — ffmpeg получал SIGSTOP. В чём дело, я разбираться особенно не стал, а просто пускал его под рутом.

<source lang="bash">
ffmpeg -y -ss 00:24:18 -i VTS_01_1.VOB -map 0.0 -map 0.1 -map 0.2 -map 0.3 -vcodec rawvideo -acodec pcm_s16le -ac 6 -ar 48000 file1.avi -acodec pcm_s16le -ac 6 -ar 48000 -newaudio -acodec pcm_s16le -ac 1 -ar 48000 -newaudio &>log1 &
ffmpeg -y -t 91 -i VTS_01_2.VOB -map 0.0 -map 0.1 -map 0.2 -map 0.3 -vcodec rawvideo -acodec pcm_s16le -ac 6 -ar 48000 file2.avi -acodec pcm_s16le -ac 6 -ar 48000 -newaudio -acodec pcm_s16le -ac 1 -ar 48000 -newaudio &>log2 &
cat file1.avi file2.avi > file.avi &
</source>

{{Cut|А в случае кучи raw-файлов было бы...|<source lang="bash">
ffmpeg -y -ss 00:24:18 -i file1.avi -an -f yuv4mpegpipe file1.v &>log1.v &
ffmpeg -y -ss 00:24:18 -i file1.avi -vn -map 0.1 -ac 6 -ar 48000 -f s16le file1.a1 &>log1.a1 &
ffmpeg -y -ss 00:24:18 -i file1.avi -vn -map 0.2 -ac 2 -ar 48000 -f s16le file1.a2 &>log1.a2 &
{ ffmpeg -y -i file2.avi -t 91 -an -f yuv4mpegpipe - 2>log2.v | tail -n +2 >file2.v ; } &
ffmpeg -y -i file2.avi -t 91 -vn -map 0.1 -ac 6 -ar 48000 -f s16le file2.a1 &>log2.a1 &
ffmpeg -y -i file2.avi -t 91 -vn -map 0.2 -ac 2 -ar 48000 -f s16le file2.a2 &>log2.a2 &
for i in v a1 a2; do
cat file1.$i file2.$i > file.$i &
done
</source>

Кстати 1: запустить один ffmpeg, который будет писать сразу несколько выходных файлов, не получится, т.к. кодирующий ffmpeg их будет анализировать по очереди, а декодирующий захочет писать все вместе. А писать в канал, из которого никто не читает, нельзя. Поэтому "сборка" просто повиснет.

Кстати 2: сырой видеоформат называется <tt>-f yuv4mpegpipe</tt>. Он допускает конкатенацию, но в этом случае нужно отрезать первую строку у всех файлов, кроме первого, чтобы их потоки начинались со слова "FRAME". Сырой видеокодек - <tt>-vcodec rawvideo</tt>.}}

'''Шаг третий''': запускаем кодирующий ffmpeg.

Кстати: для libx264, начиная с какой-то (Х-З какой) версии ffmpeg’а, нужно указывать опцию <tt>-vpre</tt>. А ещё лично я люблю забивать максимальный фактор квантования и не париться о качестве.

<source lang="bash">
ffmpeg -y -i file.avi -vcodec libx264 -vpre hq -qmax 28 -acodec libfaac -ab 448k -ac 6 BareNecessities6ch.avi -acodec libfaac -ab 384k -ac 6 -newaudio -acodec libfaac -ab 96k -ac 1 -newaudio
</source>

И всё, с данного момента вся спящая в фоновом режиме машинерия активизируется и начнёт кодировать-декодировать.

Изначально вкурено с http://ffmpeg.org/faq.html#TOC29, но сильно исправлено и дополнено :)
{{wl-publish: 2010-03-31 01:27:18 +0400 | VitaliyFilippov }}

Навигация