Ключевые слова:ffmpeg, video, (найти похожие документы)
From: Александр Майоров
Date: Mon, 16 Apr 2010 17:02:14 +0000 (UTC)
Subject: Создаем свой YouTube: Накладываем текст на видео
Материал предоставлен редакцией журнала Системный администратор.
Опубликовано в журнале "Системный администратор" N 1 2010
Продолжаем разбираться с обработкой видео средствами веб-сервера, с
автоматизацией создания превью для видеофайлов и наложением "водяных
знаков" на мультимедиа-контент.
Не хлебом единым
В прошлой статье мы подробно рассмотрели работу с FFmpeg.
Разобрались с тем, как можно конвертировать видео из разных форматов
самыми разными способами. Но кроме FFmpeg, как было уже сказано, есть
MPlayer и MEncoder, входящий в его состав MPlayer. Мы не должны себя
ограничивать одним инструментом. На практике могут понадобиться все эти
программы или можно использовать их как замену друг другу (но не во
всех случаях); если, допустим, не будет доступен ffmpeg, его может
заменить mencoder. Также у каждого из доступных нам инструментов есть
свои достоинства и недостатки.
Про установку MPlayer и MEncoder говорить особо нечего. В зависимости
от вашей ОС установка будет отличаться, естественно, но в целом все
очень похоже. В операционных системах семейства GNU/Linux вы, скорее
всего, станете устанавливать данные приложения из репозиториев через
встроенный менеджер пакетов. Это будет наилучшим вариантом. Если у вас,
к примеру, openSUSE, то вы воспользуетесь YaST'ом, если Ubuntu или
Debian-подобный дистрибутив - то вы, скорее всего, поставите его через
apt. Если у вас FreeBSD, то лучше воспользоваться системой портеджей.
Итак, давайте рассмотрим пару примеров работы с MEncoder. MEncoder -
это утилита, идущая в комплекте с MPlayer и предназначенная для
обработки и конвертирования видеофайлов из одного формата в другой. Я
не буду расписывать здесь подробно все ключи и возможности, так как
немало было рассказано в прошлой статье про FFmpeg, а работа с MEncoder
похожа. Вы всегда можете вызвать man mencoder и получить все нужные
сведения обо всех возможных опциях. Теперь рассмотрим пару примеров
работы с MEncoder.
Допустим, у вас есть множество файлов в формате avi, которые вы хотели
бы склеить в один большой фильм. К примеру, вы занимаетесь
монтированием нарезок, которые сделали на свою камеру. Нет ничего
проще. MEncoder может сделать это в два счета, достаточно в консоли
написать строчку:
mencoder -oac lavc -ovc lavc *.avi -o final_output_video_file.avi
Опция -oac указывает, какой аудиокодек мы будем использовать, а -ovc,
соответственно, видеокодек. Чтобы узнать, какие кодеки поддерживаются,
используйте команду:
mencoder -ovc help
Вы получите список доступных опций для аргумента -ovc. Наиболее важные
из них:
* copy - копирует кодек без перекодирования;
* lavc - кодек libavcodec, наилучшее качество;
* xvid - XviD-кодирвоание.
Точно так же можно получить список кодеков для аудио. Если вам нужно
использовать mp3-кодирование, не забудьте указать нужный вам битрейт:
mencoder -ovc lavc -oac lavc -lavcopts acodec=libmp3lame:abitrate=128 inputfile.mpg -o outputfile.avi
Если в вашей системе установлен libmp3lame и вам хочется расширить
список опций, доступных при кодировании аудио, вы можете использовать
аргумент lameopts. Этот аргумент также позволяет создавать файлы с
переменным битрейтом:
mencoder -ovc lavc -oac mp3lame -lameopts vbr=2:q=4 inputfile -o outputfile.avi
где q - это любое число в диапазоне от 0 до 9. Таким же образом можно
работать и с аудиодорожкой из видеофайлов:
mencoder -ovc lavc -oac lavc -lavcopts acodec=libmp3lame:abitrate=128 vcodec=xvid inputfile.mpg -o outputfile.avi
Этой информации хватит, чтобы заинтересовать вас поиграть MEncoder'ом.
Если у вас русифицированный дистрибутив (у меня, к примеру, openSUSE
11.2), то вам будет доступна полная инструкция на русском языке, так
что останется только искать нужные опции и использовать их. А мы тем
временем перейдем к животрепещущему вопросу для многих веб-мастеров и
не только - автоматизированное наложение текста на видео прямо на
сервере.
Брендирование видео
Брендирование - процесс наложения ватермарков (водяных знаков) на
видеоролик или изображение. У нас есть сервис видео, есть много
контента, но нам нужно как-то пометить свои ролики. Что же делать? Есть
много оффлайновых программ для таких нужд, но мы хотим полностью
автоматизировать наш процесс. Ну что же, начинаем думать логически, что
у нас есть и что мы можем сделать теми инструментами, что нам доступны.
Мы говорили о FFmpeg в прошлой статье очень много и узнали, что он
умеет разбивать видео по кадрам и сохранять каждый кадр в одном из
графических форматов. Работать с графикой мы умеем, используя скрипты
на том же PHP через GD-библиотеку либо прямо в консоли через
ImageMagick (или, опять же, используя соответствующее расширение PHP).
Итак, раскладываем видеофайл покадрово в какую-нибудь временную
директорию:
ffmpeg -i inputfile.avi -f image2 /tmp/videobrender%09d.png
выдираем аудиодорожку:
ffmpeg -i inputfile -vn -acodec pcm_s16le -ar 44100 -ac 2 /tmp/videobrender/audiotrack.wav
Все эти параметры подробно описывались в прошлой статье, так что
нет смысла их пояснять.
Теперь берем в руки ImageMagick и накладываем наш текст на кадры:
mogrify -pointsize 16 -fill white -annotate +4+10 'SAMAG.RU Video' /tmp/videobrender/*.png
где +4 - отступ слева и +10 - отступ сверху соответственно. После чего
собираем кадры обратно в видеоролик:
ffmpeg -f image2 -i /tmp/videobrender/%09d.png -f avi brend_file.avi
На выходе получим наш видеофайл, но без звука, как вы сами понимаете.
Картинки не могут нести в себе информацию о звуке, но мы позаботились
об этом, предварительно вытащив звуковую дорожку. Осталось наложить ее
обратно на ролик. Делается это просто:
ffmpeg -i /tmp/videobrender/audiotrack.wav -i brend_file.avi brend_audio_file.avi
Проверяем, что получилось. Таким образом можно нанести ватермарк с
адресом сайта на ваши видеоролики, которые будут скачивать
пользователи. Никто не мешает таким же образом накладывать рекламу или
еще какую-нибудь полезную информацию. Я показал, как наложить надпись
на все кадры, но никто не мешает вам накладывать разные надписи через
определенное количество кадров, что позволит создать динамический
ватермарк, несущий в себе полезную информацию. Вы можете даже делать
надписи сложной формы и делать их динамическими. Достаточно сделать
несколько кадров, как если бы вы их готовили для анимированного GIF, и
накладывать их на видеоролик последовательно. Написать такой скрипт не
составит труда любому человеку, хоть немного знакомому с
программированием. На чем писать - решать вам. Можно делать это на PHP,
а можно использовать командный интерпретатор bash.
Ниже приведен код примерного скрипта-утилиты для наложения текста на
bash.
#!/bin/bash
fname=$1
fname=${fname:?"File name can't be empty!"}
text=$2
text=${text:?"Text can't be empty!"}
tmpdir="`pwd`/jpeg"
rm "${tmpdir:?"WARNING! Not set path to temporary folder."}/*"
echo "Parse video..."
ffmpeg -i $fname -f image2 "$tmpdir/%09d.png"
echo "Parse audio..."
rm "$tmpdir/track.wav"
ffmpeg -i $fname -vn -acodec pcm_s16le -ar 44100 -ac 2 "$tmpdir/track.wav"
echo "Brend frames..."
mogrify -pointsize 16 -fill white -annotate +4+10 $text "$tmpdir/*.png"
echo "Create video..."
rm brend_$fname
ffmpeg -f image2 -i "$tmpdir/%09d.png" -f avi brend_$fname
echo "Add audio..."
ffmpeg -i jpeg/track.wav -i brend_$file brend_audio_$fname
rm brend_$fname
#EOF
Теперь на файл надо выставить права на исполнение, и его можно
использовать. Использовать эту утилиту просто (допустим, файл
называется brender):
brender inputfile.avi 'Test text'
Естественно, тут нет проверок на расширение, нет определения размеров
видео и много чего еще, но дальше, дорогой читатель, ты сможешь развить
идею в нужном русле. Но вы все можете это получить сами, особенно если
читали предыдущую статью [1]. Там было описано, как узнать всю
информацию о файле. На основе данной утилиты очень просто написать
демон, работающий на сервере и обрабатывающий поступающие видеофайлы в
автоматическом режиме.
Итак, вы знаете, как можно наложить свой лейбл на видеоролик. В
зависимости от размера видео процесс брендирования может длиться от
нескольких секунд до нескольких минут или часов. Все зависит от
ресурсов сервера и входящего видеофайла. Поэтому для обработки видео на
нагруженных проектах выделяется отдельный сервер, а все файлы
обрабатываются контроллером очереди по мере их поступления. Такой
контроллер пишется на PHP вкупе с Bash-скриптами. Можно оформить все
это в виде демона, который будет все время проверять, не поступило ли
что-то в очередь на обработку. Это уже к вопросам программирования
архитектуры вашего сервиса, которые мы тут не будем обсуждать.
Ищем пути оптимизации
Работать покадрово, конечно, с одной стороны удобно, так как у нас
больше гибкости. С изображением мы можем сделать что угодно тем же
ImageMagick'ом. Если посидеть и потратить больше времени, можно вообще
сделать динамичную 3D-надпись. Все зависит от вашей фантазии. Но мы
хотим немного упростить и ускорить процесс обработки видео. Выход -
искать готовые библиотеки. FFmpeg поддерживает плагины через так
называемый vhook. Правда, разработчики сказали, что использовать vhook
в FFmpeg нельзя, и если вы его используете - то на свой страх и риск.
Поэтому его убрали из FFmpeg до лучших времен.
Если все же вы хотите попробовать поиграть с vhook, то качайте
дистрибутив отсюда (тут он идет с поддержкой vhook):
http://www.videohelp.com/download/ffmpeg-0.5.7z
Обратите внимание на директорию vhook, которая находится в
дистрибутиве. Вот там нужные нам плагины для обработки видео. Теперь,
чтобы воспользоваться данной опцией, достаточно выполнить следующую
команду:
ffmpeg -i input.avi -acodec copy -vhook '/path/to/vhook/extensions/watermark.so \
-f /path/to/watermark/watermark.gif' output.avi
Библиотека watermark.so находится в директории с дистрибутивом в папке
vhook либо установлена в директорию, которая была указана при сборке,
если вы выполняли команду make install.
Еще один вариант работы с видео и текстом - это использование
библиотеки drawtext.so:
ffmpeg -i inputfile.avi -vhook 'drawtext.so -f tahomabd.ttf -x 10 -y 10 -t WatermarkText' outputfile.avi
По скорости работы данные методы немногим быстрее покадровой обработки.
Качество обработки, в принципе, идентичное. Про стабильность говорить
не могу, так как на практике, на реальных рабочих проектах, никогда не
использовал. Если учесть, что вы не сможете использовать последние
стабильные версии, так как в них просто убрали vhook и его поддержку,
то использовать его или нет, решать вам. Если хотите, можете поиграть с
этими библиотеками и параметрами, попробовать настроить на реальном
проекте. Возможно, для ваших нужд это будет правильный выбор.
Накладываем ватермарк в реалтайме
Вполне резонный вопрос: а кроме FFmpeg неужели ничего больше нет? И тут
мы начинаем изучать MPlayer. Пробуем разобраться в руководстве, как им
пользоваться, и находим, что MPlayer умеет накладывать ватермарки на
видео в реальном времени. Пробуем разобраться, что это и как работает.
В MPlayer есть поддержка работы с пайпами (каналами). Чтобы создать
пайп, нужно выполнить:
mkfifo pipename
В итоге, после чтения документации, получаем такой вот скрипт:
#!/bin/bash
[ -e logopipe ] && rm logopipe
mkfifo logopipe
mplayer -vf bmovl=0:1:./logopipe videofile.avi > /dev/null &
i=0
while true
do
echo "RGB24 100 50 $i 0 0 0" > logopipe
cat logo.rgb > logopipe
sleep 1
let i=i+5
done
Данная программка запустит видео в MPlayer и создаст в окне плеера
движущийся логотип.
Строка echo "RGB24 100 50 $i 0 0 0" указывает команду для плеера,
сообщая, что надо выделить графическую область размерами 100 на 50
точек.
Переменная $i - это смещение логотипа слева. Так как у нас эта величина
изменяется, то логотип будет каждую секунду съезжать вправо на 5
пикселей, потому что мы делаем инкремент на 5 единиц в строчке let
i=i+5.
Это полезно, если вы разрабатываете свой фронт-енд для данного плеера.
Таким образом, можно выводить информацию о звуке или файле. Все зависит
от вашей фантазии.
Но это немного не подходит для наших нужд. Смотрим дальше, что еще
можно сделать. Мы узнали, что можно писать в видеопоток через пайпы.
Меняем MPlayer на Mencoder и смотрим, что из этого выходит:
#!/bin/bash
(echo "RGBA32 100 50 0 0 0 0"; cat mylogo.rgba ) > pip &
mencoder -oac copy -vf bmovl=0:1:pip -ovc raw -o inputvideo.avi outputvideo.avi
Правда, сам MEncoder для кодирования использует кодеки из набора
FFmpeg, что уже говорит о том, что лучше использовать FFmpeg.
Субтитры тоже текст
А что мы знаем про субтитры? Субтитры (от фр. Sous-titres - подписи) -
текстовое сопровождение видео, на языке оригинала или переводное,
дублирующее и иногда дополняющее звуковую дорожку фильма или передачи.
В субтитрах отражена прежде всего речь людей и персонажей в кадре.
Субтитры распространяются в файлах формата *.srt.
Чтобы проиграть фильм с субтитрами тем же MPlayer'ом, нужно вызвать его
со следующими параметрами:
mplayer -subwidth 75 -subcp utf8 -subfont-text-scale 8 -sub subsfile.srt inputvideo.avi
где:
-subwidth - ширина области субтитров;
-subcp - кодировка, в которой будет текст субтитров;
-subfont-text-scale - размер шрифта;
-sub - файл субтитров.
Как подготовить субтитры? Можно воспользоваться специальными
программами, такими как gaupol, если у вас операционная система
GNU/Linux. Можно создать субтитры самостоятельно. Сам файл субтитров -
это обычный текстовый файл. Пример субтитров:
1
00:00:00,000 --> 00:00:59,000
Test subtitle!
Это первый по счету субтитр, который будет виден в течение 59 секунд.
И тут нам приходит в голову мысль: а что, если в качестве инструмента
брендирования использовать субтитры? Мы просто создаем файл субтитров,
где делаем одну запись ровно на весь фильм. Но как встроить его в
видео? Да очень просто:
mencoder -subwidth 75 -subcp utf8 -subfont-text-scale 8 -sub subsfile.srt \
-oac mp3lame -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=2000 inputvideo.avi -o outputvideo.avi
В итоге мы получим файл с текстом, который будет располагаться внизу
ролика. Как вы могли догадаться, скорость работы такого метода
наложения надписей на ролик намного выше, чем предыдущие методы с
разбиванием на кадры. Но у нас нет такой свободы над манипулированием
фильмом. Мы можем только накладывать текст. Но способ имеет право на
существование и довольно быстр и менее ресурсоемок. Так что выбирать
вам.
Кстати, вы заметили, что почти все, что можно делать через MPlayer,
можно делать и через MEncoder. Вы сначала смотрите, что может
получиться на выходе, используя плеер с нужными параметрами, а потом
просто запустить конвертер с теми же аргументами.
Советы по оптимизации
Есть несколько способов оптимизировать нашу работу.
1. Используем MEncoder вместо FFmpeg для создания превью
На практике не все бывает так гладко, как хотелось бы. Например, если у
вас большие ролики, то для создания превью лучше использовать MEncoder,
а не FFmpeg. Поиск требуемой позиции в потоке у FFmpeg заметно
медленнее, чем у того же FFplay и MPlayer. Время поиска возрастает
практически линейно. Это совершенно неприемлемо, если вам надо
обрабатывать много файлов.
FFmpeg использует более точный, при этом более ресурсоемкий способ
нахождения позиции в потоке, нежели тот же MPlayer, который
ориентируется по ключевым фреймам, в то время как FFmpeg просматривает
все фреймы подряд. Поэтому следует делать скриншоты видеороликов с
помощью MPlayer, если есть возможность. FFmpeg фактически проиграет
видео до нужного участка, в то время как MPlayer просто перейдет на
нужный кадр и сохранит изображение. Создать скриншот с помощью MPlayer
можно так:
mplayer -ss 30 -frames 1 -vo jpeg: outdir=screenshot/ -nosound inputvideo.avi
где:
-ss - через сколько секунд нужно сохранить изображение в файл;
-frames - количество сохраняемых подряд изображений;
-outdir - папка, в которую изображения будут складываться.
2. MEncoder вместо FFmpeg при склейке фильма
Бывает так, что FFmpeg может давать сбои на некоторых фильмах при
склейке фрагментов. Если у вас такое случилось, попробуйте вместо
FFmpeg использовать mencoder. Пример команды для такой операции показан
ниже:
mencoder mf://folder_with_frames/*.png -mf w=176:h=144:fps=15:type=png \
-ovc lavc -lavcopts vcodec=mpeg4 -o outputvideo.3gp
Выше мы писали программу для покадровой обработки видео, используя
FFmpeg. Ту же программу можно переписать, используя MEncoder. Если у
вас нет FFmpeg, можете вовсе переписать все примеры из предыдущей
статьи с помощью MEncoder. Лично мое мнение и практический опыт
показали, что FFmpeg более стабилен и прост в использовании и его
всегда
3. Запускаем каждый процесс обработки на отдельном процессоре
Если у вас многопроцессорный сервер, то вы можете запускать несколько
потоков по обработке видео, вешая каждый на свой процессор. Для этого
можно воспользоваться утилитой xargs. У нее есть параметр,
определяющий, какой процессор использовать для текущей задачи.
Например, запустим программу на втором процессоре:
xargs -P 2 -J mplayer -ss 30 -frames 1 -vo jpeg: outdir=screenshot/ -nosound inputvideo.avi
Таким образом, можно написать простой демон для обработки видео,
который будет работать в несколько потоков, равномерно загружая
систему.
Ну, вот и все. Я рассказал почти все, что хотел, а рассказал немало.
Почти - потому, что про обработку видео можно говорить часами. Но
некоторые вещи уже не так существенны. Главное - вы получили самую
основную информацию, а уже дальше - дело техники и фантазии. Обладая
полученными знаниями, вам не составит особого труда создать свой
видеохостинг, сервис по обработке видео или просто автоматизировать
процессы, так или иначе связанные с обработкой видеофайлов.
Надеюсь, все вышеизложенное в двух статьях вам пригодится на практике.
До встречи.
1. Майоров А. Создаем свой YouTube. Как обработать видео средствами
веб-сервера. //Системный администратор, No.12, 2009 г. - С. 88-96.
Статью можно обсудить на Форуме журнала "Системный администратор" http://www.samag.ru/forum/