Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ce3d857
rename CmcdModel to CmcdController + extract CmcdController from HTTP…
cotid-qualabs Apr 3, 2025
edd54b7
add return to _cmcdRequestModeInterceptor
cotid-qualabs Apr 7, 2025
a7f3ffe
remove migrated code from HTTPLoader
cotid-qualabs Apr 7, 2025
eaeeef6
rename CmcdModel unit test file
cotid-qualabs Apr 7, 2025
f11d89b
add remove spaces on HTTPLoader
cotid-qualabs Apr 7, 2025
22e8e47
move cmcdRequestInterceptor setup to reset function
cotid-qualabs Apr 7, 2025
251862d
remove whitespace
cotid-qualabs Apr 7, 2025
e8edb0d
remove whitespace
cotid-qualabs Apr 7, 2025
a269305
remove whitespace
cotid-qualabs Apr 7, 2025
242683f
request mode fix
cotid-qualabs Apr 8, 2025
6653314
refactor cmcdRequestModeInterceptor to return a new commonMediaReques…
sebastianpiq Apr 9, 2025
7ac84f4
Remove unnecessary concat in the interceptors array
sebastianpiq Apr 9, 2025
3993e4b
update get query and headers function
cotid-qualabs Apr 10, 2025
51086d7
reponse mode WIP
cotid-qualabs Apr 10, 2025
29eca78
response mode enabled keys
cotid-qualabs Apr 11, 2025
bca18f7
include in request for response mode
cotid-qualabs Apr 14, 2025
d2b51cc
settings update
cotid-qualabs Apr 14, 2025
6f45b1d
custom keys for response mode
cotid-qualabs Apr 14, 2025
be7ec7b
review changes
cotid-qualabs Apr 14, 2025
4d99b39
cmcd report targets JSDocs
cotid-qualabs Apr 14, 2025
cda45ea
add current keys parameter to customKeys
cotid-qualabs Apr 14, 2025
8b78a6b
fix constants
cotid-qualabs Apr 14, 2025
7190088
fix JSDocs
cotid-qualabs Apr 14, 2025
f6772a3
fix default settingscmcd targets
cotid-qualabs Apr 14, 2025
c88be65
Merge pull request #73 from qualabs/cmcdv2/response_mode
cotid-qualabs Apr 16, 2025
9e04959
add response type
cotid-qualabs Apr 17, 2025
7d6bec4
cmcdv2 interceptors sample page
cotid-qualabs Apr 23, 2025
9131547
cmcdv2 interceptors sample page html update
cotid-qualabs Apr 23, 2025
dbff09e
Merge pull request #75 from qualabs/cmcdv2/interceptor_sample_page
cotid-qualabs Apr 25, 2025
2546260
Cmcdv2/event mode (#74)
sebastianpiq Apr 28, 2025
35fca18
cmcdv2 network interceptor sample page fix
cotid-qualabs Apr 28, 2025
e43934f
CMCDv2 headers mode fix
cotid-qualabs Apr 28, 2025
6eb282f
Created constant with mandatory keys for CMD
juanmanuel-qualabs Apr 28, 2025
7372d4a
Renamed function to includeEventModeMandatoryKeys
juanmanuel-qualabs Apr 28, 2025
067cfdb
Merge pull request #76 from qualabs/cmcdv2/mandatory-keys
cotid-qualabs Apr 29, 2025
f7b3368
CMCD v2 'rc' key implementation
cotid-qualabs Apr 30, 2025
409ede6
bugfix headers undefined on unit test
cotid-qualabs Apr 30, 2025
639d689
Merge branch 'feature/cmcdv2' of github.com:qualabs/dash.js into feat…
cotid-qualabs Apr 30, 2025
46b594a
CMCD Implement 'r' Event (#77)
juanmanuel-qualabs Apr 30, 2025
edb4477
Add global synchronization functionality for DASH players
sebastianpiq May 2, 2025
120a934
Remove default video URL from global synchronization sample
sebastianpiq May 2, 2025
14f66c0
Update option text for CMAF Live stream to clarify low latency
sebastianpiq May 2, 2025
82b2a34
Use setting delay with globla sync
sebastianpiq May 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3707,7 +3707,7 @@ declare namespace dashjs {
update(manifest: object): void;
}

export interface CmcdModel {
export interface CmcdController {
getCmcdData(request: HTTPRequest): object;

getCmcdParametersFromManifest(): CMCDParameters;
Expand Down
187 changes: 187 additions & 0 deletions samples/advanced/cmcdv2-network-interceptors.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CMCD Callbacks with Network Interceptors</title>

<script src="../../dist/modern/umd/dash.all.debug.js"></script>

<!-- Bootstrap core CSS -->
<link href="../lib/bootstrap/bootstrap.min.css" rel="stylesheet">
<link href="../lib/main.css" rel="stylesheet">

<style>
video {
width: 640px;
height: 360px;
}

#trace {
height: 500px;
margin-top: 20px;
font-size: 10px;
}
</style>
<script>
function getKeysForQueryMode(cmcdString) {
var cmcdData = {};
var cmcdString = cmcdString;

extractKeyValuePairs(cmcdString, cmcdData);

return cmcdData;
}

function extractKeyValuePairs(cmcdString, cmcdData) {
if (cmcdString === '') {
return;
}
var keyValuePairs = cmcdString.split(',');

keyValuePairs.forEach(function (keyValuePair) {
var data = keyValuePair.split('=');
var key = data[0];
var value = data[1];

cmcdData[key] = value;
})
}

function log(msg) {
msg = msg.length > 200 ? msg.substring(0, 200) + '...' : msg; /* to avoid repeated wrapping with large objects */
var tracePanel = document.getElementById('trace');
tracePanel.innerHTML += msg + '\n';
tracePanel.scrollTop = tracePanel.scrollHeight;
}
</script>
<script class="code">
var CMCD_MODE_QUERY = 'query'; /* as query parameters */
var player;

function init() {
var video,
url = 'https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd',
version;

player = dashjs.MediaPlayer().create();
video = document.querySelector('video');
player.initialize();
version = player.getVersion();

player.updateSettings({
streaming: {
cmcd: {
enabled: true, /* enable reporting of cmcd parameters */
sid: 'b248658d-1d1a-4039-91d0-8c08ba597da5', /* session id send with each request */
cid: '21cf726cfe3d937b5f974f72bb5bd06a', /* content id send with each request */
mode: CMCD_MODE_QUERY,
enabledKeys: ['cid', 'sid'],
includeInRequests: ['segment', 'mpd'],
targets: [
{
cmcdMode: 'response',
enabled: true,
url: 'http://example.com/report1',
enabledKeys: ['ot'],
includeOnRequests: ['mpd'],
}
]
}
}
});
player.setAutoPlay(false);
player.attachView(video);
player.attachSource(url);

/* Callback before report */
player.addRequestInterceptor((request) => {
if (request.customData.request.type == 'Response' && request.url.includes('http://example.com/report1')) {
let customKey = 'synchronization-leader-sid';
let customKeyValue = '123'
let { cmcd } = request;
if (cmcd) {
/* Add custom key to cmcd data */
cmcd[customKey] = customKeyValue;
/* Add custom key to query parameters */
let newParam = encodeURIComponent(`,${customKey}="${customKeyValue}"`);
request.url += newParam;
}
}
return Promise.resolve(request);
});

/* Callback after server response */
player.addResponseInterceptor((response) => {
request = response.request.customData.request;
if (request.type == 'Response' && request.url.includes('http://example.com/report1')) {
console.log(request.cmcd);
}
return Promise.resolve(response);
});

const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
if (url.includes('example.com/report1')) {
const queryString = decodeURIComponent(url.split('CMCD=')[1]);
const data = getKeysForQueryMode(queryString);
var keys = Object.keys(data);
keys = keys.sort();
for (var key of keys) {
log(key.padEnd(4) + ': ' + data[key]);
}
log('');
}
return originalOpen.call(this, method, url, ...rest);
};
}
</script>
</head>
<body>

<main>
<div class="container py-4">
<header class="pb-3 mb-4 border-bottom">
<img class=""
src="../lib/img/dashjs-logo.png"
width="200">
</header>
<div class="row">
<div class="col-md-12">
<div class="h-100 p-5 bg-light border rounded-3">
<h3>CMCD Reporting</h3>
<p>This sample shows how to use Network Interceptors to execute callbacks after server response or pre-request callbacks for Response and Event Mode</p>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-md-6">
<video controls="true"></video>
</div>
<div class="col-md-6">
<div class="form-floating">
<textarea class="form-control" placeholder="Sent CMCD data will be displayed here"
id="trace"></textarea>
<label for="trace">CMCD Report Data</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="code-output"></div>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
&copy; DASH-IF
</footer>
</div>
</main>


<script>
document.addEventListener('DOMContentLoaded', function () {
init();
});
</script>
<script src="../highlighter.js"></script>
</body>
</html>
95 changes: 95 additions & 0 deletions samples/players-synchronization/globalSync.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<title>Follower client</title>

<script src="../../dist/dash.all.debug.js"></script>
<script src="./playerSynchronizationPlugin.js"></script>

<!-- Bootstrap core CSS -->
<link href="../lib/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="../lib/main.css" rel="stylesheet" />

<style>
video {
width: 640px;
height: 360px;
}
</style>
</head>

<body>
<main>
<div class="container py-4">
<header class="pb-3 mb-4 border-bottom">
<h1>Follower client</h1>
</header>
<div class="row">
<div>
<div class="input-group mb-2">
<button id="load-button" type="button" class="btn btn-primary" aria-haspopup="true" aria-expanded="false">Load</button>
<select id="url-select" class="dropdown-toggle">
<option
value="https://livesim.dashif.org/livesim2/WAVE/vectors/cfhd_sets/12.5_25_50/t1/2022-10-17/stream.mpd">
Live Sim</option>
<option value="https://cmafref.akamaized.net/cmaf/live-ull/2006350/akambr/out.mpd">Low latency Live
</option>
</select>
<input id="custom-url" type="text" class="form-control" placeholder="Paste your own DASH manifest URL here" style="max-width: 350px; margin-left: 8px;">
</div>
<video controls="true"></video>
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
&copy; DASH-IF
</footer>
</div>
</main>
<style>
.hide-controls::-webkit-media-controls {
display: none !important;
}

.hide-controls::-moz-media-controls {
display: none !important;
}

.hide-controls::-ms-media-controls {
display: none !important;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
var video,
player

video = document.querySelector("video");
player = dashjs.MediaPlayer().create();
window.player = player;

player.initialize(video, '', true);
playerSynchronization.addFollower(player, {
globalSync: true,
url: 'http://localhost:3000/',
frameDelay: 1,
seekTreshold: 0.4,
catchUpRate: 2,
syncInterval: 5000
});

const loadButton = document.getElementById('load-button');
const urlSelect = document.getElementById('url-select');
const customUrl = document.getElementById('custom-url');

loadButton.addEventListener('click', () => {
const enteredUrl = customUrl.value.trim();
const selectedUrl = urlSelect.value;
player.attachSource(enteredUrl !== '' ? enteredUrl : selectedUrl);
});
});
</script>
</body>

</html>
Loading