shaka-player 4.5.0 → 4.6.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/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/AUTHORS +2 -0
- package/CHANGELOG.md +109 -0
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTORS +2 -0
- package/README.md +38 -32
- package/demo/common/asset.js +11 -17
- package/demo/common/assets.js +117 -11
- package/demo/config.js +28 -1
- package/demo/custom.js +52 -38
- package/demo/main.js +11 -3
- package/demo/search.js +7 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +133 -124
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +133 -124
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +20 -18
- package/dist/locales.js +34 -30
- package/dist/receiver.compiled.debug.js +58 -50
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +58 -50
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +440 -390
- package/dist/shaka-player.compiled.debug.d.ts +440 -390
- package/dist/shaka-player.compiled.debug.externs.js +162 -77
- package/dist/shaka-player.compiled.debug.js +789 -738
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +162 -77
- package/dist/shaka-player.compiled.js +1147 -1113
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +491 -437
- package/dist/shaka-player.ui.debug.d.ts +491 -437
- package/dist/shaka-player.ui.debug.externs.js +167 -77
- package/dist/shaka-player.ui.debug.js +857 -791
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +167 -77
- package/dist/shaka-player.ui.js +1359 -1314
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +54 -0
- package/docs/tutorials/basic-usage.md +2 -1
- package/docs/tutorials/errors.md +2 -1
- package/docs/tutorials/offline.md +10 -8
- package/docs/tutorials/plugins.md +5 -0
- package/docs/tutorials/ui-customization.md +13 -0
- package/docs/tutorials/ui.md +2 -1
- package/docs/tutorials/upgrade.md +3 -0
- package/externs/managedmediasource.js +24 -0
- package/externs/shaka/abr_manager.js +6 -2
- package/externs/shaka/cea.js +7 -0
- package/externs/shaka/codecs.js +5 -3
- package/externs/shaka/manifest.js +21 -5
- package/externs/shaka/manifest_parser.js +17 -0
- package/externs/shaka/net.js +2 -2
- package/externs/shaka/offline.js +9 -2
- package/externs/shaka/player.js +53 -7
- package/externs/shaka/text.js +3 -1
- package/externs/shaka/transmuxer.js +1 -1
- package/lib/abr/simple_abr_manager.js +25 -8
- package/lib/ads/media_tailor_ad_manager.js +14 -3
- package/lib/cast/cast_receiver.js +1 -1
- package/lib/cea/cea_decoder.js +28 -0
- package/lib/cea/dummy_caption_decoder.js +5 -0
- package/lib/dash/dash_parser.js +251 -84
- package/lib/dash/mpd_utils.js +52 -31
- package/lib/dash/segment_base.js +4 -5
- package/lib/dash/segment_list.js +5 -4
- package/lib/dash/segment_template.js +92 -29
- package/lib/hls/hls_classes.js +28 -43
- package/lib/hls/hls_parser.js +770 -652
- package/lib/hls/hls_utils.js +64 -5
- package/lib/hls/manifest_text_parser.js +7 -11
- package/lib/media/adaptation_set.js +20 -13
- package/lib/media/adaptation_set_criteria.js +70 -18
- package/lib/media/closed_caption_parser.js +13 -0
- package/lib/media/content_workarounds.js +6 -0
- package/lib/media/drm_engine.js +8 -13
- package/lib/media/manifest_parser.js +8 -113
- package/lib/media/media_source_capabilities.js +10 -3
- package/lib/media/media_source_engine.js +75 -21
- package/lib/media/play_rate_controller.js +8 -38
- package/lib/media/presentation_timeline.js +7 -1
- package/lib/media/quality_observer.js +1 -1
- package/lib/media/segment_index.js +5 -5
- package/lib/media/segment_prefetch.js +92 -24
- package/lib/media/segment_reference.js +67 -1
- package/lib/media/segment_utils.js +343 -0
- package/lib/media/stall_detector.js +0 -3
- package/lib/media/streaming_engine.js +72 -44
- package/lib/mss/mss_parser.js +18 -2
- package/lib/net/networking_engine.js +66 -12
- package/lib/net/networking_utils.js +95 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
- package/lib/offline/manifest_converter.js +2 -0
- package/lib/offline/offline_manifest_parser.js +10 -0
- package/lib/offline/storage.js +11 -7
- package/lib/player.js +998 -1503
- package/lib/polyfill/mediasource.js +22 -1
- package/lib/text/mp4_ttml_parser.js +2 -2
- package/lib/text/srt_text_parser.js +2 -2
- package/lib/text/stub_text_displayer.js +51 -0
- package/lib/text/text_engine.js +3 -2
- package/lib/text/ttml_text_parser.js +28 -5
- package/lib/text/ui_text_displayer.js +4 -0
- package/lib/text/vtt_text_parser.js +7 -2
- package/lib/transmuxer/aac_transmuxer.js +1 -1
- package/lib/transmuxer/ac3_transmuxer.js +1 -1
- package/lib/transmuxer/ec3_transmuxer.js +1 -1
- package/lib/transmuxer/h264.js +5 -4
- package/lib/transmuxer/h265.js +5 -4
- package/lib/transmuxer/mp3_transmuxer.js +1 -1
- package/lib/transmuxer/mpeg_ts_transmuxer.js +1 -1
- package/lib/transmuxer/mss_transmuxer.js +1 -1
- package/lib/transmuxer/ts_transmuxer.js +33 -13
- package/lib/util/buffer_utils.js +26 -4
- package/lib/util/content_steering_manager.js +358 -0
- package/lib/util/error.js +2 -6
- package/lib/util/fairplay_utils.js +1 -1
- package/lib/util/fake_event.js +5 -1
- package/lib/util/id3_utils.js +50 -1
- package/lib/util/manifest_parser_utils.js +12 -8
- package/lib/util/mp4_generator.js +2 -4
- package/lib/util/mutex.js +59 -0
- package/lib/util/object_utils.js +1 -1
- package/lib/util/periods.js +154 -179
- package/lib/util/platform.js +4 -3
- package/lib/util/player_configuration.js +35 -6
- package/lib/util/stream_utils.js +105 -98
- package/lib/util/ts_parser.js +124 -73
- package/lib/util/uint8array_utils.js +5 -1
- package/lib/util/xml_utils.js +5 -0
- package/maintained-branches.md +2 -2
- package/package.json +1 -1
- package/roadmap.md +15 -5
- package/shaka-player.uncompiled.js +0 -1
- package/test/abr/simple_abr_manager_unit.js +33 -33
- package/test/ads/ad_manager_unit.js +3 -2
- package/test/cast/cast_receiver_integration.js +3 -4
- package/test/cast/cast_utils_unit.js +2 -0
- package/test/cea/cea_decoder_unit.js +7 -0
- package/test/codec_switching/codec_switching_integration.js +2 -1
- package/test/dash/dash_parser_integration.js +2 -1
- package/test/dash/dash_parser_live_unit.js +0 -19
- package/test/dash/dash_parser_manifest_unit.js +494 -2
- package/test/dash/mpd_utils_unit.js +61 -30
- package/test/hls/hls_live_unit.js +12 -3
- package/test/hls/hls_parser_unit.js +417 -27
- package/test/hls/manifest_text_parser_unit.js +32 -99
- package/test/media/adaptation_set_criteria_unit.js +172 -21
- package/test/media/adaptation_set_unit.js +1 -0
- package/test/media/content_workarounds_unit.js +1 -1
- package/test/media/drm_engine_unit.js +3 -3
- package/test/media/media_source_engine_unit.js +1 -1
- package/test/media/play_rate_controller_unit.js +0 -48
- package/test/media/segment_index_unit.js +2 -1
- package/test/mss/mss_player_integration.js +3 -2
- package/test/net/networking_engine_unit.js +3 -3
- package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
- package/test/offline/manifest_convert_unit.js +9 -0
- package/test/offline/offline_integration.js +2 -1
- package/test/offline/storage_integration.js +21 -9
- package/test/player_external.js +4 -2
- package/test/player_integration.js +15 -4
- package/test/player_load_graph_integration.js +47 -151
- package/test/player_src_equals_external.js +1 -0
- package/test/player_src_equals_integration.js +71 -4
- package/test/player_unit.js +80 -27
- package/test/test/util/fake_media_source_engine.js +5 -0
- package/test/test/util/fake_networking_engine.js +9 -1
- package/test/test/util/fake_segment_prefetch.js +3 -0
- package/test/test/util/manifest_generator.js +4 -0
- package/test/test/util/manifest_parser_util.js +14 -2
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/simple_fakes.js +2 -2
- package/test/test/util/streaming_engine_util.js +3 -0
- package/test/test/util/test_scheme.js +6 -0
- package/test/test/util/ui_utils.js +4 -3
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/srt_text_parser_unit.js +1 -1
- package/test/text/text_displayer_layout_unit.js +1 -1
- package/test/text/text_engine_unit.js +6 -0
- package/test/text/ttml_text_parser_unit.js +33 -2
- package/test/transmuxer/transmuxer_engine_integration.js +9 -0
- package/test/transmuxer/transmuxer_integration.js +33 -3
- package/test/ui/ad_ui_unit.js +2 -2
- package/test/ui/ui_customization_unit.js +17 -16
- package/test/ui/ui_integration.js +30 -20
- package/test/ui/ui_unit.js +25 -19
- package/test/util/buffer_utils_unit.js +1 -1
- package/test/util/content_steering_manager_unit.js +427 -0
- package/test/util/id3_utils_unit.js +52 -0
- package/test/util/stream_utils_unit.js +17 -113
- package/test/util/ts_parser_unit.js +3 -3
- package/third_party/closure-uri/uri.js +13 -1
- package/ui/audio_language_selection.js +9 -2
- package/ui/externs/ui.js +17 -2
- package/ui/language_utils.js +43 -8
- package/ui/less/range_elements.less +33 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/es-419.json +1 -0
- package/ui/locales/es.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +10 -0
- package/ui/remote_button.js +3 -1
- package/ui/resolution_selection.js +47 -10
- package/ui/seek_bar.js +296 -3
- package/ui/text_selection.js +2 -1
- package/ui/ui.js +6 -2
- package/lib/routing/node.js +0 -23
- package/lib/routing/payload.js +0 -47
- package/lib/routing/walker.js +0 -587
- package/test/routing/walker_unit.js +0 -505
|
@@ -750,6 +750,46 @@ describe('HlsParser', () => {
|
|
|
750
750
|
await testHlsParser(master, media, manifest);
|
|
751
751
|
});
|
|
752
752
|
|
|
753
|
+
it('parses audio+video variant with global closed captions', async () => {
|
|
754
|
+
const master = [
|
|
755
|
+
'#EXTM3U\n',
|
|
756
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",CHANNELS="2",',
|
|
757
|
+
'URI="audio"\n',
|
|
758
|
+
'#EXT-X-MEDIA:TYPE=CLOSED-CAPTIONS,GROUP-ID="cap1",LANGUAGE="eng",',
|
|
759
|
+
'INSTREAM-ID="CC1"\n',
|
|
760
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
761
|
+
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1"\n',
|
|
762
|
+
'video\n',
|
|
763
|
+
].join('');
|
|
764
|
+
|
|
765
|
+
const media = [
|
|
766
|
+
'#EXTM3U\n',
|
|
767
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
768
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
769
|
+
'#EXTINF:5,\n',
|
|
770
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
771
|
+
'main.mp4',
|
|
772
|
+
].join('');
|
|
773
|
+
|
|
774
|
+
const closedCaptions = new Map([['CC1', 'en']]);
|
|
775
|
+
const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
776
|
+
manifest.anyTimeline();
|
|
777
|
+
manifest.addPartialVariant((variant) => {
|
|
778
|
+
variant.addPartialStream(ContentType.VIDEO, (stream) => {
|
|
779
|
+
stream.closedCaptions = closedCaptions;
|
|
780
|
+
stream.mime('video/mp4', 'avc1');
|
|
781
|
+
});
|
|
782
|
+
variant.addPartialStream(ContentType.AUDIO, (stream) => {
|
|
783
|
+
stream.mime('audio/mp4', 'mp4a');
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
manifest.sequenceMode = sequenceMode;
|
|
787
|
+
manifest.type = shaka.media.ManifestParser.HLS;
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
await testHlsParser(master, media, manifest);
|
|
791
|
+
});
|
|
792
|
+
|
|
753
793
|
it('parses audio+video variant with no closed captions', async () => {
|
|
754
794
|
const master = [
|
|
755
795
|
'#EXTM3U\n',
|
|
@@ -924,7 +964,7 @@ describe('HlsParser', () => {
|
|
|
924
964
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,',
|
|
925
965
|
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1"\n',
|
|
926
966
|
'video\n',
|
|
927
|
-
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",NAME="audio"\n',
|
|
967
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",NAME="audio"\n',
|
|
928
968
|
].join('');
|
|
929
969
|
|
|
930
970
|
const media = [
|
|
@@ -941,6 +981,9 @@ describe('HlsParser', () => {
|
|
|
941
981
|
manifest.addPartialVariant((variant) => {
|
|
942
982
|
variant.addPartialStream(ContentType.VIDEO, (stream) => {
|
|
943
983
|
stream.mime('video/mp4', /** @type {?} */ (jasmine.any(String)));
|
|
984
|
+
stream.language = 'en';
|
|
985
|
+
stream.originalLanguage = 'eng';
|
|
986
|
+
stream.label = 'audio';
|
|
944
987
|
});
|
|
945
988
|
});
|
|
946
989
|
manifest.sequenceMode = sequenceMode;
|
|
@@ -1488,6 +1531,72 @@ describe('HlsParser', () => {
|
|
|
1488
1531
|
expect(actual).toEqual(manifest);
|
|
1489
1532
|
});
|
|
1490
1533
|
|
|
1534
|
+
it('parses manifest with video layout metadata', async () => {
|
|
1535
|
+
const master = [
|
|
1536
|
+
'#EXTM3U\n',
|
|
1537
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
|
|
1538
|
+
'URI="audio"\n',
|
|
1539
|
+
'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
|
|
1540
|
+
'FORCED=YES,URI="text"\n',
|
|
1541
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1542
|
+
'REQ-VIDEO-LAYOUT=CH-STEREO,RESOLUTION=960x540,FRAME-RATE=60,',
|
|
1543
|
+
'AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1544
|
+
'video\n',
|
|
1545
|
+
].join('');
|
|
1546
|
+
|
|
1547
|
+
const media = [
|
|
1548
|
+
'#EXTM3U\n',
|
|
1549
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1550
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1551
|
+
'#EXTINF:5,\n',
|
|
1552
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1553
|
+
'main.mp4',
|
|
1554
|
+
].join('');
|
|
1555
|
+
|
|
1556
|
+
const textMedia = [
|
|
1557
|
+
'#EXTM3U\n',
|
|
1558
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1559
|
+
'#EXTINF:5,\n',
|
|
1560
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1561
|
+
'main.vtt',
|
|
1562
|
+
].join('');
|
|
1563
|
+
|
|
1564
|
+
const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
1565
|
+
manifest.anyTimeline();
|
|
1566
|
+
manifest.addPartialVariant((variant) => {
|
|
1567
|
+
variant.addPartialStream(ContentType.VIDEO, (stream) => {
|
|
1568
|
+
stream.mime('video/mp4', 'avc1');
|
|
1569
|
+
stream.videoLayout = 'CH-STEREO';
|
|
1570
|
+
});
|
|
1571
|
+
variant.addPartialStream(ContentType.AUDIO, (stream) => {
|
|
1572
|
+
stream.mime('audio/mp4', 'mp4a');
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
manifest.addPartialTextStream((stream) => {
|
|
1576
|
+
stream.language = 'en';
|
|
1577
|
+
stream.originalLanguage = 'eng';
|
|
1578
|
+
stream.forced = true;
|
|
1579
|
+
stream.kind = TextStreamKind.SUBTITLE;
|
|
1580
|
+
stream.mime('text/vtt', '');
|
|
1581
|
+
});
|
|
1582
|
+
manifest.sequenceMode = sequenceMode;
|
|
1583
|
+
manifest.type = shaka.media.ManifestParser.HLS;
|
|
1584
|
+
});
|
|
1585
|
+
|
|
1586
|
+
fakeNetEngine
|
|
1587
|
+
.setResponseText('test:/master', master)
|
|
1588
|
+
.setResponseText('test:/audio', media)
|
|
1589
|
+
.setResponseText('test:/video', media)
|
|
1590
|
+
.setResponseText('test:/text', textMedia)
|
|
1591
|
+
.setResponseText('test:/main.vtt', vttText)
|
|
1592
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1593
|
+
.setResponseValue('test:/main.mp4', segmentData);
|
|
1594
|
+
|
|
1595
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
1596
|
+
await loadAllStreamsFor(actual);
|
|
1597
|
+
expect(actual).toEqual(manifest);
|
|
1598
|
+
});
|
|
1599
|
+
|
|
1491
1600
|
it('parses manifest with SUBTITLES', async () => {
|
|
1492
1601
|
const master = [
|
|
1493
1602
|
'#EXTM3U\n',
|
|
@@ -1501,7 +1610,7 @@ describe('HlsParser', () => {
|
|
|
1501
1610
|
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1502
1611
|
'video\n',
|
|
1503
1612
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1504
|
-
'RESOLUTION=960x540,FRAME-RATE=
|
|
1613
|
+
'RESOLUTION=960x540,FRAME-RATE=90,AUDIO="aud1",SUBTITLES="sub2"\n',
|
|
1505
1614
|
'video\n',
|
|
1506
1615
|
].join('');
|
|
1507
1616
|
|
|
@@ -1921,6 +2030,100 @@ describe('HlsParser', () => {
|
|
|
1921
2030
|
}
|
|
1922
2031
|
});
|
|
1923
2032
|
|
|
2033
|
+
it('supports EXT-X-I-FRAME-STREAM-INF with mjpg codec', async () => {
|
|
2034
|
+
const master = [
|
|
2035
|
+
'#EXTM3U\n',
|
|
2036
|
+
'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
|
|
2037
|
+
'URI="text"\n',
|
|
2038
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
|
|
2039
|
+
'CHANNELS="2",URI="audio"\n',
|
|
2040
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
2041
|
+
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
2042
|
+
'video\n',
|
|
2043
|
+
'#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=240×135,CODECS="mjpg",',
|
|
2044
|
+
'URI="iframe"\n',
|
|
2045
|
+
'#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=240×135,CODECS="avc",',
|
|
2046
|
+
'URI="iframeAvc"\n',
|
|
2047
|
+
].join('');
|
|
2048
|
+
|
|
2049
|
+
const video = [
|
|
2050
|
+
'#EXTM3U\n',
|
|
2051
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
2052
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
2053
|
+
'#EXTINF:5,\n',
|
|
2054
|
+
'main.mp4\n',
|
|
2055
|
+
'#EXTINF:5,\n',
|
|
2056
|
+
'main.mp4\n',
|
|
2057
|
+
'#EXTINF:5,\n',
|
|
2058
|
+
'main.mp4\n',
|
|
2059
|
+
].join('');
|
|
2060
|
+
|
|
2061
|
+
const audio = [
|
|
2062
|
+
'#EXTM3U\n',
|
|
2063
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
2064
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
2065
|
+
'#EXTINF:5,\n',
|
|
2066
|
+
'main.mp4\n',
|
|
2067
|
+
'#EXTINF:5,\n',
|
|
2068
|
+
'main.mp4\n',
|
|
2069
|
+
'#EXTINF:5,\n',
|
|
2070
|
+
'main.mp4\n',
|
|
2071
|
+
].join('');
|
|
2072
|
+
|
|
2073
|
+
const text = [
|
|
2074
|
+
'#EXTM3U\n',
|
|
2075
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
2076
|
+
'#EXTINF:5,\n',
|
|
2077
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
2078
|
+
'main.vtt',
|
|
2079
|
+
].join('');
|
|
2080
|
+
|
|
2081
|
+
const iframe = [
|
|
2082
|
+
'#EXTM3U\n',
|
|
2083
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
2084
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
2085
|
+
'#EXTINF:5,\n',
|
|
2086
|
+
'main.mp4\n',
|
|
2087
|
+
'#EXTINF:5,\n',
|
|
2088
|
+
'main.mp4\n',
|
|
2089
|
+
'#EXTINF:5,\n',
|
|
2090
|
+
'main.mp4\n',
|
|
2091
|
+
].join('');
|
|
2092
|
+
|
|
2093
|
+
fakeNetEngine
|
|
2094
|
+
.setResponseText('test:/master', master)
|
|
2095
|
+
.setResponseText('test:/audio', audio)
|
|
2096
|
+
.setResponseText('test:/video', video)
|
|
2097
|
+
.setResponseText('test:/text', text)
|
|
2098
|
+
.setResponseText('test:/iframe', iframe)
|
|
2099
|
+
.setResponseText('test:/main.vtt', vttText)
|
|
2100
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
2101
|
+
.setResponseValue('test:/main.mp4', segmentData);
|
|
2102
|
+
|
|
2103
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
2104
|
+
await loadAllStreamsFor(actual);
|
|
2105
|
+
|
|
2106
|
+
expect(actual.imageStreams.length).toBe(1);
|
|
2107
|
+
expect(actual.textStreams.length).toBe(1);
|
|
2108
|
+
expect(actual.variants.length).toBe(1);
|
|
2109
|
+
|
|
2110
|
+
const thumbnails = actual.imageStreams[0];
|
|
2111
|
+
|
|
2112
|
+
expect(thumbnails.mimeType).toBe('application/mp4');
|
|
2113
|
+
expect(thumbnails.codecs).toBe('mjpg');
|
|
2114
|
+
|
|
2115
|
+
await thumbnails.createSegmentIndex();
|
|
2116
|
+
goog.asserts.assert(thumbnails.segmentIndex != null, 'Null segmentIndex!');
|
|
2117
|
+
|
|
2118
|
+
const firstThumbnailReference = thumbnails.segmentIndex.get(0);
|
|
2119
|
+
const secondThumbnailReference = thumbnails.segmentIndex.get(1);
|
|
2120
|
+
const thirdThumbnailReference = thumbnails.segmentIndex.get(2);
|
|
2121
|
+
|
|
2122
|
+
expect(firstThumbnailReference).not.toBe(null);
|
|
2123
|
+
expect(secondThumbnailReference).not.toBe(null);
|
|
2124
|
+
expect(thirdThumbnailReference).not.toBe(null);
|
|
2125
|
+
});
|
|
2126
|
+
|
|
1924
2127
|
it('parse EXT-X-GAP', async () => {
|
|
1925
2128
|
const master = [
|
|
1926
2129
|
'#EXTM3U\n',
|
|
@@ -2587,6 +2790,106 @@ describe('HlsParser', () => {
|
|
|
2587
2790
|
expect(actual).toEqual(manifest);
|
|
2588
2791
|
});
|
|
2589
2792
|
|
|
2793
|
+
describe('When config.hls.disableCodecGuessing is set to true', () => {
|
|
2794
|
+
beforeEach(() => {
|
|
2795
|
+
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
2796
|
+
config.hls.disableCodecGuessing = true;
|
|
2797
|
+
parser.configure(config);
|
|
2798
|
+
});
|
|
2799
|
+
|
|
2800
|
+
it('gets codec info from media if omitted in playlist', async () => {
|
|
2801
|
+
const master = [
|
|
2802
|
+
'#EXTM3U\n',
|
|
2803
|
+
'#EXT-X-VERSION:3\n',
|
|
2804
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=2000000\n',
|
|
2805
|
+
'video\n',
|
|
2806
|
+
].join('');
|
|
2807
|
+
|
|
2808
|
+
const media = [
|
|
2809
|
+
'#EXTM3U\n',
|
|
2810
|
+
'#EXT-X-VERSION:3\n',
|
|
2811
|
+
'#EXT-X-TARGETDURATION:5\n',
|
|
2812
|
+
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
2813
|
+
'#EXTINF:5,\n',
|
|
2814
|
+
'video-0.ts\n',
|
|
2815
|
+
].join('');
|
|
2816
|
+
|
|
2817
|
+
fakeNetEngine
|
|
2818
|
+
.setResponseText('test:/master', master)
|
|
2819
|
+
.setResponseText('test:/video', media)
|
|
2820
|
+
.setResponseValue('test:/video-0.ts', tsSegmentData);
|
|
2821
|
+
|
|
2822
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
2823
|
+
const variant = actual.variants[0];
|
|
2824
|
+
|
|
2825
|
+
expect(variant.audio).toBe(null);
|
|
2826
|
+
expect(variant.video).toBeDefined();
|
|
2827
|
+
expect(variant.video.codecs).toBe('avc1.42C01E');
|
|
2828
|
+
});
|
|
2829
|
+
|
|
2830
|
+
it('gets codecs from playlist if CODECS attribute present', async () => {
|
|
2831
|
+
const master = [
|
|
2832
|
+
'#EXTM3U\n',
|
|
2833
|
+
'#EXT-X-VERSION:3\n',
|
|
2834
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=2000000,CODECS="foo"\n',
|
|
2835
|
+
'video\n',
|
|
2836
|
+
].join('');
|
|
2837
|
+
|
|
2838
|
+
const media = [
|
|
2839
|
+
'#EXTM3U\n',
|
|
2840
|
+
'#EXT-X-VERSION:3\n',
|
|
2841
|
+
'#EXT-X-TARGETDURATION:5\n',
|
|
2842
|
+
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
2843
|
+
'#EXTINF:5,\n',
|
|
2844
|
+
'video-0.ts\n',
|
|
2845
|
+
].join('');
|
|
2846
|
+
|
|
2847
|
+
fakeNetEngine
|
|
2848
|
+
.setResponseText('test:/master', master)
|
|
2849
|
+
.setResponseText('test:/video', media)
|
|
2850
|
+
.setResponseValue('test:/video-0.ts', tsSegmentData);
|
|
2851
|
+
|
|
2852
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
2853
|
+
const variant = actual.variants[0];
|
|
2854
|
+
|
|
2855
|
+
expect(variant.audio).toBe(null);
|
|
2856
|
+
expect(variant.video).toBeDefined();
|
|
2857
|
+
expect(variant.video.codecs).toBe('foo');
|
|
2858
|
+
});
|
|
2859
|
+
|
|
2860
|
+
it('falls back to default codecs if it could not find codec', async () => {
|
|
2861
|
+
const master = [
|
|
2862
|
+
'#EXTM3U\n',
|
|
2863
|
+
'#EXT-X-VERSION:3\n',
|
|
2864
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=2000000\n',
|
|
2865
|
+
'video\n',
|
|
2866
|
+
].join('');
|
|
2867
|
+
|
|
2868
|
+
const media = [
|
|
2869
|
+
'#EXTM3U\n',
|
|
2870
|
+
'#EXT-X-VERSION:3\n',
|
|
2871
|
+
'#EXT-X-TARGETDURATION:5\n',
|
|
2872
|
+
'#EXT-X-MEDIA-SEQUENCE:0\n',
|
|
2873
|
+
'#EXTINF:5,\n',
|
|
2874
|
+
'video-0.ts\n',
|
|
2875
|
+
].join('');
|
|
2876
|
+
|
|
2877
|
+
fakeNetEngine
|
|
2878
|
+
.setResponseText('test:/master', master)
|
|
2879
|
+
.setResponseText('test:/video', media)
|
|
2880
|
+
.setResponseValue('test:/video-0.ts', new Uint8Array([]));
|
|
2881
|
+
|
|
2882
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
2883
|
+
const variant = actual.variants[0];
|
|
2884
|
+
|
|
2885
|
+
expect(variant.video).toBeDefined();
|
|
2886
|
+
|
|
2887
|
+
const codecs = variant.video.codecs.split(',').map((c) => c.trim());
|
|
2888
|
+
|
|
2889
|
+
expect(codecs).toEqual(['avc1.42E01E', 'mp4a.40.2']);
|
|
2890
|
+
});
|
|
2891
|
+
});
|
|
2892
|
+
|
|
2590
2893
|
describe('produces syncTime', () => {
|
|
2591
2894
|
// Corresponds to "2000-01-01T00:00:00.00Z".
|
|
2592
2895
|
// All the PROGRAM-DATE-TIME values in the tests below are at or after this.
|
|
@@ -2753,10 +3056,14 @@ describe('HlsParser', () => {
|
|
|
2753
3056
|
'main.mp4',
|
|
2754
3057
|
].join(''), [0, 5, 10, 15, 20, 25], syncTimeBase + 5, (reference) => {
|
|
2755
3058
|
if (reference.startTime == 10) {
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
3059
|
+
const partialRef = makeReference(10, 12.5, syncTimeBase + 15);
|
|
3060
|
+
partialRef.partial = true;
|
|
3061
|
+
const partialRef2 = makeReference(12.5, 15, syncTimeBase + 17.5);
|
|
3062
|
+
partialRef2.partial = true;
|
|
3063
|
+
partialRef2.lastPartial = true;
|
|
3064
|
+
|
|
3065
|
+
reference.partialReferences = [partialRef, partialRef2];
|
|
3066
|
+
reference.allPartialSegments = true;
|
|
2760
3067
|
}
|
|
2761
3068
|
});
|
|
2762
3069
|
});
|
|
@@ -2976,7 +3283,8 @@ describe('HlsParser', () => {
|
|
|
2976
3283
|
const media = [
|
|
2977
3284
|
'#EXTM3U\n',
|
|
2978
3285
|
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
2979
|
-
'#EXT-X-
|
|
3286
|
+
'#EXT-X-BYTERANGE:616@0\n',
|
|
3287
|
+
'#EXT-X-MAP:URI="init.mp4"\n',
|
|
2980
3288
|
'#EXTINF:5,\n',
|
|
2981
3289
|
'main.mp4\n',
|
|
2982
3290
|
'#EXT-X-MAP:URI="init2.mp4",BYTERANGE="616@0"\n',
|
|
@@ -3004,8 +3312,15 @@ describe('HlsParser', () => {
|
|
|
3004
3312
|
// uri.
|
|
3005
3313
|
const initSegments = Array.from(actualVideo.segmentIndex).map(
|
|
3006
3314
|
(seg) => seg.initSegmentReference);
|
|
3007
|
-
expect(initSegments
|
|
3008
|
-
|
|
3315
|
+
expect(initSegments.length).toBe(2);
|
|
3316
|
+
const firstInitSegment = initSegments[0];
|
|
3317
|
+
expect(firstInitSegment.getUris()[0]).toBe('test:/init.mp4');
|
|
3318
|
+
expect(firstInitSegment.startByte).toBe(0);
|
|
3319
|
+
expect(firstInitSegment.endByte).toBe(615);
|
|
3320
|
+
const secondInitSegment = initSegments[1];
|
|
3321
|
+
expect(secondInitSegment.getUris()[0]).toBe('test:/init2.mp4');
|
|
3322
|
+
expect(secondInitSegment.startByte).toBe(0);
|
|
3323
|
+
expect(secondInitSegment.endByte).toBe(615);
|
|
3009
3324
|
});
|
|
3010
3325
|
|
|
3011
3326
|
it('parses variants encrypted with AES-128', async () => {
|
|
@@ -3015,7 +3330,7 @@ describe('HlsParser', () => {
|
|
|
3015
3330
|
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1"\n',
|
|
3016
3331
|
'video\n',
|
|
3017
3332
|
'#EXT-X-STREAM-INF:BANDWIDTH=300,CODECS="avc1,mp4a",',
|
|
3018
|
-
'RESOLUTION=960x540,FRAME-RATE=
|
|
3333
|
+
'RESOLUTION=960x540,FRAME-RATE=90,AUDIO="aud2"\n',
|
|
3019
3334
|
'video2\n',
|
|
3020
3335
|
'#EXT-X-STREAM-INF:BANDWIDTH=300,CODECS="avc1,mp4a",',
|
|
3021
3336
|
'RESOLUTION=960x540,FRAME-RATE=120,AUDIO="aud3"\n',
|
|
@@ -4183,11 +4498,14 @@ describe('HlsParser', () => {
|
|
|
4183
4498
|
it('parse variables master playlist', async () => {
|
|
4184
4499
|
const master = [
|
|
4185
4500
|
'#EXTM3U\n',
|
|
4186
|
-
'#EXT-X-DEFINE:NAME="auth",VALUE="
|
|
4501
|
+
'#EXT-X-DEFINE:NAME="auth",VALUE="token=1"\n',
|
|
4502
|
+
'#EXT-X-DEFINE:QUERYPARAM="a"\n',
|
|
4503
|
+
'#EXT-X-DEFINE:QUERYPARAM="b"\n',
|
|
4187
4504
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
4188
4505
|
'RESOLUTION=960x540,FRAME-RATE=60,VIDEO="vid"\n',
|
|
4189
|
-
'audio.m3u8{$auth}\n',
|
|
4190
|
-
'#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",
|
|
4506
|
+
'audio.m3u8?{$auth}&a={$a}&b={$b}\n',
|
|
4507
|
+
'#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",',
|
|
4508
|
+
'URI="video.m3u8?{$auth}&a={$a}&b={$b}"',
|
|
4191
4509
|
].join('');
|
|
4192
4510
|
|
|
4193
4511
|
const media = [
|
|
@@ -4199,14 +4517,14 @@ describe('HlsParser', () => {
|
|
|
4199
4517
|
].join('');
|
|
4200
4518
|
|
|
4201
4519
|
fakeNetEngine
|
|
4202
|
-
.setResponseText('test:/host/master.m3u8', master)
|
|
4203
|
-
.setResponseText('test:/host/audio.m3u8?token=1', media)
|
|
4204
|
-
.setResponseText('test:/host/video.m3u8?token=1', media)
|
|
4520
|
+
.setResponseText('test:/host/master.m3u8?a=1&b=2', master)
|
|
4521
|
+
.setResponseText('test:/host/audio.m3u8?token=1&a=1&b=2', media)
|
|
4522
|
+
.setResponseText('test:/host/video.m3u8?token=1&a=1&b=2', media)
|
|
4205
4523
|
.setResponseValue('test:/host/init.mp4', initSegmentData)
|
|
4206
4524
|
.setResponseValue('test:/host/segment.mp4', segmentData);
|
|
4207
4525
|
|
|
4208
|
-
const actual =
|
|
4209
|
-
|
|
4526
|
+
const actual = await parser.start(
|
|
4527
|
+
'test:/host/master.m3u8?a=1&b=2', playerInterface);
|
|
4210
4528
|
await loadAllStreamsFor(actual);
|
|
4211
4529
|
const video = actual.variants[0].video;
|
|
4212
4530
|
const audio = actual.variants[0].audio;
|
|
@@ -4232,26 +4550,28 @@ describe('HlsParser', () => {
|
|
|
4232
4550
|
'#EXTM3U\n',
|
|
4233
4551
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
4234
4552
|
'RESOLUTION=960x540,FRAME-RATE=60,VIDEO="vid"\n',
|
|
4235
|
-
'audio.m3u8\n',
|
|
4236
|
-
'#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",URI="video.m3u8"',
|
|
4553
|
+
'audio.m3u8?fooParam=1\n',
|
|
4554
|
+
'#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="vid",URI="video.m3u8?fooParam=1"',
|
|
4237
4555
|
].join('');
|
|
4238
4556
|
|
|
4239
4557
|
const media = [
|
|
4240
4558
|
'#EXTM3U\n',
|
|
4241
|
-
'#EXT-X-DEFINE:NAME="auth",VALUE="
|
|
4559
|
+
'#EXT-X-DEFINE:NAME="auth",VALUE="token=1"\n',
|
|
4242
4560
|
'#EXT-X-DEFINE:NAME="path",VALUE="test/"\n',
|
|
4561
|
+
'#EXT-X-DEFINE:QUERYPARAM="fooParam"\n',
|
|
4243
4562
|
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
4244
4563
|
'#EXT-X-MAP:URI="{$path}init.mp4"\n',
|
|
4245
4564
|
'#EXTINF:5,\n',
|
|
4246
|
-
'{$path}segment.mp4{$auth}',
|
|
4565
|
+
'{$path}segment.mp4?{$auth}&fooParam={$fooParam}',
|
|
4247
4566
|
].join('');
|
|
4248
4567
|
|
|
4249
4568
|
fakeNetEngine
|
|
4250
4569
|
.setResponseText('test:/host/master.m3u8', master)
|
|
4251
|
-
.setResponseText('test:/host/audio.m3u8', media)
|
|
4252
|
-
.setResponseText('test:/host/video.m3u8', media)
|
|
4570
|
+
.setResponseText('test:/host/audio.m3u8?fooParam=1', media)
|
|
4571
|
+
.setResponseText('test:/host/video.m3u8?fooParam=1', media)
|
|
4253
4572
|
.setResponseValue('test:/host/test/init.mp4', initSegmentData)
|
|
4254
|
-
.setResponseValue('test:/host/test/segment.mp4?token=1',
|
|
4573
|
+
.setResponseValue('test:/host/test/segment.mp4?token=1&fooParam=1',
|
|
4574
|
+
segmentData);
|
|
4255
4575
|
|
|
4256
4576
|
const actual =
|
|
4257
4577
|
await parser.start('test:/host/master.m3u8', playerInterface);
|
|
@@ -4268,11 +4588,11 @@ describe('HlsParser', () => {
|
|
|
4268
4588
|
// flow has gone well.
|
|
4269
4589
|
const videoReference = Array.from(video.segmentIndex)[0];
|
|
4270
4590
|
expect(videoReference.getUris())
|
|
4271
|
-
.toEqual(['test:/host/test/segment.mp4?token=1']);
|
|
4591
|
+
.toEqual(['test:/host/test/segment.mp4?token=1&fooParam=1']);
|
|
4272
4592
|
|
|
4273
4593
|
const audioReference = Array.from(audio.segmentIndex)[0];
|
|
4274
4594
|
expect(audioReference.getUris())
|
|
4275
|
-
.toEqual(['test:/host/test/segment.mp4?token=1']);
|
|
4595
|
+
.toEqual(['test:/host/test/segment.mp4?token=1&fooParam=1']);
|
|
4276
4596
|
});
|
|
4277
4597
|
|
|
4278
4598
|
it('import variables in media from master playlist', async () => {
|
|
@@ -4883,4 +5203,74 @@ describe('HlsParser', () => {
|
|
|
4883
5203
|
expect(video.width).toBe(256);
|
|
4884
5204
|
expect(video.height).toBe(110);
|
|
4885
5205
|
});
|
|
5206
|
+
|
|
5207
|
+
it('supports ContentSteering', async () => {
|
|
5208
|
+
const master = [
|
|
5209
|
+
'#EXTM3U\n',
|
|
5210
|
+
'#EXT-X-CONTENT-STEERING:SERVER-URI="http://contentsteering",',
|
|
5211
|
+
'PATHWAY-ID="a"\n',
|
|
5212
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a",LANGUAGE="eng",',
|
|
5213
|
+
'URI="audio/a/media.m3u8"\n',
|
|
5214
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="b",LANGUAGE="eng",',
|
|
5215
|
+
'URI="audio/b/media.m3u8"\n',
|
|
5216
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc,mp4a",',
|
|
5217
|
+
'AUDIO="a",PATHWAY-ID="a"\n',
|
|
5218
|
+
'a/media.m3u8\n',
|
|
5219
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc,mp4a",',
|
|
5220
|
+
'AUDIO="b",PATHWAY-ID="b"\n',
|
|
5221
|
+
'b/media.m3u8',
|
|
5222
|
+
].join('');
|
|
5223
|
+
|
|
5224
|
+
const media = [
|
|
5225
|
+
'#EXTM3U\n',
|
|
5226
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
5227
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
5228
|
+
'#EXTINF:5,\n',
|
|
5229
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
5230
|
+
'main.mp4',
|
|
5231
|
+
].join('');
|
|
5232
|
+
|
|
5233
|
+
const contentSteering = JSON.stringify({
|
|
5234
|
+
'VERSION': 1,
|
|
5235
|
+
'TTL': 1,
|
|
5236
|
+
'RELOAD-URI': 'http://contentsteering/update',
|
|
5237
|
+
'PATHWAY-PRIORITY': [
|
|
5238
|
+
'b',
|
|
5239
|
+
'a',
|
|
5240
|
+
],
|
|
5241
|
+
});
|
|
5242
|
+
|
|
5243
|
+
fakeNetEngine
|
|
5244
|
+
.setResponseText('http://master', master)
|
|
5245
|
+
.setResponseText('http://contentsteering', contentSteering)
|
|
5246
|
+
.setResponseText('http://master/a/media.m3u8', media)
|
|
5247
|
+
.setResponseText('http://master/b/media.m3u8', media)
|
|
5248
|
+
.setResponseText('http://master/audio/a/media.m3u8', media)
|
|
5249
|
+
.setResponseText('http://master/audio/b/media.m3u8', media)
|
|
5250
|
+
.setMaxUris(2);
|
|
5251
|
+
|
|
5252
|
+
/** @type {shaka.extern.Manifest} */
|
|
5253
|
+
const manifest = await parser.start('http://master', playerInterface);
|
|
5254
|
+
expect(manifest.variants.length).toBe(1);
|
|
5255
|
+
|
|
5256
|
+
const audio0 = manifest.variants[0].audio;
|
|
5257
|
+
await audio0.createSegmentIndex();
|
|
5258
|
+
goog.asserts.assert(audio0.segmentIndex, 'Null segmentIndex!');
|
|
5259
|
+
const audioSegment0 = Array.from(audio0.segmentIndex)[0];
|
|
5260
|
+
const audioUri0 = audioSegment0.getUris()[0];
|
|
5261
|
+
const audioUri1 = audioSegment0.getUris()[1];
|
|
5262
|
+
|
|
5263
|
+
expect(audioUri0).toBe('http://master/audio/b/main.mp4');
|
|
5264
|
+
expect(audioUri1).toBe('http://master/audio/a/main.mp4');
|
|
5265
|
+
|
|
5266
|
+
const video0 = manifest.variants[0].video;
|
|
5267
|
+
await video0.createSegmentIndex();
|
|
5268
|
+
goog.asserts.assert(video0.segmentIndex, 'Null segmentIndex!');
|
|
5269
|
+
const videoSegment0 = Array.from(video0.segmentIndex)[0];
|
|
5270
|
+
const videoUri0 = videoSegment0.getUris()[0];
|
|
5271
|
+
const videoUri1 = videoSegment0.getUris()[1];
|
|
5272
|
+
|
|
5273
|
+
expect(videoUri0).toBe('http://master/b/main.mp4');
|
|
5274
|
+
expect(videoUri1).toBe('http://master/a/main.mp4');
|
|
5275
|
+
});
|
|
4886
5276
|
});
|