Skip to content

Commit 2f5655c

Browse files
feat:: Enable multiple renditions in dash video element (#148)
• Use the Dash.js API (getRepresentationsByType('video')) to fetch available video renditions. • Adds to a videoTrack the renditions to be available for Media Chrome Rendition Menu. • Adds logic to respond to selection changes in , toggling between manual rendition selection and automatic adaptive bitrate (ABR).
1 parent 758f548 commit 2f5655c

3 files changed

Lines changed: 45 additions & 10 deletions

File tree

packages/dash-video-element/dash-video-element.js

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { CustomVideoElement } from 'custom-media-element';
2+
import { MediaTracksMixin } from 'media-tracks';
23

3-
class DashVideoElement extends CustomVideoElement {
4+
class DashVideoElement extends MediaTracksMixin(CustomVideoElement) {
45
static shadowRootOptions = { ...CustomVideoElement.shadowRootOptions };
56

67
static getTemplateHTML = (attrs) => {
@@ -21,19 +22,46 @@ class DashVideoElement extends CustomVideoElement {
2122
}
2223

2324
async load() {
25+
if (this.#apiInit) {
26+
this.api.attachSource(this.src);
27+
return;
28+
}
2429

25-
if (!this.#apiInit) {
26-
this.#apiInit = true;
30+
this.#apiInit = true;
2731

28-
const Dash = await import('dashjs');
32+
const Dash = await import('dashjs');
33+
this.api = Dash.MediaPlayer().create();
34+
this.api.initialize(this.nativeEl, this.src, this.autoplay);
2935

30-
this.api = Dash.MediaPlayer().create();
31-
this.api.initialize(this.nativeEl, this.src, this.autoplay);
36+
this.api.on(Dash.MediaPlayer.events.STREAM_INITIALIZED, () => {
37+
const bitrateList = this.api.getRepresentationsByType('video');
3238

33-
} else {
39+
let videoTrack = this.videoTracks.getTrackById('main');
40+
if (!videoTrack) {
41+
videoTrack = this.addVideoTrack('main');
42+
videoTrack.id = 'main';
43+
videoTrack.selected = true;
44+
}
3445

35-
this.api.attachSource(this.src);
36-
}
46+
bitrateList.forEach((rep) => {
47+
const bitrate =
48+
rep.bandwidth ?? rep.bitrate ?? (Number.isFinite(rep.bitrateInKbit) ? rep.bitrateInKbit * 1000 : undefined);
49+
50+
const rendition = videoTrack.addRendition(rep.id, rep.width, rep.height, rep.mimeType ?? rep.codec, bitrate);
51+
rendition.id = rep.id;
52+
});
53+
54+
this.videoRenditions.addEventListener('change', () => {
55+
const selected = this.videoRenditions[this.videoRenditions.selectedIndex];
56+
57+
if (selected?.id) {
58+
this.api.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: false } } } });
59+
this.api.setRepresentationForTypeById('video', selected.id, true);
60+
} else {
61+
this.api.updateSettings({ streaming: { abr: { autoSwitchBitrate: { video: true } } } });
62+
}
63+
});
64+
});
3765
}
3866
}
3967

packages/dash-video-element/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
{
2121
"imports": {
2222
"custom-media-element": "https://cdn.jsdelivr.net/npm/custom-media-element@1.2/+esm",
23+
"media-tracks": "https://cdn.jsdelivr.net/npm/media-tracks@0.3/+esm",
2324
"dashjs": "https://cdn.jsdelivr.net/npm/dashjs@5.0/dist/modern/esm/dash.all.min.js"
2425
}
2526
}
2627
</script>
2728
<script type="module" src="./dash-video-element.js"></script>
2829
<script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome/+esm"></script>
30+
<script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome/menu/+esm"></script>
2931

3032
<h1>&lt;dash-video&gt;</h1>
3133
<br>
@@ -117,6 +119,9 @@ <h2>With <a href="https://github.com/muxinc/media-chrome" target="_blank">Media
117119
>
118120
<track label="thumbnails" default kind="thumbnails" src="https://image.mux.com/r4rOE02cc95tbe3I00302nlrHfT023Q3IedFJW029w018KxZA/storyboard.vtt"></track>
119121
</dash-video>
122+
<media-rendition-menu anchor="auto" hidden>
123+
<div slot="header">Quality</div>
124+
</media-rendition-menu>
120125
<media-loading-indicator slot="centered-chrome" no-auto-hide></media-loading-indicator>
121126
<media-control-bar>
122127
<media-play-button></media-play-button>
@@ -126,6 +131,7 @@ <h2>With <a href="https://github.com/muxinc/media-chrome" target="_blank">Media
126131
<media-volume-range></media-volume-range>
127132
<media-time-range></media-time-range>
128133
<media-time-display show-duration remaining></media-time-display>
134+
<media-rendition-menu-button></media-rendition-menu-button>
129135
<media-playback-rate-button></media-playback-rate-button>
130136
<media-pip-button></media-pip-button>
131137
<media-fullscreen-button></media-fullscreen-button>

packages/dash-video-element/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
},
5454
"dependencies": {
5555
"custom-media-element": "^1.4.5",
56-
"dashjs": "^5.0.3"
56+
"dashjs": "^5.0.3",
57+
"media-tracks": "^0.3.3"
5758
},
5859
"devDependencies": {
5960
"build-react-wrapper": "^0.2.2",

0 commit comments

Comments
 (0)