Skip to content

Commit 27212ad

Browse files
authored
Feature/external subtitle file (Dash-Industry-Forum#4772)
* WiP: External subtitles * Adds an API to add external subtitle files by adding them to the manifest right after parsing. * Fix wording in sample * Fix a bug for multiperiod MPDs
1 parent 594df96 commit 27212ad

File tree

10 files changed

+689
-84
lines changed

10 files changed

+689
-84
lines changed

index.d.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,6 +2029,8 @@ declare namespace dashjs {
20292029

20302030
addABRCustomRule(type: string, rulename: string, rule: object): void;
20312031

2032+
addExternalSubtitle(externalSubtitle: ExternalSubtitle): void;
2033+
20322034
addRequestInterceptor(interceptor: RequestInterceptor): void;
20332035

20342036
addResponseInterceptor(interceptor: ResponseInterceptor): void;
@@ -2095,6 +2097,8 @@ declare namespace dashjs {
20952097

20962098
getDvrWindow(): DvrWindow;
20972099

2100+
getExternalSubtitles(): ExternalSubtitle[];
2101+
20982102
getInitialMediaSettingsFor(type: MediaType): MediaSettings;
20992103

21002104
getLowLatencyModeEnabled(): boolean;
@@ -2173,6 +2177,10 @@ declare namespace dashjs {
21732177

21742178
removeAllABRCustomRule(): void;
21752179

2180+
removeExternalSubtitleById(id: string): void;
2181+
2182+
removeExternalSubtitleByUrl(url:string): void;
2183+
21762184
removeRequestInterceptor(interceptor: RequestInterceptor): void;
21772185

21782186
removeResponseInterceptor(interceptor: ResponseInterceptor): void;
@@ -3748,6 +3756,8 @@ declare namespace dashjs {
37483756
export interface CustomParametersModel {
37493757
addAbrCustomRule(type: string, rulename: string, rule: object): void;
37503758

3759+
addExternalSubtitle(externalSubtitleObj: object): void;
3760+
37513761
addRequestInterceptor(interceptor: Function): void;
37523762

37533763
addResponseInterceptor(interceptor: Function): void;
@@ -3762,6 +3772,8 @@ declare namespace dashjs {
37623772

37633773
getCustomInitialTrackSelectionFunction(): Function;
37643774

3775+
getExternalSubtitles(): Array<ExternalSubtitle>
3776+
37653777
getLicenseRequestFilters(): Array<Function>;
37663778

37673779
getLicenseResponseFilters(): Array<Function>;
@@ -3784,6 +3796,10 @@ declare namespace dashjs {
37843796

37853797
removeAllAbrCustomRule(): void;
37863798

3799+
removeExternalSubtitleById(id: string): void;
3800+
3801+
removeExternalSubtitleByUrl(url: string): void;
3802+
37873803
removeRequestInterceptor(interceptor: Function): void;
37883804

37893805
removeResponseInterceptor(interceptor: Function): void;
@@ -5476,6 +5492,19 @@ declare namespace dashjs {
54765492
streamId: string | null;
54775493
}
54785494

5495+
export class ExternalSubtitle {
5496+
constructor(externalSubtitleObject: object);
5497+
5498+
id: string;
5499+
url: string;
5500+
language: string;
5501+
mimeType: string;
5502+
bandwidth: number;
5503+
periodId: string | null;
5504+
5505+
serializeToMpdParserFormat(): object;
5506+
}
5507+
54795508
export class FragmentRequest {
54805509
constructor(url: string);
54815510

index.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,31 @@
2929
* POSSIBILITY OF SUCH DAMAGE.
3030
*/
3131

32-
import { MediaPlayer } from './index_mediaplayerOnly.js';
32+
import {MediaPlayer} from './index_mediaplayerOnly.js';
3333
import MetricsReporting from './src/streaming/metrics/MetricsReporting.js';
3434
import Protection from './src/streaming/protection/Protection.js';
3535
import MediaPlayerFactory from './src/streaming/MediaPlayerFactory.js';
3636
import Debug from './src/core/Debug.js';
3737
import Constants from './src/streaming/constants/Constants.js';
38-
import { supportsMediaSource } from './src/streaming/utils/Capabilities.js';
38+
import {supportsMediaSource} from './src/streaming/utils/Capabilities.js';
39+
import ExternalSubtitle from './src/streaming/vo/ExternalSubtitle.js';
3940

4041
dashjs.Protection = Protection;
4142
dashjs.MetricsReporting = MetricsReporting;
4243
dashjs.MediaPlayerFactory = MediaPlayerFactory;
4344
dashjs.Debug = Debug;
4445
dashjs.supportsMediaSource = supportsMediaSource;
4546
dashjs.Constants = Constants;
47+
dashjs.ExternalSubtitle = ExternalSubtitle;
4648

4749
export default dashjs;
48-
export { MediaPlayer, Protection, MetricsReporting, MediaPlayerFactory, Debug, supportsMediaSource, Constants };
50+
export {
51+
MediaPlayer,
52+
Protection,
53+
MetricsReporting,
54+
MediaPlayerFactory,
55+
Debug,
56+
supportsMediaSource,
57+
Constants,
58+
ExternalSubtitle
59+
};
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>External WebVTT example</title>
6+
<script class="code" src="../../contrib/akamai/controlbar/ControlBar.js"></script>
7+
8+
<script src="../../dist/modern/umd/dash.all.debug.js"></script>
9+
10+
<!-- Bootstrap core CSS -->
11+
<link href="../lib/bootstrap/bootstrap.min.css" rel="stylesheet">
12+
<link href="../lib/main.css" rel="stylesheet">
13+
<link rel="stylesheet" href="../../contrib/akamai/controlbar/controlbar.css">
14+
15+
<style>
16+
video {
17+
width: 100%;
18+
}
19+
20+
.dash-video-player {
21+
position: relative; /* This position relative is needed to position the menus */
22+
margin: 0 auto;
23+
line-height: 1.0;
24+
}
25+
</style>
26+
27+
<script class="code">
28+
29+
function init() {
30+
var url = 'https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd',
31+
video = document.querySelector('video'),
32+
controlbar,
33+
player;
34+
var externalSubtitle = new dashjs.ExternalSubtitle({
35+
id: 'external_1',
36+
url: 'https://reference.dashif.org/other/content/webvtt/external-subtitle.vtt',
37+
mimeType: 'text/vtt',
38+
language: 'en',
39+
bandwidth: 256
40+
});
41+
var externalSubtitleTwo = new dashjs.ExternalSubtitle({
42+
id: 'external_2',
43+
url: 'https://reference.dashif.org/other/content/webvtt/external-subtitle-2.vtt',
44+
mimeType: 'text/vtt',
45+
language: 'de',
46+
bandwidth: 256
47+
});
48+
49+
player = dashjs.MediaPlayer().create();
50+
player.initialize(video, null, true);
51+
controlbar = new ControlBar(player); /* Checkout ControlBar.js for more info on how to target/add text tracks to UI */
52+
controlbar.initialize();
53+
player.addExternalSubtitle(externalSubtitle);
54+
player.addExternalSubtitle(externalSubtitleTwo);
55+
player.attachSource(url);
56+
}
57+
</script>
58+
</head>
59+
<body>
60+
61+
<main>
62+
<div class="container py-4">
63+
<header class="pb-3 mb-4 border-bottom">
64+
<img class=""
65+
src="../lib/img/dashjs-logo.png"
66+
width="200">
67+
</header>
68+
<div class="row">
69+
<div class="col-md-4">
70+
<div class="h-100 p-5 bg-light border rounded-3">
71+
<h3>WebVTT Dash Demo</h3>
72+
<p>This example shows how to use the dash.js API to add an external WebVTT file that is not part of
73+
the DASH manifest. </p>
74+
</div>
75+
</div>
76+
<div class="col-md-8">
77+
<div class="dash-video-player code">
78+
<div class="videoContainer" id="videoContainer">
79+
<video preload="auto" autoplay></video>
80+
<div id="videoController" class="video-controller unselectable">
81+
<div id="playPauseBtn" class="btn-play-pause" title="Play/Pause">
82+
<span id="iconPlayPause" class="icon-play"></span>
83+
</div>
84+
<span id="videoTime" class="time-display">00:00:00</span>
85+
<div id="fullscreenBtn" class="btn-fullscreen control-icon-layout" title="Fullscreen">
86+
<span class="icon-fullscreen-enter"></span>
87+
</div>
88+
<div id="bitrateListBtn" class="control-icon-layout" title="Bitrate List">
89+
<span class="icon-bitrate"></span>
90+
</div>
91+
<input type="range" id="volumebar" class="volumebar" value="1" min="0" max="1" step=".01"/>
92+
<div id="muteBtn" class="btn-mute control-icon-layout" title="Mute">
93+
<span id="iconMute" class="icon-mute-off"></span>
94+
</div>
95+
<div id="trackSwitchBtn" class="control-icon-layout" title="A/V Tracks">
96+
<span class="icon-tracks"></span>
97+
</div>
98+
<div id="captionBtn" class="btn-caption control-icon-layout" title="Closed Caption">
99+
<span class="icon-caption"></span>
100+
</div>
101+
<span id="videoDuration" class="duration-display">00:00:00</span>
102+
<div class="seekContainer">
103+
<div id="seekbar" class="seekbar seekbar-complete">
104+
<div id="seekbar-buffer" class="seekbar seekbar-buffer"></div>
105+
<div id="seekbar-play" class="seekbar seekbar-play"></div>
106+
</div>
107+
</div>
108+
</div>
109+
</div>
110+
</div>
111+
</div>
112+
</div>
113+
<div class="row">
114+
<div class="col-md-12">
115+
<div id="code-output"></div>
116+
</div>
117+
</div>
118+
<footer class="pt-3 mt-4 text-muted border-top">
119+
&copy; DASH-IF
120+
</footer>
121+
</div>
122+
</main>
123+
124+
125+
<script>
126+
document.addEventListener('DOMContentLoaded', function () {
127+
init();
128+
});
129+
</script>
130+
<script src="../highlighter.js"></script>
131+
</body>
132+
</html>

samples/samples.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,19 @@
547547
"Audio",
548548
"Events"
549549
]
550+
},
551+
{
552+
"title": "Adding external WebVTT subtitles",
553+
"description": "Example showing how to add external WebVTT subtitles that are not specified in the manifest",
554+
"href": "captioning/external-subtitle.html",
555+
"image": "lib/img/bbb-1.jpg",
556+
"labels": [
557+
"VoD",
558+
"External caption",
559+
"Video",
560+
"Audio",
561+
"Events"
562+
]
550563
}
551564
]
552565
},

0 commit comments

Comments
 (0)