我有一个flvplayback组件,正在将视频加载到该组件上。

为了模仿下一帧和上一帧的动作,我在加载的每一秒的长度中添加提示点。

下一帧/上一帧功能在视频上实现seekToNextNavCuePoint和seekToPrevNavCuePoint

但是它没有按我预期的那样工作。

这是实际的类文件。您可以使用一个fla文件直接编译该文件,该文件包含库中的按钮实例,用于播放暂停停止...。此外,您还需要一些示例flv文件。

package
{
    /*
    The fla file contains  buttons in the library;
    */
    import flash.events.*;
    import flash.display.*;
    import fl.video.*;
    public class testPlayer extends MovieClip
    {
        private var video1:FLVPlayback;

        private var play_btn:PlayButton;
        private var pause_btn:PauseButton;
        private var stop_btn:StopButton;
        private var nextFrame_btn:ForwardButton;
        private var previousFrame_btn:ForwardButton;

        public function testPlayer()
        {
            // constructor code
            addEventListener(Event.ADDED_TO_STAGE,onAdded);
        }
        private function onAdded(event:Event)
        {
            setPlayer();
            setPath();
            setButtons();

        }
        private function setPlayer()
        {
            video1 = new FLVPlayback  ;
            this.addChild(video1);
            video1.x = 50;
            video1.y = 50;
        }
        private function setPath()
        {
            video1.addEventListener(VideoEvent.READY, flvPlayback_ready);
            video1.addEventListener(MetadataEvent.CUE_POINT, flvPlayback_cuePoint);
                        // here you can give any flv you have and its total time
            video1.load("test.flv",3600,false);
        }
        private function flvPlayback_ready(evt:VideoEvent):void
        {
            var num:Number = video1.totalTime;
            for (var i:int=0; i<num; i++)
            {
                video1.addASCuePoint(i, "cuePoint"+String(i));
            }
            this.removeEventListener(VideoEvent.READY, flvPlayback_ready);
        }

        private function flvPlayback_cuePoint(evt:MetadataEvent):void
        {
            trace("CUE POINT!!!");
            trace("\t", "name:", evt.info.name);// name: cuePoint1
            trace("\t", "time:", evt.info.time);// time: 1
            trace("\t", "type:", evt.info.type);// type: actionscript
        }
        private function setButtons()
        {
            play_btn=new PlayButton();
            pause_btn=new PauseButton();
            stop_btn=new StopButton();
            nextFrame_btn=new ForwardButton();
            previousFrame_btn=new ForwardButton();
            play_btn.addEventListener(MouseEvent.CLICK,onPlay);
            pause_btn.addEventListener(MouseEvent.CLICK,onPause);
            stop_btn.addEventListener(MouseEvent.CLICK,onStop);
            nextFrame_btn.addEventListener(MouseEvent.CLICK,onNextFrame);
            previousFrame_btn.addEventListener(MouseEvent.CLICK,onPreviousFrame);

            play_btn.x = 50;
            play_btn.y = 350;
            previousFrame_btn.x = 125;
            previousFrame_btn.y = 350;
            previousFrame_btn.scaleX *=  -1;
            nextFrame_btn.x = 150;
            nextFrame_btn.y = 350;
            pause_btn.x = 200;
            pause_btn.y = 350;
            stop_btn.x = 250;
            stop_btn.y = 350;
            addChild(play_btn);
            addChild(pause_btn);
            addChild(stop_btn);
            addChild(previousFrame_btn);
            addChild(nextFrame_btn);

        }
        private function onPlay(event:MouseEvent)
        {
            video1.play();
        }
        private function onPause(event:MouseEvent)
        {
            video1.pause();
        }
        private function onStop(event:MouseEvent)
        {
            video1.stop();
        }
        private function onNextFrame(event:Event)
        {
            if (video1.playing)
            {
                //video1.pause();
            }
            // this is not working the way i expected it to
            video1.seekToNextNavCuePoint();

        }
        private function onPreviousFrame(event:Event)
        {
            if (video1.playing)
            {
                //video1.pause();
            }
            // this is not working the way i expected it to
            video1.seekToPrevNavCuePoint();
        }
    }

}


我在这里想念什么?仅运行它而不调用下一个/上一个帧功能,则表明提示点按照flvPlayback_cuePoint函数每秒被激活。



update:


当我单击previousFrame按钮时,帧将移动到cuepoint1,而不管当前提示点在哪里。当我单击nextFrame按钮时,提示点和显示似乎更改为next,但是单击几次后不久,提示点将更改为1,并且视频从头开始。


