shaka-player 3.3.4 → 4.0.1
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/config.yml +1 -0
- package/.github/workflows/build-and-test.yaml +0 -1
- package/.github/workflows/demo-version-index.yaml +8 -0
- package/.github/workflows/release-please.yaml +19 -3
- package/.github/workflows/selenium-lab-tests.yaml +0 -1
- package/.github/workflows/sync-labels.yaml +33 -0
- package/.github/workflows/update-issues.yaml +29 -0
- package/.github/workflows/validate-pr-title.yaml +35 -0
- package/AUTHORS +1 -0
- package/CHANGELOG.md +209 -28
- package/CONTRIBUTORS +1 -0
- package/README.md +10 -7
- package/app-engine/demo-version-index/README.md +3 -3
- package/app-engine/demo-version-index/app.yaml +27 -1
- package/app-engine/demo-version-index/generate.py +164 -0
- package/app-engine/demo-version-index/main.py +4 -155
- package/app-engine/demo-version-index/requirements.txt +0 -1
- package/build/README.md +2 -2
- package/build/compiler.py +1 -1
- package/build/generateTsDefs.py +0 -2
- package/build/misspellings.txt +1 -0
- package/build/shaka-lab.yaml +0 -2
- package/build/test.py +7 -1
- package/build/types/core +0 -1
- package/build/types/polyfill +0 -3
- package/demo/common/asset.js +17 -1
- package/demo/common/assets.js +29 -0
- package/demo/common/message_ids.js +6 -3
- package/demo/config.js +10 -11
- package/demo/custom.js +39 -0
- package/demo/demo_utils.js +0 -1
- package/demo/locales/en.json +6 -3
- package/demo/locales/source.json +22 -10
- package/demo/main.js +9 -6
- package/demo/search.js +2 -1
- package/dist/controls.css +1 -1
- package/dist/demo.compiled.debug.js +71 -64
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +71 -64
- package/dist/demo.compiled.map +3 -3
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +16 -20
- package/dist/locales.js +33 -31
- package/dist/receiver.compiled.debug.js +32 -28
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +32 -28
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +78 -82
- package/dist/shaka-player.compiled.debug.d.ts +78 -82
- package/dist/shaka-player.compiled.debug.externs.js +127 -126
- package/dist/shaka-player.compiled.debug.js +471 -523
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +127 -126
- package/dist/shaka-player.compiled.js +844 -858
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +80 -82
- package/dist/shaka-player.ui.debug.d.ts +80 -82
- package/dist/shaka-player.ui.debug.externs.js +135 -126
- package/dist/shaka-player.ui.debug.js +531 -581
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +135 -126
- package/dist/shaka-player.ui.js +991 -1001
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/config.md +0 -2
- package/docs/tutorials/drm-config.md +5 -0
- package/docs/tutorials/fairplay.md +7 -22
- package/docs/tutorials/faq.md +0 -11
- package/docs/tutorials/index.json +2 -8
- package/docs/tutorials/plugins.md +1 -3
- package/docs/tutorials/upgrade.md +85 -11
- package/externs/polyfill.js +15 -0
- package/externs/shaka/manifest.js +5 -1
- package/externs/shaka/net.js +12 -0
- package/externs/shaka/offline.js +5 -1
- package/externs/shaka/player.js +39 -21
- package/externs/shaka/text.js +12 -12
- package/externs/sourcebuffer.js +15 -0
- package/karma.conf.js +4 -0
- package/lib/ads/client_side_ad.js +13 -2
- package/lib/ads/client_side_ad_manager.js +22 -4
- package/lib/cast/cast_utils.js +0 -1
- package/lib/dash/content_protection.js +85 -5
- package/lib/dash/dash_parser.js +3 -3
- package/lib/hls/hls_parser.js +391 -747
- package/lib/hls/manifest_text_parser.js +2 -3
- package/lib/media/drm_engine.js +102 -37
- package/lib/media/gap_jumping_controller.js +10 -45
- package/lib/media/media_source_engine.js +157 -31
- package/lib/media/playhead.js +2 -5
- package/lib/media/presentation_timeline.js +1 -2
- package/lib/media/segment_index.js +13 -46
- package/lib/media/segment_reference.js +47 -1
- package/lib/media/streaming_engine.js +28 -11
- package/lib/media/time_ranges_utils.js +4 -9
- package/lib/net/networking_engine.js +3 -0
- package/lib/offline/indexeddb/storage_mechanism.js +4 -2
- 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 +100 -132
- package/lib/player.js +181 -307
- package/lib/polyfill/media_capabilities.js +12 -6
- package/lib/polyfill/mediasource.js +0 -28
- package/lib/polyfill/patchedmediakeys_nop.js +2 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
- package/lib/text/cue.js +0 -6
- package/lib/text/lrc_text_parser.js +8 -0
- package/lib/text/mp4_ttml_parser.js +8 -0
- package/lib/text/mp4_vtt_parser.js +8 -0
- package/lib/text/sbv_text_parser.js +8 -0
- package/lib/text/simple_text_displayer.js +1 -7
- package/lib/text/srt_text_parser.js +8 -0
- package/lib/text/ssa_text_parser.js +8 -0
- package/lib/text/text_engine.js +19 -3
- package/lib/text/ttml_text_parser.js +8 -0
- package/lib/text/ui_text_displayer.js +1 -7
- package/lib/text/vtt_text_parser.js +27 -5
- package/lib/text/web_vtt_generator.js +1 -7
- package/lib/util/config_utils.js +25 -0
- package/lib/util/error.js +16 -13
- package/lib/util/fairplay_utils.js +109 -0
- package/lib/util/functional.js +0 -42
- package/lib/util/manifest_parser_utils.js +1 -1
- package/lib/util/mime_utils.js +50 -1
- package/lib/util/periods.js +5 -4
- package/lib/util/platform.js +45 -0
- package/lib/util/player_configuration.js +26 -20
- package/lib/util/pssh.js +23 -4
- package/lib/util/stream_utils.js +96 -24
- package/lib/util/uint8array_utils.js +0 -16
- package/lib/util/xml_utils.js +1 -1
- package/package.json +4 -1
- package/roadmap.md +19 -19
- package/shaka-player.uncompiled.js +0 -3
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/dash/dash_parser_content_protection_unit.js +44 -0
- package/test/dash/dash_parser_manifest_unit.js +0 -24
- package/test/dash/dash_parser_segment_template_unit.js +3 -4
- package/test/demo/demo_unit.js +2 -1
- package/test/hls/hls_live_unit.js +121 -220
- package/test/hls/hls_parser_unit.js +515 -432
- package/test/hls/manifest_text_parser_unit.js +19 -0
- package/test/media/drm_engine_unit.js +86 -120
- package/test/media/media_source_engine_integration.js +26 -3
- package/test/media/media_source_engine_unit.js +7 -6
- package/test/media/playhead_unit.js +27 -191
- package/test/media/segment_index_unit.js +15 -25
- package/test/media/streaming_engine_integration.js +4 -39
- package/test/media/streaming_engine_unit.js +3 -2
- package/test/media/time_ranges_utils_unit.js +0 -5
- package/test/offline/indexeddb_storage_unit.js +1 -1
- package/test/offline/manifest_convert_unit.js +34 -4
- package/test/offline/offline_manifest_parser_unit.js +1 -0
- package/test/offline/storage_compatibility_unit.js +1 -1
- package/test/offline/storage_integration.js +5 -4
- package/test/player_external.js +7 -7
- package/test/player_integration.js +22 -10
- package/test/player_src_equals_integration.js +81 -83
- package/test/player_unit.js +124 -1
- package/test/test/boot.js +9 -0
- package/test/test/externs/filters.js +4 -0
- package/test/test/util/fake_media_source_engine.js +11 -4
- package/test/test/util/manifest_generator.js +3 -1
- package/test/test/util/manifest_parser_util.js +4 -1
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +31 -2
- package/test/test/util/streaming_engine_util.js +1 -0
- package/test/test/util/test_scheme.js +24 -1
- package/test/test/util/util.js +4 -4
- package/test/text/cue_integration.js +2 -2
- package/test/text/lrc_text_parser_unit.js +6 -7
- package/test/text/mp4_ttml_parser_unit.js +6 -4
- package/test/text/mp4_vtt_parser_unit.js +6 -5
- package/test/text/sbv_text_parser_unit.js +5 -6
- package/test/text/srt_text_parser_unit.js +5 -6
- package/test/text/ssa_text_parser_unit.js +17 -29
- package/test/text/text_engine_unit.js +45 -5
- package/test/text/ttml_text_parser_unit.js +77 -77
- package/test/text/vtt_text_parser_unit.js +116 -59
- package/test/ui/ui_integration.js +0 -16
- package/test/ui/ui_unit.js +27 -0
- package/test/util/cmcd_manager_unit.js +3 -0
- package/test/util/mime_utils_unit.js +54 -0
- package/test/util/periods_unit.js +79 -0
- package/test/util/stream_utils_unit.js +23 -7
- package/ui/controls.js +65 -40
- package/ui/fullscreen_button.js +26 -6
- package/ui/less/containers.less +3 -3
- package/ui/locales/en.json +1 -0
- package/ui/locales/source.json +5 -0
- package/ui/resolution_selection.js +31 -33
- package/ui/ui.js +0 -17
- package/docs/tutorials/gsoc-ideas-list.md +0 -3
- package/docs/tutorials/upgrade-v2-5.md +0 -441
- package/docs/tutorials/upgrade-v3.md +0 -38
- package/lib/polyfill/mathround.js +0 -49
- package/lib/polyfill/patchedmediakeys_apple.js +0 -744
- package/lib/polyfill/patchedmediakeys_ms.js +0 -698
- package/lib/util/mutex.js +0 -52
- package/test/util/functional_unit.js +0 -82
|
@@ -693,22 +693,6 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
693
693
|
expect(iterator.current()).toBe(null);
|
|
694
694
|
});
|
|
695
695
|
|
|
696
|
-
describe('seek', () => {
|
|
697
|
-
it('returns the matching segment', () => {
|
|
698
|
-
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
699
|
-
const iterator = index[Symbol.iterator]();
|
|
700
|
-
expect(iterator.seek(10)).toBe(inputRefs[1]);
|
|
701
|
-
expect(iterator.current()).toBe(inputRefs[1]);
|
|
702
|
-
});
|
|
703
|
-
|
|
704
|
-
it('returns the matching segment with partial segments', () => {
|
|
705
|
-
const index = new shaka.media.SegmentIndex(inputRefsWithPartial);
|
|
706
|
-
const iterator = index[Symbol.iterator]();
|
|
707
|
-
expect(iterator.seek(8)).toBe(inputRefsWithPartial[0]);
|
|
708
|
-
expect(iterator.seek(10)).toBe(partialRefs1[0]);
|
|
709
|
-
});
|
|
710
|
-
});
|
|
711
|
-
|
|
712
696
|
describe('next', () => {
|
|
713
697
|
it('starts with the first segment', () => {
|
|
714
698
|
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
@@ -725,20 +709,20 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
725
709
|
expect(iterator.next().value).toBe(null);
|
|
726
710
|
});
|
|
727
711
|
|
|
728
|
-
it('iterates
|
|
712
|
+
it('iterates from getIteratorForTime', () => {
|
|
729
713
|
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
730
|
-
const iterator = index
|
|
731
|
-
expect(iterator.
|
|
714
|
+
const iterator = index.getIteratorForTime(10);
|
|
715
|
+
expect(iterator.next().value).toBe(inputRefs[1]);
|
|
732
716
|
expect(iterator.current()).toBe(inputRefs[1]);
|
|
733
717
|
expect(iterator.next().value).toBe(inputRefs[2]);
|
|
734
718
|
expect(iterator.current()).toBe(inputRefs[2]);
|
|
735
719
|
expect(iterator.next().value).toBe(null);
|
|
736
720
|
});
|
|
737
721
|
|
|
738
|
-
it('iterates
|
|
722
|
+
it('iterates from getIteratorForTime with partial segments', () => {
|
|
739
723
|
const index = new shaka.media.SegmentIndex(inputRefsWithPartial);
|
|
740
|
-
const iterator = index
|
|
741
|
-
expect(iterator.
|
|
724
|
+
const iterator = index.getIteratorForTime(10);
|
|
725
|
+
expect(iterator.next().value).toBe(partialRefs1[0]);
|
|
742
726
|
expect(iterator.current()).toBe(partialRefs1[0]);
|
|
743
727
|
expect(iterator.next().value).toBe(partialRefs1[1]);
|
|
744
728
|
expect(iterator.current()).toBe(partialRefs1[1]);
|
|
@@ -935,11 +919,17 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
935
919
|
expect(Array.from(metaIndex)).toEqual(oldRefs);
|
|
936
920
|
|
|
937
921
|
// Every 0.1 seconds, return the next new ref.
|
|
938
|
-
|
|
939
|
-
|
|
922
|
+
const done = new Promise((resolve, reject) => {
|
|
923
|
+
index1.updateEvery(0.1, () => {
|
|
924
|
+
if (newRefs.length == 0) {
|
|
925
|
+
resolve();
|
|
926
|
+
}
|
|
927
|
+
return [newRefs.shift()];
|
|
928
|
+
});
|
|
940
929
|
});
|
|
941
930
|
// Wait long enough for all three new refs to be appended.
|
|
942
|
-
|
|
931
|
+
// Or for all of the new refs to be passed out.
|
|
932
|
+
await Promise.race([shaka.test.Util.delay(1), done]);
|
|
943
933
|
|
|
944
934
|
expect(Array.from(metaIndex)).toEqual(oldRefs.concat(inputRefs2));
|
|
945
935
|
});
|
|
@@ -214,8 +214,7 @@ describe('StreamingEngine', () => {
|
|
|
214
214
|
manifest,
|
|
215
215
|
config,
|
|
216
216
|
/* startTime= */ null,
|
|
217
|
-
onSeek
|
|
218
|
-
shaka.test.Util.spyFunc(onEvent));
|
|
217
|
+
onSeek);
|
|
219
218
|
}
|
|
220
219
|
|
|
221
220
|
function setupManifest(
|
|
@@ -403,7 +402,6 @@ describe('StreamingEngine', () => {
|
|
|
403
402
|
// TODO: Consider also adding tests for missing frames.
|
|
404
403
|
describe('gap jumping', () => {
|
|
405
404
|
it('jumps small gaps at the beginning', async () => {
|
|
406
|
-
config.smallGapLimit = 5;
|
|
407
405
|
await setupGappyContent(/* gapAtStart= */ 1, /* dropSegment= */ false);
|
|
408
406
|
|
|
409
407
|
// Let's go!
|
|
@@ -419,8 +417,6 @@ describe('StreamingEngine', () => {
|
|
|
419
417
|
});
|
|
420
418
|
|
|
421
419
|
it('jumps large gaps at the beginning', async () => {
|
|
422
|
-
config.smallGapLimit = 1;
|
|
423
|
-
config.jumpLargeGaps = true;
|
|
424
420
|
await setupGappyContent(/* gapAtStart= */ 5, /* dropSegment= */ false);
|
|
425
421
|
|
|
426
422
|
// Let's go!
|
|
@@ -436,7 +432,6 @@ describe('StreamingEngine', () => {
|
|
|
436
432
|
});
|
|
437
433
|
|
|
438
434
|
it('jumps small gaps in the middle', async () => {
|
|
439
|
-
config.smallGapLimit = 20;
|
|
440
435
|
await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
|
|
441
436
|
|
|
442
437
|
// Let's go!
|
|
@@ -451,11 +446,9 @@ describe('StreamingEngine', () => {
|
|
|
451
446
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
|
|
452
447
|
// Should be close enough to still have the gap buffered.
|
|
453
448
|
expect(video.buffered.length).toBe(2);
|
|
454
|
-
expect(onEvent).not.toHaveBeenCalled();
|
|
455
449
|
});
|
|
456
450
|
|
|
457
451
|
it('jumps large gaps in the middle', async () => {
|
|
458
|
-
config.jumpLargeGaps = true;
|
|
459
452
|
await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
|
|
460
453
|
|
|
461
454
|
// Let's go!
|
|
@@ -470,37 +463,6 @@ describe('StreamingEngine', () => {
|
|
|
470
463
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
|
|
471
464
|
// Should be close enough to still have the gap buffered.
|
|
472
465
|
expect(video.buffered.length).toBe(2);
|
|
473
|
-
expect(onEvent).toHaveBeenCalled();
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
it('won\'t jump large gaps with preventDefault()', async () => {
|
|
477
|
-
config.jumpLargeGaps = true;
|
|
478
|
-
await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
|
|
479
|
-
|
|
480
|
-
onEvent.and.callFake((event) => {
|
|
481
|
-
event.preventDefault();
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
// Let's go!
|
|
485
|
-
streamingEngine.switchVariant(variant);
|
|
486
|
-
await streamingEngine.start();
|
|
487
|
-
|
|
488
|
-
await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
|
|
489
|
-
|
|
490
|
-
let seekCount = 0;
|
|
491
|
-
eventManager.listen(video, 'seeking', () => {
|
|
492
|
-
seekCount++;
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
video.currentTime = 8;
|
|
496
|
-
video.play();
|
|
497
|
-
|
|
498
|
-
await shaka.test.Util.delay(5);
|
|
499
|
-
|
|
500
|
-
// Edge somehow plays _into_ the gap, and Xbox One plays _through_ the
|
|
501
|
-
// gap. Just make sure _we_ don't jump the gap by seeking. One seek is
|
|
502
|
-
// required to start playback at time 8.
|
|
503
|
-
expect(seekCount).toBe(1);
|
|
504
466
|
});
|
|
505
467
|
|
|
506
468
|
/**
|
|
@@ -610,6 +572,7 @@ describe('StreamingEngine', () => {
|
|
|
610
572
|
minBufferTime: 2,
|
|
611
573
|
textStreams: [],
|
|
612
574
|
imageStreams: [],
|
|
575
|
+
sequenceMode: false,
|
|
613
576
|
variants: [{
|
|
614
577
|
id: 1,
|
|
615
578
|
video: {
|
|
@@ -622,6 +585,7 @@ describe('StreamingEngine', () => {
|
|
|
622
585
|
width: 600,
|
|
623
586
|
height: 400,
|
|
624
587
|
type: shaka.util.ManifestParserUtils.ContentType.VIDEO,
|
|
588
|
+
drmInfos: [],
|
|
625
589
|
},
|
|
626
590
|
audio: {
|
|
627
591
|
id: 3,
|
|
@@ -631,6 +595,7 @@ describe('StreamingEngine', () => {
|
|
|
631
595
|
codecs: 'mp4a.40.2',
|
|
632
596
|
bandwidth: 192000,
|
|
633
597
|
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
|
|
598
|
+
drmInfos: [],
|
|
634
599
|
},
|
|
635
600
|
}],
|
|
636
601
|
};
|
|
@@ -496,7 +496,8 @@ describe('StreamingEngine', () => {
|
|
|
496
496
|
expectedMseInit.set(ContentType.VIDEO, videoStream);
|
|
497
497
|
expectedMseInit.set(ContentType.TEXT, textStream);
|
|
498
498
|
|
|
499
|
-
expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit,
|
|
499
|
+
expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit,
|
|
500
|
+
/** forceTransmuxTS= */ false, /** sequenceMode= */ false);
|
|
500
501
|
expect(mediaSourceEngine.init).toHaveBeenCalledTimes(1);
|
|
501
502
|
|
|
502
503
|
expect(mediaSourceEngine.setDuration).toHaveBeenCalledTimes(1);
|
|
@@ -801,7 +802,7 @@ describe('StreamingEngine', () => {
|
|
|
801
802
|
asymmetricMatch: (val) => val > 40 && val <= 40.1,
|
|
802
803
|
};
|
|
803
804
|
expect(mediaSourceEngine.setStreamProperties)
|
|
804
|
-
.toHaveBeenCalledWith('video', 0, lt20, gt40);
|
|
805
|
+
.toHaveBeenCalledWith('video', 0, lt20, gt40, false);
|
|
805
806
|
});
|
|
806
807
|
|
|
807
808
|
// Regression test for https://github.com/shaka-project/shaka-player/issues/3717
|
|
@@ -22,11 +22,6 @@ describe('TimeRangesUtils', () => {
|
|
|
22
22
|
expect(TimeRangesUtils.isBuffered(b, 13)).toBe(true);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
it('returns buffered when having a small gap', () => {
|
|
26
|
-
const b = createFakeBuffered([{start: 10, end: 20}]);
|
|
27
|
-
expect(TimeRangesUtils.isBuffered(b, 9, 1)).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
25
|
// Ranges: [10-20], [30-40], [50-60]
|
|
31
26
|
defineTest('returns false when before range', {time: 3, expected: false});
|
|
32
27
|
defineTest('returns true inside first range', {time: 12, expected: true});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
filterDescribe('IndexeddbStorageCell',
|
|
7
|
+
filterDescribe('IndexeddbStorageCell', offlineSupported, () => {
|
|
8
8
|
const IndexedDBUtils = shaka.test.IndexedDBUtils;
|
|
9
9
|
const OfflineUtils = shaka.test.OfflineUtils;
|
|
10
10
|
const Util = shaka.test.Util;
|
|
@@ -107,6 +107,7 @@ describe('ManifestConverter', () => {
|
|
|
107
107
|
},
|
|
108
108
|
appMetadata: null,
|
|
109
109
|
creationTime: 0,
|
|
110
|
+
sequenceMode: false,
|
|
110
111
|
};
|
|
111
112
|
|
|
112
113
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -143,6 +144,7 @@ describe('ManifestConverter', () => {
|
|
|
143
144
|
createVideoStreamDB(1, [0]),
|
|
144
145
|
createVideoStreamDB(2, [1]),
|
|
145
146
|
],
|
|
147
|
+
sequenceMode: false,
|
|
146
148
|
};
|
|
147
149
|
|
|
148
150
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -170,6 +172,7 @@ describe('ManifestConverter', () => {
|
|
|
170
172
|
createAudioStreamDB(1, [0]),
|
|
171
173
|
createAudioStreamDB(2, [1]),
|
|
172
174
|
],
|
|
175
|
+
sequenceMode: false,
|
|
173
176
|
};
|
|
174
177
|
|
|
175
178
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -182,6 +185,29 @@ describe('ManifestConverter', () => {
|
|
|
182
185
|
expect(manifest.variants[1].video).toBe(null);
|
|
183
186
|
});
|
|
184
187
|
|
|
188
|
+
it('supports containerless content', () => {
|
|
189
|
+
/** @type {shaka.extern.ManifestDB} */
|
|
190
|
+
const manifestDb = {
|
|
191
|
+
originalManifestUri: 'http://example.com/foo',
|
|
192
|
+
duration: 60,
|
|
193
|
+
size: 1234,
|
|
194
|
+
expiration: Infinity,
|
|
195
|
+
sessionIds: [],
|
|
196
|
+
drmInfo: null,
|
|
197
|
+
appMetadata: null,
|
|
198
|
+
creationTime: 0,
|
|
199
|
+
streams: [
|
|
200
|
+
createVideoStreamDB(1, [0]),
|
|
201
|
+
createAudioStreamDB(2, [0]),
|
|
202
|
+
],
|
|
203
|
+
sequenceMode: true,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
207
|
+
expect(manifest.sequenceMode).toBe(true);
|
|
208
|
+
expect(manifest.variants.length).toBe(1);
|
|
209
|
+
});
|
|
210
|
+
|
|
185
211
|
it('supports text streams', () => {
|
|
186
212
|
/** @type {shaka.extern.ManifestDB} */
|
|
187
213
|
const manifestDb = {
|
|
@@ -197,6 +223,7 @@ describe('ManifestConverter', () => {
|
|
|
197
223
|
createVideoStreamDB(1, [0]),
|
|
198
224
|
createTextStreamDB(2),
|
|
199
225
|
],
|
|
226
|
+
sequenceMode: false,
|
|
200
227
|
};
|
|
201
228
|
|
|
202
229
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -235,6 +262,7 @@ describe('ManifestConverter', () => {
|
|
|
235
262
|
createVideoStreamDB(video1, [variant1]),
|
|
236
263
|
createVideoStreamDB(video2, [variant2, variant3]),
|
|
237
264
|
],
|
|
265
|
+
sequenceMode: false,
|
|
238
266
|
};
|
|
239
267
|
|
|
240
268
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -509,8 +537,6 @@ describe('ManifestConverter', () => {
|
|
|
509
537
|
|
|
510
538
|
// Assume that we don't have to call createSegmentIndex.
|
|
511
539
|
|
|
512
|
-
const iterator = stream.segmentIndex[Symbol.iterator]();
|
|
513
|
-
|
|
514
540
|
streamDb.segments.forEach((segmentDb, i) => {
|
|
515
541
|
const uri = shaka.offline.OfflineUri.segment(
|
|
516
542
|
'mechanism', 'cell', segmentDb.dataKey);
|
|
@@ -520,10 +546,14 @@ describe('ManifestConverter', () => {
|
|
|
520
546
|
null;
|
|
521
547
|
|
|
522
548
|
/** @type {shaka.media.SegmentReference} */
|
|
523
|
-
const segment =
|
|
549
|
+
const segment =
|
|
550
|
+
stream.segmentIndex
|
|
551
|
+
.getIteratorForTime(segmentDb.startTime).next().value;
|
|
524
552
|
|
|
525
553
|
/** @type {shaka.media.SegmentReference} */
|
|
526
|
-
const sameSegment =
|
|
554
|
+
const sameSegment =
|
|
555
|
+
stream.segmentIndex
|
|
556
|
+
.getIteratorForTime(segmentDb.endTime - 0.1).next().value;
|
|
527
557
|
|
|
528
558
|
expect(segment).toBe(sameSegment);
|
|
529
559
|
expect(segment.startTime).toBe(segmentDb.startTime);
|
|
@@ -91,7 +91,7 @@ const compatibilityTestsMetadata = [
|
|
|
91
91
|
},
|
|
92
92
|
];
|
|
93
93
|
|
|
94
|
-
filterDescribe('Storage Compatibility',
|
|
94
|
+
filterDescribe('Storage Compatibility', offlineSupported, () => {
|
|
95
95
|
for (const metadata of compatibilityTestsMetadata) {
|
|
96
96
|
describe(metadata.name, () => {
|
|
97
97
|
makeTests(metadata);
|
|
@@ -1110,10 +1110,7 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1110
1110
|
aRequestIsStarted.resolve();
|
|
1111
1111
|
await promise;
|
|
1112
1112
|
|
|
1113
|
-
|
|
1114
|
-
// and will be downloaded sequentially. Thus, we expect only the first
|
|
1115
|
-
// download to be aborted.
|
|
1116
|
-
expect(abortCheck()).toBe(i == 0 ? true : false);
|
|
1113
|
+
expect(abortCheck()).toBe(true);
|
|
1117
1114
|
|
|
1118
1115
|
return new ArrayBuffer(16);
|
|
1119
1116
|
});
|
|
@@ -1355,6 +1352,8 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1355
1352
|
pixelAspectRatio: '59:54',
|
|
1356
1353
|
hdr: null,
|
|
1357
1354
|
mimeType: 'video/mp4,audio/mp4',
|
|
1355
|
+
audioMimeType: 'audio/mp4',
|
|
1356
|
+
videoMimeType: 'video/mp4',
|
|
1358
1357
|
codecs: 'mp4,mp4',
|
|
1359
1358
|
audioCodec: 'mp4',
|
|
1360
1359
|
videoCodec: 'mp4',
|
|
@@ -1397,6 +1396,8 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1397
1396
|
pixelAspectRatio: null,
|
|
1398
1397
|
hdr: null,
|
|
1399
1398
|
mimeType: 'text/vtt',
|
|
1399
|
+
audioMimeType: null,
|
|
1400
|
+
videoMimeType: null,
|
|
1400
1401
|
codecs: 'vtt',
|
|
1401
1402
|
audioCodec: null,
|
|
1402
1403
|
videoCodec: null,
|
package/test/player_external.js
CHANGED
|
@@ -107,12 +107,6 @@ describe('Player', () => {
|
|
|
107
107
|
player.configure('manifest.dash.clockSyncUri',
|
|
108
108
|
'https://shaka-player-demo.appspot.com/time.txt');
|
|
109
109
|
|
|
110
|
-
// Make sure we don't get stuck on gaps that only appear in some
|
|
111
|
-
// browsers (Safari, Firefox).
|
|
112
|
-
// TODO(https://github.com/shaka-project/shaka-player/issues/1702):
|
|
113
|
-
// Is this necessary because of a bug in Shaka Player?
|
|
114
|
-
player.configure('streaming.jumpLargeGaps', true);
|
|
115
|
-
|
|
116
110
|
// Add asset-specific configuration.
|
|
117
111
|
player.configure(asset.getConfiguration());
|
|
118
112
|
|
|
@@ -120,7 +114,13 @@ describe('Player', () => {
|
|
|
120
114
|
const networkingEngine = player.getNetworkingEngine();
|
|
121
115
|
asset.applyFilters(networkingEngine);
|
|
122
116
|
|
|
123
|
-
|
|
117
|
+
// Rather than awaiting the load() method, catch any load() errors and
|
|
118
|
+
// wait on the 'canplay' event. This has the advantage that we will
|
|
119
|
+
// get better logging of the media state on a timeout, since that
|
|
120
|
+
// capabilitiy is built into the waiter for media element events.
|
|
121
|
+
player.load(asset.manifestUri).catch(fail);
|
|
122
|
+
await waiter.timeoutAfter(60).waitForEvent(video, 'canplay');
|
|
123
|
+
|
|
124
124
|
if (asset.features) {
|
|
125
125
|
const isLive = asset.features.includes(Feature.LIVE);
|
|
126
126
|
expect(player.isLive()).toBe(isLive);
|
|
@@ -418,6 +418,22 @@ describe('Player', () => {
|
|
|
418
418
|
expect(video.playbackRate).toBe(1);
|
|
419
419
|
});
|
|
420
420
|
|
|
421
|
+
it('in sequence mode', async () => {
|
|
422
|
+
const testSchemeMimeType = 'application/x-test-manifest';
|
|
423
|
+
player = new compiledShaka.Player(video);
|
|
424
|
+
await player.load('test:sintel_sequence_compiled', 0, testSchemeMimeType);
|
|
425
|
+
expect(player.getManifest().sequenceMode).toBe(true);
|
|
426
|
+
|
|
427
|
+
// Ensure the video plays.
|
|
428
|
+
video.play();
|
|
429
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 5, 10);
|
|
430
|
+
|
|
431
|
+
// Seek the video, and see if it can continue playing from that point.
|
|
432
|
+
video.currentTime = 20;
|
|
433
|
+
// Expect that we can then reach the end of the video.
|
|
434
|
+
await waiter.timeoutAfter(20).waitForEnd(video);
|
|
435
|
+
});
|
|
436
|
+
|
|
421
437
|
// Regression test for #2326.
|
|
422
438
|
//
|
|
423
439
|
// 1. Construct an instance with a video element.
|
|
@@ -1053,16 +1069,16 @@ describe('Player', () => {
|
|
|
1053
1069
|
});
|
|
1054
1070
|
}); // describe('unloading')
|
|
1055
1071
|
|
|
1056
|
-
describe('
|
|
1057
|
-
it('
|
|
1072
|
+
describe('addChaptersTrack', () => {
|
|
1073
|
+
it('adds external chapters in vtt format', async () => {
|
|
1058
1074
|
await player.load('test:sintel_no_text_compiled');
|
|
1059
1075
|
const locationUri = new goog.Uri(location.href);
|
|
1060
1076
|
const partialUri1 = new goog.Uri('/base/test/test/assets/chapters.vtt');
|
|
1061
1077
|
const absoluteUri1 = locationUri.resolve(partialUri1);
|
|
1062
1078
|
await player.addChaptersTrack(absoluteUri1.toString(), 'en');
|
|
1063
1079
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1080
|
+
// Data should be available as soon as addChaptersTrack resolves.
|
|
1081
|
+
// See https://github.com/shaka-project/shaka-player/issues/4186
|
|
1066
1082
|
const chapters = player.getChapters('en');
|
|
1067
1083
|
expect(chapters.length).toBe(3);
|
|
1068
1084
|
const chapter1 = chapters[0];
|
|
@@ -1082,8 +1098,6 @@ describe('Player', () => {
|
|
|
1082
1098
|
const absoluteUri2 = locationUri.resolve(partialUri2);
|
|
1083
1099
|
await player.addChaptersTrack(absoluteUri2.toString(), 'en');
|
|
1084
1100
|
|
|
1085
|
-
await shaka.test.Util.delay(1.5);
|
|
1086
|
-
|
|
1087
1101
|
const chaptersUpdated = player.getChapters('en');
|
|
1088
1102
|
expect(chaptersUpdated.length).toBe(6);
|
|
1089
1103
|
const chapterUpdated1 = chaptersUpdated[0];
|
|
@@ -1112,15 +1126,13 @@ describe('Player', () => {
|
|
|
1112
1126
|
expect(chapterUpdated6.endTime).toBe(61.349);
|
|
1113
1127
|
});
|
|
1114
1128
|
|
|
1115
|
-
it('
|
|
1129
|
+
it('adds external chapters in srt format', async () => {
|
|
1116
1130
|
await player.load('test:sintel_no_text_compiled');
|
|
1117
1131
|
const locationUri = new goog.Uri(location.href);
|
|
1118
1132
|
const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
|
|
1119
1133
|
const absoluteUri = locationUri.resolve(partialUri);
|
|
1120
1134
|
await player.addChaptersTrack(absoluteUri.toString(), 'es');
|
|
1121
1135
|
|
|
1122
|
-
await shaka.test.Util.delay(1.5);
|
|
1123
|
-
|
|
1124
1136
|
const chapters = player.getChapters('es');
|
|
1125
1137
|
expect(chapters.length).toBe(3);
|
|
1126
1138
|
const chapter1 = chapters[0];
|
|
@@ -1136,5 +1148,5 @@ describe('Player', () => {
|
|
|
1136
1148
|
expect(chapter3.startTime).toBe(30);
|
|
1137
1149
|
expect(chapter3.endTime).toBe(61.349);
|
|
1138
1150
|
});
|
|
1139
|
-
}); // describe('
|
|
1151
|
+
}); // describe('addChaptersTrack')
|
|
1140
1152
|
});
|
|
@@ -319,90 +319,88 @@ describe('Player Src Equals', () => {
|
|
|
319
319
|
expect(newTrack).toBeTruthy();
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it('add external chapters in srt format', async () => {
|
|
382
|
-
await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
|
|
383
|
-
|
|
384
|
-
const locationUri = new goog.Uri(location.href);
|
|
385
|
-
const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
|
|
386
|
-
const absoluteUri = locationUri.resolve(partialUri);
|
|
387
|
-
await player.addChaptersTrack(absoluteUri.toString(), 'es');
|
|
388
|
-
|
|
389
|
-
await shaka.test.Util.delay(1.5);
|
|
322
|
+
describe('addChaptersTrack', () => {
|
|
323
|
+
it('adds external chapters in vtt format', async () => {
|
|
324
|
+
await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
|
|
325
|
+
|
|
326
|
+
const locationUri = new goog.Uri(location.href);
|
|
327
|
+
const partialUri1 = new goog.Uri('/base/test/test/assets/chapters.vtt');
|
|
328
|
+
const absoluteUri1 = locationUri.resolve(partialUri1);
|
|
329
|
+
await player.addChaptersTrack(absoluteUri1.toString(), 'en');
|
|
330
|
+
|
|
331
|
+
// Data should be available as soon as addChaptersTrack resolves.
|
|
332
|
+
// See https://github.com/shaka-project/shaka-player/issues/4186
|
|
333
|
+
const chapters = player.getChapters('en');
|
|
334
|
+
expect(chapters.length).toBe(3);
|
|
335
|
+
const chapter1 = chapters[0];
|
|
336
|
+
expect(chapter1.title).toBe('Chapter 1');
|
|
337
|
+
expect(chapter1.startTime).toBe(0);
|
|
338
|
+
expect(chapter1.endTime).toBe(5);
|
|
339
|
+
const chapter2 = chapters[1];
|
|
340
|
+
expect(chapter2.title).toBe('Chapter 2');
|
|
341
|
+
expect(chapter2.startTime).toBe(5);
|
|
342
|
+
expect(chapter2.endTime).toBe(10);
|
|
343
|
+
const chapter3 = chapters[2];
|
|
344
|
+
expect(chapter3.title).toBe('Chapter 3');
|
|
345
|
+
expect(chapter3.startTime).toBe(10);
|
|
346
|
+
expect(chapter3.endTime).toBe(20);
|
|
347
|
+
|
|
348
|
+
const partialUri2 = new goog.Uri('/base/test/test/assets/chapters2.vtt');
|
|
349
|
+
const absoluteUri2 = locationUri.resolve(partialUri2);
|
|
350
|
+
await player.addChaptersTrack(absoluteUri2.toString(), 'en');
|
|
351
|
+
|
|
352
|
+
const chaptersUpdated = player.getChapters('en');
|
|
353
|
+
expect(chaptersUpdated.length).toBe(6);
|
|
354
|
+
const chapterUpdated1 = chaptersUpdated[0];
|
|
355
|
+
expect(chapterUpdated1.title).toBe('Chapter 1');
|
|
356
|
+
expect(chapterUpdated1.startTime).toBe(0);
|
|
357
|
+
expect(chapterUpdated1.endTime).toBe(5);
|
|
358
|
+
const chapterUpdated2 = chaptersUpdated[1];
|
|
359
|
+
expect(chapterUpdated2.title).toBe('Chapter 2');
|
|
360
|
+
expect(chapterUpdated2.startTime).toBe(5);
|
|
361
|
+
expect(chapterUpdated2.endTime).toBe(10);
|
|
362
|
+
const chapterUpdated3 = chaptersUpdated[2];
|
|
363
|
+
expect(chapterUpdated3.title).toBe('Chapter 3');
|
|
364
|
+
expect(chapterUpdated3.startTime).toBe(10);
|
|
365
|
+
expect(chapterUpdated3.endTime).toBe(20);
|
|
366
|
+
const chapterUpdated4 = chaptersUpdated[3];
|
|
367
|
+
expect(chapterUpdated4.title).toBe('Chapter 4');
|
|
368
|
+
expect(chapterUpdated4.startTime).toBe(20);
|
|
369
|
+
expect(chapterUpdated4.endTime).toBe(30);
|
|
370
|
+
const chapterUpdated5 = chaptersUpdated[4];
|
|
371
|
+
expect(chapterUpdated5.title).toBe('Chapter 5');
|
|
372
|
+
expect(chapterUpdated5.startTime).toBe(30);
|
|
373
|
+
expect(chapterUpdated5.endTime).toBe(40);
|
|
374
|
+
const chapterUpdated6 = chaptersUpdated[5];
|
|
375
|
+
expect(chapterUpdated6.title).toBe('Chapter 6');
|
|
376
|
+
expect(chapterUpdated6.startTime).toBe(40);
|
|
377
|
+
expect(chapterUpdated6.endTime).toBe(61.349);
|
|
378
|
+
});
|
|
390
379
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
380
|
+
it('add external chapters in srt format', async () => {
|
|
381
|
+
await loadWithSrcEquals(SMALL_MP4_CONTENT_URI, /* startTime= */ null);
|
|
382
|
+
|
|
383
|
+
const locationUri = new goog.Uri(location.href);
|
|
384
|
+
const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
|
|
385
|
+
const absoluteUri = locationUri.resolve(partialUri);
|
|
386
|
+
await player.addChaptersTrack(absoluteUri.toString(), 'es');
|
|
387
|
+
|
|
388
|
+
const chapters = player.getChapters('es');
|
|
389
|
+
expect(chapters.length).toBe(3);
|
|
390
|
+
const chapter1 = chapters[0];
|
|
391
|
+
expect(chapter1.title).toBe('Chapter 1');
|
|
392
|
+
expect(chapter1.startTime).toBe(0);
|
|
393
|
+
expect(chapter1.endTime).toBe(5);
|
|
394
|
+
const chapter2 = chapters[1];
|
|
395
|
+
expect(chapter2.title).toBe('Chapter 2');
|
|
396
|
+
expect(chapter2.startTime).toBe(5);
|
|
397
|
+
expect(chapter2.endTime).toBe(30);
|
|
398
|
+
const chapter3 = chapters[2];
|
|
399
|
+
expect(chapter3.title).toBe('Chapter 3');
|
|
400
|
+
expect(chapter3.startTime).toBe(30);
|
|
401
|
+
expect(chapter3.endTime).toBe(61.349);
|
|
402
|
+
});
|
|
403
|
+
}); // describe('addChaptersTrack')
|
|
406
404
|
|
|
407
405
|
// Since we are not in-charge of streaming, calling |retryStreaming| should
|
|
408
406
|
// have no effect.
|