【问题标题】:Progressive Streaming flv video files, using php and Flex渐进式流式传输 flv 视频文件,使用 php 和 Flex
【发布时间】:2011-05-17 20:36:10
【问题描述】:

渐进式流媒体问题:

我一直在尝试使用来自 xmoov.com 的示例来仅获取部分视频,如博客中所述: http://polygeek.com/1423_flex_video-streaming-php-xmoov

该代码适用于他们拥有的视频链接,但是当我将链接更改为服务器上的视频文件时,我在“Alert.show(e .info.keyframes.filepositions.toString());"

同样在 onSeek( e:SliderEvent ) 线上 "while( _keyFrame_timePositions[i]

我的php代码:

受保护的函数 serve_media_test($key, $position = '') {
如果(空($位置)) $位置 = 0; $seekPos = intval($position); $key = 添加斜杠($key); $media = 新 C7_Media(); $row = $media->fetchRow("hash = '$key' AND '".$_SERVER['SERVER_NAME']."' LIKE CONCAT('%', server_domain, '%')"); 如果(空($行)) throw new C7_Exception('找不到给定密钥的文件或文件不在此服务器上'); $row->views = $row->views + 1; //增加这个媒体文件的浏览量 $row->保存();
//发送文件 $local_file = C7_Bootstrap::getConfig()->user->media->store.'/'.$row->location; // 应该发送给客户端的本地文件 $download_file = stripslashes($row->original_name); // 用户默认获取的文件名 $download_rate = C7_Bootstrap::getConfig()->user->storage->downloadrate->kbps; // 设置下载速率限制 (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");
}

和弹性代码:

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 );" />

我无法弄清楚我在这里做错了什么。以及如何解决它。

感谢任何建议。

问候 泽山

【问题讨论】:

    标签: php apache-flex video streaming xmoov


    【解决方案1】:

    如果没有媒体服务器,例如 FMS 或 Wowza(更好的 IMO),您就无法拥有渐进式视频。

    就示例而言,他们使用的是旧的已弃用代码。您将需要某种服务器端解决方案来剪切并仅返回您需要的部分视频,但我不知道有任何实用程序可以做到这一点。

    【讨论】:

    • 我有一个媒体服务器。我可以从我的服务器运行视频文件。
    • 我不明白,我有一个存储服务器,用于存储我的所有媒体文件,当我将文件上传到存储服务器时,我会对其进行处理并将其转换为 .flv,然后还在我存储文件的数据库中创建一个条目。因此,要获取任何文件,我确实需要根据 file_key 从 mysql 数据库获取文件位置。
    • 那不是媒体服务器。媒体服务器提供流媒体视频,您所做的不是渐进式视频。您实际上只是在一起破解 FLV。在继续之前,我会尝试对视频流进行更多研究。
    • 所以你是说,我不能只获取视频的一部分,而不是整个视频?
    • 我知道媒体服务器可以做到这一点,但 PHP 不确定。也许如果有某种库可以一起解码和修补新文件。在继续之前,我会进行更多研究。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2016-12-02
    • 2023-03-31
    相关资源
    最近更新 更多