« Мультимедиа-программирование вместе с Red 5 server. Часть 8 | Мультимедиа-программирование вместе с Red 5 server. Часть 10 » |
Мультимедиа-программирование вместе с Red 5 server. Часть 9
Сегодняшняя статья в серии будет посвящена тому, как мультимедиа-сервер red5 умеет работать с видео-информацией, передавая ее как в направлении от клиента к серверу, так и в обратном направлении. В частности, мы попробуем создать небольшое веб-приложение с галерей видеоизображений, и список этих изображений будет не статическим. Т.е. посетители сайта, имеющие в своем распоряжении веб-камеру, смогут сами записать небольшой ролик и опубликовать его на нашем ресурсе. Впоследствии, заходящие на наш сайт посетители смогут выбрать в меню любой из этих видеороликов и просмотреть его.Все задачи работы с видео-потоками в flash и red5 сводятся, очевидно, к двум направлениям: как захватить изображение с веб-камеры и передать его на сервер, а также как можно загружать видео с сервера и показывать его на страничке сайта. Сегодня я сосредоточусь на описании второй задачи (показ видео), а работу с веб-камерой оставлю на следующую и последнюю статью в серии. Но перед тем как перейти к рассмотрению конкретных приемов позволяющих загрузить во flash-приложение видео-файл с red5-сервера, я хочу напомнить вам основные подходы, которые существуют для работы с видео во flash. Вкратце: есть три способа как можно в flash-приложении показать видеоролик. Первый способ предполагает, что видео-файл будет внедрен внутрь самого swf-файла. Грубо говоря, создатель flash-ролика, работая в среде adobe flash cs (хотя подобная функция доступна еще со времен flash mx), может выбрать команду меню “импортировать видео-файл на временную шкалу”. Как результат видео-файл будет разбит на отдельные кадры, и они будут оформлены как ключевые кадры стандартной временной шкалы flash-ролика. К преимуществам такого подхода относится возможность дальнейшей работы с получившейся временной шкалой. Так вы можете добавлять эффекты и анимацию на шкалу с помощью стандартных инструментов adobe flash cs. Однако, и недостатков такого подхода много: начиная с ограничений на максимальную продолжительность видеоролика и возможными проблемами с синхронизацией изображения и звука. Далее вы столкнетесь со сложностями замены видеороликов. Для этого вам придется открывать fla-файл в среде разработки adobe flash cs, удалять старый и повторно импортировать новый видео-файл и, конечно, вам нужно будет повторно запустить и функцию публикации fla-файл в swf-ролик. На все это тратится много времени, а значит неприемлемо для поставленной мною цели создать видео-галерею, видеоролики в которую будут динамически добавляться и удаляться.
Второй способ работы во flash с видео (этот способ называется progressive download) предполагает, что видеоролик хранится на сайте в виде обычного файла с расширением flv. И на этот файл есть ссылка из стандартного для flash компонента “FLVPlayback” (в случае flex, это компонент VideoDisplay). В любом случае, у этих компонентов есть атрибут “source”, значение которого как раз и равно пути к flv-файлу. Использование progressive загрузки файла предполагает, что flash-клиент последовательно загружает видео-файл от начала и до конца. А по мере того как сегменты, на которые разделен файл, становятся доступными клиенту, то он может просматривать содержимое ролика. После того, как все сегменты ролика были загружены и сохранены во временный файл, вы можете свободно перемещаться по временной шкале видеоролика и смотреть любой из моментов. Чтобы не ходить далеко, я здесь же покажу на flex пример небольшого видеопроигрывателя. Этот пример делается в рамках, все того же проекта java + flash, с которым мы работали все прошлые статьи и требует минимальных усилий. Во-первых, я создал в каталоге веб-модуля папку для хранения видео-файлов “static-video” и скопировал туда flv-файл “aliens.flv”. Теперь мне нужно отредактировать файл Main.mxml и создать в нем заготовку простенького интерфейса для видеоплеера:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:VBox>
<mx:HBox>
<mx:Button label="Play" click="video.play()"/>
<mx:Button label="Pause" click="video.pause()"/>
<mx:Button label="Stop" click="video.stop()"/>
</mx:HBox>
<mx:VideoDisplay source="static-video/aliens.flv"
autoPlay="false" id="video" width="320" height="240"/>
</mx:VBox>
</mx:Application>
а пока пару слов о том, что делается в этом примере. Структурно мое flex-приложение состоит из расположенных вертикально двух блоков: набор кнопок для управления видеопроигрывателем и сам проигрыватель (компонент VideoDisplay). Для этого компонента атрибут “source” должен указывать на путь к flv-файлу. Еще мне потребовалось указать имя (video) для компонента VideoDisplay для того, чтобы иметь возможность в последующем вызывать на видеопроигрывателе различные функции. Так я создал три кнопки “Play”, “Pause”, “Stop”, по нажатию на которые вызываются одноименные методы класса VideoDisplay. Таким образом, наш видеопроигрыватель научился запускать, приостанавливать и прерывать процесс показа видеоролика.
Теперь вернемся немного назад к перечислению возможных способов работы с видео во flash. Третий способ работы с видео называется streaming и является дальнейшим развитием progressive способа доставки видеоинформации. Но сейчас нам уже не достаточно любого http сервера для хранения, собственно, видео-файла – нам нужен специальный медиа-сервер (список таких серверов я приводил еще в самой первой статье серии). Рассматриваемый нами медиа-сервер red5 позволяет в рамках установленного соединения (NetConnection) открыть поток для передачи видео-информации (NetStream) и присоединить его к компоненту для просмотра видео-потока. Из очевидных плюсов streaming-а можно назвать возможность работы с динамически формируемым видео-потоком, например, изображение, постоянно поступающее с расположенной на улице веб-камеры. Также есть возможность динамически, на основании качества соединения с клиентом (пропускная ширина канала), определить то, какой видео-поток нужно отдать. Еще, мы можем, не дожидаясь загрузки всего файла, перейти к любому моменту на временной шкалы. При этом с сервера будет загружена лишь нужная нам часть видеоролика. Также не забывайте, что поставка видео (NetStream) является теперь частью всего приложения, т.е. таким же ресурсом как и SharedObject. А значит, что в рамках одного приложения мы можем выполнять вызов методов расположенных на сервере, обмениваться информацией между несколькими подключенными к SharedObject клиентами, а также загружать и показывать видеоинформацию. Построить несложное видео-приложение во flex можно с помощью всего трех классов: NetConnection – для установления соединения с сервером, NetStream – для загрузки видео-потока и Video – графический компонент, умеющий присоединяться к NetStream и показывать приходящее по каналу изображение.
Для следующего примера (работа со streaming) мне потребуется переименовать созданный ранее каталог с видео-файлом: так ранее он назывался “static-video/aliens.flv”, а теперь должен называться “streams/alien.flv”. Все дело в том, что в случае работы с progressive download нет никаких ограничений на имя каталога с flv-файлом. То в случае с streaming red5-сервер делает предположение, что все видео-ролики должны находиться именно внутри подкаталога “/streams”. Впоследствии я покажу то, как это правило можно изменить, но сейчас лучше сосредоточимся на создании скелета видеопроигрывателя. К слову, приятной функцией red5 является механизм автоматической блокировки тех видео-файлов, что сейчас просматриваются каким-то из клиентов (т.е. например, их нельзя удалить из файловой системы пока клиенты не отсоединятся от файла). Далее я привожу mxml-код примера:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
creationComplete="completeCreation()">
<mx:Script><![CDATA[
import flash.events.MouseEvent;
private var nc:NetConnection;
private var ns:NetStream;
private var v:Video;
public function completeCreation():void {
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.connect('rtmp://localhost/warmodule/');
}
private function netStatus(event:NetStatusEvent):void {
if (event.info.code == 'NetConnection.Connect.Success') {
v = new Video();
placeholder.addChild(v);
ns = new NetStream(nc);
v.attachNetStream(ns);
ns.client = this;
ns.play(“aliens.flv");
}
}
public function onMetaData(info:Object):void {
trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height +
" framerate=" + info.framerate);
}
public function onCuePoint(info:Object):void {
trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
]]></mx:Script>
<mx:UIComponent id="placeholder" width="320" height="240"/>
</mx:Application>
//подгоняем размер компонентов Video и UIComponent под разрешение видео-потока
v.width = info.width;
v.height = info.height;
placeholder.width = info.width;
placeholder.height = info.height;
Приятно, что перечень cue points можно сохранять и в последующем загружать из специального xml-файла. Назначенный вами набор cue points будет внедрен внутрь flv-файла в ходе его конвертации. Затем по мере того как видео-файл будет проигрываться, то NetStream как только встретит cue point вызовет определенный вами метод onCuePoint и передаст туда сведения о встреченной cue point.
По правде сказать, созданная мною заготовка видеопроигрывателя не имеет необходимых для ее практического использования компонентов: кнопок перемотки, возможности управлять громкостью звука, временной шкалы, на которой показывается и общее время просмотра видеоролика, и объем уже загруженных (буферизованных данных). Сразу скажу, что если перед вами стоит задача быстро внедрить на сайт видеопроигрыватель с перечисленным выше функционалом, то не стоит изобретать велосипеда: в internet можно найти множество как бесплатных, так и платных видеопроигрывателей. Если же вы твердо решили делать видеопроигрыватель “с нуля”, то гораздо удобнее использовать для этого не класс Video, класс VideoDisplay: я уже упоминал о нем, когда показывал пример с progressive download. Однако VideoDisplay умеет работать и с streaming (т.к. внутри VideoDisplay прозрачно работают и NetConnection и NetStream и Video). Итак, я создаю mxml-компонент VideoDisplay:
<mx:VideoDisplay id="videoDisplay" width="320" height="240"/>
videoDisplay.source = "rtmp://localhost/warmodule/buran.flv";
public class StreamsLocator implements org.red5.server.api.stream.IStreamFilenameGenerator {
public String generateFilename(IScope scope, String name, GenerationType type) {
return generateFilename(scope, name, null, type);
}
public String generateFilename(IScope scope, String name, String extension, GenerationType type) {
String result = "c:/video/" + name;
if (extension != null && !extension.equals(""))
result += extension;
return result;
}
public boolean resolvesToAbsolutePath() {
return true;
}
}
<bean id="streamFilenameGenerator" class="blz.red5demo.StreamsLocator" />
« Мультимедиа-программирование вместе с Red 5 server. Часть 8 | Мультимедиа-программирование вместе с Red 5 server. Часть 10 » |