4/13/2009

Немного о lossless кодировании видео в Linux - сжатие видео без потерь

Некоторое время назад была потребность в том, чтобы сжать видеофайл без потерь в Linux (lossless compression) и воспроизводить сжатый фильм без пропуска кадров. Задача в меру прикладная, и может быть, кому-нибудь будет интересно.

Итак, мы имеем установленный mencoder в Debian GNU/Linux и настойчивое желание сжимать видео без потерь.

Сжимаем видео с помощью Mencoder
Для этого мы отобрали пару кодеков с lossless и начали сжимать наш видеоролик. Исходно в нашем распоряжении был видеоролик размером 341 Мб, в котором полутоновая картинка перемещалась по экрану. Нужно было сжать без потерь ролик так, чтобы он и места занимал немного, и воспроизводился без торможений.


Сжатие FFV1
Сначала сжимали кодеком FFV1 командой:
mencoder -ovc lavc -lavcopts vcodec=ffv1 video-before.avi -o video-compressed-ffv1.avi
Сжалось до 18Мб, что очень хорошо. Однако при попытке такой сжатый файл воспроизвести, возникли проблемы: Mplayer (как и другие) сильно грузит процессор и видео не успевает воспроизводиться с заданным FPS. О том, какие страдания были с воспроизведением и как мы их героически решали, будет сказано ниже.


Сжатие huffyuv
Ещё один метод сжатия без потерь, но жмёт он хуже, чем FFV1, зато быстрее воспроизводится и меньше грузит процессор. При этом использовали mencoder для сжатия huffyuv с параметрами:
mencoder -ovc lavc -lavcopts vcodec=ffvhuff:vstrict=-1:pred=2:context=1:format=422p video-before.avi -o video-compressed-ffvhuff.avi
Получилось видео на 99Мб, что тоже неплохо. Однако при воспроизведении оказалось, что происходит конвертирование в другое цветовое пространство 420p и мы решили отказаться от такого финта:
mencoder -ovc lavc -lavcopts vcodec=ffvhuff:vstrict=-1:pred=2:context=1 video-before.avi -o video-compressed-ffvhuff-420.avi
при этом сэкономили ещё почти 20 Мб - фильм стал занимать 80Мб и воспроизводиться чуть глаже.

Остановившись на сжатии huffyuv без опции format=422p, мы стали перебирать варианты воспроизведения видео с минимальными тормозами. История на этом не кончается...


Воспроизведение видео с помощью Mplayer
Видео у нас сжато слабо, воспроизводить надо без задержек и железо скажем сразу весьма чахлое. Как проигрывать видео в таких условиях?

Перво-наперво, используем замечательные возможности Mplayer по выводу видео куда и на что угодно: поэкспериментировать с параметром -vo было здравой идеей, и через некоторое время мы остановились на варианте -vo gl и -vo sdl для нашей задачи. Однако иксы - это хорошо, но хочется выводить видео на чёрный экран без всяких засветок.

Далее, чтобы отвязаться от дисковой подсистемы как можно больше, используем возможность Mplayer кешировать видео:
mplayer -vo gl -cache 65535 -cache-min 98 video-compressed-ffvhuff.avi
Это значит, что мы просим сделать Mplayer кеш на 64Мб и заполнять его не менее чем на 98%. Это сильно помогло делу, но это ещё не всё.

Условия нашей задачи в меру экзотические: нужно проигрывать видео без масштабирования, "как есть", и желательно на чёрном экране без фона, с максимально возможной плавностью. Всё осложняется тем, что компьютер, на котором видео будет воспроизводиться, управляется Windows, и Linux там можно задействовать только в режиме LiveCD.

Идём дальше и привлекаем для наших нужд Knoppix. В арсенале его параметров загрузки есть неприметный параметр fb1280x1024 для работы с framebuffer. Замечательное дело, и мы решили этим воспользоваться. У нас теперь появилась графическая консоль, чёрная и мрачная, как полярная ночь.

Теперь, чтобы воспроизвести сжатое нами видео, копируем видео в память на Knoppix в каталог Desktop. После этого воспроизводим наше многострадальное видео в консоли так:
mplayer -vo fbdev -cache 65535 -cache-min 98 -quiet video-compressed.avi
Ключик -quiet нужен для того, чтобы при воспроизведении Mplayer не выводил статистику в бегущей строке. Всё, после этого получаем фильм на чёрном экране, который воспроизводится плавно и без затей.

Скорость воспроизведения в Mplayer
На всякий случай, если потребуется запускать фильм с другой скоростью, всегда можно попросить Mplayer изменить число кадров в секунду (вплоть до 1 кадра в секунду) так:

mplayer -fps 1 video-compressed.avi
Эта команда будет воспроизводить фильм со скоростью 1 кард в секунду.
(спасибо тов.linuxfreshman за наводку)

Выводы и ссылки
Воспроизведение таких огромных файлов с большим FPS (у нас это 40FPS) - действительно непростая задача, на любой ОС. Надеюсь, что эта заметка пригодится не только нам, но и тем, кто хочет сжимать видео без потерь. Напоследок приведу интересную ссылку на перечень кодеков, который имеется в арсенале libavcodec.

12 комментариев:

  1. Интересный материал!
    Хотелось бы еще увидеть статью о lossless в звуке :)

    ОтветитьУдалить
  2. NVIDIA GF8xxx и старше с VDPAU и вот уже загрузка процессора при вопроизведении x264 не превышает и 10%. ^^

    ОтветитьУдалить
  3. хорошая статья.
    Мне сейчас нравится запускать видеофайлы в mplayer без gui. Правда возник один вопрос. Как перематывать видео покадрово назад? Вперед это получается с помошью клавиши английской точки.

    ОтветитьУдалить
  4. 2 duke комментирует...
    Интересный материал!
    Спасибо. На самом деле, по lossless написано довольно мало, и нам пришлось потерзать старину Гугла, чтобы выискать нужные сведения.

    Хотелось бы еще увидеть статью о lossless в звуке :)
    Увы, но обработка звука находится вне поля моих профессиональных интересов. Большая часть файлов у меня в MP3 (ибо на дисках только в этом распространяется), часть в ogg (которые кодировал с CD-Audio).

    2 Анонимный комментирует...
    NVIDIA GF8xxx и старше с VDPAU и вот уже загрузка процессора при вопроизведении x264 не превышает и 10%.
    Дык где ж я такое возьму!? :-)

    2 linuxfreshman комментирует...
    Правда возник один вопрос. Как перематывать видео покадрово назад?
    Интересный вопрос. Быстрое загугление ответа не принесло: народ говорит, что жмите на точку . и мотайте вперёд, а про назад ссылаются на avidemux.

    Нам назад пока не надо. Но иногда надо поменять скорость воспроизведения, что делается замечательным ключиком -fps

    ОтветитьУдалить
  5. А кодеком Nuppel никто не пользовался?

    ОтветитьУдалить
  6. virens комментирует...

    2 Анонимный комментирует...
    NVIDIA GF8xxx и старше с VDPAU и вот уже загрузка процессора при вопроизведении x264 не превышает и 10%.
    Дык где ж я такое возьму!? :-)

    По крайней мере GF8600 дешевле двухъдерного процессора, да и кушать электричества компьютер будет меньше. ^^

    ОтветитьУдалить
  7. 2 Анонимный комментирует...
    А кодеком Nuppel никто не пользовался?
    Нет. А какие от него бенефиты? Гуглёж показал навскидку, что явных как-то не просматривается. Буду благодарен за примеры.

    ОтветитьУдалить
  8. Насколько знаю Nuppel это формат записи видео без потерь(но при желании потери можно внести). Mencoder для кодирования в этот формат использует кодек nuv.

    ОтветитьУдалить
  9. Кажется вы перепутали местами исходное видео и сжатое в команде, которая кодирует в FFV1.

    ОтветитьУдалить
  10. +1
    перенесите -o перед последним видео
    mencoder -ovc lavc -lavcopts vcodec=ffv1 video-before.avi -o video-compressed-ffv1.avi

    ОтветитьУдалить
  11. 2 Пуляев комментирует...
    Насколько знаю Nuppel это формат записи видео без потерь
    Спасибо, поглядим.


    2 Анонимный и LeX комментирует...
    перенесите -o перед последним видео
    Да, есть промах :-)
    Перенёс, обновил пост. Большое спасибо!

    ОтветитьУдалить
  12. Почему про x264 не ниписали? Он lossless умеет :)

    ОтветитьУдалить