Встала задача оцифровать несколько видеокассет (VHS) через usb-свисток EasyCap. Попробовал сделать это на Windows в программе Virtual Dub, довольно удобно, но иногда почему-то случается проседание FPS, из-за этого картинка застывает на мнгновения и сильно увеличивается рассинхрон аудио-видео. Решил проверить работу в Linux через FFMpeg, в свежем ядре есть нужные драйвера. Обновил ядро и о чудо, FPS стабилен, а рассинхрона нет!
Однако, это только если вся кассета снята одним дублем. А если есть паузы с шумом, наслоения записей, итд, то тогда адаптер выдает неверные PTS таймстемпы и получается прогрессирующий рассинхрон. Пофиксить его ранее описанным мною методом (ремуксингом с дробной частотой кадров) не получилось, т.к. ошибки не монотонные, а возникают в случайных местах, т.е. рассинхрон то больше, то меньше. Решение было найдено.
- Итак, для начала сама команда для видеозахвата:
ffmpeg -f video4linux2 -standard PAL -thread_queue_size 64 -i /dev/video2 -f alsa -i hw:1 -c:v ffvhuff -c:a aac -b:a 320k -ac 1 tape.avi
thread_queue_size поставил побольше, потому что выводилось предупреждение, что 8 - слишком мало.
Устройство /dev/video2 создается при вставке карты видеозахвата в usb-порт.
- Захваченное видео сжимаю с использованием кодека H.264:
ffmpeg -i tape.avi -itsoffset 0.2 -i tape.avi -map 0:v -map 1:a -vf yadif -c:v h264 -crf 28 -preset veryslow -tune grain -c:a copy -af "asetpts=PTS-(1.1*PTS/2776)" -ss 5 -t 46:16 -pix_fmt yuv420p tape.mp4
Начальный рассинхрон 200мс почему-то есть всегда. Ну и ладно, сразу же фиксим.
Видеофильтр yadif убирает бегущие строчки интерлейса из изображения.
Дефолтный CRF 23 выдает слишком большой битрейт, поэтому поставил 28, качество чуть похуже, но битрейт разумный, около 2Мбит/с.
Параметры -ss
и -t
задают время старта и продолжительность
Ну и самое главное, аудиофильтр asetpts
, который исправляет растущий рассинхрон путем обновления меток времени в аудиопотоке.
В данном примере рассинхрон в конце видео увеличивался на 1100мс, а само видео длилось 2776 секунд.