问题1:使用addASCuePoint()沿着加载的影片的长度在ActionScript 3.0中动态添加提示点的正确方法是什么?
问题2:我们可以以33毫秒的间隔添加提示点吗?
可以适当寻求吗?
问题3:以上代码有什么问题?

更新:
增加赏金:解决问题和回答3个问题



更新:




经过上述方法的大量失败尝试,并尝试了Trevor的建议。
我通过seek()方法获得了该功能,但是相当缺乏精度。

package
{
    /*
    The fla file contains  buttons in the library;
    */
    import flash.events.*;
    import flash.display.*;
    import fl.video.*;
    public class testPlayer extends MovieClip
    {
        private var video1:FLVPlayback;
        private var play_btn:PlayButton;
        private var pause_btn:PauseButton;
        private var stop_btn:StopButton;
        private var nextFrame_btn:ForwardButton;
        private var previousFrame_btn:ForwardButton;
        private var playHeadTime:Number;
        private var cue:Object;

        public function testPlayer()
        {
            addEventListener(Event.ADDED_TO_STAGE,onAdded);
        }
        private function onAdded(event:Event)
        {
            setPlayer();
            setPath();
            setButtons();
            playHeadTime = 0;
        }
        private function setPlayer()
        {
            video1 = new FLVPlayback  ;
            this.addChild(video1);
            video1.x = 50;
            video1.y = 50;
        }
        private function setPath()
        {
            video1.playheadUpdateInterval = 50;
            video1.seekToPrevOffset = 0.01;
            video1.addEventListener(VideoEvent.READY, flvPlayback_ready);
            video1.addEventListener(MetadataEvent.CUE_POINT, flvPlayback_cuePoint);
            video1.load("test.flv",3600,false);
        }
        private function flvPlayback_ready(evt:VideoEvent):void
        {
            // changing this loop to add more cue points causes the program to hang.
            for (var i:int=0; i<video1.totalTime; i++)
            {
                cue= new Object();
                cue.time = i;
                cue.type = "navigation";// this does not seem to get set the type
                cue.name = "cuePoint" + String(i);
                video1.addASCuePoint(cue,cue.name);
            }
            video1.removeEventListener(VideoEvent.READY, flvPlayback_ready);
        }

        private function flvPlayback_cuePoint(evt:MetadataEvent):void
        {
            trace("CUE POINT!!!");
            trace("\t", "name:", evt.info.name);// name: cuePoint1
            trace("\t", "time:", evt.info.time ," playhead time :",String(Math.round(video1.playheadTime)));// time: 1
            trace("\t", "====type:", evt.info.type);// traces actionscript instead of navigation
        }
        private function setButtons()
        {
            play_btn=new PlayButton();
            pause_btn=new PauseButton();
            stop_btn=new StopButton();
            nextFrame_btn=new ForwardButton();
            previousFrame_btn=new ForwardButton();
            play_btn.addEventListener(MouseEvent.CLICK,onPlay);
            pause_btn.addEventListener(MouseEvent.CLICK,onPause);
            stop_btn.addEventListener(MouseEvent.CLICK,onStop);
            nextFrame_btn.addEventListener(MouseEvent.CLICK,onNextFrame);
            previousFrame_btn.addEventListener(MouseEvent.CLICK,onPreviousFrame);

            play_btn.x = 50;
            play_btn.y = 350;
            previousFrame_btn.x = 125;
            previousFrame_btn.y = 350;
            previousFrame_btn.scaleX *=  -1;
            nextFrame_btn.x = 150;
            nextFrame_btn.y = 350;
            pause_btn.x = 200;
            pause_btn.y = 350;
            stop_btn.x = 250;
            stop_btn.y = 350;
            addChild(play_btn);
            addChild(pause_btn);
            addChild(stop_btn);
            addChild(previousFrame_btn);
            addChild(nextFrame_btn);

        }
        private function onPlay(event:MouseEvent)
        {
            video1.play();
        }
        private function onPause(event:MouseEvent)
        {
            video1.pause();
        }
        private function onStop(event:MouseEvent)
        {
            video1.stop();
        }
        private function onNextFrame(event:Event)
        {
            if (video1.playing)
            {
                video1.stop();
            }
            trace("Calling nextFrame :::",playHeadTime);
            video1.seek(playHeadTime);
            playHeadTime +=  1;
        }
        private function onPreviousFrame(event:Event)
        {
            if (video1.playing)
            {
                video1.stop();
            }
            trace("Calling prevFrame ::::",playHeadTime);
            video1.seek(playHeadTime);
            playHeadTime -=  1;
        }
    }
}


以下内容的输出如下所示。问题是下一个和上一个功能会不断跳过提示点,并且在某些提示点似乎不起作用。下面的迹线应该给出清晰的图片。

Calling nextFrame ::: 0
CUE POINT!!!
     name: cuePoint0
     time: 0  playhead time : 0
     ====type: actionscript
Calling nextFrame ::: 1
CUE POINT!!!
     name: cuePoint2
     time: 2  playhead time : 2
     ====type: actionscript
Calling nextFrame ::: 2
Calling nextFrame ::: 3
CUE POINT!!!
     name: cuePoint4
     time: 4  playhead time : 4
     ====type: actionscript
Calling prevFrame :::: 4
Calling prevFrame :::: 3
Calling prevFrame :::: 2
CUE POINT!!!
     name: cuePoint2
     time: 2  playhead time : 2
     ====type: actionscript


编辑:



问题1:如何在连续的提示点上触发MetadataEvent.CUE_POINT,即不跳过提示点。
问题2:当每个提示点间隔100毫秒时,我们如何在每个提示点触发MetadataEvent.CUE_POINT事件。

最佳答案

第三组问题

*如何在连续的提示点上触发MetadataEvent.CUE_POINT,即不跳过提示点。

*当每个提示点以100 ms的间隔说话时,出租车如何在每个提示点触发MetadataEvent.CUE_POINT事件。

这似乎很奇怪,但是您不能保证会收到特定的提示点事件。提示点事件不会编组或排队。由于FLV容器和swf之间的帧频不同,因此某些事件只会被抛出。如果包含的swf文件位于“帧之间”,则几乎可以肯定会错过flv上的提示点。如果提示点相隔100毫秒,并且您对swf使用标准的24fps。我估计您可以期望每5个提示点事件中至少释放1个。这类似于Flash处理许多事情的方式(如垃圾回收),它会尽力而为,但是如果需要继续运行“框架”,它将停止执行底层进程。即使您同步了帧频和提示点间隔,您仍然偶尔会错过事件。

现在...所有这些。您可以不使用提示点来完成所需的操作。只需监视playheadUpdate事件并随着播放头时间的增加而调度您需要的许多事件。例如...如果您希望事件每100毫秒一次,并且播放头自上次以来已移动223毫秒,则调度2个事件。如果仅移动30毫秒,则不调度任何事件。

第二组问题

问题1:为什么搜索跳过提示点而不在每次通话时都起作用

您将只能在视频中寻找关键帧。您可以在任意位置定义提示点,但是搜索始终会搜索到下一个最近的关键帧。这就是为什么您看到自己所看到的行为的原因。

excerpt from FLVPlayback.seek() on livedocs


...对于渐进式下载,您只能搜索关键帧,因此,寻道会将您带到指定时间后的第一个关键帧的时间...寻道是异步的,...要获得寻道之后的时间,完成后,收听seek事件...




问题2:如何使它在工厂的第二提示点工作

没有人喜欢听这个,但是除非您能够修改flv并在这些位置插入关键帧,否则您可能无法做到这一点。但是我猜想,如果您可以执行此操作,则无需动态添加提示点。



问题3:如何在不破坏程序的情况下在毫秒范围内动态添加提示点。

因此,这是我分歧点所在的地方,建议您完全不要使用提示点。看来您正在尝试在播放flv时尝试在给定间隔触发事件和/或尝试在flv中寻找给定位置。

在flv中寻找任何位置都不需要提示点。只需将时间(以毫秒为单位)传递给seek命令。 (通过上述警告,您将只能寻找关键帧。)

有一种更简单的方法可以从flvplayback间隔获取事件,该间隔要设置playheadUpdateInterval并将侦听器添加到playheadUpdate事件。此事件包括派发之时的播放时间。

在您的情况下,只需将间隔设置为33 ms,然后在与事件关联的侦听器中执行您想做的任何事情即可。

所有这些要记住的一件事是,FLV回放是在单独的“时间轴”上发生的,其帧速率与swf文件不同。由于两者之间的时间间隔几乎永远都不是精确的。



第一组问题

问题1:使用addASCuePoint()沿着加载的影片的长度在ActionScript 3.0中动态添加提示点的正确方法是什么?

纠正上面的for循环看起来不错



问题2:我们能否以33毫秒的间隔添加提示点,我们可以适当地寻找提示点?
是的,您可以在任意间隔或位置添加提示点,但这与关键帧的位置无关。



问题3:以上代码有什么问题?
坦白说,这是对提示点的滥用。它们确实不是您想要的。

10-06 00:04