3 июня 2009 г. ffmpeg Flash flowplayer FLV Nginx PHP yamdi Сервисы FreeBSD

Видеосервис своими руками и организация псевдостримминга

videoservice

Сегодня я расскажу как работают "видеохостинги" и мы разработаем свой "видеосервис" для закачивания видео-файлов, с последующим конвертирование и созданием картинки для превью. Далее организуем показ во флеш-плеере и эмулируем стримминг (для перемотки на не загруженные части видео-файла).

Для всего этого нам понадобиться:

  • Флеш-плеер для проигрывания видео-файлов - flowplayer
  • Программа для конвертирования видео-файлов - ffmpeg
  • Расширение PHP для получения превью-изображения - php-ffmpeg и библиотека для работы с графикой - GD
  • Эмуляция потокового видео (псевдостримминг) с помощью утилиты yamdi, модуля для nginx - http_flv_module и плагина для flowplayer - flowplayer.pseudostreamming

scheme-medium

Серверная ОСь по традиции - FreeBSD.

Установка необходимых нам утилит

ffmpeg

Для того чтобы конвертировать видео, нам необходимо установить утилиту ffmpeg. Есть еще аналогичная утилита - mencoder, тоже очень хорошая, но ffmpeg более популярен, поэтому именно его буду сейчас использовать. Эти утилиты с переменным успехом конкурируют между собой, поэтому также рекомендую посмотреть на mencoder в свободное время.

# cd /usr/ports/multimedia/ffmpeg
# make config

и выбираем LAME (lame MP3 codec)

# make install
Windows сборки ffmpeg: http://ffmpeg.arrozcru.org/builds/

yamdi

Далее, необходимо установить утилиту yamdi, которая вшивает мета-данные в видео-файл. Мета-данные необходимы для индексирования файла, то есть для того, чтобы можно было в еще не скачанном (не буферизированном) файле при перемотке перемещаться по индексам.

# cd /usr/ports/multimedia/yamdi
# make install

nginx

Теперь подошло время для nginx, который будет отдавать индексируемый (с помощью yamdi) видео-файл. На его месте может быть и lighttpd или еще какой-нибудь другой веб-сервер. Но я поддержу отечественного производителя! :)

# cd /usr/ports/www/nginx
# make config

и выбираем HTTP_FLV_MODULE, далее

# make install

Ну или просто при установке укажите опцию "--with-http_flv_module".

nginx-0.7.52. Теперь и под Windows: http://rmcreative.ru/blog/post/nginx-0.7.52-teper-i-pod-windows
Можно конечно использовать в качестве бекенда - PHP, например с помощью такого кода:
$start = (int) @$_GET['position'];
if ($start < 0) die("You fucking idiot");
// open file for reading
$fp = fopen($file, 'r+');
$fsize = filesize($file);
if ($start > 0)
{
    // seek to requested position
    fseek($fp, $start);
    // FLV header for the movie part. Magic. Just trust me.
    // Header code is completely taken from flv4php project
    $header = "FLV" . pack('C', 1 ) . pack('C', 5 ) . pack('N', 9 ) . pack('N', 9 );
    header("Content-Length: " . (strlen($header) + $fsize - $start));
    echo $header;
} else {
    header("Content-Length: " . $fsize);
}
set_time_limit(0);
while(!feof($fp)) {
    print(fread($fp, 1024));
    usleep(1000);// limit download speed
}
fclose($fp);

Но мне удобнее использовать для этого модуль nginx'а, да и быстрее будет.

php5-ffmpeg

Это расширение PHP нам понадобиться для того чтобы получать информацию о видео-файле, а также для получения видео-фрейма для превью. Также необходимо установить библиотеку GD и сам PHP в частности.

# cd /usr/ports/graphics/php5-ffmpeg
# make install
php5-ffmpeg для Windows: http://pyha.ru/forum/attachment/1256/1317.0 и http://pyha.ru/forum/attachment/1257/1317.0
Можно конечно получать информацию путем обращения к
# ffmpeg -i /path/filename.flv

и делать превью
# ffmpeg -i /path/filename.flv  -an -ss ВРЕМЯ_ПОЗИЦИИ_В_СЕКУНДАХ -r 1 -vframes 1 -s 320x240 -y -f mjpeg /path/filename.jpg

