I am trying to solve byte range intervals with a single file using dash.js in the MKV container that I have been working on for a while.
The files are not on my local disk. It’s on a remote server and I can’t get it and use tools like ffmpeg on my local disk,
I want to use mediaRange ranges with a single URL (example: test.com/video.mkv) to play with Dash.js.
For this, I use NodeJS to parse parts of the MKV file on the server side like EBML Head
, SeekHead
, Tracks
and CuePoints
I calculate the ranges of the Cluster positions using the CuePoints I get and the CueClusterPosition values.
As a result, I get a dash manifest similar to the one below.
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011" type="static" mediaPresentationDuration="PT1H45M58.42S">
<Period>
<AdaptationSet contentType="video" mimeType="video/mp4" startWithSAP="1" segmentAlignment="true">
<Representation id="1" bandwidth="6001808" width="1920" height="1080" codecs="hvc1.2.4.L150.B0">
<BaseURL>VIDEOURL</BaseURL>
<SegmentList timescale="1000" duration="6358042" frameRate="24000/1">
<Initialization range="40-7609"/>
<SegmentURL mediaRange="171496669-176746935"/>
<SegmentURL mediaRange="176746935-181903774"/>
<SegmentURL mediaRange="181903774-183583869"/>
<SegmentURL mediaRange="183583869-185160671"/>
mediaRange values indicate cluster positions taken from CuePoints
this.result.tracks[0].cues.forEach((cue, index) => {
let nextCurePos = this.result.tracks[0].cues[index + 1] ? this.result.tracks[0].cues[index + 1].clusterPos : 'end';
segmentList.ele('SegmentURL', {
mediaRange: `${cue.clusterPos}-${nextCurePos}`
})
});
I am currently printing only video track information. If I can play the video, I will include tracks such as audio, subtitle
Here is the data I got with MKVToolNix;
Dash.js debug
[43][DashParser] Parsing complete: ( xml2json: 17.2ms, objectiron: 0.00ms, total: 0.0172s)
[44][StreamController] Manifest updated... updating data system wide.
[44][ManifestUpdater] Manifest has been refreshed at Tue May 07 2024 11:56:48 GMT+0300 (GMT+03:00)[1715072208.713]
[47][StreamController] Switch to stream defaultId_0. Seektime is 0, current playback time is null. Seamless period switch is set to false
[47][MediaSourceController] Created MediaSource
[49][MediaSourceController] Set MediaSource duration:6358.42
[55][Stream] No audio data.
[55][Stream] No text data.
[55][Stream] No muxed data.
[55][Stream] No image data.
[384][StreamProcessor] OnFragmentLoadingCompleted for stream id defaultId_0 and media type video - Url: http://test.com/video.mkv , Range:52-7609
[385][StreamProcessor] lastInitializedRepresentationInfo changed to 0
[386][PlaybackController] Native video element event: play
[386][PlaybackController] Native video element event: waiting
[386][ScheduleController] Top quality video index has changed from NaN to 0
[1356][StreamProcessor] OnFragmentLoadingCompleted for stream id defaultId_0 and media type video - Url: http://test.com/video.mkv , Range:171496669-176746935
[3047][StreamProcessor] OnFragmentLoadingCompleted for stream id defaultId_0 and media type video - Url: http://test.com/video.mkv , Range:176746935-181903774
[3067][StreamController] [onStreamBufferingCompleted] calls signalEndOfStream of mediaSourceController.
My goal here is to create a video player with different audio and subtitle options on the web by creating a dash manifest by pulling data from a remote url.
Trying to play the video by getting Cluster byte ranges from CuePoints