View Full Version : Getting the duration of an FLV
Sekter
01-08-2008, 11:05 PM
Hey, Ive been scratching my head for quite some time now trying to find a way to retrieve the properties (specifically the duration) of an flv file. There are many forums about how to do this in AS2 but none of them seem to work anymore in AS3 since the newer version changed so many different things in video packages now. I originally have an FLVplayback which attaches an FLV by actionscript and ofcourse it plays and all but i can't seem to get any properties about the flv it is playing. I kind of know that i need to use the metadata class to get info about the file but ive tried many methods out and nothing seemed to work. If this is not possible via FLVPlayback then i would still be greatful with any solution anyone can give me as to how to get properties of an flv in another way. Any ideas anyone?:eek:
hangalot
01-09-2008, 08:57 AM
you need to listen to the metadata events to get the duration. be warned however that some videos do not have a duration due to how they were encoded
Sekter
01-09-2008, 09:46 AM
Thx for quick reply hangalot,
import mx.video.*;
var listenerObject:Object = new Object();
listenerObject.metadataReceived = function(eventObject:Object):Void {
trace("canSeekToEnd is " + my_FLVPlybk.metadata.canSeekToEnd);
trace("Number of cue points is " + my_FLVPlybk.metadata.cuePoints.length);
trace("Frame rate is " + my_FLVPlybk.metadata.framerate);
trace("Height is " + my_FLVPlybk.metadata.height);
trace("Width is " + my_FLVPlybk.metadata.width);
trace("Duration is " + my_FLVPlybk.metadata.duration + " seconds");
};
my_FLVPlybk.addEventListener("metadataReceived", listenerObject);
my_FLVPlybk.contentPath = "http://www.helpexamples.com/flash/video/cuepoints.flv";
This is the only code that i can seem to find to receive the duration of an flv. But it is in AS2 so doesnt seem to work in AS3. Im not so sure how im suppost to be listening to metadata in another way. (API about metadata with FLVplayback is confusin hell outa me:confused:). U think u cud give me a small coding example of how to be listening for the metadata?
Btw about what you said regarding the flv encodings, logically speaking if i can view information (the duration) by using the FLV player.exe then i should also be able to see it in the metadata while coding in AS shouldnt i? Or is there something that i dont understand about encodings?:eek:
hangalot
01-09-2008, 10:02 AM
i am a bit busy so just dumping some of my code
/**
* @author Johannes Nel
* @author Sven Woermann
*/
package memorphic.video.controllers
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.ObjectEncoding;
import flash.utils.Timer;
import memorphic.video.errors.StreamManagerError;
import memorphic.video.events.StreamManagerEvent;
import flash.events.TimerEvent;
import flash.media.SoundTransform;
import flash.events.AsyncErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.utils.getTimer;
import memorphic.utils.URLUtilMM;
////////////////////////////////////////////////////////////////////////\
/**
* @eventType StreamManagerEvent.BUFFER_EMPTY
*/
[Event (name="bufferEmpty",type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.BUFFER_FULL
*/
[Event (name="bufferFull",type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.PLAYHEAD_UPDATE
* This event gets dispatched when the NetStreams time changes
*/
[Event (name="playheadUpdate",type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.SEEK_COMPLETE
* This event gets dispatched when the seek operation in completed.
*/
[Event (name="seekComplete",type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.VIDEO_META_DATA_AVAILIBLE
*/
[Event (name="metaDataAvailible", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.CONNECTED
*/
[Event (name="connected", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.NETSTREAM_LOAD_START
*/
[Event (name="netstreamLoadStart", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.ERROR_STREAM_NOT_FOUND
*/
[Event (name="streamNotFound", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.ERROR_CONNECTION_CLOSED
*/
[Event (name="netconnectionClosed", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.ERROR_CONNECTION_CALL_FAILED
*/
[Event (name="netconnectionCallFailed", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.NETSTREAM_PLAY_STOP
*/
[Event (name="netstreamPlayStop", type="memorphic.video.events.StreamManagerEvent")]
/**
* @eventType StreamManagerEvent.VIDEO_LOAD_UPDATE
* this event contains the following properties from the netstream object
* Property Defined by
* bufferLength : Number
* [read-only] The number of seconds of data currently in the buffer. NetStream
* bufferTime : Number
* Specifies how long to buffer messages before starting to display the stream. NetStream
* bytesLoaded : uint
* [read-only] The number of bytes of data that have been loaded into the player. NetStream
* bytesTotal : uint
* [read-only] The total size in bytes of the file being loaded into the player.
*/
[Event (name="videoLoadUpdate", type="memorphic.video.events.StreamManagerEvent")]
///////////////////////////////////////////////////////////////////////////////////////
public class StreamManager extends EventDispatcher
{
/**
* the list of ports that this component tries to get connect to over the RTMP protocol
*/
public static var PORTS_LIST:Array = [80,443,1935];
private var __nc:NetConnection;
private var __pendingConnections:Array = [];
private var __ns:NetStream;
private var __ncURI:String;
private var __nsURI:String;
private var __streamVideo:Boolean = false;
private var __currentPlayHeadTime:Number = 0;
private var __currentBufferTime:Number = 0;
private var __currentBytesLoaded:Number = 0;
private var __volume:Number = 0.8;
private var __minimumBufferTime:Number = 5;
private var __seekedTime:int;
private var __debugLog:Array = [];
private var __playheadMonitorTimer:Timer;
private var __currentState:String;
private var __rtmptPort:uint = 80;
private static const STATE_PLAYING:String = "statePlaying";
private static const STATE_PAUSED:String = "statePaused";
private static const STATE_STOPPED:String = "stateStopped";
/**
* Constructer
*/
public function StreamManager()
{
super();
}
public function get hasPendingConnection():Boolean
{
return Boolean(__pendingConnections.length);
}
/////////////////////////////////////////////////
// Methods for connecting to pregressive and streaming video
/////////////////////////////////////////////////
/**
* This function loads a video and estabnlished a connection to the server to either stream it or load it progressively
* it calls connect and sets the default volume
*
* @param streamURI URI pointing to a flv. Either progressive or streaming depending wether
* this class must streamVideos
* @param serverURI if you want this class to connect to a streaming server the serverUri needs to point to a valid app
* @see connect (uri)
* @see play()
* @returns NetStream
*/
public function loadStream(streamURI:String, serverURI:String = null):NetStream
{
log("LoadStream: Server URI " + serverURI + ", Stream URI " + streamURI);
//save the uri this will be used in the play() method
__nsURI = streamURI;
if(__streamVideo && serverURI != __ncURI && !is_connected && !hasPendingConnection)
{
connect(serverURI);
return null;
}
if(__nc == null)
{
//this is well and truly going progressive now
connect(null);
}
if(__ns != null)
{
cleanupNS();
}
__ns = new NetStream(__nc);
__ns.addEventListener(NetStatusEvent.NET_STATUS,on Status);
__ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
//the client class is defined inside this file at the bottom.
/**
* more information needed about callback classes
*/
__ns.client = new MetaDataHandler(this);
this.volume = __volume;
return __ns;
}
/**
* Property of the connected status of the netConnection.
*/
have to break the code accross two posts
hangalot
01-09-2008, 10:03 AM
public function get is_connected():Boolean{
if (__nc == null || !__ncURI || !streamVideo){
return false
}
else{
return __nc.connected;
}
}
/**
* This function clears all pending connections, closes all open netstream and netconnections.
* if we are streaming video then we create an array of pending connections trying to connect via rtmp (non-tunneling) through each port listed in the ports array
* and also creates a rtmpt connection over the rtmptPort.
* if we are connecting to a progressive video we connect to url null.
* @param serverURI URI to a media server (rtmp and the like).
* @see rtmptPort
*/
protected function connect(serverURI:String):void
{
log("Net connection connect attempt to serverURI: " + serverURI);
noConnectionAvailible();
__ncURI = serverURI;
clearPendingConnections();
var nc:NetConnection;
if(serverURI && streamVideo)
{
serverURI = URLUtilMM.replaceProtocol(serverURI,"rtmp");
for each(var port:uint in PORTS_LIST)
{
serverURI = URLUtilMM.replacePort(serverURI,port);
nc = addConnection();
__pendingConnections.push(nc);
nc.connect(serverURI);
log("Add streaming connection " + serverURI);
}
if(URLUtilMM.getProtocol(serverURI).toLowerCase() != "rtmpt")
{
var t:String = serverURI;
serverURI = URLUtilMM.replacePort(serverURI,rtmptPort);
serverURI = URLUtilMM.replaceProtocol(serverURI,"rtmpt");
nc = addConnection();
__pendingConnections.push(nc);
if(serverURI == "")
{
nc.connect(serverURI);
}
else
{
trace("THIS IS THE URL THAT IS BREAKING EVERYTHING",t );
}
log("Add streaming connection " + serverURI);
}
}
else if(!streamVideo || !is_connected)
{
nc = addConnection();
__pendingConnections.push(nc);
nc.connect(null);
log("Add connection progressive video");
}
}
/**
* create a netconnection object, sets the neconding type to AMF0 and add the metadatahandler and adds all the event listeners we use to it.
* @returns NetConnection
*/
protected function addConnection():NetConnection
{
var nc:NetConnection = new NetConnection();
nc.objectEncoding = ObjectEncoding.AMF0;
nc.client = new MetaDataHandler(this);
nc.addEventListener(SecurityErrorEvent.SECURITY_ER ROR, securityErrorHandler);
nc.addEventListener(NetStatusEvent.NET_STATUS,onSt atus);
return nc;
}
/**
* if an individual connection has failed we remove that connection from the pending connections array. if the pending connections
* array is emtpry we dispatch the StreamManagerEvent.ERROR_CONNECTION_CALL_FAILED event
* @param NetConnection - the connection which failed
* @eventType StreamManagerEvent.ERROR_CONNECTION_CALL_FAILED
*/
private function onConnectionFailed(nc:NetConnection):void
{
log("Connection failed, NetConnection URL: " + nc.uri);
var l:uint = __pendingConnections.length;
for(var i:uint = 0 ; i < l ;i++)
{
if(__pendingConnections[i] == nc)
{
nc.removeEventListener(SecurityErrorEvent.SECURITY _ERROR, securityErrorHandler);
nc.removeEventListener(NetStatusEvent.NET_STATUS,o nStatus);
nc.addEventListener(NetStatusEvent.NET_STATUS,onSt atusDummy);
__pendingConnections.splice(i,1);
nc = null;
break;
}
}
if(__pendingConnections.length == 0)
{
log("__pendingConnections == 0");
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_CONNEC TION_CALL_FAILED));
}
}
/**
* this function gets executed if streaming is set to true and the netconnection has not connected
* but a play command has been executed.it also empties the pending connection array, closing all the pending connections
*/
private function onNCConnect(nc:NetConnection):void
{
log("Netconnection connected " + nc.uri);
for each(var con:NetConnection in __pendingConnections)
{
if(nc != con)
{
log("Remove pending connection :" + con.uri);
con.removeEventListener(SecurityErrorEvent.SECURIT Y_ERROR, securityErrorHandler);
con.removeEventListener(NetStatusEvent.NET_STATUS, onStatus);
con.addEventListener(NetStatusEvent.NET_STATUS,onS tatusDummy);
}
}
__nc = nc;
__pendingConnections = [];
loadStream(__nsURI,__ncURI);
}
/**
* Closes the netconnection. This will cause onStatus to through an StreamManagerEvent.ERROR_CONNECTION_CLOSED event.
*/
public function closeConnection():void
{
__nc.close();
}
private function onStatusDummy(evt:NetStatusEvent):void
{
//hack: ignores the event
}
private function cleanupNS():void
{
//IF WE ARE DOWNLOADING A PROGRESSIVE VIDEO AT THIS STAGE WE NEED TO MAKE CERTAIN THAT WE KILL THE HTTP DOWNLOAD
if (__ns)
{
__ns.removeEventListener(NetStatusEvent.NET_STATUS ,onStatus);
__ns.removeEventListener(AsyncErrorEvent.ASYNC_ERR OR, asyncErrorHandler);
__ns.close();
__ns.addEventListener(NetStatusEvent.NET_STATUS,on StatusDummy);
__ns.play("this movie does not exist.flv",0);
//trace(":smnoConnectionAvailible>> ", __streamVideo ,__nsURI);
__currentState = StreamManager.STATE_STOPPED;
}
__ns = null;
}
private function clearPendingConnections():void
{
for each (var con:NetConnection in __pendingConnections)
{
log("remove pending connection :" + con.uri);
con.removeEventListener(SecurityErrorEvent.SECURIT Y_ERROR, securityErrorHandler);
con.removeEventListener(NetStatusEvent.NET_STATUS, onStatus);
con.addEventListener(NetStatusEvent.NET_STATUS,onS tatusDummy);
if(con.connected)
{
con.close();
}
con = null;
}
__pendingConnections = [];
}
/**
* this function handles cleanup when a Connection is refused or breaks
*/
public function noConnectionAvailible():void
{
cleanupNS();
if(__nc){
__nc.removeEventListener(SecurityErrorEvent.SECURI TY_ERROR, securityErrorHandler);
__nc.removeEventListener(NetStatusEvent.NET_STATUS ,onStatus);
__nc.addEventListener(NetStatusEvent.NET_STATUS,on StatusDummy);
if(__nc.connected)
{
__nc.close();
}
}
__nc = null;
}
// NetConnection security error handler
private function securityErrorHandler(event:SecurityErrorEvent):voi d {
//trace("StreamManager securityErrorHandler: " + event);
log("NetConnection security error.");
}
// NetStream AsyncErrorHandler
private function asyncErrorHandler(event:AsyncErrorEvent):void {
//trace("StreamManager asyncErrorHandler: " + event);
log("NetStream async error.");
}
hangalot
01-09-2008, 10:04 AM
//////////////////////////////////////////
//Handler function
//////////////////////////////////////////
/**
* onStatus functions as the listener for the NetConnection and NetStream on status events
* This function dispatches custom events for NetStatusEvents as well as calls local handlers
* @param NetStatusEvent Generated from either the NetConnection or NetStream
* @eventType StreamManagerEvent.CONNECTED
* @eventType StreamManagerEvent.ERROR_STREAM_NOT_FOUND
* @eventType StreamManagerEvent.ERROR_CONNECTION_CALL_FAILED
* @eventType StreamManagerEvent.NETSTREAM_PLAY_STOP
* @eventType StreamManagerEvent.BUFFER_FULL
* @eventType StreamManagerEvent.PAUSE_NOTIFICATION
*/
protected function onStatus(evt:NetStatusEvent):void
{
var s:String = evt.info.code;
log("NetStatusEvent: " + s);
//trace("onStatus info code:",s);
//if (__ns) //trace("current playhead time is:",__ns.time);
switch(s)
{
case "NetStream.Buffer.Empty":
handleBufferEmpty();
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.BUFFER_EMPTY ,evt));
break
case "NetStream.Buffer.Full" :
handleBufferFull();
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.BUFFER_FULL, evt));
break;
/*case"NetStream.Buffer.Flush":
break;
case"NetStream.Publish.Start":
break;
case"NetStream.Publish.BadName":
break;
case"NetStream.Publish.Idle":
break;
case"NetStream.Unpublish.Success":
break;
*/
case"NetStream.Play.Start":
//if (__currentState == StreamManager.STATE_STOPPED) pause();
__currentState = StreamManager.STATE_PLAYING;
break;
case"NetStream.Play.Stop" :
stop();
// dispatchEvent(new StreamManagerEvent(StreamManagerEvent.NETSTREAM_PL AY_STOP));
break;
case"NetStream.Play.Failed":
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_STREAM _NOT_FOUND,evt));
__currentState = StreamManager.STATE_STOPPED;
break;
case"NetStream.Play.StreamNotFound" :
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_STREAM _NOT_FOUND,evt));
__currentState = StreamManager.STATE_STOPPED;
break;
/*case"NetStream.Play.Reset" :
break;
case "NetStream.Play.PublishNotify" :
break;
case"NetStream.Play.UnpublishNotify":
break;
*/
case "NetStream.Pause.Notify" :
//this is only dispatched in the streaming version - pause does not do anything netstatus-wize on progressive
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.PAUSE_NOTIFI CATION,evt));
break;
/*case"NetStream.Unpause.Notify":
break;
case "NetStream.Record.Start":
break;
case"NetStream.Record.NoAccess":
break;
case"NetStream.Record.Stop" :
break;
case"NetStream.Record.Failed":
break;
case"NetStream.Seek.Failed" :
break;
case"NetStream.Seek.InvalidTime":
break;
case"NetStream.Seek.Notify" :
// dispatchEvent(new StreamManagerEvent(StreamManagerEvent.SEEK_NOTIFIC ATION,evt));
break;
case"NetConnection.Call.BadVersion" :
break;*/
case "NetConnection.Connect.Failed" :
onConnectionFailed(evt.target as NetConnection);
break;
/*case"NetConnection.Call.Failed" :
break;
case "NetConnection.Call.Prohibited" :
break;
*/
case "NetConnection.Connect.Closed" :
onConnectionFailed(evt.target as NetConnection);
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_CONNEC TION_CLOSED,evt));
break;
case "NetConnection.Connect.Success":
onNCConnect(evt.target as NetConnection);
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.CONNECTED,ev t));
break;
case "NetConnection.Connect.Rejected":
onConnectionFailed(evt.target as NetConnection);
//dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_CONNEC TION_CALL_FAILED,evt));
break;
case "NetConnection.Connect.AppShutdown" :
onConnectionFailed(evt.target as NetConnection);
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_CONNEC TION_CLOSED,evt));
break;
case "NetConnection.Connect.InvalidApp" :
onConnectionFailed(evt.target as NetConnection);
//dispatchEvent(new StreamManagerEvent(StreamManagerEvent.ERROR_CONNEC TION_CALL_FAILED,evt));
break;
/*case "SharedObject.Flush.Success" :
break;
case "SharedObject.Flush.Failed" :
break;
case "SharedObject.BadPersistence":
break;
case "SharedObject.UriMismatch" :
break;*/
default:
trace("default net status info code: " + s);
}
}
/**
* Callback from the Netstream object.
* @param info Object - ideally should contain duration,width,height,frameRate
* @param args any number of optional arguments. Not used currently
* eventType StreamManagerEvent.VIDEO_META_DATA_AVAILIBLE, type StreamManagerEvent
*/
public function onMetaData(info:Object,... args):void
{
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.VIDEO_META_D ATA_AVAILIBLE,null,info));
//trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
//_video.duration = info.duration;
}
/**
* the following methods are callbacks for the netstream.client
*/
public function onCuePoint(info:Object):void
{
////trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
public function onTransition(info:Object,... args):void
{
//trace("onTransition: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
/**
* end of callbacks
*/
/////////////////////////////////////////////
// Methods for controlling the netstream
//////////////////////////////////////////////
/**
* Calls the play method on the netstream object passing in the URI you passed in with.
* If the netstream object playhead position is not 0, it calls the resume method to play from current playhead position.
* Also starts the poling of the playhead so we can dispatch StreamManagerEvent.PLAYHEAD_UPDATE events.
* @throws StreamManagerError : StreamManagerError.NETSTREAM_NOT_INSTANTIATED;
* @eventType StreamManagerEvent.NETSTREAM_LOAD_START
* @see StreamManagerEvent.PLAYHEAD_UPDATE
*/
public function play():void
{
log("Video play called:");
if(__ns == null)
{
// The netstream has not been instantiated by the loadStram method.
// Either the loadStream method was not yet called or,
// if streaming, the _netConnection is not connected yet.
throw new StreamManagerError(StreamManagerError.NETSTREAM_NO T_INSTANTIATED);
}
if (__ns.time){
__ns.resume();
}else if(__currentState != StreamManager.STATE_PLAYING){
__ns.play(__nsURI,0);
__ns.pause();
__ns.bufferTime = __minimumBufferTime;
__currentState = StreamManager.STATE_PLAYING;
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.NETSTREAM_LO AD_START));
if(!__playheadMonitorTimer)
{
__playheadMonitorTimer = new Timer(100,0);
__playheadMonitorTimer.addEventListener(TimerEvent .TIMER,onPlayheadMonitorTimeEvent);
}
__playheadMonitorTimer.start();
}
else if(__currentState == StreamManager.STATE_PLAYING || __currentState == StreamManager.STATE_PAUSED){
__ns.resume()
__playheadMonitorTimer.start();
}
//resume();
}
/**
* Pauses the netstream
* Also stops the Timer associates with StreamManagerEvent.PLAYHEAD_UPDATE event.
*
* @throws typeStreamManagerError const:StreamManagerError.NO_STREAMING_VIDEO_URI_SP ECIFIED;
* @see StreamManagerEvent.PLAYHEAD_UPDATE
*/
public function pause():void
{
log("Video pause called:");
if(__ns == null)
{
// The netstream has not been instantiated by the loadStram method.
// Either the loadStream method was not yet called or,
// if streaming, the _netConnection is not connected yet.
throw new StreamManagerError(StreamManagerError.NETSTREAM_NO T_INSTANTIATED);
}
if (__currentState != StreamManager.STATE_PAUSED && __currentState != StreamManager.STATE_STOPPED)
{
__ns.pause();
__currentState = StreamManager.STATE_PAUSED;
}
//__playheadMonitorTimer.stop();
}
/**
* Stops playing all data on the stream, sets the time property to 0, and makes the stream available for another use.
*
* @throws typeStreamManagerError const:StreamManagerError.NO_STREAMING_VIDEO_URI_SP ECIFIED;
*/
public function stop():void
{
log("Video stop called:");
if(__ns == null)
{
// The netstream has not been instantiated by the loadStram method.
// Either the loadStream method was not yet called or,
// if streaming, the _netConnection is not connected yet.
throw new StreamManagerError(StreamManagerError.NETSTREAM_NO T_INSTANTIATED);
}
if (__currentState != StreamManager.STATE_STOPPED){
__currentState = StreamManager.STATE_STOPPED;
__ns.close();
}
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.NETSTREAM_PL AY_STOP));
}
/**
* Seeks to a point in the current FLV in seconds
*/
hangalot
01-09-2008, 10:05 AM
public function seek(seconds:int):void
{
if(__ns == null)
{
// The netstream has not been instantiated by the loadStram method.
// Either the loadStream method was not yet called or,
// if streaming, the _netConnection is not connected yet.
throw new StreamManagerError(StreamManagerError.NETSTREAM_NO T_INSTANTIATED);
}
__seekedTime = seconds;
//trace("seek to: " ,seconds,netStream.time);
__ns.seek(seconds);
__ns.bufferTime = __minimumBufferTime;
}
public function get netStream():NetStream
{
return __ns;
}
/////////////////////////////////////////////
// Public properties
//////////////////////////////////////////////
[Inspectable (defaultValue='5',type="Number")]
public function set minimumBufferTime(v:Number):void
{
__minimumBufferTime = v;
}
public function get minimumBufferTime():Number
{
return __minimumBufferTime;
}
/**
* The port we this component tries to connect to over the RTMPT protocol (tunneling)
*/
[Inspectable (defaultValue='80',type="uint")]
public function set rtmptPort(v:uint):void
{
__rtmptPort = v;
}
public function get rtmptPort():uint
{
return __rtmptPort;
}
/**
* sets wether we should try to connect as progressive or streaming
*/
public function set streamVideo(v:Boolean):void
{
//if (v!=__streamVideo)
//{
//destroy any existing netstream and netConnection
noConnectionAvailible();
__streamVideo = v;
//}
}
public function get streamVideo():Boolean
{
return __streamVideo;
}
/**
* Set the audio volume of the net stream. Value between 0 and 1.
* Default value 0.8.
*/
[Inspectable (defaultValue='0.8')]
public function set volume(v:Number):void
{
__volume = v;
if (__ns) {
var transform:SoundTransform = __ns.soundTransform;
transform.volume = __volume;
__ns.soundTransform = transform;
}
}
public function get volume():Number
{
return __volume;
}
/**
* The current implementation for this method is as follows
* on bufferFull
* <code>
* factor = Math.ceil(bufferTime/minBufferTime);
* if(factor < 5)
* {
* factor ++
* buffertime = factor * minBufferTime;
* }
* </code>
* override to change this behaviour.
* this method is invoked
*/
protected function handleBufferFull():void
{
// //trace("__ns.bufferTime",__ns.bufferTime);
var factor:Number = Math.ceil(__ns.bufferTime/__minimumBufferTime);
if(factor < 5)
{
factor++;
__ns.bufferTime = __minimumBufferTime * factor;
}
}
/**
* Resets the bufffer to the minumum buffer time.
* @see StreamManager.minimumBufferTime
*/
protected function handleBufferEmpty():void
{
__ns.bufferTime = __minimumBufferTime;
}
/**
* @eventType StreamManagerEvent.PLAYHEAD_UPDATE
*/
protected function onPlayheadMonitorTimeEvent(evt:TimerEvent):void
{
if (__ns){
//trace("ns time = ",__ns.time);
if (__ns.time != __currentPlayHeadTime)
{
if ((__seekedTime < __ns.time) && (__seekedTime != 0)){
__seekedTime = 0;
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.SEEK_COMPLET E,null,null,__ns.time));
}
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.PLAYHEAD_UPD ATE,null,null,__ns.time));
//dispatchEvent(new StreamManagerEvent(StreamManagerEvent.VIDEO_LOAD_U PDATE,null,null,null,__ns.bufferLength,__ns.buffer Time,__ns.bytesLoaded,__ns.bytesTotal));
// //trace("__ns.bufferLength: ", __ns.bufferLength);
__currentPlayHeadTime = __ns.time;
}
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.VIDEO_LOAD_U PDATE,null,null,null,__ns.bufferLength,__ns.buffer Time,__ns.bytesLoaded,__ns.bytesTotal));
}
}
/* Work in progress. This function can monitor the load progress.
protected function onLoadMonitorTimeEvent(evt:TimerEvent):void
{
if (__currentState == StreamManager.STATE_PLAYING)
{
if (streamVideo)
{
if (__ns.bufferTime != __currentBufferTime){
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.VIDEO_LOAD_U PDATE,null,null,null,__ns.bufferLength,__ns.buffer Time,__ns.bytesLoaded,__ns.bytesTotal));
__currentBufferTime = __ns.bufferTime
}
else
{
}
}
else
{
if (__ns.bytesLoaded != __currentBytesLoaded){
dispatchEvent(new StreamManagerEvent(StreamManagerEvent.VIDEO_LOAD_U PDATE,null,null,null,__ns.bufferLength,__ns.buffer Time,__ns.bytesLoaded,__ns.bytesTotal));
__currentBytesLoaded = __ns.bytesLoaded;
}
}
}
}*/
////////////////////////////////////////
// Output log
///////////////////////////////////////
/**
* returns an duplicate of the log array, each entry containing an object with time,location and message properties
*/
public function getLog():Array
{
/*var p:int = __debugLog.length - 1;
var s:String = "";
while(p>=0)
{
s += p + ". " + __debugLog[p].toString() + "\n";
p--;
}
*/
return __debugLog.slice();
}
hangalot
01-09-2008, 10:05 AM
private function log(msg:Object):void
{
__debugLog.push({time:getTimer(),location:this,mes sage:msg});
}
}
}
import flash.events.Event;
import memorphic.video.controllers.StreamManager;
dynamic class MetaDataHandler{
private var __trgt:StreamManager;
public function MetaDataHandler(target:StreamManager)
{
__trgt = target;
}
/**
* this is a callback function in red5 server
*/
public function onBWDone(... args):void
{
//ignore onBWDone
}
public function close(... args):void{
/*i'm not sure about this one, i got this error and added this function--- Sven
Error #2044: Unhandled AsyncErrorEvent:. text=Error #2095: flash.net.NetConnection was unable
to invoke callback close. error=ReferenceError: Error #1069: Property close not found on .MetaDataHandler
and there is no default value.
*/
//trace("StreamManager: NetStream.client callback close()");
}
public function onMetaData(info:Object,... args):void
{
__trgt.onMetaData(info,args);
}
public function onCuePoint(info:Object):void
{
__trgt.onCuePoint(info);
}
public function onTransition(info:Object,... args):void
{
__trgt.onTransition(info,args);
}
}
hangalot
01-09-2008, 10:06 AM
sorry about the size of the dump, but lots of issues with video are addressed in this, and its pure as3 works in flex and flash, but we changed the way we work with video seperatly to this so its still not ideal.
just merge all this inb one code file
Sekter
01-09-2008, 04:31 PM
Thx this gives me some idea as to how AS3 looks at things in video. However this is all done using netstream. I currently already have an flvplayback imported onto the stage with name of flvPlayback. This flvplayback detects events such as VideoEvent.playheadTime,VideoEvent.complete etc. I realise that in the API flvPlayback has a totalTime property (total playing time for the video in seconds.) and metadataReceived event. So now i need an alternative of netstream but for FLVplayback. The net stream is:
stream_ns.onMetaData = function(infoObject:Object) {
/*for (var propName in infoObject) {
trace(propName+" = "+infoObject[propName]);
}*/
var FLVduration = infoObject["duration"];
var minutes2:Number = Math.floor(FLVduration/60);
var seconds2 = Math.floor(FLVduration%60);
if (seconds2<10) {
seconds2 = "0"+seconds2;
}
totalTimeText = " Total time:"+minutes2+":"+seconds2;
};
So in theory i should be able to use flvPlayback.metadataReceived = function(bla bla) {bla bla} but i can't. Any ideas?
springframework
01-09-2008, 04:48 PM
during conversion to flv format, it is possible that no metadata is written to the file.
'flvtool2' can apparently write the meta information( including duration ) into the file.
i have not used flvtool2 myself, but i have heard good things about it from friends.
Jesse Couch (http://www.jessecouch.com)
Sekter
01-09-2008, 05:00 PM
Im not having a problem with determining whether a file has metadata or not :p. I know for a fact that the file has metadata because i can get this metadata using the code that i have mentioned below. The problem i am having is that i need to find out how to extract the duration of the flv using flvplayback (possibly with metadataReceived event)? anyone yet :confused:
|
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.