Но мне нравиться использовать расширение, это удобнее.

И перегрузите apache или nginx, смотря как вы используете PHP.

Конвертирование видео и получение изображения для превью

Для начала нам надо указать путь до исходного и результирующего файлов, прописать пути до превью-файлов, а также указать минимальную позицию фрейма для создания превью.

// Путь до залитого видео-файла, например временный файл полученный по $_FILES['tmp_file']
$inputPath = $_FILES['tmp_file'];

//Путь до результирующего файла, то есть отконвертированный и прошитый мета-данными видео-файл
$outputPath = "/path/video/filename.flv";

// Указываем минимальную позицию фрейма для захвата превью
$previewFrameMin = '3'; 

// Путь до превью-файла
$previewPath = "/path/preview/filename.jpg";

// Путь до мини-превью
$previewMiniPath = "/path/preview/filename_mini.jpg";

// Массив для сбора ошибок
$errorInfo = array();

Конвертируем исходный файл во временный, в формате FLV и разрешением 320x240, использую в качестве аудио-кодека mp3lame с частотой 44100, остальные настройки по умолчанию. Временный файл нужен для того, чтобы yamdi смог вшить мета-данные, так как он не может вшить в исходный файл.

/* 
 * Конвертируем FLV во временный файл ($outputPath . '_temp').
 */
passthru(
    '/usr/local/bin/ffmpeg -i ' . escapeshellarg($inputPath) .
        ' -f flv '.
        ' -s 320x240 '.
        ' -acodec libmp3lame '.
        ' -ar 44100 '.
        escapeshellarg($outputPath . '_temp'),
    $errorInfo['ffmpeg']
);

Прошиваем в видео-файл мета-данные для индексирования. Утилита yamdi написана на Си и работает очень быстро! А также удаляем временный файл.

/*
 * Прошиваем metadata (позиции ключевых фреймов) для перемотки
 */
passthru(
    '/usr/local/bin/yamdi -i ' . escapeshellarg($outputPath . '_temp') . 
        ' -o ' . escapeshellarg($outputPath),
    $errorInfo['yamdi']);

/*
 * Удаление временного файла, он нам уже не нужен...
 */
unlink($outputPath . '_temp');

Теперь получаем информацию о видео-файле и получаем объект фрейма для превью.

/*
 * С помощью расширения php5-ffmpeg получаем информацию о видео-файле
 */
$movie = new ffmpeg_movie($outputPath);

/*
 * Вычисляем время воспроизведения видеофайла
 */
$duration = $movie->getDuration();

/*
 * Вычисляем количество кадров
 */
$frameCount = $movie->getFrameCount();

/*
 * Вычисляем позицию фрейма для его захвата
 */
$framePosition = ($frameCount > $previewFrameMin) ? $frameCount / 2 : $previewFrameMin;

/*
 * Получаем объект фрейма для превью
 */
$preview = $movie->getFrame($framePosition);

А теперь получим и сохраним наши превьюшки.

/*
 * Записываем в файл - Превью (320x240)
 */
imagejpeg ($preview->toGDImage(), $previewPath);

/*
 * Записываем в файл - Мини-превью (160x120)
 */

$previewMini = imagecreatetruecolor(160, 120);

$r = imagecopyresized(
    $previewMini,
    $preview->toGDImage(),
    0, 0, 0, 0,
    160, 120,
    320, 240
);

imagejpeg($previewMini, $previewMiniPath);

Все, файл отконвертирован в FLV и прошит мета-данными, также созданы превью, теперь займемся выводом видео-файла - клиенту.

Плеер и показ видео

Почему flowplayer?

Сначала нам понадобится флеш-плеер, умеющий проигрывать видео в формате FLV и показывать картинки в формате JPEG (для превью).

