开发者

Progressive Streaming flv video files, using php and Flex

Progressive Streaming problem:

I have been trying to use the example from xmoov.com to fetch only a part of video, as explained in the blog: http://polygeek.com/1423_flex_video-streaming-php-xmoov

The code works fine for the video link they have, but when i change the link to a video file on my server, I get null object error for onMetaData( e:MetadataEvent ) function on the line "Alert.show(e.info.keyframes.filepositions.toString());"

Also on onSeek( e:SliderEvent ) on line "while( _keyFrame_timePositions[i] < seekTo ) { i++ }"

My php code:

protected function serve_media_test($key, $position = '') {

if(empty($position)) $position = 0; $seekPos = intval($position); $key = addslashes($key); $media = new C7_Media(); $row = $media->fetchRow("hash = '$key' AND '".$_SERVER['SERVER_NAME']."' LIKE CONCAT('%', server_domain, '%')"); 开发者_运维百科 if(empty($row)) throw new C7_Exception('File not found for given key OR file not on this server'); $row->views = $row->views + 1; //increment views for this media file $row->save();

//Send the file $local_file = C7_Bootstrap::getConfig()->user->media->store.'/'.$row->location; // local file that should be send to the client $download_file = stripslashes($row->original_name); // filename that the user gets as default $download_rate = C7_Bootstrap::getConfig()->user->storage->downloadrate->kbps; // set the download rate limit (kb/s) if(file_exists($local_file) && is_file($local_file)) {

        //$fh = fopen($local_file, 'rb') or die ('<b>ERROR:</b> xmoov-php could not open (' . $download_file . ')');

        $fileSize = filesize($local_file) - (($seekPos > 0) ? $seekPos  + 1 : 0);

        // send headers
        header('Pragma: private');
        header('Expires: '.date('D, d M Y H:i:s \G\M\T', time() + 7200));
        header('Cache-control: private, max-age=7200, must-revalidate');        //longer age set for media file
        header('Content-Length: '.filesize($local_file));
        header('Content-Disposition: filename='.md5($local_file));
        header('Content-Type: video/x-flv');
        /*$scratch = explode('.', $local_file); //determine file type by extension
        $file_extension =  $scratch[count($scratch)-1];
        switch($file_extension)
        {
            case 'flv': header('Content-Type: video/x-flv');
                        break;
            case 'mp4': header('Content-Type: video/mp4');
                        break;
            default:    header('application/octet-stream');
                        break;
        }*/
        flush();                    // flush content
        //$file = fopen($local_file, "r");              
        $file = fopen($local_file, 'rb');           // open file stream
        # FLV file format header
        if($seekPos != 0) 
        {
            print('FLV');
            print(pack('C', 1));
            print(pack('C', 1));
            print(pack('N', 9));
            print(pack('N', 9));
        }
        //Seeks on a file pointer           
        fseek($file, $seekPos);

        while(!feof($file)) 
        {               
            print fread($file, round($download_rate * 1024));   // send the current file part to the browser    
            ob_flush();     //flush php buffer          
            flush();        // flush apache buffer              
            //sleep(1);     // sleep one second
        }
        fclose($file);      // close file stream
    }               
    else 
        throw new C7_Exception("File= $local_file, could not be downloaded");
}

and the flex code:

width="360" height="280"
creationComplete="init();">

