Skip to content

Instantly share code, notes, and snippets.

@peaBerberian
Created January 8, 2021 14:52
Show Gist options
  • Save peaBerberian/4a30f77dccef676bea87f689f04a87e2 to your computer and use it in GitHub Desktop.
Save peaBerberian/4a30f77dccef676bea87f689f04a87e2 to your computer and use it in GitHub Desktop.
Initial seek after media segment pushed
<!DOCTYPE html>
<!--
This file allows to quickly test if starting a content at a position different
from `0` after the media segments have been pushed works.
To do that:
1. You might want to update the variables at the top of the script (default
values should be alright but maybe the content is not available anymore).
2. Run this page from the environment (device and/or browser) you want to test
3. The logs should indicate when/if the test failed.
Also, the first picture of the stream should be visible after some time and
the logged current time value should equal, or really close to the
configured `initialPosition` value.
-->
<html lang="en">
<head>
<head>
<meta charset="UTF-8">
<title>RxPlayer Conformance Test - MediaKeySystemAccess support</title>
</head>
<body>
<video />
<script charset="utf-8">
// =============== CONFIG ===============
/** Initial position you want to seek to. */
var initialPosition = 301;
/** URL for the video initialization segment */
var videoInitUrl = "http://www.bok.net/dash/tears_of_steel/cleartext/video/6/init.mp4";
/** URL for the audio initialization segment */
var audioInitUrl = "http://www.bok.net/dash/tears_of_steel/cleartext/audio/en/init.mp4";
/** URL for the first video segment available at `initialPosition` */
var videoSeg10Min = "http://www.bok.net/dash/tears_of_steel/cleartext/video/6/seg-101.m4f";
/** URL for the first audio segment available at `initialPosition` */
var audioSeg10Min = "http://www.bok.net/dash/tears_of_steel/cleartext/audio/en/seg-101.m4f";
// ======================================
var videoElement = document.querySelector("video");
loadContent();
/**
* Create MediaSource instance, attach it to the video element, push the
* configured audio and video segments on it and then perform a seek.
* Print logs to report the current operation.
*/
function loadContent() {
console.info("Creating MediaSource");
var mediaSource = new MediaSource();
var objectURL = URL.createObjectURL(mediaSource);
mediaSource.addEventListener("sourceopen", onSourceOpen);
mediaSource.addEventListener("webkitsourceopen", onSourceOpen);
videoElement.src = objectURL;
}
/**
* Actions to perform once the MediaSource has been attached to the video
* element and opened.
*/
function onSourceOpen() {
var mediaSource = this;
console.info("MediaSource opened");
console.info("Setting duration on the MediaSource");
MediaSource.duration = initialPosition + 60;
var audioSourceBuffer = mediaSource.addSourceBuffer("audio/mp4;codecs=\"mp4a.40.2\"");
var videoSourceBuffer = mediaSource.addSourceBuffer("video/mp4;codecs=\"avc1.4D401E\"");
/** `true` after the audio media segment has been pushed with success. */
var isAudioSegPushed = false;
/** `true` after the video media segment has been pushed with success. */
var isVideoSegPushed = false;
// fetch + push audio init segment
fetch(audioInitUrl, function (ab) {
audioSourceBuffer.addEventListener("updateend", onAudioInitSegmentPushed);
audioSourceBuffer.appendBuffer(ab);
});
// fetch + push video init segment
fetch(videoInitUrl, function (ab) {
videoSourceBuffer.addEventListener("updateend", onVideoInitSegmentPushed);
videoSourceBuffer.appendBuffer(ab);
})
function onAudioInitSegmentPushed() {
console.info("audio init segment pushed.");
audioSourceBuffer.removeEventListener("updateend", onAudioInitSegmentPushed);
audioSourceBuffer.addEventListener("updateend", function() {
console.info("audio media segment pushed.");
isAudioSegPushed = true;
if (isVideoSegPushed) {
setInitialPositionAndCheck();
}
});
// fetch audio media segment
fetch(audioSeg10Min, function(ab) {
audioSourceBuffer.appendBuffer(ab);
});
}
function onVideoInitSegmentPushed() {
console.info("video init segment pushed.");
videoSourceBuffer.removeEventListener("updateend", onVideoInitSegmentPushed);
videoSourceBuffer.addEventListener("updateend", function() {
console.info("video media segment pushed.");
isVideoSegPushed = true;
if (isAudioSegPushed) {
setInitialPositionAndCheck();
}
});
// fetch video media segment
fetch(videoSeg10Min, function(ab) {
videoSourceBuffer.appendBuffer(ab);
});
}
}
function setInitialPositionAndCheck() {
console.info("Setting initial position", initialPosition);
videoElement.currentTime = initialPosition;
checkCurrentTime();
setInterval(checkCurrentTime, 1000);
}
/**
* Check that the video element's `currentTime` property is equal (or close
* enough) to the configured `initialPosition` property.
* Print an error log when that's not the case and a regular log when it is.
*/
function checkCurrentTime() {
var currentTime = videoElement.currentTime;
if (Math.abs(currentTime - initialPosition) > 1 / 60) {
console.error(
"Test failed: current time should be equal to", initialPosition,
"but is equal to", currentTime);
} else {
console.log("Coherent currentTime:", currentTime);
}
}
/**
* Perform a GET request at the URL given and give the response - in an
* ArrayBuffer form - to the given callback when done.
* @param {string} url
* @param {Function} callback
*/
function fetch(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onerror = function (evt) {
console.error("Request for", url, "failed:", evt);
};
xhr.onload = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
var arrayBuffer = xhr.response; // Note: not xhr.responseText
callback(arrayBuffer);
} else {
console.error("Bad status for request", url, xhr.status);
}
}
};
xhr.send(null);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment