Wowza Community

Dynamic Bandwidth Detection (BWCheck)

The approach is to use the bandwidth checker to determine available bandwidth to the client, then use that information to play a video with appropriate bit rate for that connection. The buffer is not something you want to adjust for this purpose.

And bandwidth checking is not automatic. And what you do with the results of the bandwidth checking is not automatic. You have to add the module to Application.xml, and you have to run the bandwith checking functions in the player, and you have to take the result and do something with it: play a version of the video that you have encoded to a bit rate for that connection speed.

http://www.wowza.com/community/t/-/31

Richard

Yes, the source code for bandwidth checker is in first post of this thread. You can compile your own version in the Wowza IDE to make adjustments.

Richard

Did you add the jar file to wowza/lib folder then restart Wowza, and did you add the module to Application.xml. You want to connect to the Wowza server that you added that jar to, and to the application that you added the Module to.

Richard

There is a Actionscript 3 version of ctosbwcheck in [wowza-install-dir]/examples/BWCheck/CtoSBWCheck.fla

The results of the bwcheck do vary from moment to moment, which is normal result of varying network conditions.

Richard

It should be here:

[install dir]\examples\BWChecker\client\CtoSBWCheck.fla

I’ll send it to that email too.

Richard

There is a working AS3 example here:

[wowza-install-dir]/examples/BWChecker/client/bwchecker.fla

Richard

It’s on page 2 of this thread. You have to build it in the Wowza IDE

It tests from client to server. The default one at the top tests from server to client.

Richard

I don’t understand the question. Can you explain?

Richard

I think you are talking about using Netstream.play2() and netstreaminfo object. This what is used to implement Flash Dynamic Streaming, for example JW Player’s implementation

You can search around but here is one article that looks useful

http://help.adobe.com/en_US/flashmediaserver/devguide/WSae44d1d92c7021ff-1f5381712889cd7b56-8000.html

Here is how the simple, before connect method to check bandwidth

https://www.wowza.com/docs/how-to-test-server-to-client-bandwidth-for-rtmp-clients

I think that camera.setQuality() will have an affect on a stream after you do netstream.publish()

Richard

You’re English is great. Thanks for the update.

Richard

i’m having some problems with converting the BWChecker to AS3.

this is what i’ve got :

var constring="rtmp://localhost/bwcheck";
var detected_bw:String;
var counter:Number=0;
var nc:NetConnection=new NetConnection;
nc.client=this;
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler );
function netStatusHandler (e:NetStatusEvent):void{
	trace("Level: "+e.info.level+" Code: "+e.info.code);
	if (e.info.code == "NetConnection.Connect.Success") {
		trace("--- connected to: " + nc.uri);	//this.uri
	}
}
function onBWCheck(latency:String):Number{
	trace("in onBWCheck");
	return ++counter; // Serverside, just ignore any return value, For now return the call count
}
function onBWDone(kbitDown, deltaDown, deltaTime, latency):void{
	trace("==>in onBW_DONE");
	trace("onBWDone: kbitDown:"+kbitDown+" deltaDown:"+deltaDown+" deltaTime:"+deltaTime+" latency:"+latency);
	//detected_bw = kbitDown;
	nc.close();
}
nc.connect(constring, true);
stop();

and i get this as a result (haven’t changed anything to serverside code, or is it necessary that i do that?):

in onBWCheck

Level: status Code: NetConnection.Connect.Success

— connected to: rtmp://localhost/bwcheck

ok , works like a charm now. Thanks a lot !

Hi Craigweb,

You may find netlimiter useful:

http://www.netlimiter.com

Regards,

Dean

Hi Charlie,

like balint.pelhos , I need to calculate the actual bandwidth after the stream has started without start another connection and generating an extra traffic.

I read your reply about it, but I’m not able to use IOPerformanceCounter interface like you suggested…

Is it possible have some indication or some reference how to implement it (server side and client side).

Thanks!

For using the bandwidth checker module, the instruction (posted below) asks for the FLVPlayback module to be removed. I would like to know why this needs to be done?

thanks

maple01

Configuration:

Create a folder named [install-dir]/applications/bwcheck