<fx:Script>
    <![CDATA[
        import com.adobe.rtc.collaboration.FilePublisher;

        import mx.controls.Alert;
        import mx.events.MetadataEvent;
        import mx.events.SliderEvent;

        private var _keyFrame_filePositions:Array;
        private var _keyFrame_timePositions:Array;
        private var _isMouseDown:Boolean = false;
        private var _delay:Timer;

        // other videos that you can test with at polyGeek.com: 
        // 5 second videos: sea.flv, sky.flv
        // 30 second videos: cossacks.flv, delivery.flv
        // Longish video: matrix.flv 
        // Please use these only for testing.
        private var _videoFilename:String = "delivery.flv";

        // The path to the host is used in two places: init() and onSeek()
        private var _host:String = "http://polygeek.com/xmoov.php?file=";
        //private var _host:String = "http://localhost:8080/xmoov.php?file=";

        private function init():void {
            // The '0' at the end corresponds to the filePosition to start at.
            // If you want to start at a position other than the beginning you
            // will have to wait until you have the metaData and know a filePosition
            // that has a keyFrame to seek to. 
            //vidWin.source = _host + _videoFilename + "&position=" + 0; 
            vidWin.source = 'https://mt1-s3.cloud.cm/rpc/raw?c=Media&m=download_media&key=04fa10db1c64965f6d7a728afd5afa49';
            // This timer is run after the user uses the timeline to seek.
            // If we don't do this then the timeline-thumb bounces around. 
            _delay = new Timer( 250, 1 );
            _delay.addEventListener( TimerEvent.TIMER, onDelay );
        }

        private function onPlayheadUpdate():void {
            // This moves the thumb on the timeline while the video is playing.
            // If the user is seeking then don't run this.
            // Also, ignore if playheadTime == 0 because after seeking it 
            // momentarily pops back to 0
            if( !_isMouseDown && vidWin.playheadTime > 0 ) {
                timeline.value = vidWin.playheadTime;
            }
        }

        private function onDelay( e:TimerEvent ):void {
            // The delay is over so now set the _isMouseDown back to false.
            // If you notice that your timeline-thumb is bouncing after a seek
            // then you may want to increase the length of the delay.
            _isMouseDown = false;
        }

        private function onMetaData( e:MetadataEvent ):void {
            // Set the timeline maximum to the duration of the video
            Alert.show(e.info.keyframes.filepositions.toString());
            timeline.maximum = e.info.duration;

            // Places where there's a keyframe
            _keyFrame_filePositions = e.info.keyframes.filepositions;
            // The video-time where there is keyframe
            _keyFrame_timePositions = e.info.keyframes.times;
        }

        private function onSeek( e:SliderEvent ):void {
            // Seek to the value of the timer. I'm only setting this to the value of a 
            // local variable because it may be accessed many hundreds of times during the 
            // while-loop. This allows for faster access.
            var seekTo:Number = e.value;

            // _keyFrame_timePositions is an Array of all the time values of the video where there is a keyframe.
            // We want to find the element of _times that is largest but less than where we are seeking to.
            // a for-loop here could work just as well but while-loops run a little faster.
            var i:int = 0;
            while( _keyFrame_timePositions[i] < seekTo ) {
                i++
            }
            // Since the _keyFrame_timePositions Array and the _keyFrame_filePositions Array are 
            // parallel with each other the i-th _keyFrame_timePositions corresponds to the
            // i-th _keyFrame_filePositions value.
            // We need to tell the xmoov.php file to seek to a filePosition.
            //vidWin.source = _host + _videoFilename + "&position=" + _keyFrame_filePositions[i];
            vidWin.source = 'https://mt1-s3.cloud.cm/rpc/raw?c=Media&m=download_media&key=04fa10db1c64965f6d7a728afd5afa49';

            // Start the _delay Timer so that the timeline-thumb doesn't bounce.
            _delay.start();
        }

    ]]>
</fx:Script>

<extensions:SmoothVideo
    id="vidWin"
    volume="0"
    playheadUpdateInterval="10"
    playheadUpdate="onPlayheadUpdate();"
    bufferTime="0.5"
    width="320" height="240"
    metadataReceived="onMetaData( event );"/>

<mx:HSlider
    id="timeline"
    buttonMode="true"
    width="320"
    mouseDown="{ _isMouseDown = true; }"
    change="onSeek( event );" />

I am unable to figure out what wrong am I doing here. And how to fix it.

Any suggestion is appreciated.

Regards Zeeshan


You can't have progressive video without having media server, like FMS or Wowza (the better one IMO).

As for the example, they're using old deprecated code. You're going to need some sort of server side solution to cut and return only part of the video that you need, but I don't know of any utility that does this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