Collecting streaming media measures from Flash players

HTML5 media tags have a standardized API that enables the AppMon JavaScript Agent to collect metrics for streaming media out of the box. However, no such standardized API is available for the many different Flash media players that populate the web, which makes it unfeasible to support collection of streaming media metrics for Flash media players out of the box.

As long as the Flash media player offers a public API, either for ActionScript or for JavaScript, it is usually straightforward to implement the missing link between the Flash media player and the AppMon Server, because the different APIs offer the same functionality and only syntax details vary among the different implementations. This topic describes how the implementation would work in principle. It does not provide implementation details for a specific Flash player.

Requirements

AppMon

The requirements for the AppMon installation are as follows:

  • The AppMon release must be 5.5 or later.
  • A UEM license must be available.
  • The AppMon JavaScript ADK must be embedded in the HTML pages that contain the Flash player. AppMon 6.5 and later bundles it with the JavaScript Agent, so this is no longer necessary.

Flash media player

The requirements for the Flash media player are as follows:

  • The player must have a public API that can be used to access the state of the media player. Manipulation of the state is not necessary.
  • An Event-API is available to register event listeners for the player like start and stop, and media stream events like ready for playback and buffering start. Ways to implement the desired functionality without listening to events like polling the state of the media player are not covered in this guide, because events are widely supported.

Some media players that fulfill these requirements are:

Required events

It is assumed that the Flash media player allows registering listeners for the following events.

Event Description
beforeStart This event happens before the start of the playback, when the media stream is loaded. It enables accessing the metadata (URL, type, duration, autostart) of the media stream.
stateChange This event is called whenever the state of the player changes. Available values for this event are the new state and the old state. Possible states are:
  • IDLE ‐ The initial state of the player.
  • BUFFERING ‐ The player has to stop playback and wait until additional data is loaded.
  • PLAYING ‐ The player is playing the media stream.
playing This event happens at least once every second while the playback of the media stream is in progress. It updates timing information (maxPlayTime, playtime). If a playing event is not present, it can be simulated using the setInterval JavaScript function.
complete This event happens when playback of the media stream is complete.
error This event happens when a error occurs during playback.

The exact naming and syntax for registering event listeners differs among media players. Most players support the previously listed events in some way. A larger API is generally offered to deal with advanced use cases such as playlist handling or starting playback of a different media stream in the same player. Refer to the medial player or API documentation for more information.

Required values

The values that must be collected from the Flash player to submit streaming media information to AppMon are described in JavaScript ADK and JavaScript Ajax ADK.

Implementation

Implementation involves three steps:

  1. The local variables that track the state are initialized and the event listeners are registered.
  2. The player plays the streaming media and, when an event occurs, calls the callback functions that were registered in step 1. Depending on the type of events that occur and the player state,  information is sent to the AppMon Server.
  3. Collected values are reported to AppMon whenever the page is unloaded. It is assumed that only one video is displayed per page.

Each step is described in detail below. The example code is from the plugin developed for the JWPlayer. Comments and some special case handling are removed from the example code for clarity. It is recommended that you review the fully detailed, commented code of the media player implementation before starting with your own implementation.

Step 1. Initialize Variables and Register Event Listeners

When the media player (or the page containing the media player) is loaded, variables for each of the values that need to be collected are initialized.

JWPlayer code example - initialize of variables

var mediaType = null;
var source = null;
var duration = -1;
var playTime = 0;
var playTimeForSending = 0;
var maxPlayTime = 0;
var autoplay = config.autoplay; // this information can be retrieved from the player configuration right away
var watchedTillEnd = false;
var bufferingCount = 0;
var bufferingTime = 0;

Event listeners are registered for the player. Because the JWPlayer has a separate function for each type of statechange, the same function is registered for all state changes.

JWPlayer code example - register events

// assign event listeners to player
player.onReady(setup);

function setup(evt) {
	player.onComplete(onCompleteEvent);
	player.onTime(onTimeEvent);
	player.onBeforePlay(updateVideoInformation);
	player.onError(onErrorEvent);
	player.onMeta(updateVideoInformation);

	// state change events
	player.onBuffer(onStateChange);
	player.onIdle(onStateChange);
	player.onPlay(onStateChange);
	player.onPause(onStateChange);
};

Step 2. Call Event Listeners

The player calls event listeners whenever an event occurs during media playback. The following table describes what actions need to be taken whenever an event occurs. Some actions are only to be performed if a certain condition is fulfilled. In that case, the condition is described in the Condition column.

beforeStart event

Event Condition Actions
beforeStart Source, type, duration, and userTriggered are retrieved from the Flash player and stored in the respective variables. The other variables are initialized to false or 0, respectively.
JWPlayer code example - beforeStart event listener
function updateVideoInformation() {
	var videoInformation = player.getPlaylist()[0];
	if (!mediaType) {
		if (videoInformation.type == "video") {
			mediaType = "_video_";
		} else if (videoInformation.type == "audio") {
			mediaType = "_audio_";
		}
	}

	if (!source && videoInformation.file) {
		source = videoInformation.file;
	}

	if (duration < 0 && videoInformation.duration > 0) {
		duration = Math.round(videoInformation.duration);
	}
}

stateChange event

Event Condition Actions
stateChange If new state is BUFFERING Increase bufferingCount by 1. Store current timestamp as bufferingStartTime.
If new state is PLAYING and previous state was BUFFERING. Calculate the duration of the buffer event, based on the stored bufferingStartTime and the current timestamp, and add it to bufferingTime.
JWPlayer code example - stateChange event listener
function onStateChange(stateChange) {
	if (stateChange.newstate == "BUFFERING") {
		bufferingCount++;
		bufferingStart = getCurrentTime();
	} else if (stateChange.oldstate == "BUFFERING") {
		bufferingTime += getCurrentTime() - bufferingStart;
		bufferingStart = -1;
	}
}

playing event

Event Condition Actions
playing Add the time elapsed between the current playing event and the previous playing event to playTime.
If current media stream position is greater than maxPlayTime Set maxPlayTime to the current media stream position.
JWPlayer code example - playing event listener
function onTimeEvent(mediaTime) {
	if (Math.round(mediaTime.position) > maxPlayTime) {
		maxPlayTime = Math.round(mediaTime.position);
	}
	var currentTime = getCurrentTime();
	if (lastTimeEvent > 0) {
		playTime += currentTime - lastTimeEvent;
	}
	lastTimeEvent = currentTime;
}

complete event

Event Condition Actions
complete Set watchedCompletely to true, and set maxPlayTime to the duration of the video to prevent inconsistencies.
JWPlayer code example - complete event listener
function onCompleteEvent() {
	maxPlayTime = duration;
	watchedTillEnd = true;
}

error event

Event Condition Actions
error Report the error, using the AppMon JavaScript ADK.
JWPlayer code example - error event listener
function onErrorEvent(message) {
	dynaTrace.reportError(message);
}

Step 3. Report Collected Values to the AppMon Server

Assuming the Flash media player only replays a single video, collected values should be reported to the AppMon Server before the onbeforeUnload event. The easiest way to achieve this is to use the function addPageLeavingListener() provided by the AppMon ADK, as shown in the following example.

JWPlayer code example - sending streaming media information

dynaTrace.addPageLeavingListener(reportMediaStateToDynaTraceAgent);

function reportMediaStateToDynaTraceAgent() {
	dynaTrace.addStreamingNode(source, duration, autoplay, watchedTillEnd,
		maxPlayTime, playTime, bufferingCount, bufferingTime, mediaType);
}