Из всех аналогов (смотрите ниже, в "Полезные ссылки -> Видео-плееры") мне больше всего понравился flowplayer, он:

  • Кроссбраузерный и очень гибкий, и удобный в настройке
  • Бесплатный для некоммерческого использования, а коммерческая версия стоит его возможностей!
  • Имеет Flash и Javascript API, также поддерживает библиотеку JQuery (там доп. фишки какие-то)
  • Имеет кучу полезных плагинов
  • Умеет работать со стриммингом и псевдостриммингом
  • Легко поменять шаблоны оформления и языковые шаблоны для настройки локализованного интерфейса
  • Обширная документация, имеет достаточно большое сообщество в собственном форуме, а также оказывает бесплатную поддержку для коммерческой версии
  • Поддерживает плейлисты и имеет полноэкранный режим
  • Поддерживаемые форматы: FLV, SWF, MP3, MP4, H.264 video, JPG, PNG
  • Сырцы открыты!

flowplayer

Остальное описание возможностей на официальном сайте: http://flowplayer.org/

Настройка flowplayer

С плеером мы определились, теперь надо его настроить для показа видео. В дистрибутив плеера входит:

  • flowplayer-3.1.1.swf - сам плеер
  • flowplayer.controls-3.1.1.swf - flash-controls
  • flowplayer-3.1.1.min.js - это так называемый js-api

Для реализации псевдо-стримминга нам не хватает flowplayer.pseudostreaming-3.1.2.swf, который можно скачать и ознакомиться с использованием тут: http://flowplayer.org/plugins/streaming/pseudostreaming.html.

Для работы со всеми видами стриминга есть титуриал: http://flowplayer.org/documentation/configuration/streaming.html

Итак, приступим:

<!-- Подключаем js-api -->
<script type="text/javascript" src="/swf/flowplayer-3.1.1.min.js"></script>

<!-- Настраиваем плеер -->
<script type="text/javascript">
    flowplayer(
        "player",
        "/swf/flowplayer-3.1.1.swf",
        { 
            playlist: [
                {
                    url: 'http://example.com/preview/filename.jpg' 
                }, 
                { 
                    url: 'http://example.com/video/filename.flv',  
                    autoPlay: false,
                    autoBuffering: false,
                    provider: 'pseudo'
                }
            ],
            plugins: {
                pseudo: { 
                    url: '/swf/flowplayer.pseudostreaming-3.1.2.swf' 
                }
            }
        }
    );
</script>

<!-- DIV в который мы поместим плеер --> 
<div style="width:416px;height:312px;display:block;padding:10px;" id="player"></div> 

Все опции указанные в настройках можно посмотреть тут: http://flowplayer.org/documentation/configuration/clips.html

Настройка http_flv_module

Теперь настроим nginx на отдачу файла со смещением, для эмуляции стримминга.

location ~ \.flv$ {
                flv;
                root /path/video;
        }

То есть, говорим nginx'у чтобы он для расширения "flv" использовал модуль http_flv_module и указываем в root путь до видео-файлов. Документация по http_flv_module: Директивы модуля ngx_http_flv_module

Ну вот и все, теперь у вас полноценный "видеосервис"!

Полезные ссылки

ffmpeg
Работа с видео на php с помощью php ffmpeg
Продвинутый метод воспроизведения flash-видео на веб-страницах (или эмулируем стрим-видео)
Наносим водяной знак на видео с помощью ffmpeg
Как же работают видеохостинги? Часть первая. Сборка.
Как же работают видеохостинги? Часть вторая. Ffmpeg.

Видео-плееры
Подборка видео-проигрывателей на флэше
Видео и аудио плееры для сайтов
Идеальный видео-плеер
Идеальный видеоплеер. Не утопия

Комментарии

неплохой обзорчег. а как же мультидоменность, прогрессбар при загрузке и прочие вкусности?)))))))))))))

Мультидоменность обеспечивает коммерческая версия flowplayer :)

отлично, молодец!

пхп бекэнд это нечто))) работать будет только столько потоков вещания одновременно сколько воркеров в нгинкс-конфиге. про скорость я вообще молчу) так что не вариант)

Спасибо, хороший обзор!

сколько воркеров в нгинкс-конфиге
или в апаче :)

Это кто-то реализовал уже??

Дима, что именно?

Неплохо.а эти бибиотеки позволяют работатьь с mp3 файлами ?
выдирать кусочки, менять битрейт и т.д.?

Сергей, ffmpeg умеет работать с mp3 и flowplayer тоже.

выдирать кусочки, менять битрейт и т.д.?
да

как можно с вами связатьс лично?

Сергей, пройти в раздел сайта "Контакты", а по какому вопросу? Почему не в блог комментировать?

