shaka-player 4.4.3 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-please.yaml +2 -27
- package/CHANGELOG.md +64 -45
- package/README.md +16 -10
- package/demo/asset_card.js +18 -21
- package/demo/cast_receiver/index.html +0 -1
- package/demo/close_button.js +0 -3
- package/demo/common/asset.js +22 -5
- package/demo/common/assets.js +132 -49
- package/demo/config.js +192 -253
- package/demo/custom.js +39 -98
- package/demo/front.js +7 -10
- package/demo/index.html +19 -22
- package/demo/input.js +6 -11
- package/demo/input_container.js +8 -9
- package/demo/main.js +51 -123
- package/demo/search.js +22 -34
- package/demo/service_worker.js +0 -3
- package/demo/tooltip.js +3 -5
- package/demo/visualizer.js +3 -5
- package/demo/visualizer_button.js +1 -20
- package/dist/demo.compiled.debug.js +152 -178
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +152 -178
- package/dist/demo.compiled.map +4 -4
- package/dist/deps.js +27 -24
- package/dist/locales.js +31 -31
- package/dist/receiver.compiled.debug.js +22 -43
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +22 -43
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.d.ts +507 -365
- package/dist/shaka-player.compiled.debug.externs.js +205 -51
- package/dist/shaka-player.compiled.debug.js +541 -450
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +205 -51
- package/dist/shaka-player.compiled.js +1120 -1066
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +562 -410
- package/dist/shaka-player.ui.debug.d.ts +562 -410
- package/dist/shaka-player.ui.debug.externs.js +226 -51
- package/dist/shaka-player.ui.debug.js +606 -506
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +226 -51
- package/dist/shaka-player.ui.js +1266 -1207
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/lcevc-integration.md +14 -14
- package/docs/tutorials/faq.md +27 -55
- package/docs/tutorials/index.json +2 -1
- package/docs/tutorials/lcevc.md +118 -0
- package/docs/tutorials/ui-customization.md +4 -0
- package/externs/css_style_declaration.js +19 -0
- package/externs/lcevc.js +37 -13
- package/externs/media_remote.js +68 -0
- package/externs/mediatailor.js +193 -0
- package/externs/pictureinpicture.js +11 -0
- package/externs/shaka/ads.js +27 -0
- package/externs/shaka/manifest.js +10 -5
- package/externs/shaka/manifest_parser.js +7 -1
- package/externs/shaka/offline.js +4 -0
- package/externs/shaka/player.js +12 -1
- package/karma.conf.js +7 -3
- package/lib/abr/simple_abr_manager.js +43 -3
- package/lib/ads/ad_manager.js +104 -50
- package/lib/ads/media_tailor_ad.js +297 -0
- package/lib/ads/media_tailor_ad_manager.js +828 -0
- package/lib/cea/ts_cea_parser.js +15 -2
- package/lib/config/codec_switching_strategy.js +24 -0
- package/lib/dash/content_protection.js +120 -2
- package/lib/dash/dash_parser.js +75 -12
- package/lib/dash/mpd_utils.js +10 -6
- package/lib/dash/segment_base.js +13 -5
- package/lib/dash/segment_list.js +13 -5
- package/lib/dash/segment_template.js +43 -85
- package/lib/dependencies/all.js +8 -7
- package/lib/hls/hls_parser.js +44 -16
- package/lib/lcevc/lcevc_dec.js +220 -0
- package/lib/media/adaptation_set.js +22 -11
- package/lib/media/adaptation_set_criteria.js +25 -7
- package/lib/media/media_source_engine.js +215 -27
- package/lib/media/segment_index.js +1 -1
- package/lib/media/segment_reference.js +7 -7
- package/lib/media/streaming_engine.js +33 -18
- package/lib/mss/mss_parser.js +1 -0
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +3 -0
- package/lib/player.js +142 -72
- package/lib/routing/payload.js +5 -1
- package/lib/text/cue.js +15 -0
- package/lib/text/ttml_text_parser.js +17 -0
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +33 -20
- package/lib/transmuxer/h265.js +862 -0
- package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
- package/lib/transmuxer/ts_transmuxer.js +160 -15
- package/lib/util/error.js +28 -9
- package/lib/util/exp_golomb.js +30 -2
- package/lib/util/fake_event.js +3 -0
- package/lib/util/mp4_generator.js +4 -4
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +40 -0
- package/lib/util/player_configuration.js +8 -0
- package/lib/util/state_history.js +6 -2
- package/lib/util/stream_utils.js +133 -217
- package/lib/util/ts_parser.js +226 -40
- package/maintained-branches.md +3 -2
- package/package.json +4 -6
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +2 -1
- package/support.html +0 -1
- package/test/cast/cast_receiver_integration.js +47 -0
- package/test/codec_switching/codec_switching_integration.js +181 -0
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_integration.js +73 -0
- package/test/dash/dash_parser_live_unit.js +2 -0
- package/test/dash/dash_parser_manifest_unit.js +42 -0
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -0
- package/test/dash/dash_parser_segment_template_unit.js +2 -0
- package/test/demo/demo_unit.js +0 -16
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +8 -6
- package/test/media/adaptation_set_criteria_unit.js +118 -0
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/media_source_engine_unit.js +165 -1
- package/test/media/segment_index_unit.js +4 -4
- package/test/media/segment_prefetch_unit.js +1 -1
- package/test/media/streaming_engine_unit.js +17 -17
- package/test/mss/mss_parser_unit.js +2 -0
- package/test/offline/manifest_convert_unit.js +5 -0
- package/test/offline/storage_integration.js +1 -4
- package/test/player_unit.js +102 -131
- package/test/routing/walker_unit.js +1 -0
- package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
- package/test/test/assets/dash-aes-128/dash.mpd +18 -0
- package/test/test/assets/dash-aes-128/license +1 -0
- package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
- package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
- package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
- package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
- package/test/test/assets/hls-ts-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
- package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
- package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
- package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad_manager.js +20 -0
- package/test/test/util/fake_media_source_engine.js +8 -2
- package/test/test/util/manifest_generator.js +7 -3
- package/test/test/util/mss_parser_util.js +4 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +7 -4
- package/test/text/ttml_text_parser_unit.js +52 -0
- package/test/text/vtt_text_parser_unit.js +103 -31
- package/test/transmuxer/transmuxer_integration.js +117 -0
- package/test/ui/ui_unit.js +3 -10
- package/test/util/stream_utils_unit.js +208 -74
- package/ui/controls.js +125 -0
- package/ui/externs/ui.js +8 -1
- package/ui/pip_button.js +22 -120
- package/ui/remote_button.js +201 -0
- package/ui/ui.js +5 -2
- package/demo/common/message_ids.js +0 -309
- package/demo/locales/en.json +0 -288
- package/demo/locales/source.json +0 -1146
- package/externs/mux.js +0 -69
- package/lib/lcevc/lcevc_dil.js +0 -152
- package/lib/transmuxer/muxjs_transmuxer.js +0 -242
- package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#EXTM3U
|
|
2
|
+
#EXT-X-VERSION:3
|
|
3
|
+
#EXT-X-TARGETDURATION:6
|
|
4
|
+
#EXT-X-PLAYLIST-TYPE:VOD
|
|
5
|
+
#EXT-X-INDEPENDENT-SEGMENTS
|
|
6
|
+
#EXTINF:6.000,
|
|
7
|
+
ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts
|
|
8
|
+
#EXTINF:6.000,
|
|
9
|
+
ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts
|
|
10
|
+
#EXTINF:6.000,
|
|
11
|
+
ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts
|
|
12
|
+
#EXTINF:6.000,
|
|
13
|
+
ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts
|
|
14
|
+
#EXT-X-ENDLIST
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#EXTM3U
|
|
2
|
+
#EXT-X-TARGETDURATION:6
|
|
3
|
+
#EXT-X-ALLOW-CACHE:YES
|
|
4
|
+
#EXT-X-PLAYLIST-TYPE:VOD
|
|
5
|
+
#EXT-X-VERSION:3
|
|
6
|
+
#EXT-X-MEDIA-SEQUENCE:1
|
|
7
|
+
#EXTINF:2.436,
|
|
8
|
+
seg-1-v1-a1.ts
|
|
9
|
+
#EXTINF:3.337,
|
|
10
|
+
seg-2-v1-a1.ts
|
|
11
|
+
#EXTINF:3.337,
|
|
12
|
+
seg-3-v1-a1.ts
|
|
13
|
+
#EXTINF:5.005,
|
|
14
|
+
seg-4-v1-a1.ts
|
|
15
|
+
#EXTINF:5.005,
|
|
16
|
+
seg-5-v1-a1.ts
|
|
17
|
+
#EXTINF:5.005,
|
|
18
|
+
seg-6-v1-a1.ts
|
|
19
|
+
#EXTINF:5.606,
|
|
20
|
+
seg-7-v1-a1.ts
|
|
21
|
+
#EXTINF:5.005,
|
|
22
|
+
seg-8-v1-a1.ts
|
|
23
|
+
#EXT-X-ENDLIST
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -45,6 +45,8 @@ shaka.test.Dash = class {
|
|
|
45
45
|
enableLowLatencyMode: () => {},
|
|
46
46
|
updateDuration: () => {},
|
|
47
47
|
newDrmInfo: (stream) => {},
|
|
48
|
+
onManifestUpdated: () => {},
|
|
49
|
+
getBandwidthEstimate: () => 1e6,
|
|
48
50
|
};
|
|
49
51
|
try {
|
|
50
52
|
const manifest = await dashParser.start('dummy://foo', playerInterface);
|
|
@@ -85,6 +87,8 @@ shaka.test.Dash = class {
|
|
|
85
87
|
enableLowLatencyMode: () => {},
|
|
86
88
|
updateDuration: () => {},
|
|
87
89
|
newDrmInfo: (stream) => {},
|
|
90
|
+
onManifestUpdated: () => {},
|
|
91
|
+
getBandwidthEstimate: () => 1e6,
|
|
88
92
|
};
|
|
89
93
|
|
|
90
94
|
try {
|
|
@@ -39,6 +39,14 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
|
|
|
39
39
|
/** @override */
|
|
40
40
|
updateClientSideAdsRenderingSettings(adsRenderingSettings) {}
|
|
41
41
|
|
|
42
|
+
/** @override */
|
|
43
|
+
initMediaTailor(networkingEngine, video) {}
|
|
44
|
+
|
|
45
|
+
/** @override */
|
|
46
|
+
requestMediaTailorStream(url, adsParams, backupUrl) {
|
|
47
|
+
return Promise.resolve('fake:url');
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
/** @override */
|
|
43
51
|
initServerSide(adContainer, video) {}
|
|
44
52
|
|
|
@@ -57,11 +65,23 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
|
|
|
57
65
|
return [];
|
|
58
66
|
}
|
|
59
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @override
|
|
70
|
+
*/
|
|
71
|
+
getCuePoints() {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
/** @override */
|
|
61
76
|
getStats() {
|
|
62
77
|
return this.stats_;
|
|
63
78
|
}
|
|
64
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @override
|
|
82
|
+
*/
|
|
83
|
+
onManifestUpdated(isLive) {}
|
|
84
|
+
|
|
65
85
|
/**
|
|
66
86
|
* @override
|
|
67
87
|
*/
|
|
@@ -134,8 +134,8 @@ shaka.test.FakeMediaSourceEngine = class {
|
|
|
134
134
|
jasmine.createSpy('setSegmentRelativeVttTiming').and.stub();
|
|
135
135
|
|
|
136
136
|
/** @type {!jasmine.Spy} */
|
|
137
|
-
this.
|
|
138
|
-
jasmine.createSpy('
|
|
137
|
+
this.updateLcevcDec =
|
|
138
|
+
jasmine.createSpy('updateLcevcDec').and.stub();
|
|
139
139
|
|
|
140
140
|
/** @type {!jasmine.Spy} */
|
|
141
141
|
this.resync=
|
|
@@ -341,6 +341,12 @@ shaka.test.FakeMediaSourceEngine = class {
|
|
|
341
341
|
return Promise.resolve();
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
+
|
|
345
|
+
/** @override */
|
|
346
|
+
isResetMediaSourceNecessary() {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
|
|
344
350
|
/**
|
|
345
351
|
* @param {string} type
|
|
346
352
|
* @return {!Promise}
|
|
@@ -459,9 +459,11 @@ shaka.test.ManifestGenerator.Stream = class {
|
|
|
459
459
|
* @param {string=} label
|
|
460
460
|
*/
|
|
461
461
|
constructor(manifest, isPartial, id, type, lang, label) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
462
|
+
// variants can be made up of different combinations of video
|
|
463
|
+
// and audio streams
|
|
464
|
+
// goog.asserts.assert(
|
|
465
|
+
// !manifest || !manifest.isIdUsed_(id),
|
|
466
|
+
// 'Streams should have unique ids!');
|
|
465
467
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
466
468
|
|
|
467
469
|
/** @const {shaka.test.ManifestGenerator.Manifest} */
|
|
@@ -499,6 +501,8 @@ shaka.test.ManifestGenerator.Stream = class {
|
|
|
499
501
|
|
|
500
502
|
/** @type {?string} */
|
|
501
503
|
this.originalId = null;
|
|
504
|
+
/** @type {?string} */
|
|
505
|
+
this.groupId = null;
|
|
502
506
|
/** @type {shaka.extern.CreateSegmentIndexFunction} */
|
|
503
507
|
this.createSegmentIndex = shaka.test.Util.spyFunc(create);
|
|
504
508
|
/** @type {shaka.media.SegmentIndex} */
|
|
@@ -45,6 +45,8 @@ shaka.test.Mss = class {
|
|
|
45
45
|
enableLowLatencyMode: () => {},
|
|
46
46
|
updateDuration: () => {},
|
|
47
47
|
newDrmInfo: (stream) => {},
|
|
48
|
+
onManifestUpdated: () => {},
|
|
49
|
+
getBandwidthEstimate: () => 1e6,
|
|
48
50
|
};
|
|
49
51
|
const manifest = await mssParser.start('dummy://foo', playerInterface);
|
|
50
52
|
const stream = manifest.variants[0].audio;
|
|
@@ -81,6 +83,8 @@ shaka.test.Mss = class {
|
|
|
81
83
|
enableLowLatencyMode: () => {},
|
|
82
84
|
updateDuration: () => {},
|
|
83
85
|
newDrmInfo: (stream) => {},
|
|
86
|
+
onManifestUpdated: () => {},
|
|
87
|
+
getBandwidthEstimate: () => 1e6,
|
|
84
88
|
};
|
|
85
89
|
const p = mssParser.start('dummy://foo', playerInterface);
|
|
86
90
|
await expectAsync(p).toBeRejectedWith(
|
|
@@ -149,13 +149,13 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
149
149
|
* ranges for each type of init segment.
|
|
150
150
|
* @param {!Object.<string,number>=} timestampOffsets The timestamp offset
|
|
151
151
|
* for each type of segment
|
|
152
|
-
* @param {shaka.extern.
|
|
152
|
+
* @param {shaka.extern.aes128Key=} aes128Key The AES-128 key to provide
|
|
153
153
|
* to streams, if desired.
|
|
154
154
|
* @return {shaka.extern.Manifest}
|
|
155
155
|
*/
|
|
156
156
|
static createManifest(
|
|
157
157
|
presentationTimeline, periodStartTimes, presentationDuration,
|
|
158
|
-
segmentDurations, initSegmentRanges, timestampOffsets,
|
|
158
|
+
segmentDurations, initSegmentRanges, timestampOffsets, aes128Key) {
|
|
159
159
|
const Util = shaka.test.Util;
|
|
160
160
|
|
|
161
161
|
/**
|
|
@@ -268,9 +268,9 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
268
268
|
appendWindowStart,
|
|
269
269
|
appendWindowEnd);
|
|
270
270
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
271
|
-
if (
|
|
271
|
+
if (aes128Key &&
|
|
272
272
|
(type == ContentType.AUDIO || type == ContentType.VIDEO)) {
|
|
273
|
-
ref.
|
|
273
|
+
ref.aes128Key = aes128Key;
|
|
274
274
|
}
|
|
275
275
|
return ref;
|
|
276
276
|
};
|
|
@@ -394,6 +394,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
394
394
|
return {
|
|
395
395
|
id: id,
|
|
396
396
|
originalId: id.toString(),
|
|
397
|
+
groupId: null,
|
|
397
398
|
createSegmentIndex: Util.spyFunc(jasmine.createSpy('createSegmentIndex')),
|
|
398
399
|
segmentIndex: null,
|
|
399
400
|
mimeType: 'audio/mp4',
|
|
@@ -433,6 +434,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
433
434
|
return {
|
|
434
435
|
id: id,
|
|
435
436
|
originalId: id.toString(),
|
|
437
|
+
groupId: null,
|
|
436
438
|
createSegmentIndex: Util.spyFunc(jasmine.createSpy('createSegmentIndex')),
|
|
437
439
|
segmentIndex: null,
|
|
438
440
|
mimeType: mimeType,
|
|
@@ -473,6 +475,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
473
475
|
return {
|
|
474
476
|
id: id,
|
|
475
477
|
originalId: id.toString(),
|
|
478
|
+
groupId: null,
|
|
476
479
|
createSegmentIndex: Util.spyFunc(jasmine.createSpy('createSegmentIndex')),
|
|
477
480
|
segmentIndex: null,
|
|
478
481
|
mimeType: 'text/vtt',
|
|
@@ -1147,6 +1147,31 @@ describe('TtmlTextParser', () => {
|
|
|
1147
1147
|
{startTime: 62.05, endTime: 3723.2});
|
|
1148
1148
|
});
|
|
1149
1149
|
|
|
1150
|
+
it('supports textCombine setting', () => {
|
|
1151
|
+
verifyHelper(
|
|
1152
|
+
[
|
|
1153
|
+
{
|
|
1154
|
+
startTime: 62.05,
|
|
1155
|
+
endTime: 3723.2,
|
|
1156
|
+
payload: 'Test',
|
|
1157
|
+
textCombineUpright: 'all',
|
|
1158
|
+
writingMode: Cue.writingMode.VERTICAL_LEFT_TO_RIGHT,
|
|
1159
|
+
},
|
|
1160
|
+
],
|
|
1161
|
+
'<tt xmlns:tts="http://www.w3.org/ns/ttml#styling">' +
|
|
1162
|
+
'<layout>' +
|
|
1163
|
+
'<region xml:id="subtitleArea" ' +
|
|
1164
|
+
'tts:writingMode="tb" ' +
|
|
1165
|
+
'tts:textCombine="all"/>' +
|
|
1166
|
+
'</layout>' +
|
|
1167
|
+
'<body region="subtitleArea"><div>' +
|
|
1168
|
+
'<p begin="01:02.05" end="01:02:03.200">Test</p>' +
|
|
1169
|
+
'</div></body></tt>',
|
|
1170
|
+
{periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0},
|
|
1171
|
+
{startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}},
|
|
1172
|
+
{startTime: 62.05, endTime: 3723.2});
|
|
1173
|
+
});
|
|
1174
|
+
|
|
1150
1175
|
it('disregards empty divs and ps', () => {
|
|
1151
1176
|
verifyHelper(
|
|
1152
1177
|
[
|
|
@@ -1286,6 +1311,33 @@ describe('TtmlTextParser', () => {
|
|
|
1286
1311
|
{startTime: 62.05, endTime: 3723.2});
|
|
1287
1312
|
});
|
|
1288
1313
|
|
|
1314
|
+
it('supports tts:ruby', () => {
|
|
1315
|
+
verifyHelper(
|
|
1316
|
+
[{
|
|
1317
|
+
startTime: 62.05,
|
|
1318
|
+
endTime: 3723.2,
|
|
1319
|
+
payload: '',
|
|
1320
|
+
nestedCues: [{
|
|
1321
|
+
startTime: 62.05,
|
|
1322
|
+
endTime: 3723.2,
|
|
1323
|
+
payload: 'Line1',
|
|
1324
|
+
}, {
|
|
1325
|
+
startTime: 62.05,
|
|
1326
|
+
endTime: 3723.2,
|
|
1327
|
+
payload: 'Line2',
|
|
1328
|
+
rubyTag: 'rt',
|
|
1329
|
+
}],
|
|
1330
|
+
rubyTag: 'ruby',
|
|
1331
|
+
}],
|
|
1332
|
+
// With anonymous spans
|
|
1333
|
+
'<tt xmlns:tts="http://www.w3.org/ns/ttml#styling"><body><div>' +
|
|
1334
|
+
'<p begin="01:02.05" end="01:02:03.200" tts:ruby="container">' +
|
|
1335
|
+
'<span tts:ruby="base">Line1</span><span tts:ruby="text">Line2' +
|
|
1336
|
+
'</span></p></div></body></tt>',
|
|
1337
|
+
{periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0},
|
|
1338
|
+
{startTime: 62.05, endTime: 3723.2});
|
|
1339
|
+
});
|
|
1340
|
+
|
|
1289
1341
|
it('inserts line breaks for <br> tags', () => {
|
|
1290
1342
|
verifyHelper(
|
|
1291
1343
|
[{
|
|
@@ -646,6 +646,7 @@ describe('VttTextParser', () => {
|
|
|
646
646
|
payload: 'Test',
|
|
647
647
|
color: 'cyan',
|
|
648
648
|
fontSize: '10px',
|
|
649
|
+
textCombineUpright: 'all',
|
|
649
650
|
textShadow: textShadow,
|
|
650
651
|
},
|
|
651
652
|
{
|
|
@@ -654,6 +655,7 @@ describe('VttTextParser', () => {
|
|
|
654
655
|
payload: 'Test2',
|
|
655
656
|
color: 'cyan',
|
|
656
657
|
fontSize: '10px',
|
|
658
|
+
textCombineUpright: 'all',
|
|
657
659
|
textShadow: textShadow,
|
|
658
660
|
},
|
|
659
661
|
],
|
|
@@ -663,6 +665,7 @@ describe('VttTextParser', () => {
|
|
|
663
665
|
'color: cyan;\n'+
|
|
664
666
|
'font-size: 10px;\n'+
|
|
665
667
|
`text-shadow: ${textShadow};\n`+
|
|
668
|
+
'text-combine-upright: all;\n'+
|
|
666
669
|
'}\n\n' +
|
|
667
670
|
'00:00:20.000 --> 00:00:40.000\n' +
|
|
668
671
|
'Test\n\n' +
|
|
@@ -761,16 +764,21 @@ describe('VttTextParser', () => {
|
|
|
761
764
|
{
|
|
762
765
|
startTime: 50,
|
|
763
766
|
endTime: 60,
|
|
764
|
-
payload: '
|
|
765
|
-
fontWeight: Cue.fontWeight.BOLD,
|
|
766
|
-
fontStyle: Cue.fontStyle.NORMAL,
|
|
767
|
-
},
|
|
768
|
-
{
|
|
769
|
-
startTime: 50,
|
|
770
|
-
endTime: 60,
|
|
771
|
-
payload: '5',
|
|
767
|
+
payload: '',
|
|
772
768
|
fontWeight: Cue.fontWeight.BOLD,
|
|
773
|
-
|
|
769
|
+
nestedCues: [
|
|
770
|
+
{
|
|
771
|
+
startTime: 50,
|
|
772
|
+
endTime: 60,
|
|
773
|
+
payload: 'Test',
|
|
774
|
+
},
|
|
775
|
+
{
|
|
776
|
+
startTime: 50,
|
|
777
|
+
endTime: 60,
|
|
778
|
+
payload: '5',
|
|
779
|
+
fontStyle: Cue.fontStyle.ITALIC,
|
|
780
|
+
},
|
|
781
|
+
],
|
|
774
782
|
},
|
|
775
783
|
],
|
|
776
784
|
},
|
|
@@ -801,16 +809,21 @@ describe('VttTextParser', () => {
|
|
|
801
809
|
{
|
|
802
810
|
startTime: 80,
|
|
803
811
|
endTime: 90,
|
|
804
|
-
payload: '
|
|
805
|
-
fontWeight: Cue.fontWeight.BOLD,
|
|
806
|
-
fontStyle: Cue.fontStyle.NORMAL,
|
|
807
|
-
},
|
|
808
|
-
{
|
|
809
|
-
startTime: 80,
|
|
810
|
-
endTime: 90,
|
|
811
|
-
payload: '7',
|
|
812
|
+
payload: '',
|
|
812
813
|
fontWeight: Cue.fontWeight.BOLD,
|
|
813
|
-
|
|
814
|
+
nestedCues: [
|
|
815
|
+
{
|
|
816
|
+
startTime: 80,
|
|
817
|
+
endTime: 90,
|
|
818
|
+
payload: 'Test ',
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
startTime: 80,
|
|
822
|
+
endTime: 90,
|
|
823
|
+
payload: '7',
|
|
824
|
+
fontStyle: Cue.fontStyle.ITALIC,
|
|
825
|
+
},
|
|
826
|
+
],
|
|
814
827
|
},
|
|
815
828
|
],
|
|
816
829
|
},
|
|
@@ -903,6 +916,48 @@ describe('VttTextParser', () => {
|
|
|
903
916
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
904
917
|
});
|
|
905
918
|
|
|
919
|
+
it('supports ruby html tags', () => {
|
|
920
|
+
verifyHelper(
|
|
921
|
+
[
|
|
922
|
+
{
|
|
923
|
+
startTime: 20,
|
|
924
|
+
endTime: 40,
|
|
925
|
+
payload: '',
|
|
926
|
+
nestedCues: [
|
|
927
|
+
{
|
|
928
|
+
startTime: 20,
|
|
929
|
+
endTime: 40,
|
|
930
|
+
payload: '',
|
|
931
|
+
rubyTag: 'ruby',
|
|
932
|
+
nestedCues: [
|
|
933
|
+
{
|
|
934
|
+
startTime: 20,
|
|
935
|
+
endTime: 40,
|
|
936
|
+
payload: 'Test',
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
startTime: 20,
|
|
940
|
+
endTime: 40,
|
|
941
|
+
payload: '2',
|
|
942
|
+
rubyTag: 'rt',
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
startTime: 20,
|
|
946
|
+
endTime: 40,
|
|
947
|
+
payload: '3',
|
|
948
|
+
rubyTag: 'rp',
|
|
949
|
+
},
|
|
950
|
+
],
|
|
951
|
+
},
|
|
952
|
+
],
|
|
953
|
+
},
|
|
954
|
+
],
|
|
955
|
+
'WEBVTT\n\n' +
|
|
956
|
+
'00:00:20.000 --> 00:00:40.000\n' +
|
|
957
|
+
'<ruby>Test<rt>2</rt><rp>3</rp></ruby>',
|
|
958
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
959
|
+
});
|
|
960
|
+
|
|
906
961
|
it('supports only two digits in the timestamp', () => {
|
|
907
962
|
verifyHelper(
|
|
908
963
|
[
|
|
@@ -998,14 +1053,22 @@ describe('VttTextParser', () => {
|
|
|
998
1053
|
{
|
|
999
1054
|
startTime: 70,
|
|
1000
1055
|
endTime: 80,
|
|
1001
|
-
payload: '
|
|
1056
|
+
payload: '',
|
|
1002
1057
|
color: 'red',
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1058
|
+
nestedCues: [
|
|
1059
|
+
{
|
|
1060
|
+
startTime: 70,
|
|
1061
|
+
endTime: 80,
|
|
1062
|
+
payload: 'Test5.1',
|
|
1063
|
+
color: 'red',
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
startTime: 70,
|
|
1067
|
+
endTime: 80,
|
|
1068
|
+
payload: 'Test5.2',
|
|
1069
|
+
color: 'lime',
|
|
1070
|
+
},
|
|
1071
|
+
],
|
|
1009
1072
|
},
|
|
1010
1073
|
],
|
|
1011
1074
|
},
|
|
@@ -1185,9 +1248,17 @@ describe('VttTextParser', () => {
|
|
|
1185
1248
|
{
|
|
1186
1249
|
startTime: 10,
|
|
1187
1250
|
endTime: 20,
|
|
1188
|
-
payload: '
|
|
1251
|
+
payload: '',
|
|
1189
1252
|
color: 'magenta',
|
|
1190
|
-
|
|
1253
|
+
nestedCues: [
|
|
1254
|
+
{
|
|
1255
|
+
startTime: 10,
|
|
1256
|
+
endTime: 20,
|
|
1257
|
+
payload: '2',
|
|
1258
|
+
color: 'magenta',
|
|
1259
|
+
fontStyle: Cue.fontStyle.ITALIC,
|
|
1260
|
+
},
|
|
1261
|
+
],
|
|
1191
1262
|
},
|
|
1192
1263
|
],
|
|
1193
1264
|
},
|
|
@@ -1255,13 +1326,14 @@ describe('VttTextParser', () => {
|
|
|
1255
1326
|
parser.setSequenceMode(sequenceMode);
|
|
1256
1327
|
const result = parser.parseMedia(data, time);
|
|
1257
1328
|
|
|
1258
|
-
const
|
|
1329
|
+
const checkCue = (cue) => {
|
|
1259
1330
|
if (cue.nestedCues) {
|
|
1260
|
-
cue.nestedCues = cue.nestedCues.map(
|
|
1261
|
-
(nestedCue) => jasmine.objectContaining(nestedCue));
|
|
1331
|
+
cue.nestedCues = cue.nestedCues.map((nestedCue) => checkCue(nestedCue));
|
|
1262
1332
|
}
|
|
1263
1333
|
return jasmine.objectContaining(cue);
|
|
1264
|
-
}
|
|
1334
|
+
};
|
|
1335
|
+
|
|
1336
|
+
const expected = cues.map(checkCue);
|
|
1265
1337
|
expect(result).toEqual(expected);
|
|
1266
1338
|
}
|
|
1267
1339
|
|
|
@@ -273,6 +273,33 @@ describe('Transmuxer Player', () => {
|
|
|
273
273
|
|
|
274
274
|
await player.unload();
|
|
275
275
|
});
|
|
276
|
+
|
|
277
|
+
it('H.265 in TS', async () => {
|
|
278
|
+
const chromeVersion = shaka.util.Platform.chromeVersion();
|
|
279
|
+
if (shaka.util.Platform.isWindows() &&
|
|
280
|
+
chromeVersion && chromeVersion === 117) {
|
|
281
|
+
// It appears that Chrome 117 beta in Windows is incorrectly reporting
|
|
282
|
+
// H.265 in MediaCapabilities
|
|
283
|
+
pending('Codec H.265 is not supported by the platform.');
|
|
284
|
+
}
|
|
285
|
+
const mimeType = 'video/mp4; codecs="hvc1.2.4.L123.B0"';
|
|
286
|
+
if (!MediaSource.isTypeSupported(mimeType)) {
|
|
287
|
+
pending('Codec H.265 is not supported by the platform.');
|
|
288
|
+
}
|
|
289
|
+
await player.load('/base/test/test/assets/hls-ts-h265/hevc.m3u8');
|
|
290
|
+
await video.play();
|
|
291
|
+
expect(player.isLive()).toBe(false);
|
|
292
|
+
|
|
293
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
294
|
+
// seconds, fail the test.
|
|
295
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
296
|
+
|
|
297
|
+
// Play for 15 seconds, but stop early if the video ends. If it takes
|
|
298
|
+
// longer than 45 seconds, fail the test.
|
|
299
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 15, 45);
|
|
300
|
+
|
|
301
|
+
await player.unload();
|
|
302
|
+
});
|
|
276
303
|
});
|
|
277
304
|
|
|
278
305
|
describe('for muxed content', () => {
|
|
@@ -292,5 +319,95 @@ describe('Transmuxer Player', () => {
|
|
|
292
319
|
|
|
293
320
|
await player.unload();
|
|
294
321
|
});
|
|
322
|
+
|
|
323
|
+
it('H.265+AAC in TS', async () => {
|
|
324
|
+
const chromeVersion = shaka.util.Platform.chromeVersion();
|
|
325
|
+
if (shaka.util.Platform.isWindows() &&
|
|
326
|
+
chromeVersion && chromeVersion === 117) {
|
|
327
|
+
// It appears that Chrome 117 beta in Windows is incorrectly reporting
|
|
328
|
+
// H.265 in MediaCapabilities
|
|
329
|
+
pending('Codec H.265 is not supported by the platform.');
|
|
330
|
+
}
|
|
331
|
+
if (!MediaSource.isTypeSupported('video/mp4; codecs="hvc1.1.6.L93.90"')) {
|
|
332
|
+
pending('Codec H.265 is not supported by the platform.');
|
|
333
|
+
}
|
|
334
|
+
// eslint-disable-next-line max-len
|
|
335
|
+
await player.load('/base/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8');
|
|
336
|
+
await video.play();
|
|
337
|
+
expect(player.isLive()).toBe(false);
|
|
338
|
+
|
|
339
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
340
|
+
// seconds, fail the test.
|
|
341
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
342
|
+
|
|
343
|
+
// Play for 15 seconds, but stop early if the video ends. If it takes
|
|
344
|
+
// longer than 45 seconds, fail the test.
|
|
345
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 15, 45);
|
|
346
|
+
|
|
347
|
+
await player.unload();
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it('H.264+MP3 in TS', async () => {
|
|
351
|
+
if (!MediaSource.isTypeSupported('audio/mp4; codecs="mp3"')) {
|
|
352
|
+
pending('Codec MP3 in MP4 is not supported by the platform.');
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// eslint-disable-next-line max-len
|
|
356
|
+
await player.load('/base/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8');
|
|
357
|
+
await video.play();
|
|
358
|
+
expect(player.isLive()).toBe(false);
|
|
359
|
+
|
|
360
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
361
|
+
// seconds, fail the test.
|
|
362
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
363
|
+
|
|
364
|
+
// Play for 15 seconds, but stop early if the video ends. If it takes
|
|
365
|
+
// longer than 45 seconds, fail the test.
|
|
366
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 15, 45);
|
|
367
|
+
|
|
368
|
+
await player.unload();
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('H.264+AC3 in TS', async () => {
|
|
372
|
+
if (!isAc3Supported()) {
|
|
373
|
+
pending('Codec AC-3 is not supported by the platform.');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// eslint-disable-next-line max-len
|
|
377
|
+
await player.load('/base/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8');
|
|
378
|
+
await video.play();
|
|
379
|
+
expect(player.isLive()).toBe(false);
|
|
380
|
+
|
|
381
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
382
|
+
// seconds, fail the test.
|
|
383
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
384
|
+
|
|
385
|
+
// Play for 15 seconds, but stop early if the video ends. If it takes
|
|
386
|
+
// longer than 45 seconds, fail the test.
|
|
387
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 15, 45);
|
|
388
|
+
|
|
389
|
+
await player.unload();
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('H.264+EC3 in TS', async () => {
|
|
393
|
+
if (!isEc3Supported()) {
|
|
394
|
+
pending('Codec EC-3 is not supported by the platform.');
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// eslint-disable-next-line max-len
|
|
398
|
+
await player.load('/base/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8');
|
|
399
|
+
await video.play();
|
|
400
|
+
expect(player.isLive()).toBe(false);
|
|
401
|
+
|
|
402
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
403
|
+
// seconds, fail the test.
|
|
404
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
405
|
+
|
|
406
|
+
// Play for 15 seconds, but stop early if the video ends. If it takes
|
|
407
|
+
// longer than 45 seconds, fail the test.
|
|
408
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 15, 45);
|
|
409
|
+
|
|
410
|
+
await player.unload();
|
|
411
|
+
});
|
|
295
412
|
});
|
|
296
413
|
});
|
package/test/ui/ui_unit.js
CHANGED
|
@@ -616,19 +616,10 @@ describe('UI', () => {
|
|
|
616
616
|
player.configure('abr.enabled', false);
|
|
617
617
|
|
|
618
618
|
const tracks = player.getVariantTracks();
|
|
619
|
-
const en2 =
|
|
620
|
-
tracks.find((t) => t.language == 'en' && t.channelsCount == 2);
|
|
621
619
|
const en1 =
|
|
622
620
|
tracks.find((t) => t.language == 'en' && t.channelsCount == 1);
|
|
623
621
|
const es = tracks.find((t) => t.language == 'es');
|
|
624
622
|
|
|
625
|
-
// There are 3 variants with English 2-channel, but one is a duplicate
|
|
626
|
-
// and shouldn't appear in the list.
|
|
627
|
-
goog.asserts.assert(en2, 'Unable to find tracks');
|
|
628
|
-
player.selectVariantTrack(en2, true);
|
|
629
|
-
await updateResolutionMenu();
|
|
630
|
-
expect(getResolutions()).toEqual(['240p', '480p']);
|
|
631
|
-
|
|
632
623
|
// There is 1 variant with English 1-channel.
|
|
633
624
|
goog.asserts.assert(en1, 'Unable to find tracks');
|
|
634
625
|
player.selectVariantTrack(en1, true);
|
|
@@ -646,7 +637,9 @@ describe('UI', () => {
|
|
|
646
637
|
const manifest =
|
|
647
638
|
shaka.test.ManifestGenerator.generate((manifest) => {
|
|
648
639
|
manifest.addVariant(0, (variant) => {
|
|
649
|
-
variant.addAudio(0)
|
|
640
|
+
variant.addAudio(0, (stream) => {
|
|
641
|
+
stream.roles = ['main'];
|
|
642
|
+
});
|
|
650
643
|
variant.bandwidth = 100000;
|
|
651
644
|
});
|
|
652
645
|
manifest.addVariant(1, (variant) => {
|