shaka-player 4.3.7 → 4.3.9
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/ISSUE_TEMPLATE/bug_report.md +11 -0
- package/.github/workflows/appspot.yaml +39 -0
- package/.github/workflows/build-and-test.yaml +8 -0
- package/.github/workflows/selenium-lab-tests.yaml +3 -2
- package/.github/workflows/update-issues.yaml +1 -0
- package/CHANGELOG.md +44 -0
- package/CONTRIBUTORS +1 -0
- package/demo/custom.js +1 -1
- package/dist/demo.compiled.debug.js +2 -2
- package/dist/demo.compiled.debug.map +2 -2
- package/dist/demo.compiled.js +2 -2
- package/dist/demo.compiled.map +2 -2
- package/dist/deps.js +2 -2
- package/dist/locales.js +31 -31
- package/dist/shaka-player.compiled.d.ts +24 -2
- package/dist/shaka-player.compiled.debug.d.ts +24 -2
- package/dist/shaka-player.compiled.debug.js +251 -247
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +796 -793
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +24 -2
- package/dist/shaka-player.ui.debug.d.ts +24 -2
- package/dist/shaka-player.ui.debug.js +289 -286
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.js +831 -827
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/drm-config.md +9 -6
- package/docs/tutorials/selenium-grid-config.md +60 -8
- package/externs/ima.js +34 -0
- package/externs/shaka/manifest.js +5 -1
- package/externs/shaka/offline.js +5 -1
- package/karma.conf.js +50 -7
- package/lib/abr/simple_abr_manager.js +6 -6
- package/lib/cea/mp4_cea_parser.js +24 -18
- package/lib/dash/dash_parser.js +19 -3
- package/lib/hls/hls_parser.js +24 -4
- package/lib/media/drm_engine.js +14 -8
- package/lib/media/gap_jumping_controller.js +24 -2
- package/lib/media/media_source_engine.js +11 -8
- package/lib/media/playhead.js +11 -0
- package/lib/media/region_observer.js +19 -1
- package/lib/media/streaming_engine.js +41 -21
- package/lib/media/video_wrapper.js +6 -1
- 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 +1 -0
- package/lib/player.js +20 -9
- package/lib/polyfill/abort_controller.js +7 -0
- package/lib/polyfill/orientation.js +34 -7
- package/lib/text/vtt_text_parser.js +3 -1
- package/lib/util/manifest_parser_utils.js +5 -3
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +14 -0
- package/lib/util/stream_utils.js +70 -26
- package/package.json +2 -2
- package/test/cast/cast_utils_unit.js +4 -1
- package/test/cea/mp4_cea_parser_unit.js +28 -5
- package/test/dash/dash_parser_manifest_unit.js +120 -0
- package/test/hls/hls_parser_unit.js +216 -0
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/drm_engine_integration.js +2 -2
- package/test/media/media_source_engine_unit.js +1 -1
- package/test/media/region_observer_unit.js +2 -1
- package/test/media/segment_index_unit.js +3 -3
- package/test/media/streaming_engine_integration.js +14 -11
- package/test/media/streaming_engine_unit.js +26 -2
- package/test/offline/manifest_convert_unit.js +5 -0
- package/test/offline/offline_integration.js +6 -3
- package/test/player_external.js +19 -16
- package/test/player_integration.js +35 -48
- package/test/player_src_equals_integration.js +9 -5
- package/test/test/assets/multiple-trun-init.mp4 +0 -0
- package/test/test/assets/multiple-trun-segment.mp4 +0 -0
- package/test/test/util/fake_demo_main.js +7 -3
- package/test/test/util/layout_tests.js +2 -2
- package/test/test/util/manifest_generator.js +2 -0
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +3 -0
- package/test/test/util/ui_utils.js +9 -2
- package/test/test/util/util.js +6 -27
- package/test/test/util/waiter.js +73 -3
- package/test/ui/ad_ui_unit.js +9 -9
- package/test/util/stream_utils_unit.js +46 -0
- package/ui/range_element.js +5 -0
- package/ui/resolution_selection.js +7 -1
|
@@ -395,7 +395,7 @@ shaka.test.NativeTextLayoutTests = class extends shaka.test.TextLayoutTests {
|
|
|
395
395
|
// The this.video must be played a little now, after the cues were appended,
|
|
396
396
|
// but before the screenshot.
|
|
397
397
|
this.video.playbackRate = 1;
|
|
398
|
-
this.video.play();
|
|
398
|
+
await this.video.play();
|
|
399
399
|
await this.waiter.failOnTimeout(false).timeoutAfter(5)
|
|
400
400
|
.waitForMovement(this.video);
|
|
401
401
|
this.video.pause();
|
|
@@ -404,7 +404,7 @@ shaka.test.NativeTextLayoutTests = class extends shaka.test.TextLayoutTests {
|
|
|
404
404
|
this.video.currentTime = time;
|
|
405
405
|
// Get into a playing state, but without movement.
|
|
406
406
|
this.video.playbackRate = 0;
|
|
407
|
-
this.video.play();
|
|
407
|
+
await this.video.play();
|
|
408
408
|
|
|
409
409
|
// Add a short delay to ensure that the system has caught up and that
|
|
410
410
|
// native text displayers have been updated by the browser.
|
|
@@ -410,6 +410,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
410
410
|
roles: [],
|
|
411
411
|
forced: false,
|
|
412
412
|
spatialAudio: false,
|
|
413
|
+
external: false,
|
|
413
414
|
};
|
|
414
415
|
}
|
|
415
416
|
|
|
@@ -447,6 +448,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
447
448
|
roles: [],
|
|
448
449
|
forced: false,
|
|
449
450
|
spatialAudio: false,
|
|
451
|
+
external: false,
|
|
450
452
|
};
|
|
451
453
|
}
|
|
452
454
|
|
|
@@ -482,6 +484,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
482
484
|
roles: [],
|
|
483
485
|
forced: false,
|
|
484
486
|
spatialAudio: false,
|
|
487
|
+
external: false,
|
|
485
488
|
};
|
|
486
489
|
}
|
|
487
490
|
};
|
|
@@ -115,11 +115,18 @@ shaka.test.UiUtils = class {
|
|
|
115
115
|
// Destroying the UI destroys the controls and player inside.
|
|
116
116
|
destroys.push(ui.destroy());
|
|
117
117
|
}
|
|
118
|
-
|
|
118
|
+
|
|
119
|
+
const allDestroyed = Promise.all(destroys);
|
|
120
|
+
// 10 seconds should be more than enough to tear down the UI.
|
|
121
|
+
// Adding this silent timeout fixes several tests that inconsistently hang
|
|
122
|
+
// during teardown and cause failures in afterEach() clauses.
|
|
123
|
+
await Promise.race([allDestroyed, shaka.test.Util.delay(10)]);
|
|
119
124
|
|
|
120
125
|
// Now remove all the containers from the DOM.
|
|
121
126
|
for (const container of containers) {
|
|
122
|
-
container.parentElement
|
|
127
|
+
if (container.parentElement) {
|
|
128
|
+
container.parentElement.removeChild(container);
|
|
129
|
+
}
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
132
|
|
package/test/test/util/util.js
CHANGED
|
@@ -255,33 +255,12 @@ shaka.test.Util = class {
|
|
|
255
255
|
* @param {string} uri
|
|
256
256
|
* @return {!Promise.<!ArrayBuffer>}
|
|
257
257
|
*/
|
|
258
|
-
static fetch(uri) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
xhr.onload = (event) => {
|
|
265
|
-
if (xhr.status >= 200 &&
|
|
266
|
-
xhr.status <= 299 &&
|
|
267
|
-
!!xhr.response) {
|
|
268
|
-
resolve(/** @type {!ArrayBuffer} */(xhr.response));
|
|
269
|
-
} else {
|
|
270
|
-
let message = '';
|
|
271
|
-
if (xhr.response) {
|
|
272
|
-
message = ': ' + shaka.util.StringUtils.fromUTF8(
|
|
273
|
-
/** @type {!ArrayBuffer} */(xhr.response));
|
|
274
|
-
}
|
|
275
|
-
reject(xhr.status + message);
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
xhr.onerror = (event) => {
|
|
280
|
-
reject('shaka.test.Util.fetch failed: ' + uri);
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
xhr.send(/* body= */ null);
|
|
284
|
-
}));
|
|
258
|
+
static async fetch(uri) {
|
|
259
|
+
const response = await fetch(uri);
|
|
260
|
+
if (!response.ok) {
|
|
261
|
+
throw new Error('shaka.test.Util.fetch failed: ' + uri);
|
|
262
|
+
}
|
|
263
|
+
return response.arrayBuffer();
|
|
285
264
|
}
|
|
286
265
|
|
|
287
266
|
/**
|
package/test/test/util/waiter.js
CHANGED
|
@@ -109,6 +109,8 @@ shaka.test.Waiter = class {
|
|
|
109
109
|
* @return {!Promise}
|
|
110
110
|
*/
|
|
111
111
|
waitUntilPlayheadReaches(mediaElement, timeGoal) {
|
|
112
|
+
this.macPlaybackWorkaround_(mediaElement);
|
|
113
|
+
|
|
112
114
|
// The name of what we're waiting for
|
|
113
115
|
const goalName = 'movement from ' + mediaElement.currentTime +
|
|
114
116
|
' to ' + timeGoal;
|
|
@@ -153,6 +155,8 @@ shaka.test.Waiter = class {
|
|
|
153
155
|
* @return {!Promise}
|
|
154
156
|
*/
|
|
155
157
|
waitForEnd(mediaElement) {
|
|
158
|
+
this.macPlaybackWorkaround_(mediaElement);
|
|
159
|
+
|
|
156
160
|
// The name of what we're waiting for.
|
|
157
161
|
const goalName = 'end of media';
|
|
158
162
|
|
|
@@ -207,13 +211,64 @@ shaka.test.Waiter = class {
|
|
|
207
211
|
* Wait for the video to end or for |timeout| seconds to pass, whichever
|
|
208
212
|
* occurs first. The Promise is resolved when either of these happens.
|
|
209
213
|
*
|
|
210
|
-
* @param {!HTMLMediaElement}
|
|
214
|
+
* @param {!HTMLMediaElement} mediaElement
|
|
211
215
|
* @param {number} timeout in seconds, after which the Promise succeeds
|
|
212
216
|
* @return {!Promise}
|
|
213
217
|
*/
|
|
214
|
-
waitForEndOrTimeout(
|
|
218
|
+
waitForEndOrTimeout(mediaElement, timeout) {
|
|
215
219
|
this.failOnTimeout(false).timeoutAfter(timeout);
|
|
216
|
-
return this.waitForEnd(
|
|
220
|
+
return this.waitForEnd(mediaElement);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Wait until a certain amount of content is buffered.
|
|
225
|
+
*
|
|
226
|
+
* @param {!HTMLMediaElement} mediaElement
|
|
227
|
+
* @param {number} bufferingGoal in seconds, after which the Promise succeeds
|
|
228
|
+
* @return {!Promise}
|
|
229
|
+
*/
|
|
230
|
+
waitUntilBuffered(mediaElement, bufferingGoal) {
|
|
231
|
+
// The name of what we're waiting for.
|
|
232
|
+
const goalName = `${bufferingGoal} seconds buffered`;
|
|
233
|
+
|
|
234
|
+
// The conditions for success.
|
|
235
|
+
const bufferedEnough = () => {
|
|
236
|
+
const end = shaka.media.TimeRangesUtils.bufferEnd(mediaElement.buffered);
|
|
237
|
+
if (end == null) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
return end - mediaElement.currentTime >= bufferingGoal;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
if (bufferedEnough()) {
|
|
244
|
+
return Promise.resolve();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Cleanup on timeout.
|
|
248
|
+
let timer = null;
|
|
249
|
+
const cleanup = () => {
|
|
250
|
+
if (timer) {
|
|
251
|
+
timer.stop();
|
|
252
|
+
}
|
|
253
|
+
this.eventManager_.unlisten(mediaElement, 'timeupdate');
|
|
254
|
+
this.eventManager_.unlisten(mediaElement, 'ended');
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const p = new Promise((resolve) => {
|
|
258
|
+
const check = () => {
|
|
259
|
+
if (bufferedEnough()) {
|
|
260
|
+
cleanup();
|
|
261
|
+
resolve();
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
timer = new shaka.util.Timer(check);
|
|
266
|
+
timer.tickEvery(/* seconds= */ 1);
|
|
267
|
+
this.eventManager_.listen(mediaElement, 'timeupdate', check);
|
|
268
|
+
this.eventManager_.listen(mediaElement, 'ended', check);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return this.waitUntilGeneric_(goalName, p, cleanup, mediaElement);
|
|
217
272
|
}
|
|
218
273
|
|
|
219
274
|
/**
|
|
@@ -333,4 +388,19 @@ shaka.test.Waiter = class {
|
|
|
333
388
|
`buffered: ${JSON.stringify(buffered)}\n`;
|
|
334
389
|
shaka.log.error(error.message);
|
|
335
390
|
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* @param {!HTMLMediaElement} mediaElement
|
|
394
|
+
* @private
|
|
395
|
+
*/
|
|
396
|
+
macPlaybackWorkaround_(mediaElement) {
|
|
397
|
+
if (shaka.util.Platform.isMac()) {
|
|
398
|
+
// Work around bizarre playback slowdowns that only seem to occur with
|
|
399
|
+
// WebDriver and only on Mac. Increasing the playback rate allows tests
|
|
400
|
+
// to complete without timing out.
|
|
401
|
+
if (mediaElement.playbackRate == 1) {
|
|
402
|
+
mediaElement.playbackRate = 2;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
336
406
|
};
|
package/test/ui/ad_ui_unit.js
CHANGED
|
@@ -25,15 +25,6 @@ describe('Ad UI', () => {
|
|
|
25
25
|
shaka.Player.setAdManagerFactory(() => new shaka.test.FakeAdManager());
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
afterEach(async () => {
|
|
29
|
-
await UiUtils.cleanupUI();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
afterAll(() => {
|
|
33
|
-
document.head.removeChild(cssLink);
|
|
34
|
-
shaka.Player.setAdManagerFactory(() => new shaka.ads.AdManager());
|
|
35
|
-
});
|
|
36
|
-
|
|
37
28
|
beforeEach(() => {
|
|
38
29
|
container =
|
|
39
30
|
/** @type {!HTMLElement} */ (document.createElement('div'));
|
|
@@ -45,6 +36,15 @@ describe('Ad UI', () => {
|
|
|
45
36
|
adManager = video['ui'].getControls().getPlayer().getAdManager();
|
|
46
37
|
});
|
|
47
38
|
|
|
39
|
+
afterEach(async () => {
|
|
40
|
+
await UiUtils.cleanupUI();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterAll(() => {
|
|
44
|
+
document.head.removeChild(cssLink);
|
|
45
|
+
shaka.Player.setAdManagerFactory(() => new shaka.ads.AdManager());
|
|
46
|
+
});
|
|
47
|
+
|
|
48
48
|
it('is invisible if no ad is playing', () => {
|
|
49
49
|
const adControlsContainer =
|
|
50
50
|
UiUtils.getElementByClassName(container, 'shaka-ad-controls');
|
|
@@ -718,6 +718,52 @@ describe('StreamUtils', () => {
|
|
|
718
718
|
expect(manifest.variants.length).toBe(1);
|
|
719
719
|
});
|
|
720
720
|
|
|
721
|
+
it('supports fLaC codec', async () => {
|
|
722
|
+
if (!MediaSource.isTypeSupported('audio/mp4; codecs="flac"')) {
|
|
723
|
+
pending('Codec fLaC is not supported by the platform.');
|
|
724
|
+
}
|
|
725
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
726
|
+
manifest.addVariant(0, (variant) => {
|
|
727
|
+
variant.addAudio(1, (stream) => {
|
|
728
|
+
stream.mime('audio/mp4', 'fLaC');
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
manifest.addVariant(2, (variant) => {
|
|
732
|
+
variant.addAudio(3, (stream) => {
|
|
733
|
+
stream.mime('audio/mp4', 'flac');
|
|
734
|
+
});
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
await shaka.util.StreamUtils.filterManifest(
|
|
739
|
+
fakeDrmEngine, /* currentVariant= */ null, manifest);
|
|
740
|
+
|
|
741
|
+
expect(manifest.variants.length).toBe(2);
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it('supports Opus codec', async () => {
|
|
745
|
+
if (!MediaSource.isTypeSupported('audio/mp4; codecs="opus"')) {
|
|
746
|
+
pending('Codec Opus is not supported by the platform.');
|
|
747
|
+
}
|
|
748
|
+
manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
749
|
+
manifest.addVariant(0, (variant) => {
|
|
750
|
+
variant.addAudio(1, (stream) => {
|
|
751
|
+
stream.mime('audio/mp4', 'Opus');
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
manifest.addVariant(2, (variant) => {
|
|
755
|
+
variant.addAudio(3, (stream) => {
|
|
756
|
+
stream.mime('audio/mp4', 'opus');
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
await shaka.util.StreamUtils.filterManifest(
|
|
762
|
+
fakeDrmEngine, /* currentVariant= */ null, manifest);
|
|
763
|
+
|
|
764
|
+
expect(manifest.variants.length).toBe(2);
|
|
765
|
+
});
|
|
766
|
+
|
|
721
767
|
it('supports legacy AVC1 codec', async () => {
|
|
722
768
|
if (!MediaSource.isTypeSupported('video/mp4; codecs="avc1.42001e"')) {
|
|
723
769
|
pending('Codec avc1.42001e is not supported by the platform.');
|
package/ui/range_element.js
CHANGED
|
@@ -110,6 +110,11 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
|
|
|
110
110
|
this.onChangeEnd();
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
|
+
|
|
114
|
+
this.eventManager.listen(this.bar, 'contextmenu', (e) => {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
});
|
|
113
118
|
}
|
|
114
119
|
|
|
115
120
|
/** @override */
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
goog.provide('shaka.ui.ResolutionSelection');
|
|
9
9
|
|
|
10
10
|
goog.require('goog.asserts');
|
|
11
|
+
goog.require('shaka.Player');
|
|
11
12
|
goog.require('shaka.ui.Controls');
|
|
12
13
|
goog.require('shaka.ui.Enums');
|
|
13
14
|
goog.require('shaka.ui.Locales');
|
|
@@ -67,7 +68,12 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
|
|
|
67
68
|
/** @private */
|
|
68
69
|
updateResolutionSelection_() {
|
|
69
70
|
/** @type {!Array.<shaka.extern.Track>} */
|
|
70
|
-
let tracks =
|
|
71
|
+
let tracks = [];
|
|
72
|
+
// When played with src=, the variant tracks available from
|
|
73
|
+
// player.getVariantTracks() represent languages, not resolutions.
|
|
74
|
+
if (this.player.getLoadMode() != shaka.Player.LoadMode.SRC_EQUALS) {
|
|
75
|
+
tracks = this.player.getVariantTracks();
|
|
76
|
+
}
|
|
71
77
|
|
|
72
78
|
// If there is a selected variant track, then we filter out any tracks in
|
|
73
79
|
// a different language. Then we use those remaining tracks to display the
|