могу и в блог.
мне нужно разработать небольшой скриптик, желательно в связке с флеш, чтобы можно было вырезать кусок mp3 файла. уже неделю не могу найти кто бы мне помог...

Сергей, я во флеше не спец, а на серверной стороне надо просто передавать позиции и всё. Вся задача упирается во флеш.

ну а если без флеш?
какие варианты?, цены?, сроки? и самое главное - кто может сделать?

Сергей, что значит без флеш?

ну без флеш, значит без прослушивания и забиваем ручками в минутах и секундах откуда и до куда вырезаем...

цены?, сроки? и самое главное — кто может сделать?
если я, то возьмусь за 2000-3000 руб (судя по заданию), в течении 2х дней смогу сделать

при этом либо должен быть сервер с ssh доступом и freebsd в качестве платформы, либо толковый админ, который все сам настроит что ему скажу

что могу сделать:
* вырезаю аудио по переданным параметрам секунд
* проигрываю обрезанное аудио
* смена битрейта

аську надобы для оперативности ;)
моя тридцать семь десять пять семь.

Сергей, у меня только жаббер и скайп

отписал вам на почту.

Я вот что-то понять не могу... вот этот кусок

/*
 * Удаление временного файла, он нам уже не нужен...
 */
unlink($outputPath . '_temp');
/*
 * С помощью расширения php5-ffmpeg получаем информацию о видео-файле
 */
$movie = new ffmpeg_movie($outputPath);

До этого мы НИГДЕ не копировали файлик в $outputPath,т.е. получается, что мы грохаем темповый файл и пытаемся создать "из ниоткуда" $outputPath-файл... или я что-то не понимаю?

Все - нашел... мои кривые глаза - ямди прошивает escapeshellarg($outputPath)...

Алексей, угу )

Не знаю как и быть. У меня есть свой плеер, написаный на acstinscript 2. Думаю как бы мне туда запихнуть этот псевдостример... Ведь .as библиотека псевдострименга под 3-ий идет, а я в нем ни бум-бум((( Декомпильнул этот flowplayer - нифига там не понял. У гого есть какие мысли что мне делать7

Либо использовать flowplayer, либо учить AS3

Обнадежил(((... Т.е. других вариантов нет7 Неужели нет какой-нить недокументированного метода или еще какого-нить способа грузить видео с нужной метки как seek(5), например7 Просто чисто для этой задачки пока AS3 учить нет времени, т.к. он сильно отличается от AS2 как я посмотрел, а плеер мне нужен именно мой... там своя специфика и другие плеера не подойдут ну никак... Может хоть какая зацепка есть7 а...7

Я не специалист во Flash/Flex и не знаю язык AS

на http://uppod.ru/talk_177 в первом абзаце понял, что нужно чтобы на сервере был lighttpd. Что это такое7 А флеш-проигрыватель даже не придется трогать. Как я понял просто запрос будет не к file.flv, а file.flv?start=123, например и сервак пришлет видео с нужного места. Если я правильно понял - все не так уж и плохо и возможно даже этот flowplayer ковырять не придется. Тока что это за lighttpd, как его сделать, что прописать в var so = new SWFObject("flash/my_swf.swf", "movie", "100%", "100%", "9", "#ffffff");... html страницы? Вроде что-то проясняется, но непонятно что конкретно.

лайти это веб-сервер, альтернативный nginx
если у вас будет работать с лайти без проблем, то и с nginx тоже будет

[code]

stenogramma

var so = new SWFObject("flash/psevdo_1.swf", "movie", "100%", "100%", "9", "#ffffff");//Мой плеер)))
so.addParam("allowFullScreen", "true");
so.addVariable("start_seek", "1");//Стартовый параметр
so.addVariable('autostart','true');//Тоже откуда-то возможно нужно
so.addVariable("file_name", "http://flowplayer.org/video/Extremists.flv");//Беру с http://flowplayer.org
so.addVariable("streamscript", "lighttpd");//Это я вычитал с форумов всяких
so.write("flashcontent1");

[/code]

Так вот когда я отсылаю с параметром start_seek=0 - все окейно работает. В моем плеере переменная start_seek прибавляется к переменной file_name и получается запрос типа "http://flowplayer.org/video/Extremists.flv?start=0" и видео грузится по этому пути. Как я понял - главное что запрос идет на сервак lighttpd, а http://flowplayer.org должно быть именно то что нужно. и как я понял нужно передавать в GET-е переменную start. Но работает тока с start=0. Не знаю - вроде капаю в нужном направлении, но файл отказывается грузиться если start не равно 0. Мысли есть7

Я не работал с лайти, по идее все должно быть нормально

В строке so.addVariable("streamscript", "lighttpd"); я передаю переменную — как ее должен обработать плеер? Может в этом дело, что я никак эту переменную не обрабатываю во флеше?

попробую поискать на форумах... блин, инфы мало((( В основном рассматривают уже готовые плееры, а что в нем должно быть, чтобы работало нигде нет. Должно быть все просто .....myFlv.flv?start=10, а файл лежать на lighttpd, например. Но не пашет. Чего-то я не учитываю((

А какой для видео нужен хостинг? Т.е. должны ли быть какие-то особые характеристики - выделенный сервер и т.п. Есть два "обычных" хостинга - буфферизация происходит медленно, хотя ролики не очень большие, и смотрю их я один.

Max Folder, нужен установленный ffmpeg, yamdi, nginx (+mod_flv), php-ffmpeg. Но, можно обойтись только ffmpeg, а через скрипт, который я приводил в статье можно эмулировать mod_flv

adw0rd, это я понял. А технические характеристики сервера, толщина канала? Нужно ли что-то специфическое (например, аренда сервера за 10000 рублей в месяц), или я просто беру хостинг, условно говоря, за 200 рублей в месяц и радуюсь жизни?

Условно говоря - да, можете взять хостинг и радоваться жизни :) А там уже узнаете - подходит он вам или нет. У меня прекрасно работает на FirstFDS за 600 руб.

Извиняюсь, за очередной глупый вопрос. FirstFDS (хотя оно где-то упоминается) я не нашел, нашел firstvds.ru - это оно? Виртуальный выделенный сервер.

Max Folder, да, именно FirstVDS, извините, с просони не то написал :/

Друзья, подскажите - какие ключи у хука watermark??? что-то не могу в инете найти нормальное описание. И работает ли корректно watermark.so с водяными знаками в формате png?

Алексей, вам сюда

Я конвертирую видео используя Fedora+mencoder+On2VP6. Качество просто ураган. Нарезку делаю напрямую с DVD iso файла. Качество практически без потерь при битрейте 700кБит.
Тестировал производительность на реальных серверах.
Один WindowsXP другой Fedora конфигурации идентичные. Конвертера настроены идентично.
В Windows XP в 5 потоков конвертации 1 фильм снимает часов так за 14.
В Fedora в 10 потоков конвертации 1 фильм снимает практически в риалтайме - 1.5-2 часа.
Вывод: под Linux-ом фильм конвертируется в 14 раз быстрее.
Здесь полностью подробно описано как настроить качественный HDTV-видеохостинг
http://webmax.do.am/publ/administration/nastroyka_servera_hdtv_videohostinga/1-1-0-1
Настраивал полностью по этой статье.

подскажите кто тестировал данный скрипт скриминга на php, он работает вообще?

и каким плеером передавать GET['position']; ??
я так понимаю тут есть какие-то своя реализация...?

===
$start = (int) @$_GET['position'];
if ($start < 0) die("You fucking idiot");
// open file for reading

....

мне вот захотелось переписать его на perl (или на Си) :)

зашел сюда http://fanno.dk/index.php?option=com_content&task=blogcategory&id=15&Itemid=53, там увидел скрипт стримминаг очень навороченный и большой...

ЗЫ: вариант в этой статье работает?

да, и еще стояла задача:
конкретный файл отдавать конкретному пользователю у которого есть права...
то тут настроить внутрений редирект на nginx со стримингом...

ngx_http_flv и X-Accel-Redirect

а как эти два модуля связать? нужно сделать внутриний редирект на файл? и он начнет скачиваться, правильно? но а как смтриминг сюда можно прикрутить...?

вот есть дискусия http://kovyrin.net/2006/10/14/flash-video-flv-streaming-nginx/comment-page-1/#comment-55530

но я там не понял, как эти два модуля связать?

dima,

подскажите кто тестировал данный скрипт скриминга на php, он работает вообще? и каким плеером передавать GET['position']; ?? я так понимаю тут есть какие-то своя реализация...?

Вот отсюда взят код http://vbolshov.org.ru/?id=20&ctrl=article (ссылку приводил в конце статьи)

ЗЫ: вариант в этой статье работает?
я его не проверял, ибо статья не о нем, это просто вариант. А в статье рассказывается именно о nginx модуле

а как эти два модуля связать? нужно сделать внутриний редирект на файл? и он начнет скачиваться, правильно? но а как смтриминг сюда можно прикрутить...?
Да, задачу вашу понял... Подумаю на досуге, сразу не могу ничего сказать :/

поняно, тут они написали http://vbolshov.org.ru/?id=20&ctrl=article
что переделали плеер из flv4php, НО не написали как переделали

вся проблема плеер прикрутить...

"Не меньшая благодарность – Willyam Bradberry (willyam[at]newmail[dod]ru) – за работу над нашей версией плеера (видоизмененный плеер из flv4php)."

подскажите, почему нельзя поставить просто файл с метанными и через JavaScript подгрузить flash?

есть ли у кого-то такой вариант на JS? а то не поулчается вот пробовал 100 раз:

1)

<script type='text/javascript' src='http://localhost:3000/fplayer/swfobject.js'></script>
<div id='mediaspace'>This text will be replaced</div>
<script type='text/javascript'>
  var so = new SWFObject('http://localhost:3000/fplayer/player-viral.swf','ply','470','320','9','#ffffff');
  so.addParam('allowfullscreen','true');
  so.addParam('allowscriptaccess','always');
  so.addParam('wmode','opaque');
  so.addVariable('file','http://localhost:3000/fplayer/video.flv');
  so.write('mediaspace');
</script>    
http://www.longtailvideo.com/support/jw-player-setup-wizard?example=1


2)

<script type="text/javascript" src="/video/swfobject.js"></script>
<!-- Здесь мы включили в документ SWFObject -->
<script type="text/javascript">
var flashvars = {way:"http://lissyara.org.ua/fplayer/video.flv", swf:"http://localhost:3000/video/uflvplayer.swf", w:"500", h:"375", 
skin:"greyblack", pic:"http://lissyara.org.ua/video/sample.jpg", autoplay:"0", tools:"2", q:"0", volume:"70", comment:"Название"};
// Здесь мы перечислили параметры flashvars настройки плеера
var params = {bgcolor:"#FFFFFF", allowFullScreen:"true"}
// Здесь мы указали в параметрах цвет фона flash-ролика
var attributes = {id:"uplayer_flv",name:"uplayer_flv"};
// Здесь мы указали в атрибутах идентификатор и имя объекта в документе
swfobject.embedSWF("http://lissyara.org.ua/video/uflvplayer.swf", "http://lissyara.org.ua/fplayer/video.flv", "500", "70", "9.0.0", "http://lissyara.org.ua/video/expressInstall.swf", 
flashvars, params, attributes);
// Здесь мы запустили SWFObject для публикации flash-ролика в формате: путь к файлу, id блока для публикации, ширина, высота, минимальная 
версия flash-плеера, путь к файлу экспресс-инсталяции, flashvars переменные, params параметры, attributes атрибуты
</script>
....

<div id=uplayer_flv>
<a href=http://www.adobe.com/go/getflashplayer>
<img src=http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif alt="Get Adobe Flash player" />
</a>
</div>


  1. Кто-нибудь использовал flvtool2 вместо yamdi? Интересует, принципиально ли использовать именно тот или иной продукт? Вроде задача одна и та же, добавление meta-данных.
  2. После загрузки файла пользователя на сервер ffmpeg будет довольно долго обрабатывать видео. Как это можно ускорить? Неужели у Google настолько быстрые сервера, что они конвертируют видео за "5 сек."?
  3. Как дополнение вторго вопроса. Хорошо, меня "все" уговорили и я жду пока обработается файл. Пользователю надо передавать данные, о том, сколько осталось, хотя бы в процентах. Интересует, можно ли ffmpeg'ом получить данные о видео, без старта конвертации? На сервере нет php, он там не планируется, поэтому модуль php5-ffmpeg использовать не получится.
  1. Не знаю, проведите тесты и узнаете что лучше
  2. Надо добавлять задание в одчередь и фоном обрабатывать, либо использовать например fastcgi_finish_request() и т.д.
  3. Получить можно, а почему без старта?
  1. В общем практика (и отзывы из сети это подтверждают), что yamdi пошустрее. С (Си) сделал Ruby :)

  2. Про очередь понятно, в целом вопрос немного был не корректен, так как видео там кодируется долго, если оно HD-качества :) А про ускорить... Или убить качество, или мощный сервер, занимающийся только эти (а-ля CUDA) :)

  3. В целом можно получить все важные данные о видео при старте конвертации, скинуть эти данные куда надо и использовать. Почему хотел без старта - если мне залили видео, я его ещё не начал обрабатывать, но хочу знать, сколько оно длится и ещё чего-нибудь.

  1. Для этого достаточно выполнить ffmpeg -i video.avi

Можно ли для превью использовать не статичные изображения а кусок видео из исходного FLV?

Думаю можно, но касательно flowplayer, то лучше посмотреть на их сайте в документации, я не в курсе.

Здравствуйте! Подскажите, а куда вписывать код(ы) приведены в подразделе "Конвертирование видео и получение изображения для превью" ?

Туда, куда вы файл загружаете :)
Я думаю вам надо с чего-то попроще начинать, раз у вас такие вопросы...

организация псевдостримминга - оч важна для меня. вот и хочу разобраться, т.к. у вас найболее шикарная статья из всех в Рунете об оррганизации псевдостримминга. но для новичков (таких как я) нехватает, может и мелких, но деталей

Так как там используется

$_FILES['tmp_file']
, то вам следует поместить этот код так, что бы он вызывался при загрузке видео-файла через html-форму. Упрощенно это так:


# index.php
<form action="/exec.php" method="POST" enctype="multipart/form-data">
    <input type="file" name="tmp_file" />
    <input type="submit" />
</form>

# exec.php
<?php
    // Путь до залитого видео-файла, например временный файл полученный по $_FILES['tmp_file']
    $inputPath = $_FILES['tmp_file']['tmp_name'];

    //Путь до результирующего файла, то есть отконвертированный и прошитый мета-данными видео-файл
    $outputPath = dirname(__FILE__) . "/files/video/filename.flv";

    // Указываем минимальную позицию фрейма для захвата превью
    $previewFrameMin = '3';

    // Путь до превью-файла
    $previewPath = dirname(__FILE__) . "/files/preview/filename.jpg";

    // Путь до мини-превью
    $previewMiniPath = dirname(__FILE__) . "/files/preview/mini/filename.jpg";

    // Массив для сбора ошибок
    $errorInfo = array();

    // ...

На сколько я понял, код для прошитья видео мата-данными тоже нужно в exec.php дописать?
и еще вопрос: где/в какой папке появится файл загружённый через форму index.php?

  1. да, нужно в exec.php
  2. сделайте в exec.php
    var_dump($_FILES);
    и вы узнаете куда сохранился загруженный файл через форму index.php

выдаёт ошибку

array(0) { }
, хотя файл грузится кудато...

  1. а форма то у вас на exec.php смотрит?
  2. какой размер у файла?
  1. да
  2. размер видео 9.3МБ, хотя в будущем планируються видео и побольше. это всеголишь для теста

Случайно у вас максимально не 8 Mb в конфиге php.ini?

Макс размер стоит 32 Мb, размер запроса стоял 8 Mb. изменил тоже на 32 Mb. в итоге выдало ошибку:

array(1) { ["tmp_file"]=> array(5) { ["name"]=> string(15) "xmoovstream.flv" ["type"]=> string(24) "application/octet-stream" ["tmp_name"]=> string(34) "/home/site/data/mod-tmp/phpobKBUl" ["error"]=> int(0) ["size"]=> int(9840149) } }

Это не ошибка, это информация о загруженном файле. Вот ваш файл:

["tmp_name"]=> string(34) "/home/site/data/mod-tmp/phpobKBUl"

Но к сожалению, там нет такового файла :(
код exec.php:


<?php
    // Путь до залитого видео-файла, например временный файл полученный по $_FILES['tmp_file']
    $inputPath = $_FILES['tmp_file']['tmp_name'];
    var_dump($_FILES);
    //Путь до результирующего файла, то есть отконвертированный и прошитый мета-данными видео-файл
    $outputPath = dirname(__FILE__) . "/home/porka/data/www/porka.tv/play/filename.flv";

    // Массив для сбора ошибок
    $errorInfo = array();

passthru(
    '/usr/local/bin/ffmpeg -i ' . escapeshellarg($inputPath) .
        ' -f flv '.
        ' -s 320x240 '.
        ' -acodec libmp3lame '.
        ' -ar 44100 '.
        escapeshellarg($outputPath . '_temp'),
    $errorInfo['ffmpeg']
);

passthru(
    '/usr/local/bin/yamdi -i ' . escapeshellarg($outputPath . '_temp') . 
        ' -o ' . escapeshellarg($outputPath),
    $errorInfo['yamdi']);

/*
 * Удаление временного файла, он нам уже не нужен...
 */
unlink($outputPath . '_temp');
?>

мб что-то не так прописал...

Но к сожалению, там нет такового файла :(

В смысле его там нет? Думаете PHP вас обманывает?)
Я подозреваю, что вы его пытаетесь найти на сервере по адресу "/home/site/data/mod-tmp/phpobKBUl" и его там нет?) Конечно нет, он живет в рамках одного http-сессии, то есть вы загрузили, если не обработали, то он удаляется сразу же...

Сделайте перед passthru


echo '/usr/local/bin/ffmpeg -i ' . escapeshellarg($inputPath) .
        ' -f flv '.
        ' -s 320x240 '.
        ' -acodec libmp3lame '.
        ' -ar 44100 '.
        escapeshellarg($outputPath . '_temp');

и мне покажите

то что удаляется временный файл я знаю, но результатирующий файл не создаётся.

Вот что выдало:


array(1) { ["tmp_file"]=> array(5) { ["name"]=> string(15) "xmoovstream.flv" ["type"]=> string(24) "application/octet-stream" ["tmp_name"]=> string(34) "/home/site/data/mod-tmp/phpobKBUl" ["error"]=> int(0) ["size"]=> int(9840149) } } /usr/local/bin/ffmpeg -i '/home/site/data/mod-tmp/phpobKBUl' -f flv -s 320x240 -acodec libmp3lame -ar 44100 '/home/site/data/www/site.tv/play/filename.flv_temp'

создаётся файл с суфиксом _temp и как я понял тутже удаляется?

Плз, подскажите как можно прикрутить http_flv_module для httpd ?

Не пойму, сдесь есть кто нибудь? Подскажите на Апаче 2.2 возможно реализовать стриминг? в инете нашел только под lighthttpd и nginx.

Я не знаю как прикрутить к Apache, за других не ручаюсь.

Народ ну откликнитесь кто нибудь, кто на Апаче псевдостриминг делал или сталкивался, киньте инфу почитать, только из за этого сервер менять ой как не хочеться, кстати сдесь http://flowplayer.org/documentation/index.html пишут что можно сделать.

Гуглится впринципе просто :)
http://tperspective.blogspot.com/2009/02/apache-flv-streaming-done-right.html

День добрый.
А как насчёт ватермарка?
Можно убрать стандартный и поставить свой?
Очень надо.
Заранее спасибо.

отличная статья. мне как новичку в этом вопросе много информации. попытаюсь реализовать локально, с последующим применением на сайте.
спасибо автору за подробное описание.

yamdi -i filename.flv -o aaa.flv -w где ааа.флв несуществующий файл, перезапишит метаданные в исходном файле.
man yamdi

неполучаеться поставить расширения php_ffmpeg под windows.

запись из логов
PHP Warning: PHP Startup: ffmpeg: Unable to initialize module\nModule compiled with module API=20060613\nPHP compiled with module API=20090626\nThese options need to match\n in Unknown on line 0

кто знает помогите, буду признателен

И где тут сервер. Или "превьюшки" - это и есть файлы... Вместе с "имхо". Как только прочитаешь вашу статью так сразу "сервер" напишешь...

@Rostislav статье почти 8 лет, думаю в PHP мире уже все сильно поменялось. У вас есть конкретные вопросы?

Оставьте свой комментарий

Markdown