28 нояб. 2009 г.

Пакетное перекодирование видео: cmd.exe + virtual dub + avisynth

В этом посте я расскажу, как правильно переконвертировать видео в нужный формат, используя только опен-сорсовые решения. Переконвертация будет на примере видео роликов от 5DMk2.

Для работы потребуются:
* Windows XP
* Avisynth, скачать и установить c одноименного сайта в домене org
* Virtual Dub, лежит тоже на своем сайте.
* K-lite codec pack с набором DirectShow кодеков

Ависинт используется для того, чтобы виртуал даб открывал неизвестные ему видеофайлы - а таких сейчас большинство: например, MOV, MKV файлы с кодеком H.264 и др.

Вкратце - мы будем на примере одного файла создавать данные для автоматической перекомпрессии подобных ему видеофайлов с аналогичными параметрами компрессии.

Итак, шаги:
(1) Настраиваем кодеки:
Пуск->Программы->K-Lite Codec Pack->Configuration->ffdshow audio decoder -- ставим вот это поле в "all supported", иначе звука в видеоролике не будет:

Пуск->Программы->K-Lite Codec Pack->Configuration->ffdshow video decoder
Здесь надо сделать такие настройки для правильного декодирования цвета:


(2) Пишем простенький скрипт на ависинте, и сохраняем этот текст в файл с именем "3.avs":
DirectShowSource("PROCESS.MOV", fps=30).ConvertToYUY2(matrix="Rec709").TemporalSoften(4,4,8,15,2)

Параметр fps задает частоту кадров исходного видео, если она по каким-то причинам некорректно самоорпеделится. Тут важным параметром является matrix, который правильно конвертирует цвета.

(3) Далее открываем этот текстовый файл в virtual dub как видео, переключаем в меню Audio в Fill Processing Mode, потом Audio->Compression выставляем в AC3 384 Kbit/s (тут можно выбрать нужный аудио кодек по желанию; мои эксперименты показывают, что если выбрать MP3, то будет рассинхронизация аудио и видео в фильме).

(4) Выставляем компрессию видео: Video->Compression. Я выбираю XVID кодек и выставляю его настройки так:


(5) Теперь самое интересное: нажимаем File->Save as AVI и не забываем поставить внизу галочку.


(6) Потом переходим в File->Job Control и выбираем в этом меню пункт Save Job List и сохраняем файл описания будущей перекодировки как process.job.

(7) Теперь редактируем файл process.jobs - меняем вот эти строки
VirtualDub.subset.Clear();
VirtualDub.subset.AddRange(0,100);
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();
// -- $reloadstop --
VirtualDub.SaveAVI("E:\\Photo\\2009_11_28\\MVI_0034.avi");


на такие:
VirtualDub.subset.Delete();
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();
// -- $reloadstop --
VirtualDub.SaveAVI(VirtualDub.params[0]);

Все остальные строчки оставляем без изменения.

(8) Теперь все готово для автоматической перепаковки видеофайлов. Это будет делать вот этот скрипт:
@echo off                           

del /q /s PROCESS.MOV >nul 2>&1
FOR %%i IN (*.mov) do (
if not exist %%~ni.avi (
echo.
echo.
echo Re-compressing %%i
ren %%i PROCESS.MOV
set TM=!TIME::=!
"C:\Program Files\VirtualDub\vdub.exe" /i recode.job %%~ni.avi >nul
set TM2=!TIME::=!
set /A RES=!TM2:~0,2!*3600 + !TM2:~2,2!*60 + !TM2:~4,2! - !TM:~0,2!*3600 - !TM:~2,2!*60 - !TM:~4,2!
set /A HRS=!RES! / 3600
set /A MINS=!RES! - !HRS!*3600
set /A MINS=!MINS! / 60
set /A SECS=!RES! - !HRS!*3600 - !MINS!*60
if !MINS! LSS 10 set MINS=0!MINS!
if !SECS! LSS 10 set SECS=0!SECS!
echo Elapsed time !HRS!:!MINS!:!SECS!
ren PROCESS.MOV %%i
)
)


Этот скрипт написан на языке командного интерпретатора cmd.exe. Чтобы он правильно работал, надо создать в реестре вот этот ключик DelayedExpansion = 1:

Этот ключик говорит о том, чтобы cmd.exe использовал отложенное связывание переменных со значениями. Это необходимо, т.к. иначе внутри цикла переменные бы не обновлялись. Чтобы они стали обновляться, необходимо обращаться к ним по имени типа !VAR! а не %VAR%.

Вот, вроде все. Этот скрипт будет перекодировать все видеофайлы в текущей директории с один раз указанными параметрами, и в качестве бонуса скрипт будет выводить, сколько времени заняло перекодировать каждый файл.