Задачу быстро сделать проигрыватель видео (управление видео-презентацией) я оценил в пару часов. Т.к. совсем недавно разобрался с
воспроизведением высококачественного видео, с тех-частью проблем не должно было возникнуть. Проект начал делать на Flex, дабы лишний раз попрактиковаться.
Воспроизводить видео действительно получилось быстро. Класс
VideoDisplay, управляемый несколькими кнопками и слайдером.
И тут встали более сложные задачи.
- Необходимо в определенные моменты времени останавливать видео (презентация).
- Небходима навигация по этим стоп-точкам.
Первая задача создала одну основную проблему:
Получить видео-файл, содержащий сигнальные-точки (cue points).Видео мы выгоняли из AfterEffects в MOV кодеком H.264. Можно ли туда загнать сигнальные-точки (которые, собственно были расставлены в тайм-лайне) и как это сделать - не смогли выяснить.
Решили экспортировать в FLV (задрав качество до порядка 3000) - расставить сигнальные точки пришлось вручную в "Adobe Flash CS3 Video Encoder". В принципе, была идея выгнать видео в MOV (высокое качество) и FLV (минимального качества), использовать сигнальные точки FLV а воспроизводить MOV.
Для получения сигнальных точек использую следующий код:
private function onMeta(event:MetadataEvent):void {
this.slider.maximum=event.info.duration;
this.__cue_points=event.info.cuePoints;
}
. . .
<mx:VideoDisplay metadataReceived="this.onMeta(event)" . . . >
. . .
Таким образом, по событию
metadataReceived - когда Flex получает метаданные видео-файла - мы получаем массив сигнальных точек.
Внимание - свойство
cuePoints класса
VideoDisplay не будет содержать сигнальные точки, которые находятся в метаданных видео-файла. Это свойство нужно для "ручной" установки сигнальных точек. Управление (добавление/удаление) сигнальными точками
cuePoints осуществляется менеджером сигнальных точек
cuePointManager. Можно задать их прямо во Flex:
<mx:VideoDisplay . . . >
<mx:cuePointManagerClass>mx.controls.videoClasses.CuePointManager</mx:cuePointManagerClass>
<mx:cuePoints>
<mx:Array>
<mx:Object time="0" name="point1"/>
<mx:Object time="3.034" name="point2"/>
<mx:Object time="4.774" name="point3"/>
<mx:Object time="8.344" name="point4"/>
<mx:Object time="12.271" name="point5"/>
</mx:Array>
</mx:cuePoints>
</mx:VideoDisplay>
Итак, мы можем контролировать сигнальные точки. Переходим к обработке пауз на этих точках. Событие cuePoint отлично справляется с нашей задачей:
private function onCue(event:CuePointEvent):void {
this.video_display.pause();
}
<mx:VideoDisplay id="video_display" cuePoint="this.onCue(event)" . . . >
При обработке события сигнальной точки, воспроизведение видео останавливается четко в том месте, которое задает сигнальная точка. Это превосходно.
Задача номер два. А теперь начинается самое нехорошее. Мы имеем массив точек (каждый элемент содержит объект с двумя свойствами: name - имя маркера, time - время в секундах), и можем позиционировать воспроизведение видео по его элементам. Казалось бы, чего проще:
private function onClickNext(event:FlexEvent):void {
this.video_display.playheadTime=cue_points[position].time;
}
Ан нет. Видео позиционируется не точно в указанную позицию - то перескочет на пару секунд, то недотянет. Причем точность настолько низка, что нам пришлось отказаться от такого способа позиционирования.
По этому поводу, в документации Flex к свойству
playheadTime сказано, что для FLV-файла позиционирование происходит в ключевой фрейм, ближайший к указанной позиции, причем эти ключевые фреймы формируются во время кодирования видео. Поэтому, извиняйте, но точно спозиционироваться в указанное место не получится, если там по близости нет ключевого фрейма. Попробовал позиционировать по тем же контрольным точкам MOV файл. Та же петрушка.
Эксперименты показали, что если видео экспортировать в SWF и позиционироваться по фреймам тайм-лайна, точность позиционирования абсолютна.
Раз нельзя реализовать нормальную навигацию по подгружаемому MOV/FLV видео, то дальнейшая разработка этого проекта на Flex потеряла всякий смысл.
Проще было импортировать видео в SWF, загнать его в мой старый, проверенный презентационный AS2 движок и обработать массив фреймов (составленный вручную за 15 минут), что и было сделано примерно за час.
Отрицательный результат - тоже результат. Потратив день на разборки, я узнал мгного нового и получил хороший опыт Flex-разработки.