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.
精彩评论