Implementation of Stream Measurement
Please check the actual "Implementation of Stream Measurement" within each SDK-package
The SDK-package now contains the latest implementation documentation, as well as integration examples on a more detailed level.
This website will be closed soon
Implementation of Stream Measurement
Version | 2.3 |
|---|---|
Date | 11.11.2019 |
Author | Kantar Media Division |
Version history
Version | Date | Author | Comments |
|---|---|---|---|
0.1 | 23.05.2005 | Christopher Wirtz | Initial |
0.5 | 26.05.2005 | Christopher Wirtz | Changes |
1.0 | 02.06.2005 | Christopher Wirtz | Release |
1.1 | 12.03.2007 | Christopher Wirtz | Flash added |
1.2 | 06.07.2009 | Christopher Wirtz | Review/Changes |
1.3 | 14.07.2009 | Christopher Wirtz | Added Example to set the „duration“ manually in ActionScript |
1.4 | 29.06.2010 | Christopher Wirtz | Unload Delay |
1.5 | 02.11.2010 | Frank Kammann | Add Example using a NetStreamAdapter, Streaming Segments and parallel Streams |
1.6 | 14.03.2011 | Frank Kammann | Description of the general Operation (API) and Information on the Security Settings for Flash |
1.7 | 17.09.2012 23.10.2012 | Christopher Wirtz Ralf Cornehl | Adapting the position-based Stream Measurement to event-based Measurement Review, Adapting Explanations |
1.8 | 04.12.2012 04.12.2012 | Frank Kammann Ralf Cornehl | Mobile Streaming added Review, Adapting Explanations, Translation into English |
1.9 | 13.05.2013 13.05.2013 26.09.2013 | Frank Kammann Katrin Joachimsky Ralf Cornehl | Chapter HTML5 added Translation into English Adapting Stream Name Guidelines |
2.0 | 22.01.2014 10.11.2014 19.08.2015 | Hendrik Vermeylen Ralf Cornehl Ralf Cornehl | Offline Mode for App Streaming Opt-Out Method URL-scheme added for iOS |
2.1 | 25.09.2015 | Ralf Cornehl | iOS9 Support (URL-Scheme-White-listing, ATS, Bitcode) |
2.2 | 18.10.2017 | Marc Born | Android Streaming Sensor now uses Singleton template for creation |
2.3 | 11.11.2019 | Christopher Kirch | Implementation Streaming for Cordova |
Content
- 1 Please check the actual "Implementation of Stream Measurement" within each SDK-package
- 2 Implementation of Stream Measurement
- 3 Introduction
- 4 Concept of Measurement
- 5 Implementation via Javascript for any Player (also proprietary ones)
- 6 Implementation via Javascript (Windows Media player)
- 7 Implementation via HTML5
- 8 Implementation in Flash
- 9 Advanced Topics
- 10 Mobile App Streaming
- 10.1 Features on Platforms
- 10.2 Information (optional)
- 10.3 Opt-Out
Introduction
Whether news shows, product presentations or online radio programs - all are now using audio and video streams as medium of communication.
Even more than on the static pages, not only the number of visitors but also the behavior of users within a stream is of interest. For how long the clip was actually viewed, which sections were of particular interest and which were not?
When streaming media is called from a web site that is composed by the COM model and/or Flash, it is not only possible to track the number of users, but also watching the users’ behavior.
This document describes the integration of streaming measurement for different applications.
Concept of Measurement
In order to measure any streaming content, a sensor on the client side is necessary, which measures which sequences of the stream were played by the user.
These sequences can be defined by time intervals in seconds - therefore, the player or the playing instance must be able to provide a method for delivering the actual position on the stream in seconds.
The regular reading of the current position allows the tracking of all actions on a stream. Winding operations can be identified, if there are unexpected jumps in reading out the position. Stop or pause operations are identified by the fact, that the current position will not change.
User actions and operations like stop or pause are not measured directly (not player event based) but are instead derived from measuring the current position on stream.
The following chart shows the architecture of the API:
Gliffy Diagram is only supported by the cloud editor
Because Forge macros arent supported by the legacy editor, you'll need to convert this content to the cloud editor to display this macro properly. Find out more about converting to the cloud editorThe simplicity of the API and the concept lead to the following features:
Any desired streaming content, that is able to provide the current position in seconds on the stream, can be measured.
The API can easily be ported to other programming languages.
The same method is used in a cross-technology manner, which makes the same streaming content comparable even on different frameworks and technologies.
Basic Use of the API
The following discussion is presented in JavaScript syntax. The procedure is more or less the same in any programming language used.
// 1. Instantiate the API object
var sensors = new SpringStreams("site code");
// 2. Create a description object for streaming content
var desc = {
"stream":"videos/mystream",
"duration":600, // in seconds
"sx":video.width,
"sy":video.height
};
// 3. Provide a content object
var content = ...; // Any object, which is able to deliver the current position on the stream in seconds
// 4. Register the content with the description object on the sensor
var stream = sensors.track(content, desc);
Remarks:
to 1: Instantiate the API object
The correct site code must be setup. The site code is delivered by the owner of the streaming solution.
var sensors = new SpringStreams("site code");One instance of the object
SpringStreamshas to be setup once on the framework. From there, one or more streams can be transmitted to the measurement by thetrackmethod.
to 2: Create a description object for streaming content
In the description object, at least the name of the stream must be given
var desc = { "stream":"videos/mystream", "duration":600 // in seconds };With the description object more information about the streaming content can be passed to the API. The following variables are permitted or can be understood by the measurement system:
Variable | Optional | Description |
|---|---|---|
| No | Name of the stream, which is ideally given as a hierarchy. Example: In general there is no limitation of the charset – conform to the JSON standard http://json.org – , but for having a better interpretation of stream paths in scores we advice to use the described standards below. The allowable character set for all values in the tagging is UTF-8. It is however recommended to limit to the following characters: a-z The slash "/" is used as a separator within the |
| Yes | The duration must be setup if there's no adapter implementation. |
| Yes | Any value, that makes a statement about the content type can be used |
| Yes | Any value, that makes a statement about the content quality can be used |
| Yes | The width of the stream window - if it's a movie |
| Yes | The height of the stream window - if it's a movie |
to 3: Provide a content object
The only requirement of the streaming API for this object is delivering the current position on a stream in seconds. Depending on the programming language used certain technical software solutions are possible, such as the implementation of interfaces or the implementation of adapter classes.
var content = ...;
to 4: Register the content with the description object on the sensor
In the next step the streaming content and the description object can be transmitted to the API method
track. From this point on the current position on the stream is tracked. At this point it's possible to measure several parallel streams, where each additional streaming content with the accompanying description object is given to thetrackmethod.
var stream = sensors.track(content, desc);
The measurement of individual streams may be stopped at any time by calling the method
Stream.stop().
Internal Function Description of the API
After the streaming content with the accompanying description object has been passed to the track method, the current position on the streaming content is queried every 200ms. Internally, all intervals are collected, which were viewed by the user on the stream. At a constant viewing this is one interval.
Once it's determined that the current position changes by more than 1 second to the expected position a start, stop or winding event or even a buffering phase can be assumed. In this case, a new interval is created.
An interval is defined as:
[start, end, timestamp]
All the collected usage information of the measured streams are encoded in an HTTP request and regularly transmitted to the measuring system. The following rules apply:
at each interaction (start, stop or winding events or buffering phase) an update is sent immediately.
at a constant viewing at least every 20 seconds.
Data Transport
// System Object
[{"sx":1280,
"sy":1024,
"pl":"FlashPlugin",
"plv":"WIN 10,0,45,2"
},
// Usage Information
{"stream":"spring/teststream",
"dur":"600",
"sx":"400",
"sy":"300",
"uid":"267fgut",
"vt":356,
"pst":[[0,0,"kzog7e"],[22,378,"kzog7e"]]
}]
Two objects are sent by the data transport:
The system object that contains information such as screen resolution, player name and player version.
The usage information of a measurement
The description of the Encoding for the HTTP request is not part of this documentation. The request is designed in a manner that the variables are still clearly identifiable during debugging activities.
Implementation via Javascript for any Player (also proprietary ones)
Prior to using the springStreams-functions the Javascript-library must be loaded.
This is achieved by the following script-tag:
<script src=".../springstreams.js"></script>
The springStreams-functions are provided by the class SpringStreams. The code of a site will be passed on with the creation of an object of this class:
var sensors = new SpringStreams("test");
test = The site code in this case is “test”. You have to replace the site code "test" by the site code (unique name provided by Kantar) for the measured site.
To measure any player – even proprietary ones – an adapter to the specific player can be used to pass on data to the sensors of the measurement system. This adapter provides the following three functions:
var myAdapter = {
"getMeta" : function(id) {
return {
"pl" :"own player",
"plv" :"version1",
"sx" : screen.width,
"sy" : screen.height
}
},
"getDuration" : function(id) {
return streamlength in seconds;
},
"getPosition" : function(id) {
return new Date().getTime() / 1000;
}
};
1. The function getMeta is used to acquire a description of the player and the available screen area. By calling this function a return of an object with the following attributes is expected:
| player description |
| player version |
| screen width in pixel |
| screen height in pixel |
2. The function getDuration is used to acquire the total duration of the stream in seconds. If this cannot be done (because it is e.g. a live stream) 0 should be returned.
3. The function getPosition is used to acquire the current position in the stream. The function delivers the current play position in seconds. This function is also used to determine the intervals within the streams being played, skipped or stopped.
By calling the object to be measured (from the first parameter of the call to sensors.track(…)) it will be transmitted to all functions.
The self-created adapter can now be used for the measurement:
In the next step the stream content, the description object and the adapter can be transmitted to the API method track.
sensors.track(someObject, desc, myAdapter);
The measurement can be monitored by using the method debug on the SpringStreams object:
sensors.debug = function(v) {
window.status = " " + v;
}
Upon each transmission of the sensor to the measurement system this method is attached as a parameter (string) to the URL called.
SpringStreams does not intervene with the event model of the surrounding document. Therefore it is necessary to notify the sensors of any termination event of the streams by using events outside of the player. The most simple option for such a method is the insertion of an unload function by calling the method sensors.unload(), when the website is left by the user:
function unload() {
sensors.unload();
}
Because the browser will close the web site after the unload sequence is finished, it is possible that the closing counting impulse was not committed. An improvement can be achieved by inserting a piece of code at the end of the unload sequence.
function unload() {
sensors.unload();
// give time for submission
var start= new Date(); var now = null; do now = new Date();
while(now-start < 100);
}
To do so, this function can be added into the body tag:
<body onunload="unload();">
Single streams can also be terminated directly, for example by changing the play list:
var stream = sensors.track(someObject, desc, myAdapter);
...
stream.stop();
For other embedded players than the WMP, an adapter can be used. Find below an example for the Real Player with the id rvplayer:
sensors.track(rvplayer, description, sensors.RVStreamAdapter);
Example for a proprietary player
<html>
<head>
<title>spring sensors</title>
<script src="springstreams.js"></script>
</head>
<body onunload="unload();">
<script type="text/javascript">
var sensors = new SpringStreams("test");
var adapter = {
"getMeta" : function() {
return {
"pl" :"own player",
"plv" :"version1",
"sx" : screen.width,
"sy" : screen.height
}
},
"getDuration" : function() {
return streamlength in seconds;
},
"getPosition" : function() {
return new Date().getTime() / 1000;
}
};
var desc = {
"stream": "videos/teststream"
}
sensors.track("someid", desc, adapter);
// uncomment for debugging
// sensors.debug = function(v) {
// window.status = v;
// }
function unload() {
sensors.unload();
// give time for submission
var start= new Date(); var now = null; do now = new Date();
while(now-start < 100);
}
</script>
</body>
Implementation via Javascript (Windows Media player)
Prior to using the springStreams-functions the Javascript-library must be loaded.
This is achieved by the following script-tag:
<script src=".../springstreams.js"></script>
The springStreams-functions are provided by the class SpringStreams. The code of a site will be passed on with the creation of an object of this class:
var sensors = new SpringStreams("test");
test = The site code in this case is “test”. You have to replace the site code “test” by the site code (unique name provided by Kantar) for the measured site.
A media player embedded into the website can now be measured directly. For this, the object which is to be measured is required. In most cases this will be available through the id of the object’s tag. In the following example an object with the ID wmplayer with a reference to the Windows Media Player is being used.
sensors.track(wmplayer, {});
Beyond the ID of the object a number of descriptive information can be passed on in form of a JavaScript object:
var description = {
"stream": "videos/teststream"
"desc": "some additional description"
};
sensors.track(wmplayer, description);
It is possible to include more additional attributes to the description. The declaration of stream with the name or the hierarchy of the stream is expected as a minimum.
More than one object can be measured.
Example Windows Media Player
<html>
<head>
<title>spring sensors</title>
<script src="springstreams.js"></script>
</head>
<body onunload="unload();">
<SCRIPT type="text/javascript">
if(-1 != navigator.userAgent.indexOf("MSIE"))
{
document.write('<OBJECT id="wmplayer" width="435" height="326" CLASSID="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" type="application/x-ms-wmp">');
document.write(' <param name="URL" value="http://wstreaming.zdf.de/zdf/veryhigh/070912_iaa_mim.asx">');
document.write(' <param name="AutoStart" VALUE="1">');
document.write(' <param name="ShowStatusBar" VALUE="1">');
document.write('</object>');
}
else {
document.write('<OBJECT id="wmplayer" width="435" height="326" type="application/x-ms-wmp">');
document.write(' <param name="URL" value="http://wstreaming.zdf.de/zdf/veryhigh/070912_iaa_mim.asx">');
document.write(' <param name="AutoStart" VALUE="1">');
document.write(' <param name="ShowStatusBar" VALUE="1">');
document.write(' </object>');
}
</SCRIPT>
<script type="text/javascript">
// "test" is the name of the tracked website
var sensors = new SpringStreams("test");
// wmplayer is the id of the stream above
sensors.track(wmplayer, {"stream":"videos/teststream"});
// uncomment for debugging
//sensors.debug = function(v) {
// window.status = v;
//}
function unload() {
sensors.unload();
// give time for submission
var start= new Date(); var now = null; do now = new Date();
while(now-start < 100);
}
</script>
</body>
Implementation via HTML5
Before using the springstreams-functions, the javascript library has to be uploaded. This is done via the following script-tag:
<script src=".../springstreams.js"></script>The springstreams-functions are available via SpringStreams class. During creation of an object in this class, the website-identification is transferred:
var sensors = new SpringStreams("test"); test is the identification of the website in this case. This identification has to be replaced by the own identification provided by Kantar.
A video- or audio element (see: http://www.w3schools.com/tags/ref_av_dom.asp) embedded into the website can now be measured directly. In order to perform the measurement, the object to be measured is needed. Usually this is available via the id of the object-tag. In this example, the object with the ID video5 is used with a reference to an HTML video element.
sensors.track(video5, {});In addition to the ID of the object to be measured, descriptive information concerning the object in form of Javascript-object can be indicated:
var description = {
"stream": "videos/teststream"
"desc": "some additional description"
};
sensors.track(video5, description);There is the possibility to add additional attributes to the description. Minimum the identification of stream indicating the name/hirarchy of the stream is expected.
Example HTML5 video
<!DOCTYPE html>
<html lang="en">
<head>
<title>HTML5 Video Example</title>
<script src="./springstreams.js"></script>
</head>
<body onunload="unload()">
<script type="text/javascript">
var sensors = new SpringStreams("test");
</script>
<div align="center">
<video id='video' controls preload='none' >
<source id='mp4' src="./wetter.ard.20101209.mp4" type='video/mp4; codecs="avc1, mp4a"'></source>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</div>
<script type="text/javascript">
var description = {
"stream":"videos/news/wetter.ard.20101209.mp4"
};
var handle = sensors.track(video, description, sensors.HTML5Adapter);
function unload() {
sensors.unload();
}
</script>
</body>
</html>
Implementation in Flash
The implementation in Flash is similar to the one in Javascript. To use the springStreams functions the library springstreams.as3.swc (resp. springstreams.as2.swc for Actionscript2) is embedded into the application.
Now the springStreams-functions are available via the class SpringStreams. When an object of this class is created, the name of the website is being passed on:
var sensors:SpringStreams = new SpringStreams("test");
test = The site code in this case is “test”. You have to replace the site code “test” by the site code (unique name provided by Kantar) for the measured site.
The measurements are passed on via an http call to the measurement systems. In the case that this call should be done via SSL (HTTPS) this can be achieved by passing on this information to the sensor:
var sensors:SpringStreams = new SpringStreams("test", true);
A NetStream object can now be measured directly:
sensors.track(ns,{});
Beyond the ID of the object a number of descriptive information can be passed on as a JavaScript object:
var description:Object = {
"stream": "videos/teststream",
"desc": "some additional infos",
"sx": video.width,
"sy": video.heigth,
};
sensors.track(ns, description);
It is possible to include more additional attributes to the description. The declaration of stream with the name of the stream or the hierarchy and sx respectively sy with the sizing description of the visible area is expected as a minimum.
Requests to the measurement system can be monitored via the ActionScript function trace in the debug environment.
The class SpringStreams defines a function SPRING_UNLOAD via the Flash class ExternalInterface (if available). Analogous to the Javascript version, this function can be used to signal the termination of the runtime environment. This can be implemented as follows:
<body onunload="unload()">
...
function unload() {
FlexProject.SPRING_UNLOAD();
}
Because the browser will close the web site after the unload sequence is finished, it is possible, that the closing counting impulse was not initiated. An improvement will be reached by inserting a part of a little application at the end of the unload sequence, which will not be noticed by customers.
function unload() {
FlexProject.SPRING_UNLOAD();
// give time for submission
var start= new Date(); var now = null; do now = new Date();
while(now-start < 100);
}
FlexProject is the ID of the flash object. If the Flash application already uses an unload mechanism, this mechanism can call the static function SpringStreams.unload().
Use as an Embedded Player and Security Settings
If the player should be used as Embedded Player on an other website, the security settings have to be respected.
The following settings must be setup (siehe: ExternalInterface#addCallback())
Set in the HTML page at the object tag for the SWF file the following parameters:
<param name="allowScriptAccess" value="always" />Paste in the SWF file the following ActionScript code:
flash.system.Security.allowDomain( sourceDomain )
At absence of these settings, a security error appears in the API, because the trial of registering the SPRING_UNLOAD() function on the website will fail. This error is handled by the API and will be ignored. However, it isn't essential for the proper functioning of the measurement.
Furthermore, for the proper functioning the entry of the attribute onunload="..." in the body tag is necessary in order to report the leaving of the side to the API. At absence of these settings, it's possible that the last event at the end of the measurement is no longer transmitted to the measurement system.
Example integration in Flash
var nsClient:Object = {};
nsClient.onMetaData = ...
nsClient.onCuePoint = ...
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.play(streamlocation);
ns.client = nsClient;
video = new Video();
video.attachNetStream(ns);
addChild(video);
var tracker:SpringStreams = new SpringStreams("test");
tracker.track(ns,{"stream":"videos/teststream","sx":video.width,"sy":video.height});
The determination of the stream’s total duration is achieved by an intermediate stream-client, which accesses all meta-events of the stream. This stream-client transparently routes all events to the already registered client (nsClient in the above example).
A meta event (onMetaData) containing an info-object is expected. The attribute duration (info.duration) is requested from this info-object and interpreted as the length of the stream.
If this information should not be provided by your streams, the duration of the stream can be assigned externally (in seconds).
via the stream reference:
var nsClient:Object = {};
nsClient.onMetaData = ...
nsClient.onCuePoint = ...
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.play(streamlocation);
ns.client = nsClient;
video = new Video();
video.attachNetStream(ns);
addChild(video);
var tracker:SpringStreams = new SpringStreams("test");
var stream:Stream = tracker.track(ns,{"stream":"videos/teststream","sx":video.width,"sy":video.height});
stream.setDuration(600/*10 minutes*/);
Measurement for any Streaming Content in Adobe Flash
As described in the last chapter, you need a library for a flash.net.NetStream object to measure a streaming content. Inside the measurement, the actual position on the stream object will be readout.
The measurement is constantly calling the property NetStream.time.
var net:NetConnection = new NetConnection();
net.connect(null);
var ns:NetStream = new NetStream(net);
var currentPosition:Number = ns.time;
With this knowledge it is possible to measure any streaming object, where the actual position in seconds on the stream is transmitted.
For this you have to implement an own NetStream object and overwrite the call ns.time.
In the following example a NetStream adapter for the flash.media.Sound object is implemented.
package
{
import flash.media.SoundChannel;
import flash.net.NetConnection;
import flash.net.NetStream;
public class SoundNetStreamAdapter extends NetStream
{
private var channel:SoundChannel;
public function SoundNetStreamAdapter(net:NetConnection, c:SoundChannel)
{
super(net);
channel = c;
}
override public function get time():Number {
// return the position in seconds
return channel.position/1000;
}
}
}
This adapter is also a NetStream object and can be transmitted to the streaming library. By implementing, the property time is overwritten. This property delivers the actual position in seconds. This value is divided by 1000 because the SoundChannel object delivers milliseconds instead of seconds. This is necessary to adapt the interface description of the NetStream object.
The length of the stream is taken by the property Sound.length, transformed to seconds and is written into the description object with the name duration.
var tracker:SpringStreams = new SpringStreams("test");
var s:Sound = new Sound();
s.load(new URLRequest("file:///pathto/sound.mp3"));
var desc:Object = {
"stream":"sounds/sound.mp3",
"sx":0,"sy":0,
};
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new SoundNetStreamAdapter(nc, s.play());
var stream:Stream = tracker.track(ns, desc);
stream.setDuration(s.length/1000); // duration in seconds
Advanced Topics
Segmentation of Streams
Possibly there is a need for a deeper/different segmentation of streams. This can be desirable in case of a live stream or recorded streams with several content parts, so that the individual segments or parts of the stream can be distinguished.
This can also be realized with the library by measuring each consignment separately. To do this, the player needs to know when and what is broadcasted. It simply needs something like a program structure or "play list".
Example for the measurement of individual segments or parts on a live stream
var nsClient:Object = {};
nsClient.onMetaData = ...
nsClient.onCuePoint = ...
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.play(streamlocation);
ns.client = nsClient;
video = new Video();
video.attachNetStream(ns);
addChild(video);
// 20:00 - 20:15 Tagesschau
// 20:15 - 21:00 PlusMinus
var tracker:SpringStreams = new SpringStreams("test");
// 20:00
var stream:Stream = tracker.track(ns,{"stream":"livestreams/ard/Tagesschau","sx":video.width,"sy":video.height});
// 20:15
stream.stop();
stream = tracker.track(ns,{"stream":"livestreams/ard/PlusMinus","sx":video.width,"sy":video.height});
Several Streams in parallel Measurement
The library is able to measure several streams in parallel. All the streams which have been started can be measured directly by being transmitted with the method “track” to the measurement of streaming.
Example for the measurement of two parallel streams
...
ns1 = new NetStream(...);
...
ns2 = new NetStream(...);
...
var tracker:SpringStreams = new SpringStreams("test");
var stream1:Stream = tracker.track(ns1,{"stream":"streams/stream1","sx":video.width,"sy":video.height});
var stream2:Stream = tracker.track(ns2,{"stream":"streams/stream2","sx":video.width,"sy":video.height});
Mobile App Streaming
Features on Platforms
Information (optional)
The user can be informed at some point that the application monitors the user actions and transmits them to a measuring system. Furthermore, the user must be informed that he has the possibility to switch of the tracking in the application and can contradict this way. (see: Opt-Out)
For this purpose, you can include data privacy information in your language into an appropriate place of your app implementation: