Hi everyone,
I play live stream via flash client. My main goal is to send duration of stream to client. I found out we can do it passing this duration to metadata. In Wowza server side API in Publisher class there is a method addDataData(). Using it we can send matadata to client. Here is the question: how to correctly invoke this method to achieve this ?
Thanks
Try this:
IMediaStream stream = client.getAppInstance().getStreams().getStream(streamname);
AMFDataMixedArray data = new AMFDataMixedArray();
data.put("duration", new AMFDataItem(240);
stream.sendDirect("@setDataFrame","onMetaData",data);
Richard
Yes, it should work. For example in the IMediaStreamActionNotify2 onPlay handler.
You can also insert cuepoints similarly:
IMediaStream stream = client.getAppInstance().getStreams().getStream("yourStream");
AMFDataMixedArray data = new AMFDataMixedArray();
data.put("message", new AMFDataItem("hello Wowza"));
stream.sendDirect("clientsideCallbackFunction", data);
client-side:
var clientObj:Object = new Object();
clientObj.clientsideCallBackFunction(data:Object):void
{
trace(data.message);
});
netstream.client = clientObj;
netstream.play("myStream");
Richard
Is the onPlay handler in the context of IMediaStreamActionNotify interface?
Has to be setup like this:
https://www.wowza.com/docs/imediastreamactionnotify2-example
Richard
I’m not sure what this line is:
out("RTMPMediaEventsListener","onPlay()");
Put a break poin in the IDE, or getLogger statement, to see if you are hitting that line. Put a break point or trace on the client-side as well.
Richard
You can use the LiveVideoStreaming example. There is an AS3 version with FLA for Flash CS, or a Flex Builder 3 version. In either other one look for:
nsPlayClientObj.onMetaData = function(infoObject:Object):void
{
for (var propName:String in infoObject)
{
trace(" "+propName + " = " + infoObject[propName]);
}
}
You are missing a paren in your snip. Start with this:
IMediaStream stream = client.getAppInstance().getStreams().getStream("myStream");
AMFDataMixedArray data = new AMFDataMixedArray();
data.put("message", new AMFDataItem("HELLO WOWZA"));
stream.sendDirect("@setDataFrame","onMetaData",data);
Richard
Use cuepoints instead. It’s very similar. See 2nd (compact) example in this post:
https://www.wowza.com/docs/how-to-inject-cue-points-or-metadata
Server-side:
String streamname = params.getString(PARAM1);
String caption = params.getString(PARAM2);
IMediaStream stream = client.getAppInstance().getStreams().getStream(streamname);
AMFDataMixedArray data = new AMFDataMixedArray();
data.put("caption", new AMFDataItem(capton);
stream.sendDirect("setCaption", data);
Flash client-side:
var nsPlayClientObj:Object = new Object();
nsPlayClientObj.setCaption = function(obj:Object):void
{
trace(obj.caption)
}
nsPlay.client = nsPlayClientObj;
Richard
Pedro,
Sounds like the Application.xml /StreamType is “default”. It should be “live”.
Make sure the StreamType is “live”, and that Application.xml is below conf:
/conf[app-name]/Application.xml
And that there is no xml errors in the Application.xml. That would cause the default /conf/Application.xml to be used. Check the Wowza access and error logs, it will report any problems with the configuration file around the app-start event for that application.
Richard
Pedro,
That’s is the way metadata works, the player gets onMetaData event once per stream. Using the Stream class (e.g. the Scheduler), the player can get onMetaData on switch, as you describe
Richard
Are you adding “cuepoints” actually? Something like this:
public void setCaption (IClient client, RequestFunction function, AMFDataList params)
{
String streamname = params.getString(PARAM1);
String caption = params.getString(PARAM2);
IMediaStream stream = client.getAppInstance().getStreams().getStream(streamname);
//essential code
AMFDataMixedArray data = new AMFDataMixedArray();
data.put("caption", new AMFDataItem(capton);
stream.sendDirect("setCaption", data);
getLogger().info("Caption: " + caption);
}
This method will add data to the stream that will trigger a callback in the client if it is setup. Which is something like:
// set up netstream for callback on recorded stream
var nsPlayClientObj:Object = new Object();
nsPlayClientObj.setCaption = function(obj:Object):void
{
trace(obj.caption)
}
nsPlay.client = nsPlayClientObj;
The callback that works for a live stream will also work for vod, if you recorded in Wowza, when you playback.
Rciared
Pedro,
Server-side, you are inserting two cuepoints at the same time. I don’t think this can work, or one might work but not the other. Probably the 2nd one might work, setCaption, but you are not handling cuepoint named setCaption in the client.
And you are naming one of the cuepoints “onMetaData”, which is probably okay, but very confusing. I would use any other name.
Cuepoints are associated with a frame in the video and the function is triggered when that frame plays. Metadata is associated with the stream. The onMetaData event is built in and is triggered when the stream starts. See the source code for the Wowza example players: LiveVideoStreaming and SimpleVideoStreaming for how onMetaData event is handled.
Richard
I copied that to a module to try it, but after adding the imports, there is still a bunch of other stuff going on. You have to step through in in your environment, use the Wowza debugger, see if it hits that line:
auxStream.sendDirect("setCaption",data);
Suggest you simplify your code enough so this basic feature is working, then build your custom logic up again around that.
Richard
Also, onStreamCreate is probably not the place to do this. onStreamCreate runs for publish and play streams.
Implement IMediaStreamActionNotify2 interface, and use its onPublish event handler instead:
https://www.wowza.com/docs/imediastreamactionnotify2-example
But strip it down still, make sure that line is getting hit.
Richard
Pedro,
onPublish can run many times for a connection using an encoder like FMLE or Wirecast. In FMLE every time you click the Start button you should get onPublish event, and an onUnPublish event when you click Stop. The connect/disconnect button will trigger onConnect and onDisconnect
Richard
You have to inject metadata per stream. You can handle multiple streams in one application instance. onPublish will run once for each stream.
Richard
Pedro,
At present this only works for Flash RTMP (and possibly Flash HTTP). Eventually there will be examples of an equivalent for iOS with ID3 tags, and in Smooth streams maybe. I don’t think there will ever be an equivalent of this for RTSP.
Richard
I can call this code in any place after stream was created ?
Richard,
Thank you a lot for your reply
But unfortunatelly this does not work:
Code:
public void onPlay(IMediaStream stream, String streamName, double playStart, double playLen, int playReset)
{
out("RTMPMediaEventsListener","onPlay()");
AMFDataMixedArray data = new AMFDataMixedArray();
data.put("message", new AMFDataItem("hello Wowza"));
stream.sendDirect("clientsideCallbackFunction", data);
}
client-side:
Code:
nsPlay = new NetStream(nc);
nsPlay.addEventListener(NetStatusEvent.NET_STATUS, nsOnStatus);
var nsPlayClientObj:Object = new Object();
nsPlayClientObj.clientsideCallbackFunction = function(data:Object):void {
trace(data.message);
}
nsPlayClientObj.onMetaData = function(infoObject:Object):void
{
trace("onMetaData");
//clearInterval(progressTimer);
// print debug information about the metaData
for (var propName:String in infoObject)
{
trace(" "+propName + " = " + infoObject[propName]);
}
// grab the movies duration from the metadata
if (duration == 0)
{
duration = infoObject.duration;
//duration = 1000;
slider.maximum = duration ;
progressTimer = setInterval(updateProgress, 250);
}
};
// print debug information when we encounter a cuePoint
nsPlayClientObj.onCuePoint = function(infoObject:Object):void
{
trace("onCuePoint: "+infoObject.name+" ("+infoObject.type+")");
var param:String;
for(param in infoObject.parameters)
{
trace(" param: "+param+"="+infoObject.parameters[param]);
}
};
// print debug information when we play status changes
nsPlayClientObj.onPlayStatus = function(infoObject:Object):void
{
trace("onPlayStatus");
for (var prop:String in infoObject)
{
trace("\t"+prop+":\t"+infoObject[prop]);
}
};
nsPlay.client = nsPlayClientObj;
// set the buffer time and attach the video and audio
nsPlay.bufferTime = 3;
videoObj.attachNetStream(nsPlay);
// start playback
isProgressUpdate = false;
isPlaying = true;
nsPlay.play(streamStr.text);
I use flash client which Wowza supplies in examples. Do you have any ideas how to make ti work ?
Thanks
Yes, onPlay is in the context of IMediaStreamActionNotify and listener is registred as in link, but I still can not call function on client… Do you have any ideas ?