actionscript-3videomp4durationnetstream

Why is NetStream metadata reading wrong video duration?


I am trying to play and control a video, and one of key elements I need to control it is it's duration. I wrote a function that plays, pauses, resumes and stops videos, but, if I use slider to seek video near the end, I get an error saying that time is wrong.

I tried to trace time and to subtract 0.5 and 1 second. In that case, video is 2-5 seconds longer than expected?! Wierd.

myVideoData = new Video();
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.client = {};
ns.client.onMetaData = ns_onMetaData;
ns.client.onCuePoint = ns_onCuePoint;
myVideoData.attachNetStream(ns);
ns.play(menu.videolist.selectedItem.data); //Video is loading and playing just fine

function ns_onMetaData(item: Object): void {
    myVideoDataW = item.width;
    myVideoDataH = item.height;
    myVideoDuration = item.duration;
    //Below this line is added for testing.
    ns.seek(item.duration); //It fails as Error #2044: Unhandled NetStatusEvent:. level=error, code=NetStream.Seek.InvalidTime
    //Tried to ns.seek(item.duration-1); and it works, except it seeks video not 1, but 2-5 seconds, depending on video length
    //I have same issue for every video, and I have tried like... 50-ish...
}

I just want to know is it about the code, about me...? Is it possible that all 50 videos I have tried have same problem? Sources of my videos are from my phone, from youtube, from professional web stores. All files are mp4!


Solution

  • (1)

    "...If I use slider to seek video near the end, I get an error saying that time is wrong."

    Make sure myVideoDurationis known or set to = 0; as starting point. For example: Since your ns_onMetaData function updates the duration, there you could also enable seeking with a:

    mc_Seekbar.addEventListener(MouseEvent.CLICK, on_click_SeekBar );
    

    Then you could use this logic to seek:

    function on_click_SeekBar (evt:Event = null) :void
    {
        var myTime:int = (myVideoDuration / mc_Seekbar.width ) *  mc_Seekbar.mouseX;
        trace(">>> Seeking to : " + myTime + " seconds");
        ns.seek( myTime );
    }
    

    (2)

    "Why is NetStream metadata reading wrong video duration?

    ns.seek(item.duration);

    It fails as Error #2044: Unhandled NetStatusEvent:. level=error, code=NetStream.Seek.InvalidTime"

    That's because .duration is a Number data-type but .seek actually expects an int value.

    The difference is... Number = 16.005; vs int = 16;. Number includes a decimal point. NetStream's .seek expects a whole numerals without fractions (basically: Just use integers, no decimal points).

    Solution:
    Simply cast the .duration into an int data type.

    ns.seek( int(item.duration) );
    

    Here's a testable example based on your code. Give it a file called video.mp4 at same location as compiled.

    var myVideoData :Video = new Video();
    var nc = new NetConnection(); nc.connect(null);
    var ns :NetStream = new NetStream(nc);
    ns.client = {};
    ns.client.onMetaData = ns_onMetaData;
    //ns.client.onCuePoint = ns_onCuePoint;
    myVideoData.attachNetStream(ns);
    
    var myVideoDuration:int, myVideoDataW:int, myVideoDataH:int = 0;
    
    addChild(myVideoData);
    //ns.play(menu.videolist.selectedItem.data); //Video is loading and playing just fine
    ns.play("video.mp4");
    
    function ns_onMetaData(item: Object) :void 
    {
        myVideoDataW = item.width;
        myVideoDataH = item.height;
        myVideoDuration = item.duration; //update Int with duration
        
        //# Below this line is added for testing.
        ns.seek( int(item.duration) ); //option A: cast the Number to Int
        //ns.seek( myVideoDuration ); //option B: use an Int value
        trace("duration ( item.duration ) : " + ( item.duration) + " seconds.");
        trace("duration (myVideoDuration) : " + ( myVideoDuration) + " seconds.");
        
    }