Скрипт действий 2. Ключевые точки событий: findNearestCuePoint

Привет всем и каждому!

Хорошо... Я буквально несколько недель бился головой об эту проблему, но до сих пор не могу найти ответ, который успешно решил проблему.

Я создал FLA-файл и поместил на сцену компонент FLV с именем экземпляра videoPlay.

videoPlay направляется к потоковому FLV со встроенными контрольными точками событий. Ключевые точки нумеруются последовательно от повествования1 до повествования16.

Я установил объект слушателя:

     var videoPlayCuePointListener:Object = new Object();

Слушатель событий для контрольных точек:

   videoPlayCuePointListener.cuePoint = function(eventObject:Object):Void{
   if(eventObject.info.name == "narration1"){_root.cc_box.cc_txt.htmlText = cueTxt1);}
   else if(eventObject.info.name == "narration2"){_root.cc_box.cc_txt.htmlText = cueTxt2);}
   etc, through narration16 }

и так далее по ходу повествования16.

Затем я прикрепил прослушиватель событий к FLV-компоненту на сцене:

   videoPlay.addEventListener("cuePoint", videoPlayCuePointListener);

Все это работает очень хорошо. Во время воспроизведения FLV каждая ключевая точка события запускает правильный текст в динамическом текстовом поле cc_txt.

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

Я изучил это так тщательно, как только мог, прежде чем, наконец, решил опубликовать проблему, но, хотя документация и различные публикации, касающиеся findNearestCuePoint, обнаруженные в Интернете, предоставили множество примеров, ни один из них не был успешным.

Я попытался добавить прослушиватель в videoPlay, который создает объект (nearestCue) и присваивает ближайшегоCue значение videoPlay.findNearestCuePoint(videoPlay.playheadTime), а затем считывает имя, метку и т. д. ближайшегоCue.

Ничто из предложенного в сообщениях, которые я просмотрел (много, много сообщений), не дало ответа.

Кажется, что это было бы проще всего сделать, но я ни разу не добился успеха.

Любые предложения или помощь будут высоко оценены.

Спасибо за уделенное время!


person Rod    schedule 10.08.2011    source источник


Ответы (2)


Давно не трогал AS2. Я сделал базовый тест, и findNearestCuePoint сработал. Вы используете компонент FLVPlayback, верно? Вот что я пробовал:

videoPlayer.autoPlay = false;
onEnterFrame = function():Void{
    videoPlayer.seekPercent(_xmouse/Stage.width * 100);
    videoPlayer.play();
    trace(videoPlayer.findNearestCuePoint(videoPlayer.playheadTime).name);
}

Рекомендуемый способ — найти ближайшую ключевую точку в playheadUpdate обработчик, который срабатывает после того, как указатель воспроизведения изменяет свое значение. (например, 1. сказать, чтобы указатель воспроизведения переместился, 2. указатель воспроизведения фактически изменяет значение, 3. вызывается playheadUpdate)

Вот более простой подход:

onEnterFrame = function():Void{
    if(videoPlayer.metadata) trace(videoPlayer.findNearestCuePoint(_xmouse/Stage.width * videoPlayer.metadata.duration).name);
}

В моем тесте я добавил 4 ключевые точки. Пробовал их все: actionscript/event/navigation. Странно было то, что когда я пытался получить доступ к свойству cuePoints через videoPlayer или через videoPlayer.metadata, я получил массив из 8 неопределенных объектов, и длина массива была 4, когда я его трассировал. Не знаю, в чем проблема, возможно, кодировка/кодек и совместимость с as2, не уверен.

В любом случае... пока у вас есть массив cuePoints, вы можете вручную найти ближайший, перебирая их все и получая наименьшую абсолютную разницу между временем каждой ключевой точки и текущим временем:

function getClosestCuePoint(cuePoints:Array,time:Number):Object{
    var numCuePoints:Number = cuePoints.length;
    var minDist:Number = 100000000,result:Object;
    for(var i:Number = 0 ; i < numCuePoints ; i++){
        if(Math.abs(cuePoints[i].time - time) < minDist){
            minDist = Math.abs(cuePoints[i].time - time);
            result = cuePoints[i];
        }
    }
    return result;
}

Вот пример макета: давайте представим, что некоторые поля на экране являются контрольными точками, а позиция _xmouse будет временем воспроизведения. Попробуйте это в новом документе:

//fake cue points
var numCuePoints:Number = 5;
var cuePoints = [];
for(var i:Number = 0 ; i < numCuePoints ; i++) cuePoints[i] = {name:'narration ' + (i+1),time: 10 + (80 + Math.random() * 20) * i}
//visual hint - separated from the cue points
for(var i:Number = 0 ; i < numCuePoints ; i++) drawBox(this,0x009900,10,15,cuePoints[i].time,Stage.width * .5);
var playhead:TextField = drawText(this,'playhead');

//playhead update
onEnterFrame = function():Void{
    playhead._x = _xmouse;
    playhead.setTextFormat(new TextFormat('Verdana',11));
    playhead.text = 'time: ' + _xmouse+' / cue ' + getClosestCuePoint(cuePoints,_xmouse).name;
}
//find the shortest marker within the shortest distance from the current value
function getClosestCuePoint(cuePoints:Array,time:Number):Object{
    var numCuePoints:Number = cuePoints.length;
    var minDist:Number = 100000000,result:Object;
    for(var i:Number = 0 ; i < numCuePoints ; i++){
        if(Math.abs(cuePoints[i].time - time) < minDist){
            minDist = Math.abs(cuePoints[i].time - time);
            result = cuePoints[i];
        }
    }
    return result;
}
//utils
function drawBox(target:MovieClip,color:Number,width:Number,height:Number,x:Number,y:Number):Void{
    target.lineStyle(3,color);
    target.moveTo(x,y);
    target.lineTo(x+width,y);
    target.lineTo(x+width,y+height);
    target.lineTo(x,y+height);
    target.lineTo(x,y);
}
function drawText(target:MovieClip,name:String):TextField{
    var result:TextField = target.createTextField(name,target.getNextHighestDepth(),0,Stage.width * .5-20,100,20);
    result.autoSize = 'left';
    result.border = true;
    result.selectable = false;
    return result;
}

ХТН

person George Profenza    schedule 11.08.2011
comment
Большое спасибо за ваш ответ... Я очень ценю это. К сожалению, ни один код, который вы разместили здесь, не привел к отслеживанию существующих контрольных точек. Кроме того, часть _xmouse первых двух функций onEnterFrame просто заставляет видео подпрыгивать вперед и назад. Я попытался использовать прослушиватель событий playheadUpdate, и, хотя он эффективно сообщал, все результаты были нулевыми или неопределенными. Все еще не уверен, что я делаю неправильно, потому что все примеры, которые я использовал до сих пор, должны работать. - person Rod; 15.08.2011
comment
Мне жаль слышать, что код не работает для вас. Я загружу/опубликую свои тестовые файлы позже сегодня (которые действительно работают), может быть, они могут быть полезны. Вы на 100% уверены, что ваши ключевые точки закодированы и доступны из actionscript? Что будет напечатано на панели вывода, если вы проследите массив контрольных точек? - person George Profenza; 15.08.2011
comment
@Rob Я загрузил тестовый файл здесь. Проверьте, работает ли это для вас. Не могли бы вы загрузить очень простую версию вашей установки для проверки? Не уверен, что что-то в as2 не работает или как кодируется видео - person George Profenza; 16.08.2011

Джордж,

Я считаю, что обнаружил проблему, и я думаю, что это было то, что вы описали в своем предыдущем посте, но я случайно не упомянул об этом.

В F4V, с которым я работал, ключевые точки были встроены с помощью Adobe Media Encoder... и в этом была вся проблема.

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

Престо, как ни удивительно, у меня не было проблем с поиском ключевых точек, их отслеживанием и использованием для любых целей.

Так что в будущем мне просто нужно не забыть настроить ключевые точки в диалоговом окне «Свойства» и установить для них сценарий действия, и я должен быть золотым. До сих пор он безупречно работал со всеми файлами F4V с момента внесения изменений.

Большое спасибо за подробный ответ и за продолжение!

person Rod Schmidt    schedule 18.08.2011