Wowza Community

Wowza Default RTMP player very poor quality why?

hi wowza team

I am using wowza rtmp player but very poor quality.

How can I improve the quality of the player in?

Hello there.

Can you please provide a little more detail about the stream in question:

  1. What is the bandwidth in kbps / mbps

  2. What is the stream resolution set to?

  3. What is the codec of the stream? (H.264/AAC-44.1kHz/FPS/KeyFrame Intervals/etc…)

  4. Is the stream live or VOD?

  5. If live what is the source?

We look forward to hearing back from you and getting this issue resolved.

Kind regards,

Salvadore

only the quality problem with wowza rtmp player

flow, VLC, f4player no problem

modified Wowza RTMP player coding

VOD content

import flash.geom.*;
import com.wowza.encryptionAS3.TEA;
var nc:NetConnection;
var nsPlay:NetStream = null;
var sharedSecret:String = "#ed%h0#w@1"; //<--- SecureToken change here - set sharedSecret
var serverName:String = "rtmp://localhost:1935/vod";
var movieName:String = "mp4:sample.mp4";
var debugInterval:Number = 0;
var duration:Number = 0;
var progressTimer:Number = 0;
var isPlaying:Boolean = false;
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 saveStageW:Number;
var saveStageH: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;
var muted:Boolean=false;
var fullscreen:Boolean=false;
var knobWidth:Number;
var trackWidth:Number;
var trackX:Number;
var boundsWidth:Number;
var boundsRect:Rectangle;
var draggingBug:Boolean=false;
var sliderBugY:Number;
var silderBug:MovieClip;
var sliderTrack:MovieClip;
var videoSound:SoundTransform = new SoundTransform(0.5);
var playControlsX = playControls.x;
var playControlsY = playControls.y;
flash.system.Security.LOCAL_TRUSTED;
flash.system.Security.allowDomain('*');
	
