dash.js – Common-Media-Client-Data

HTTP Live Streaming (HLS) and Dynamic Adaptive Streaming over HTTP (MPEG-DASH) are the two main formats used for adaptive streaming. While HLS is natively supported on most of its target platforms (iOS and MacOSX), external players are needed for MPEG-DASH. For browser-based environments, there is a great open-source option called dash.js. It is written in JavaScript and use MediaSourceExtensions (MSE) and EncryptedMediaExtensions (EME) to enable playback directly in the browser without the need for external plugins. dash.js is the official reference player of the DASH Industry Forum

In this series of blog posts, I focus on the concrete implementation of features in dash.js and how they can be used within applications. This time, we are looking at a specification called Common-Media-Client-Data (CTA-5004), defined by CTA WAVE.

CMCD – Who? How? What? Why?

Back when I was a kid, there was a very popular show called Sesame Street. To be honest, I don’t know what kids watch today, but the main message of the theme song is very valuable, even for technical blogs. The song goes something like this: “Who? How? What? Why? People who do not ask questions remain stupid”. That may be the only time something sounds better in German than in English. In any case, directing these questions towards the Common-Media-Client-Data (CMCD) specification will help us understand its purpose:

  • Who wrote CMCD? The specification is an outcome of the CTA WAVE project (you can learn more about CTA WAVE here). Essentially, the project consists of four different working groups that deal with different aspects of internet-delivered media.
  • How is CMCD accessible? The specification is currently under community review and accessible here.
  • What does CMCD specify? CMCD defines data that is collected by a media streaming client and is sent to the CDN as a custom header or a custom query parameter alongside each segment or manifest request.
  • Why do we need CMCD? CMCD can help the CDN provider increase the overall performance of the CDN itself. Values defined in the specification can be useful for “log analysis, QoS monitoring and delivery optimization”. Additionally, CDNs can “fine-tune their traffic and cross-correlated performance problems with player software versions or specific devices“.

So, to sum it up: with CMCD, the CDN provider improves the CDN performance while the user enjoys a better quality of experience.

CMCD – Technical View

Now that we know what CMCD is about, we can dig deeper into the technical aspect of the specification.

CMCD – Parameters

For starters, CMCD defines three types of identifiers: content id, device id and session id. These identifiers are unique strings that describe the current content, device and session. Using these identifiers, the CDN provider can detect potential problems with either the content itself, the device, a certain streaming session or a combination of all of them.

Next to the identifiers, multiple streaming relevant metrics are defined in the specification:

  • Encoded bitrate: encoded bitrate of the audio or video object being requested.
  • Buffer state: particular buffer states, such as buffer empty or startup.
  • Object duration: playback duration (in milliseconds) of the object being requested.
  • Deadline: deadline from the request time until the first sample of this segment/object needs to be available in order to prevent a buffer underrun or any other playback problems.
  • Measured throughput: the throughput between the client and server, as measured by the client.
  • Next object request: relative path of the next requested object.
  • Object type: media type of the currently requested object. For instance, a manifest or a segment request.
  • Playback rate: current playback rate on the client.
  • Requested maximum throughput: requested maximum throughput that the client considers sufficient for the delivery of an asset.
  • Streaming format: for example, DASH or HLS.
  • Stream type: for example, VoD or live.

CMCD – Delivery

Overall, there are several interesting and useful parameters. CMCD allows two ways in sending this data from the client to the CDN. One way is by adding a custom header to each request; the other is adding all parameters as a query object. Keep in mind, however, that a lot of CDNs reject requests with unknown headers. Consequently, we implemented the query parameter version in dash.js.

CMCD with dash.js

Now that we’ve covered the theoretical aspects of the spec, we can move onto a more practical part, the implementation. To the best of my knowledge, dash.js is the only player that’s implemented the CMCD specification as of now. Let’s take a deeper look on how it works.


CmcdModel is the main class of the CMCD implementation in dash.js. It is responsible for collecting the required values from different parts of the player, as well as generating the final payload to send alongside the CDN request. Figure 1 illustrates the basic workflow in a simplified manner.

Figure 1: CMCD implementation in dash.js

In the bootstrap process of the player, CmcdModel registers for certain callback events, like manifestLoaded, playbackRateChanged and bufferLevelChanged. CmcdModel is a singleton class, and updates its internal state whenever it receives valid payload from one of those events. Before sending each request to the CDN, may it be a manifest request or a segment request, the HTTPLoader class will ask the CmcdModel for the CMCD-specific query parameter.

Building the Query String

In order to build the query string, CmcdModel internally distinguishes between different types of requests, namely, MPD, media segment and init segment requests, as illustrated below:

if (request.type === HTTPRequest.MPD_TYPE) {
     return _getCmcdDataForMpd(request);
} else if (request.type === HTTPRequest.MEDIA_SEGMENT_TYPE) {
     return _getCmcdDataForMediaSegment(request);
} else if (request.type === HTTPRequest.INIT_SEGMENT_TYPE) {
     return _getCmcdDataForInitSegment(request);

This is mainly caused by the fact that requests for media segments require additional logic. For instance, we need to provide details on the type of media segment, which can be audio or video. Generic data, which is required by all of the different types of request objects, is provided by a generic function:

    function _getGenericCmcdData() {
        const data = {};

        if (!isNaN(internalData.pr) && internalData.pr !== 1 && internalData.pr !== null) {
            data.pr = internalData.pr;

        if (internalData.st) {
            data.st = internalData.st;

        if (internalData.sf) {
            data.sf = internalData.sf;

        return data;

In the example above, you may have noticed that we used very short names for our variables. The CMCD specification tries to keep the required query string as short as possible – like sending “pr” instead of playback rate, or “sf” instead of streaming format. A complete list of the abbreviations can be found in specification itself.

The final decoded query string for a request to an audio segment can look like the following:


In this case, we specified a session id(sid), a content id(cid) and a device id(did). We also made some further specifications:

  • stream type(st): VoD(v)
  • streaming format(sf): DASH(d)
  • bitrate of the requested segment(br): 130kbps
  • object type(ot): audio(a)
  • object duration(d): 1997ms
  • measured throughput(mtp): 17807kbps
  • deadline(dl): 31231ms

How to Use CMCD Today

The current CMCD implementation was released in dash.js version 3.0.3. A concrete example on how to use it is available here. Feel free to leave comments below, we are happy to hear any feedback and/or suggestions!

If you have any question regarding our DASH activities or dash.js in particular, feel free to check out our website.

Leave a Reply

Your email address will not be published. Required fields are marked *