Create a folder named [install-dir]/conf/bwcheck

Copy [install-dir]/conf/Application.xml into new bwcheck config folder

Edit copied Application.xml file and remove the module reference to ModuleFLVPlayback and add the module reference below as the last entry in the section (it is important that it is the last entry):

A complete built version can be downloaded from here. Follow Charlie’s instructions at the top of the page to install.

Please let me know if there are any problems.

Roger.

This link is dead, can anyone help? Ive tried to compile it myself but im ignorant when it comes java. Thanks.

-jason

thanks! you guys are top notch support - jason

Hi CHarlie,

I have been trying to make the bandwidth test work before we go ahead and purchase the lincense but no luck. I work for a university and we have many extension workers with dial up connection and I have been working with Richard by email to test the bandwidth check but it seems impossible to get it done. I have the plug-in in lib folder and have appropriate video files for each bandwidth here is the code:

var bandwidthVer = “_100”;

if (detected_bw >= 800)

bandwidthVer = “_750”;

else if (detected_bw >= 550)

bandwidthVer = “_500”;

else if (detected_bw >= 300)

bandwidthVer = “_250”;

But on dial up modem still gets the the one with _750, I am soo frustrated here and want to know what am I doing wrong?

thanks ina dvance for your help.

Richard,

how do I know if bandwidthVer have default of “_750”?

thanks

The default is _100

Here is the code:

import flash.geom.*;

var nc:NetConnection;

var nsPlay:NetStream = null;

var serverName:String = “rtmp://server/video”;

var movieName:String = “Extremists”;

var duration:Number = 0;

var progressTimer:Number = 0;

var isPlaying:Boolean = true;

var isProgressUpdate:Boolean = false;

var fastSettings:Array = new Array();

var currFastDir:Number = 0;

var currFastIndex:Number = 0;

var scrubTimer:Number = 0;

var isScrubbing:Boolean = false;

var scrubTime:Number = 0;

var scrubIsPlaying:Boolean;

var stageListener:Object = new Object();

var saveVideoObjX:Number;

var saveVideoObjY:Number;

var saveVideoObjW:Number;

var saveVideoObjH:Number;

var adjVideoObjW:Number;

var adjVideoObjH:Number;

var videoSizeTimer:Number = 0;

var videoLastW:Number = 0;

var videoLastH:Number = 0;

var fullscreenCapable:Boolean = false;

var hardwareScaleCapable:Boolean = false;

function mainInit()

{

// get movie name from parameter is defined

if (_root.zmovieName != undefined)

movieName = _root.zmovieName;

// initialize player control events

_root.controls.doPlay.onPress = _root.doPlayToggle;

_root.controls.doRewind.onPress = _root.doRewind;

_root.slider.onPress = _root.startScrub;

_root.slider.onRelease = _root.stopScrub;

_root.slider.onReleaseOutside = _root.stopScrub;

// uncomment this to monitor frame rate and buffer length

//setInterval(_root, “updateStreamValues”, 500);

_root.connect.connectStr.text = serverName;

_root.connect.streamStr.text = movieName;

_root.connect.connectButton.onPress = _root.doConnect;

_root.doFullscreen.onPress = _root.enterFullscreen;

enablePlayControls(false);

stageListener.onFullScreen = enterLeaveFullscreen;

Stage.addListener( stageListener );

saveVideoObjX = videoObj._x;

saveVideoObjY = videoObj._y;

adjVideoObjW = (saveVideoObjW = videoObj._width);

adjVideoObjH = (saveVideoObjH = videoObj._height);

videoObj._visible = false;

fullscreenCapable = testVersion(9, 0, 28, 0);

hardwareScaleCapable = testVersion(9, 0, 60, 0);

}

function doConnect()

{

// connect to the Wowza Media Server

if (nc == null)

{

enablePlayControls(true);

nc = new NetConnection();

nc.onStatus = function(infoObject)

{

trace(“nc.onStatus: “+infoObject.code+” (”+infoObject.description+")");

for (var prop in infoObject)

{

trace("\t"+prop+":\t"+infoObject[prop]);

}

// once we are connected to the server create the nsPlay NetStream object

if (infoObject.code == “NetConnection.Connect.Success”)

{

enablePlayControls(true);

createPlayStream();

videoLastW = 0;

videoLastH = 0;

videoSizeTimer = setInterval(_root, “updateVideoSize”, 500);

}

else if (infoObject.code == “NetConnection.Connect.Failed”)

_root.prompt.text = “Connection failed: Try rtmp://[server-ip-address]/simplevideostreaming”;

else if (infoObject.code == “NetConnection.Connect.Rejected”)

_root.prompt.text = infoObject.description;

}

nc.connect(_root.connect.connectStr.text);

// uncomment this to monitor frame rate and buffer length

//debugInterval = setInterval(_root, “updateStreamValues”, 500);

_root.connect.connectButton.label = “Stop”;

}

else

{

videoObj.attachVideo(null);

videoObj.attachAudio(null);

videoObj.clear();

videoObj._visible = false;

if (videoSizeTimer)

clearInterval(videoSizeTimer);

videoSizeTimer = 0;

videoLastW = 0;

videoLastH = 0;

nc.close();

nc = null;

if (debugInterval > 0)

clearInterval(debugInterval);

debugInterval = 0;

enablePlayControls(false);

setProgress(0);

_root.connect.connectButton.label = “Play”;

_root.prompt.text = “”;

}

}

function enablePlayControls(isEnable:Boolean)

{

_root.controls.doPlay.enabled = isEnable;

_root.controls.doRewind.enabled = isEnable;

_root.doFullscreen._visible = isEnable & fullscreenCapable;

}

// function to monitor the frame rate and buffer length

function updateStreamValues()

{

var newVal:String = “”;

if (nsPlay != null)

newVal = (Math.round(nsPlay.currentFps1000)/1000)+" fps/"+(Math.round(nsPlay.bufferLength1000)/1000)+" secs";

fpsText.text = newVal;

}

// create the nsPlay NetStream object

function createPlayStream()

{

nsPlay = new NetStream(nc);

nsPlay.onStatus = function(infoObject)

{

trace("onStatus: ");

for (var propName:String in infoObject)

{

trace(" "+propName + " = " + infoObject[propName]);

}

if (infoObject.code == “NetStream.Play.Start”)

_root.isProgressUpdate = true;

else if (infoObject.code == “NetStream.Play.StreamNotFound” || infoObject.code == “NetStream.Play.Failed”)

_root.prompt.text = infoObject.description;

};

nsPlay.onMetaData = function(infoObject:Object)

{

trace(“onMetaData”);

// print debug information about the metaData

for (var propName:String in infoObject)

{

trace(" "+propName + " = " + infoObject[propName]);

}

// grab the movies duration from the metadata

if (_root.duration == 0)

{

_root.duration = infoObject.duration;

progressTimer = setInterval(_root, “updateProgress”, 250);

}

};

// print debug information when we encounter a cuePoint

nsPlay.onCuePoint = function(infoObject)

{

trace(“onCuePoint: “+infoObject.name+” (”+infoObject.type+")");

for(param in infoObject.parameters)

{

trace(" param: “+param+”="+infoObject.parameters[param]);

}

};

// print debug information when we play status changes

nsPlay.onPlayStatus = function(infoObject:Object)

{

trace(“onPlayStatus”);

for (var prop in infoObject)

{

trace("\t"+prop+":\t"+infoObject[prop]);

}

};

// set the buffer time and attach the video and audio

nsPlay.setBufferTime(3);

_root.videoObj.attachVideo(nsPlay);

_root.videoObj.attachAudio(nsPlay);

// start playback

_root.isProgressUpdate = false;

_root.isPlaying = true;

var bandwidthVer = “_100”;

if (detected_bw >= 800)

bandwidthVer = “_750”;

else if (detected_bw >= 550)

bandwidthVer = “_500”;

else if (detected_bw >= 300)

bandwidthVer = “_250”;

_root.connect.streamStr.text = _root.connect.streamStr.text+bandwidthVer;

nsPlay.play(_root.connect.streamStr.text);

}