mainInit();
viewbutton.addEventListener(MouseEvent.MOUSE_OVER, movieBar);
viewbutton.addEventListener(MouseEvent.ROLL_OUT, movieBarOut);
slider.addEventListener(MouseEvent.MOUSE_OVER, movieBar);
slider.addEventListener(MouseEvent.ROLL_OUT, movieBarOut);
playControls.addEventListener(MouseEvent.MOUSE_OVER, movieBar);
playControls.addEventListener(MouseEvent.ROLL_OUT, movieBarOut);
function movieBar (e:MouseEvent):void 
{
	if (playControlsY > playControls.y) {
		trace ("konum zaten yukarda:"+playControlsY);
	} else {
		trace ("konum yukari tasindi"+playControlsY);
		playControls.y = playControls.y - 30;
		slider.y = slider.y -30
	}
}
function movieBarOut (e:MouseEvent):void 
{
	if (playControlsY > playControls.y) {
		trace ("konum asahi tasindi");
		playControls.y = playControls.y + 30;
		slider.y = slider.y +30
	} else {
		trace ("konum zaten asagida");
	}
}
function mainInit()
{
	knobWidth=playControls.volumeContainer.sliderBug.width;
	trackWidth=playControls.volumeContainer.sliderTrack.width;
	trackX=playControls.volumeContainer.sliderTrack.x;
	boundsWidth=trackWidth-knobWidth;
	sliderBugY=playControls.volumeContainer.sliderBug.y;
	boundsRect=new Rectangle(trackX,sliderBugY,boundsWidth,0);
	trace(boundsRect);
	playerVersion.text = Capabilities.version+" (Flash-AS3)";
	stage.align = "TL";
	stage.scaleMode = "showAll";
	// get movie name from parameter is defined
	if (root.loaderInfo.parameters.zmovieName != undefined)
		movieName = root.loaderInfo.parameters.zmovieName;
	playControls.doPause.visible=false;
	// initialize player control events
	playControls.doPlay.addEventListener(MouseEvent.CLICK, doPlayToggle);
	playControls.doPause.addEventListener(MouseEvent.CLICK, doPlayToggle);
	playControls.doRewind.addEventListener(MouseEvent.CLICK, doRewind);
	playControls.doFullscreen.addEventListener(MouseEvent.CLICK, enterFullscreen);
	
	slider.addEventListener(MouseEvent.MOUSE_DOWN, startScrub);
	slider.addEventListener(MouseEvent.MOUSE_UP, stopScrub);
	
	playControls.volumeContainer.sliderBug.addEventListener(MouseEvent.MOUSE_DOWN, volumeMouseDown);
	playControls.volumeContainer.sliderBug.addEventListener(MouseEvent.MOUSE_UP, volumeMouseUp);
	addEventListener(MouseEvent.MOUSE_UP, volumeMouseUp);
	playControls.volumeContainer.addEventListener(MouseEvent.CLICK, volumeClick);
	addEventListener(MouseEvent.MOUSE_MOVE, volumeMouseMove);
	playControls.doMute.visible=false;
	playControls.doMute.addEventListener(MouseEvent.MOUSE_DOWN, muteSound);
	playControls.doUnmute.addEventListener(MouseEvent.MOUSE_DOWN, muteSound);
	// uncomment this to monitor frame rate and buffer length
	setInterval(updateStreamValues, 500);
	
	connect.connectStr.text = serverName;
	try {
		var str:String=ExternalInterface.call("getVODRTMPServer");
		if(str!=null && str!="") {
			connect.connectStr.text = str;
		}		
	} 
	catch (error:Error) {
	}
	connect.streamStr.text = movieName;
	try {
		var streamStr:String=ExternalInterface.call("getVODRTMPStream");
		if(str!=null && streamStr!="") {
			connect.streamStr.text = streamStr;
		}		
	} 
	catch (error:Error) {
	}
	connect.connectButton.addEventListener(MouseEvent.CLICK, doConnect);
	enablePlayControls(false);
	
	stage.addEventListener( FullScreenEvent.FULL_SCREEN, enterLeaveFullscreen );
	saveVideoObjX = videoObj.x;
	saveVideoObjY = videoObj.y;
	saveStageW = stage.width;
	saveStageH = stage.height;
	adjVideoObjW = (saveVideoObjW = videoObj.width);
	adjVideoObjH = (saveVideoObjH = videoObj.height);
	//videoObj.visible = false;
	
	fullscreenCapable = testVersion(9, 0, 28, 0);
	hardwareScaleCapable = testVersion(9, 0, 60, 0);
	setProgress(0);
}
function stopAll()
{
	if(nsPlay != null) {
		playControls.doPause.visible=false;
		playControls.doPlay.visible=true;
		setProgress(0);
		videoObj.attachNetStream(null);
		videoObj.clear();
		videoObj.visible = false;
		if (videoSizeTimer)
			clearInterval(videoSizeTimer);
		videoSizeTimer = 0;
		videoLastW = 0;
		videoLastH = 0;
		duration = 0;
		nsPlay = null;
	}
	if(nc!=null) {
		nc.close();
		nc = null;
	}
	if (debugInterval > 0)
		clearInterval(debugInterval);
	debugInterval = 0;
	
	enablePlayControls(false);
	connect.connectButton.label = "Start";
	prompt.text = "Disconnected";
}
function setServer(server:String)
{
	connect.connectStr.text=server;
}
function setStream(stream:String)
{
	connect.streamStr.text=stream;
}
function volumeMouseDown(event:MouseEvent)
{
	if(!isPlaying) {
		return;
	}
	playControls.volumeContainer.sliderBug.y=sliderBugY;
	playControls.volumeContainer.sliderBug.startDrag(false, boundsRect);
	draggingBug=true;
	
	nsPlay.soundTransform = new SoundTransform(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	muted = false;
	trace(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	playControls.doMute.visible=false;
	playControls.doUnmute.visible=true;
}
function volumeMouseMove(event:MouseEvent)
{
	playControls.volumeContainer.sliderBug.y=sliderBugY;
	if(!isPlaying || !draggingBug ) {
		return;
	}
	nsPlay.soundTransform = new SoundTransform(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	muted = false;
		trace(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	playControls.doMute.visible=false;
	playControls.doUnmute.visible=true;
}
function volumeMouseUp(event:MouseEvent)
{
	if(!isPlaying || !draggingBug) {
		return
	}
	trace(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	playControls.volumeContainer.sliderBug.stopDrag();
	draggingBug=false;
}
function volumeClick(event:MouseEvent)
{
	if(!isPlaying || draggingBug) {
		return
	}
	nsPlay.soundTransform = new SoundTransform(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	playControls.doMute.visible=false;
	playControls.doUnmute.visible=true;
}
function muteSound(event:MouseEvent)
{
	if(!isPlaying) {
		return;
	}
	if(muted) {
		muted = false;
		playControls.doMute.visible=false;
		playControls.doUnmute.visible=true;
		nsPlay.soundTransform = new SoundTransform(playControls.volumeContainer.sliderBug.x/playControls.volumeContainer.sliderTrack.width);
	} else {
		muted = true;
		playControls.doMute.visible=true;
		playControls.doUnmute.visible=false;
		nsPlay.soundTransform = new SoundTransform(0);
	}
}
function ncOnStatus(infoObject:NetStatusEvent)
{
	trace("nc.onStatus: "+infoObject.info.code+" ("+infoObject.info.description+")");
	for (var prop in infoObject)
	{
		trace("\t"+prop+":\t"+infoObject.info[prop]);
	}
	
	// once we are connected to the server create the nsPlay NetStream object
	if (infoObject.info.code == "NetConnection.Connect.Success")
	{
		if (infoObject.info.secureToken != undefined) //<--- SecureToken change here - respond with decoded secureToken
		{
			var secureResult:Object = new Object();
			secureResult.onResult = function(isSuccessful:Boolean)
			{
				trace("secureTokenResponse: "+isSuccessful);
			}
			nc.call("secureTokenResponse", new Responder(secureResult.onResult), TEA.decrypt(infoObject.info.secureToken, sharedSecret));
		}
		enablePlayControls(true);
		createPlayStream();
		videoLastW = 0;
		videoLastH = 0;
		videoSizeTimer = setInterval(updateVideoSize, 0);
	}
	else if (infoObject.info.code == "NetConnection.Connect.Failed")
		prompt.text = "Connection failed: Try rtmp://[wowza-ip-address]/vod";
	else if (infoObject.info.code == "NetConnection.Connect.Rejected")
		prompt.text = infoObject.info.description;
}
function doConnect(event:MouseEvent)
{
	// connect to the Wowza Media Server
	if (nc == null)
	{
		enablePlayControls(true);
		nc = new NetConnection();
		var str:String  = connect.connectStr.text.substr(0,5) ;
		if(str.toLowerCase() == "rtmps")
		{
			nc.proxyType="best";
		}
		
		nc.addEventListener(NetStatusEvent.NET_STATUS, ncOnStatus);
		nc.connect(connect.connectStr.text);
				
		// uncomment this to monitor frame rate and buffer length
		//debugInterval = setInterval(updateStreamValues, 500);
		
		connect.connectButton.label = "Stop";
		prompt.text = "Connected";
	}
	else
	{
		stopAll();
	}
}
function enablePlayControls(isEnable:Boolean)
{
	playControls.doPlay.enabled = isEnable;
	playControls.doRewind.enabled = isEnable;
	playControls.doFullscreen.visible = isEnable && fullscreenCapable;
}
// function to monitor the frame rate and buffer length
function updateStreamValues()
{
	var newVal:String = "";
	if (nsPlay != null && isPlaying) {
		newVal = (Math.round(nsPlay.currentFPS*1000)/1000)+" fps/"+(Math.round(nsPlay.bufferLength*1000)/1000)+" secs";
		playControls.currentBitrate.text = "Current bitrate: "+Math.round((nsPlay.info.playbackBytesPerSecond*8)/1000)+"kbps";
	} else {
		playControls.currentBitrate.text = "";
	}
}
function nsOnStatus(infoObject:NetStatusEvent)
{
	trace("onStatus: ");
	for (var propName:String in infoObject.info)
	{
		trace("  "+propName + " = " + infoObject.info[propName]);
	}
	if (infoObject.info.code == "NetStream.Play.Start")
		isProgressUpdate = true;
	else if (infoObject.info.code == "NetStream.Play.StreamNotFound" || infoObject.info.code == "NetStream.Play.Failed")
		prompt.text = "Source stream or file could not be found or access was denied.";
	else
		prompt.text = infoObject.info.description;
}
// create the nsPlay NetStream object
function createPlayStream()
{
	trace ("createPlaystream");
	nsPlay = new NetStream(nc);
	nsPlay.addEventListener(NetStatusEvent.NET_STATUS, nsOnStatus);
	
	var nsPlayClientObj:Object = new Object();
	nsPlay.client = nsPlayClientObj;
	
	nsPlayClientObj.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 (duration == 0)
		{
			duration = infoObject.duration;
			progressTimer = setInterval(updateProgress, 250);
		}		
	};		
	
	// print debug information when we encounter a cuePoint
	nsPlayClientObj.onCuePoint = function(infoObject)
	{
		trace("onCuePoint: "+infoObject.name+" ("+infoObject.type+")");
		var param;
		for(param in infoObject.parameters)
		{
			trace("  param: "+param+"="+infoObject.parameters[param]);
		}
	};
	
	// print debug information when we play status changes
	nsPlayClientObj.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.bufferTime = 3;
	videoObj.attachNetStream(nsPlay);
	videoSound = new SoundTransform(0.5);
	nsPlay.soundTransform = videoSound;
	playControls.doPause.visible=true;
	playControls.doPlay.visible=false;
	// start playback
	isProgressUpdate = false;
	isPlaying = true;
	nsPlay.play(connect.streamStr.text);
	
}
// play video (no fast play)
function doPlay()
{
	if(nsPlay != null) {
		currFastDir = 0;
		currFastIndex = 0;
		
		trace("doPlay");
	
		isProgressUpdate = false;
		if (!isPlaying)
			nsPlay.resume();
		nsPlay.seek(nsPlay.time);
		isPlaying = true;
	}
}
// event for clicking the play button
// if we are paused or in fast play mode just play the video
// else pause the video
function doPlayToggle(event:MouseEvent)
{
	if(nsPlay == null) {
		doConnect(event);
	}
	if (!isPlaying)
	{
		playControls.doPause.visible=true;
		playControls.doPlay.visible=false;
		doPlay();
	}
	else
	{
		playControls.doPause.visible=false;
		playControls.doPlay.visible=true;
		isProgressUpdate = false;
		isPlaying = false;
		nsPlay.pause();
	}
}
// rewind to the beginning of the movie and start playing
function doRewind(event:MouseEvent)
{
	isProgressUpdate = false;
	nsPlay.seek(0);
}
// update the progress bar
function setProgress(timecode:Number)
{
	var totalWidth:Number = slider.sliderBack.width;
	
	var newTimecode:Number = timecode;
	
	var newWidth = (totalWidth*newTimecode)/duration;
	if (newWidth > totalWidth)
		newWidth = totalWidth;
	
	if (!isScrubbing && isProgressUpdate)
		slider.sliderSlide.width = newWidth;
}
function updateProgress()
{
	if(nsPlay != null)
		setProgress(nsPlay.time);
}
// calculate the movie scrub location based on current mouse position
function calcScrub()
{
	var xpos:Number = slider.mouseX;
	var xmax:Number = slider.width;
	
	if (xpos < 0)
		xpos = 0;
	else if (xpos > xmax)
		xpos = xmax;
		
	scrubTime = (duration*xpos)/xmax;
	slider.sliderSlide.width = xpos;
}
// update the scrub location as we are scrubbing
function updateScrub()
{
	calcScrub();
}
// start scrubbing
function startScrub(event:MouseEvent)
{
	scrubTimer = setInterval(updateScrub, 250);
	isScrubbing = true;
	scrubTime = -1;
	calcScrub();
	
	scrubIsPlaying = isPlaying;
	if (isPlaying)
		nsPlay.pause();
}
// stop scrubbing and setup new play position
function stopScrub(event:MouseEvent)
{
	if (scrubTimer)
		clearInterval(scrubTimer);
	scrubTimer = 0;
	
	if (scrubTime != -1)
	{
		isProgressUpdate = false;
		if (scrubIsPlaying)
		{
			isPlaying = true;
			nsPlay.resume();
			nsPlay.seek(scrubTime);
		}
		else
		{
			isPlaying = false;
			nsPlay.seek(scrubTime);
		}
	}
	
	isScrubbing = false;
}
function updateVideoSize()
{
	//trace("updateVideoSize: "+stage["displayState"]);
	
	// when we finally get a valid video width/height resize the video frame to make it proportional
	if (videoObj.videoWidth != videoLastW || videoObj.videoHeight != videoLastH)
	{
		videoLastW = videoObj.videoWidth;
		videoLastH = videoObj.videoHeight;
		var videoAspectRatio:Number = videoLastW/videoLastH;
		var frameAspectRatio:Number = saveVideoObjW/saveVideoObjH;
		
		adjVideoObjW = saveVideoObjW;
		adjVideoObjH = saveVideoObjH;
		if (videoAspectRatio > frameAspectRatio)
			adjVideoObjH = saveVideoObjW/videoAspectRatio;
		else
			adjVideoObjW = saveVideoObjH*videoAspectRatio;
		
		videoObj.width = adjVideoObjW;
		videoObj.height = adjVideoObjH;
		videoObj.y = saveVideoObjY + (saveVideoObjH - adjVideoObjH)/2;
		videoObj.x = saveVideoObjX + (saveVideoObjW - adjVideoObjW)/2;
		videoObj.visible = true;
	}
}
// show/hide the controls when we enter/leave fullscreen
function hideAllControls(doHide:Boolean)
{
	//fpsText.visible = !doHide;
	//logo.visible = !doHide;
	connect.visible = !doHide;
	controls.visible = !doHide;
	playControls.doFullscreen.visible = !doHide;
	slider.visible = !doHide;
	backdrop.visible = !doHide;
	playerVersion.visible = !doHide;
}
function enterLeaveFullscreen(fsEvent:FullScreenEvent)
{
	trace("enterLeaveFullscreen: "+fsEvent.fullScreen);
	
	hideAllControls(fsEvent.fullScreen);
	if (!fsEvent.fullScreen)
	{
		// reset back to original state
		stage.scaleMode = "showAll";
		videoObj.width = adjVideoObjW;
		videoObj.height = adjVideoObjH;
		videoObj.y = saveVideoObjY + (saveVideoObjH - adjVideoObjH)/2;
		videoObj.x = saveVideoObjX + (saveVideoObjW - adjVideoObjW)/2;
	}
}
function enterFullscreen(event:MouseEvent)
{
	trace("enterFullscreen: "+hardwareScaleCapable);
	if (hardwareScaleCapable)
	{
		// best settings for hardware scaling
		videoObj.smoothing = false;
		videoObj.deblocking = 0;
		
		// set the video frame size to the actual video size
		videoObj.width = videoObj.videoWidth;
		videoObj.height = videoObj.videoHeight;
		
		// grab the portion of the stage that is just the video frame
		stage["fullScreenSourceRect"] = new Rectangle(
			videoObj.x, videoObj.y, 
			videoObj.width, videoObj.height);
	}
	else
	{
		stage.scaleMode = "showAll";
		
		var videoAspectRatio:Number = videoObj.width/videoObj.height;
		var stageAspectRatio:Number = saveStageW/saveStageH;
		var screenAspectRatio:Number = Capabilities.screenResolutionX/Capabilities.screenResolutionY;
		
		// calculate the width and height of the scaled stage
		var stageObjW:Number = saveStageW;
		var stageObjH:Number = saveStageH;
		if (stageAspectRatio > screenAspectRatio)
			stageObjW = saveStageH*screenAspectRatio;
		else
			stageObjH = saveStageW/screenAspectRatio;
		// calculate the width and height of the video frame scaled against the new stage size
		var fsVideoObjW:Number = stageObjW;
		var fsVideoObjH:Number = stageObjH;
		if (videoAspectRatio > screenAspectRatio)
			fsVideoObjH = stageObjW/videoAspectRatio;
		else
			fsVideoObjW = stageObjH*videoAspectRatio;
		
		// scale the video object
		videoObj.width = fsVideoObjW;
		videoObj.height = fsVideoObjH;
		videoObj.x = (stageObjW-fsVideoObjW)/2.0;
		videoObj.y = (stageObjH-fsVideoObjH)/2.0;
	}
	stage["displayState"] = "fullScreen";
	
}
function testVersion(v0:Number, v1:Number, v2:Number, v3:Number):Boolean
{
	var version:String = Capabilities.version;
	var index:Number = version.indexOf(" ");
	version = version.substr(index+1);
	var verParts:Array = version.split(",");
	
	var i:Number;
	
	var ret:Boolean = true;
	while(true)
	{
		if (Number(verParts[0]) < v0)
		{
			ret = false;
			break;
		}
		else if (Number(verParts[0]) > v0)
			break;
			
		if (Number(verParts[1]) < v1)
		{
			ret = false;
			break;
		}
		else if (Number(verParts[1]) > v1)
			break;
			
		if (Number(verParts[2]) < v2)
		{
			ret = false;
			break;
		}
		else if (Number(verParts[2]) > v2)
			break;
			
		if (Number(verParts[3]) < v3)
		{
			ret = false;
			break;
		}
		break;
	}
	trace("testVersion: "+Capabilities.version+">="+v0+","+v1+","+v2+","+v3+": "+ret);
	
	return ret;
}
try {
		ExternalInterface.addCallback("playerStop", stopAll);
		ExternalInterface.addCallback("setStream", setStream);
		ExternalInterface.addCallback("setServer", setServer);
} catch(error:Error) {
	prompt.text=""+error;
}

Are you able to reproduce the problems you experience with the default player that ships with Wowza? [install-dir]/examples/VideoOnDemandStreaming/FlashRTMPPlayer/player.html

If you have the same issues with the default player, please send your findings to support@wowza.com to open a ticket.

You can use the code in the default player as a starting place/reference to develop a custom player. Assisting in the development of a custom player is beyond the scope of the support forum.

You will find many talented developers eager to assist you in the find a consultant forum

Kind regards,

Salvadore