shaka-player 4.3.13 → 4.3.14
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/.github/ISSUE_TEMPLATE/question.md +7 -0
- package/.github/workflows/release-please.yaml +2 -27
- package/AUTHORS +5 -0
- package/CHANGELOG.md +87 -0
- package/CODE_OF_CONDUCT.md +1 -1
- package/CONTRIBUTORS +6 -0
- package/README.md +2 -0
- package/demo/common/asset.js +0 -1
- package/demo/common/assets.js +0 -1
- package/demo/custom.js +2 -0
- package/dist/demo.compiled.debug.js +1 -1
- package/dist/demo.compiled.debug.map +1 -1
- package/dist/demo.compiled.js +1 -1
- package/dist/demo.compiled.map +1 -1
- package/dist/deps.js +6 -6
- package/dist/locales.js +29 -29
- package/dist/receiver.compiled.debug.map +1 -1
- package/dist/receiver.compiled.map +1 -1
- package/dist/shaka-player.compiled.d.ts +25 -5
- package/dist/shaka-player.compiled.debug.d.ts +25 -5
- package/dist/shaka-player.compiled.debug.externs.js +73 -45
- package/dist/shaka-player.compiled.debug.js +414 -396
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +73 -45
- package/dist/shaka-player.compiled.js +912 -903
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +37 -6
- package/dist/shaka-player.ui.debug.d.ts +37 -6
- package/dist/shaka-player.ui.debug.externs.js +74 -45
- package/dist/shaka-player.ui.debug.js +438 -418
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +74 -45
- package/dist/shaka-player.ui.js +1060 -1051
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/ad_monetization.md +54 -0
- package/docs/tutorials/fairplay.md +2 -2
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/plugins.md +4 -0
- package/docs/tutorials/text-displayer.md +15 -0
- package/docs/tutorials/ui-customization.md +29 -0
- package/docs/tutorials/ui.md +4 -1
- package/externs/lcevc.js +6 -0
- package/externs/shaka/manifest_parser.js +8 -0
- package/externs/shaka/player.js +1 -1
- package/externs/shaka/text.js +3 -1
- package/lib/abr/simple_abr_manager.js +1 -1
- package/lib/ads/client_side_ad.js +9 -0
- package/lib/ads/client_side_ad_manager.js +7 -2
- package/lib/ads/server_side_ad_manager.js +4 -0
- package/lib/cast/cast_proxy.js +18 -0
- package/lib/cea/cea608_memory.js +1 -1
- package/lib/cea/cea_decoder.js +11 -1
- package/lib/dash/dash_parser.js +75 -41
- package/lib/dash/mpd_utils.js +39 -27
- package/lib/hls/hls_parser.js +90 -27
- package/lib/hls/hls_utils.js +5 -5
- package/lib/media/content_workarounds.js +30 -0
- package/lib/media/drm_engine.js +16 -12
- package/lib/media/media_source_engine.js +4 -2
- package/lib/media/play_rate_controller.js +1 -0
- package/lib/media/presentation_timeline.js +11 -0
- package/lib/media/quality_observer.js +1 -1
- package/lib/media/segment_reference.js +5 -2
- package/lib/media/streaming_engine.js +50 -30
- package/lib/media/transmuxer.js +1 -1
- package/lib/media/video_wrapper.js +4 -3
- package/lib/offline/offline_manifest_parser.js +5 -0
- package/lib/offline/session_deleter.js +0 -8
- package/lib/offline/storage.js +4 -1
- package/lib/player.js +79 -18
- package/lib/polyfill/media_capabilities.js +23 -3
- package/lib/text/mp4_ttml_parser.js +2 -2
- package/lib/text/simple_text_displayer.js +7 -6
- package/lib/text/srt_text_parser.js +2 -2
- package/lib/text/text_engine.js +3 -2
- package/lib/text/ttml_text_parser.js +33 -5
- package/lib/text/ui_text_displayer.js +81 -15
- package/lib/text/vtt_text_parser.js +15 -2
- package/lib/util/buffer_utils.js +26 -4
- package/lib/util/cmcd_manager.js +10 -0
- package/lib/util/fairplay_utils.js +1 -1
- package/lib/util/manifest_parser_utils.js +14 -8
- package/lib/util/object_utils.js +1 -1
- package/lib/util/periods.js +91 -36
- package/lib/util/platform.js +39 -2
- package/lib/util/player_configuration.js +5 -3
- package/lib/util/stream_utils.js +36 -28
- package/lib/util/xml_utils.js +5 -0
- package/package.json +2 -2
- package/test/cea/cea_decoder_unit.js +40 -0
- package/test/dash/dash_parser_live_unit.js +5 -8
- package/test/hls/hls_parser_unit.js +50 -3
- package/test/media/buffering_observer_unit.js +13 -0
- package/test/media/content_workarounds_unit.js +1 -1
- package/test/media/drm_engine_unit.js +30 -3
- package/test/media/media_source_engine_unit.js +1 -1
- package/test/media/transmuxer_integration.js +2 -2
- package/test/offline/storage_integration.js +3 -0
- package/test/player_integration.js +40 -40
- package/test/player_unit.js +31 -0
- package/test/polyfill/media_capabilities_unit.js +12 -6
- package/test/test/util/fake_drm_engine.js +7 -0
- package/test/test/util/layout_tests.js +2 -1
- package/test/test/util/simple_fakes.js +2 -2
- package/test/test/util/test_scheme.js +3 -0
- package/test/test/util/waiter.js +5 -0
- package/test/text/mp4_ttml_parser_unit.js +4 -4
- package/test/text/simple_text_displayer_unit.js +1 -1
- package/test/text/srt_text_parser_unit.js +1 -1
- package/test/text/text_engine_unit.js +6 -0
- package/test/text/ttml_text_parser_unit.js +49 -18
- package/test/text/ui_text_displayer_unit.js +9 -0
- package/test/util/buffer_utils_unit.js +1 -1
- package/test/util/periods_unit.js +113 -0
- package/third_party/closure-uri/uri.js +1 -1
- package/ui/externs/ui.js +24 -0
- package/ui/language_utils.js +11 -5
- package/ui/play_button.js +20 -0
- package/ui/playback_rate_selection.js +4 -0
- package/ui/presentation_time.js +5 -5
- package/ui/small_play_button.js +2 -2
- package/ui/volume_bar.js +10 -6
- /package/.github/{config.yml → ISSUE_TEMPLATE/config.yml} +0 -0
|
@@ -638,8 +638,8 @@ describe('TtmlTextParser', () => {
|
|
|
638
638
|
id: 'subtitleArea',
|
|
639
639
|
viewportAnchorX: 50,
|
|
640
640
|
viewportAnchorY: 16,
|
|
641
|
-
width:
|
|
642
|
-
height:
|
|
641
|
+
width: 50,
|
|
642
|
+
height: 84,
|
|
643
643
|
},
|
|
644
644
|
startTime: 62.05,
|
|
645
645
|
endTime: 3723.2,
|
|
@@ -666,8 +666,8 @@ describe('TtmlTextParser', () => {
|
|
|
666
666
|
region: {
|
|
667
667
|
viewportAnchorX: 50,
|
|
668
668
|
viewportAnchorY: 16,
|
|
669
|
-
width:
|
|
670
|
-
height:
|
|
669
|
+
width: 50,
|
|
670
|
+
height: 84,
|
|
671
671
|
},
|
|
672
672
|
startTime: 62.05,
|
|
673
673
|
endTime: 3723.2,
|
|
@@ -694,8 +694,8 @@ describe('TtmlTextParser', () => {
|
|
|
694
694
|
region: {
|
|
695
695
|
viewportAnchorX: 50,
|
|
696
696
|
viewportAnchorY: 16,
|
|
697
|
-
width:
|
|
698
|
-
height:
|
|
697
|
+
width: 50,
|
|
698
|
+
height: 84,
|
|
699
699
|
},
|
|
700
700
|
startTime: 62.05,
|
|
701
701
|
endTime: 3723.2,
|
|
@@ -872,8 +872,8 @@ describe('TtmlTextParser', () => {
|
|
|
872
872
|
viewportAnchorY: 16,
|
|
873
873
|
regionAnchorX: 0,
|
|
874
874
|
regionAnchorY: 0,
|
|
875
|
-
width:
|
|
876
|
-
height:
|
|
875
|
+
width: 50,
|
|
876
|
+
height: 84,
|
|
877
877
|
heightUnits: CueRegion.units.PERCENTAGE,
|
|
878
878
|
widthUnits: CueRegion.units.PERCENTAGE,
|
|
879
879
|
viewportAnchorUnits: CueRegion.units.PERCENTAGE,
|
|
@@ -945,8 +945,8 @@ describe('TtmlTextParser', () => {
|
|
|
945
945
|
id: 'subtitleArea',
|
|
946
946
|
viewportAnchorX: 50,
|
|
947
947
|
viewportAnchorY: 16,
|
|
948
|
-
width:
|
|
949
|
-
height:
|
|
948
|
+
width: 50,
|
|
949
|
+
height: 84,
|
|
950
950
|
},
|
|
951
951
|
startTime: 62.05,
|
|
952
952
|
endTime: 3723.2,
|
|
@@ -973,8 +973,8 @@ describe('TtmlTextParser', () => {
|
|
|
973
973
|
region: {
|
|
974
974
|
viewportAnchorX: 50,
|
|
975
975
|
viewportAnchorY: 16,
|
|
976
|
-
width:
|
|
977
|
-
height:
|
|
976
|
+
width: 50,
|
|
977
|
+
height: 84,
|
|
978
978
|
},
|
|
979
979
|
startTime: 62.05,
|
|
980
980
|
endTime: 3723.2,
|
|
@@ -1001,8 +1001,8 @@ describe('TtmlTextParser', () => {
|
|
|
1001
1001
|
region: {
|
|
1002
1002
|
viewportAnchorX: 50,
|
|
1003
1003
|
viewportAnchorY: 16,
|
|
1004
|
-
width:
|
|
1005
|
-
height:
|
|
1004
|
+
width: 50,
|
|
1005
|
+
height: 84,
|
|
1006
1006
|
},
|
|
1007
1007
|
startTime: 62.05,
|
|
1008
1008
|
endTime: 3723.2,
|
|
@@ -1032,8 +1032,8 @@ describe('TtmlTextParser', () => {
|
|
|
1032
1032
|
id: 'subtitleArea',
|
|
1033
1033
|
viewportAnchorX: 12.2,
|
|
1034
1034
|
viewportAnchorY: 50.005,
|
|
1035
|
-
width:
|
|
1036
|
-
height:
|
|
1035
|
+
width: 87.8,
|
|
1036
|
+
height: 49.995,
|
|
1037
1037
|
},
|
|
1038
1038
|
startTime: 62.05,
|
|
1039
1039
|
endTime: 3723.2,
|
|
@@ -1238,6 +1238,35 @@ describe('TtmlTextParser', () => {
|
|
|
1238
1238
|
});
|
|
1239
1239
|
});
|
|
1240
1240
|
|
|
1241
|
+
it('supports smpte:backgroundImage attribute with url', () => {
|
|
1242
|
+
verifyHelper(
|
|
1243
|
+
[
|
|
1244
|
+
{
|
|
1245
|
+
startTime: 62.05,
|
|
1246
|
+
endTime: 3723.2,
|
|
1247
|
+
payload: '',
|
|
1248
|
+
},
|
|
1249
|
+
],
|
|
1250
|
+
'<tt ' +
|
|
1251
|
+
'xmlns:ttm="http://www.w3.org/ns/ttml#metadata" ' +
|
|
1252
|
+
'xmlns:smpte="http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt">' +
|
|
1253
|
+
'<metadata>' +
|
|
1254
|
+
'<smpte:image imageType="PNG" encoding="Base64" xml:id="img_0">' +
|
|
1255
|
+
'base64EncodedImage</smpte:image>' +
|
|
1256
|
+
'</metadata>' +
|
|
1257
|
+
'<body><div smpte:backgroundImage="img_0.png">' +
|
|
1258
|
+
'<p begin="01:02.05" end="01:02:03.200"></p>' +
|
|
1259
|
+
'</div></body></tt>',
|
|
1260
|
+
{periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0},
|
|
1261
|
+
{startTime: 62.05, endTime: 3723.2},
|
|
1262
|
+
{
|
|
1263
|
+
startTime: 62.05,
|
|
1264
|
+
endTime: 3723.2,
|
|
1265
|
+
backgroundImage: 'foo://bar/img_0.png',
|
|
1266
|
+
isContainer: false,
|
|
1267
|
+
});
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1241
1270
|
it('supports smpte:backgroundImage attribute in div element', () => {
|
|
1242
1271
|
verifyHelper(
|
|
1243
1272
|
[],
|
|
@@ -2060,7 +2089,8 @@ describe('TtmlTextParser', () => {
|
|
|
2060
2089
|
function verifyHelper(cues, text, time, bodyProperties, divProperties) {
|
|
2061
2090
|
const data =
|
|
2062
2091
|
shaka.util.BufferUtils.toUint8(shaka.util.StringUtils.toUTF8(text));
|
|
2063
|
-
const result = new shaka.text.TtmlTextParser()
|
|
2092
|
+
const result = new shaka.text.TtmlTextParser()
|
|
2093
|
+
.parseMedia(data, time, 'foo://bar');
|
|
2064
2094
|
shaka.test.TtmlUtils.verifyHelper(
|
|
2065
2095
|
cues, result, bodyProperties, divProperties);
|
|
2066
2096
|
}
|
|
@@ -2087,7 +2117,8 @@ describe('TtmlTextParser', () => {
|
|
|
2087
2117
|
expect(() => {
|
|
2088
2118
|
new shaka.text.TtmlTextParser().parseMedia(
|
|
2089
2119
|
shaka.util.BufferUtils.toUint8(data),
|
|
2090
|
-
{periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0}
|
|
2120
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 10, vttOffset: 0},
|
|
2121
|
+
'foo://bar');
|
|
2091
2122
|
}).toThrow(error);
|
|
2092
2123
|
}
|
|
2093
2124
|
});
|
|
@@ -605,4 +605,13 @@ describe('UITextDisplayer', () => {
|
|
|
605
605
|
(e) => e.nodeType == Node.ELEMENT_NODE);
|
|
606
606
|
expect(childrenOfTwo.length).toBe(3);
|
|
607
607
|
});
|
|
608
|
+
|
|
609
|
+
it('textDisplayer does not crash if destroy is called more than once', () => {
|
|
610
|
+
expect(videoContainer.childNodes.length).toBe(1);
|
|
611
|
+
|
|
612
|
+
textDisplayer.destroy();
|
|
613
|
+
textDisplayer.destroy();
|
|
614
|
+
|
|
615
|
+
expect(videoContainer.childNodes.length).toBe(0);
|
|
616
|
+
});
|
|
608
617
|
});
|
|
@@ -598,6 +598,55 @@ describe('PeriodCombiner', () => {
|
|
|
598
598
|
}
|
|
599
599
|
});
|
|
600
600
|
|
|
601
|
+
// Regression test for #6054, where we failed on multi-period content with
|
|
602
|
+
// different numbers of forced-subtitle streams per period.
|
|
603
|
+
it('Does not combine subtitle and forced-subtitle tracks', async () => {
|
|
604
|
+
const videoStreams = [makeVideoStream(1280)];
|
|
605
|
+
const audioStreams = [makeAudioStream('en', /* channels= */ 2)];
|
|
606
|
+
const imageStreams = [];
|
|
607
|
+
|
|
608
|
+
const forcedSubtitle = makeTextStream('de');
|
|
609
|
+
forcedSubtitle.roles = ['forced-subtitle'];
|
|
610
|
+
forcedSubtitle.forced = true;
|
|
611
|
+
|
|
612
|
+
const subtitle = makeTextStream('de');
|
|
613
|
+
subtitle.roles = ['subtitle'];
|
|
614
|
+
|
|
615
|
+
/** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
|
|
616
|
+
const periods = [
|
|
617
|
+
{
|
|
618
|
+
id: '1',
|
|
619
|
+
videoStreams,
|
|
620
|
+
audioStreams,
|
|
621
|
+
textStreams: [
|
|
622
|
+
forcedSubtitle,
|
|
623
|
+
subtitle,
|
|
624
|
+
],
|
|
625
|
+
imageStreams,
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
id: '2',
|
|
629
|
+
videoStreams,
|
|
630
|
+
audioStreams,
|
|
631
|
+
textStreams: [
|
|
632
|
+
subtitle,
|
|
633
|
+
],
|
|
634
|
+
imageStreams,
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
id: '3',
|
|
638
|
+
videoStreams,
|
|
639
|
+
audioStreams,
|
|
640
|
+
textStreams: [],
|
|
641
|
+
imageStreams,
|
|
642
|
+
},
|
|
643
|
+
];
|
|
644
|
+
|
|
645
|
+
await combiner.combinePeriods(periods, /* isDynamic= */ true);
|
|
646
|
+
const textStreams = combiner.getTextStreams();
|
|
647
|
+
expect(textStreams.every((s) => s.roles.length === 1)).toBe(true);
|
|
648
|
+
});
|
|
649
|
+
|
|
601
650
|
// Regression test for #3383, where we failed on multi-period content with
|
|
602
651
|
// multiple image streams per period.
|
|
603
652
|
it('Can handle multiple image streams', async () => {
|
|
@@ -1004,6 +1053,70 @@ describe('PeriodCombiner', () => {
|
|
|
1004
1053
|
expect(audio2.originalId).toBe('2,4');
|
|
1005
1054
|
});
|
|
1006
1055
|
|
|
1056
|
+
it('Matches streams with labels', async () => {
|
|
1057
|
+
const stream1 = makeAudioStream('en', /* channels= */ 2);
|
|
1058
|
+
stream1.originalId = '1';
|
|
1059
|
+
stream1.bandwidth = 129597;
|
|
1060
|
+
stream1.codecs = 'mp4a.40.2';
|
|
1061
|
+
|
|
1062
|
+
const stream2 = makeAudioStream('en', /* channels= */ 2);
|
|
1063
|
+
stream2.originalId = '2';
|
|
1064
|
+
stream2.bandwidth = 129637;
|
|
1065
|
+
stream2.codecs = 'mp4a.40.2';
|
|
1066
|
+
stream2.label = 'description';
|
|
1067
|
+
|
|
1068
|
+
const stream3 = makeAudioStream('en', /* channels= */ 2);
|
|
1069
|
+
stream3.originalId = '3';
|
|
1070
|
+
stream3.bandwidth = 131037;
|
|
1071
|
+
stream3.codecs = 'mp4a.40.2';
|
|
1072
|
+
|
|
1073
|
+
const stream4 = makeAudioStream('en', /* channels= */ 2);
|
|
1074
|
+
stream4.originalId = '4';
|
|
1075
|
+
stream4.bandwidth = 131034;
|
|
1076
|
+
stream4.codecs = 'mp4a.40.2';
|
|
1077
|
+
stream4.label = 'description';
|
|
1078
|
+
|
|
1079
|
+
/** @type {!Array.<shaka.util.PeriodCombiner.Period>} */
|
|
1080
|
+
const periods = [
|
|
1081
|
+
{
|
|
1082
|
+
id: '0',
|
|
1083
|
+
videoStreams: [
|
|
1084
|
+
makeVideoStream(1080),
|
|
1085
|
+
],
|
|
1086
|
+
audioStreams: [
|
|
1087
|
+
stream1,
|
|
1088
|
+
stream2,
|
|
1089
|
+
],
|
|
1090
|
+
textStreams: [],
|
|
1091
|
+
imageStreams: [],
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
id: '1',
|
|
1095
|
+
videoStreams: [
|
|
1096
|
+
makeVideoStream(1080),
|
|
1097
|
+
],
|
|
1098
|
+
audioStreams: [
|
|
1099
|
+
stream3,
|
|
1100
|
+
stream4,
|
|
1101
|
+
],
|
|
1102
|
+
textStreams: [],
|
|
1103
|
+
imageStreams: [],
|
|
1104
|
+
},
|
|
1105
|
+
];
|
|
1106
|
+
|
|
1107
|
+
await combiner.combinePeriods(periods, /* isDynamic= */ true);
|
|
1108
|
+
const variants = combiner.getVariants();
|
|
1109
|
+
expect(variants.length).toBe(2);
|
|
1110
|
+
// We can use the originalId field to see what each track is composed of.
|
|
1111
|
+
const audio1 = variants[0].audio;
|
|
1112
|
+
expect(audio1.label).toBe(null);
|
|
1113
|
+
expect(audio1.originalId).toBe('1,3');
|
|
1114
|
+
|
|
1115
|
+
const audio2 = variants[1].audio;
|
|
1116
|
+
expect(audio2.label).toBe('description');
|
|
1117
|
+
expect(audio2.originalId).toBe('2,4');
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1007
1120
|
it('Matches streams with related codecs', async () => {
|
|
1008
1121
|
const stream1 = makeVideoStream(1080);
|
|
1009
1122
|
stream1.originalId = '1';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Use new goog.Uri(string) to parse a URI string.
|
|
10
10
|
*
|
|
11
|
-
* e.g
|
|
11
|
+
* e.g.: <code>var myUri = new goog.Uri(window.location);</code>
|
|
12
12
|
*
|
|
13
13
|
* Implements RFC 3986 for parsing/formatting URIs.
|
|
14
14
|
* http://www.ietf.org/rfc/rfc3986.txt
|
package/ui/externs/ui.js
CHANGED
|
@@ -443,3 +443,27 @@ shaka.extern.IUISeekBar.Factory = class {
|
|
|
443
443
|
*/
|
|
444
444
|
create(rootElement, controls) {}
|
|
445
445
|
};
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* @interface
|
|
449
|
+
* @exportDoc
|
|
450
|
+
*/
|
|
451
|
+
shaka.extern.IUIPlayButton = class {
|
|
452
|
+
/**
|
|
453
|
+
* @param {!HTMLElement} parent
|
|
454
|
+
* @param {!shaka.ui.Controls} controls
|
|
455
|
+
*/
|
|
456
|
+
constructor(parent, controls) {
|
|
457
|
+
/**
|
|
458
|
+
* @protected {!HTMLButtonElement}
|
|
459
|
+
* @exportDoc
|
|
460
|
+
*/
|
|
461
|
+
this.button;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** @return {boolean} */
|
|
465
|
+
isPaused() {}
|
|
466
|
+
|
|
467
|
+
/** @return {boolean} */
|
|
468
|
+
isEnded() {}
|
|
469
|
+
};
|
package/ui/language_utils.js
CHANGED
|
@@ -55,7 +55,11 @@ shaka.ui.LanguageUtils = class {
|
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
const getCombination = (language, rolesString) => {
|
|
58
|
+
const getCombination = (language, rolesString, label) => {
|
|
59
|
+
if (label &&
|
|
60
|
+
trackLabelFormat == shaka.ui.Overlay.TrackLabelFormat.LABEL) {
|
|
61
|
+
return language + ': ' + label + ': ' + rolesString;
|
|
62
|
+
}
|
|
59
63
|
return language + ': ' + rolesString;
|
|
60
64
|
};
|
|
61
65
|
|
|
@@ -72,7 +76,8 @@ shaka.ui.LanguageUtils = class {
|
|
|
72
76
|
/** @type {!Set.<string>} */
|
|
73
77
|
const combinationsMade = new Set();
|
|
74
78
|
const selectedCombination = selectedTrack ? getCombination(
|
|
75
|
-
selectedTrack.language, getRolesString(selectedTrack)
|
|
79
|
+
selectedTrack.language, getRolesString(selectedTrack),
|
|
80
|
+
selectedTrack.label) : '';
|
|
76
81
|
|
|
77
82
|
for (const track of tracks) {
|
|
78
83
|
const language = track.language;
|
|
@@ -80,7 +85,8 @@ shaka.ui.LanguageUtils = class {
|
|
|
80
85
|
const LocIds = shaka.ui.Locales.Ids;
|
|
81
86
|
const forcedString = localization.resolve(LocIds.SUBTITLE_FORCED);
|
|
82
87
|
const rolesString = getRolesString(track);
|
|
83
|
-
const
|
|
88
|
+
const label = track.label;
|
|
89
|
+
const combinationName = getCombination(language, rolesString, label);
|
|
84
90
|
if (combinationsMade.has(combinationName)) {
|
|
85
91
|
continue;
|
|
86
92
|
}
|
|
@@ -124,8 +130,8 @@ shaka.ui.LanguageUtils = class {
|
|
|
124
130
|
}
|
|
125
131
|
break;
|
|
126
132
|
case shaka.ui.Overlay.TrackLabelFormat.LABEL:
|
|
127
|
-
if (
|
|
128
|
-
span.textContent =
|
|
133
|
+
if (label) {
|
|
134
|
+
span.textContent = label;
|
|
129
135
|
} else {
|
|
130
136
|
// Fallback behavior. This probably shouldn't happen.
|
|
131
137
|
shaka.log.alwaysWarn('Track #' + track.id + ' does not have a ' +
|
package/ui/play_button.js
CHANGED
|
@@ -16,6 +16,7 @@ goog.requireType('shaka.ui.Controls');
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @extends {shaka.ui.Element}
|
|
19
|
+
* @implements {shaka.extern.IUIPlayButton}
|
|
19
20
|
* @export
|
|
20
21
|
*/
|
|
21
22
|
shaka.ui.PlayButton = class extends shaka.ui.Element {
|
|
@@ -72,6 +73,11 @@ shaka.ui.PlayButton = class extends shaka.ui.Element {
|
|
|
72
73
|
this.updateIcon();
|
|
73
74
|
});
|
|
74
75
|
|
|
76
|
+
this.eventManager.listen(this.adManager, AdManager.AD_STOPPED, () => {
|
|
77
|
+
this.updateAriaLabel();
|
|
78
|
+
this.updateIcon();
|
|
79
|
+
});
|
|
80
|
+
|
|
75
81
|
this.eventManager.listen(this.button, 'click', () => {
|
|
76
82
|
if (this.ad && this.ad.isLinear()) {
|
|
77
83
|
this.controls.playPauseAd();
|
|
@@ -90,6 +96,7 @@ shaka.ui.PlayButton = class extends shaka.ui.Element {
|
|
|
90
96
|
/**
|
|
91
97
|
* @return {boolean}
|
|
92
98
|
* @protected
|
|
99
|
+
* @override
|
|
93
100
|
*/
|
|
94
101
|
isPaused() {
|
|
95
102
|
if (this.ad && this.ad.isLinear()) {
|
|
@@ -99,6 +106,19 @@ shaka.ui.PlayButton = class extends shaka.ui.Element {
|
|
|
99
106
|
return this.controls.presentationIsPaused();
|
|
100
107
|
}
|
|
101
108
|
|
|
109
|
+
/**
|
|
110
|
+
* @return {boolean}
|
|
111
|
+
* @protected
|
|
112
|
+
* @override
|
|
113
|
+
*/
|
|
114
|
+
isEnded() {
|
|
115
|
+
if (this.ad && this.ad.isLinear()) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this.video.ended;
|
|
120
|
+
}
|
|
121
|
+
|
|
102
122
|
/**
|
|
103
123
|
* Called when the button's aria label needs to change.
|
|
104
124
|
* To be overridden by subclasses.
|
|
@@ -44,6 +44,10 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
|
|
|
44
44
|
this.updateLocalizedStrings_();
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
this.eventManager.listen(this.player, 'loaded', () => {
|
|
48
|
+
this.updatePlaybackRateSelection_(this.player.getPlaybackRate());
|
|
49
|
+
});
|
|
50
|
+
|
|
47
51
|
this.eventManager.listen(this.player, 'ratechange', () => {
|
|
48
52
|
this.updatePlaybackRateSelection_(this.player.getPlaybackRate());
|
|
49
53
|
});
|
package/ui/presentation_time.js
CHANGED
|
@@ -64,7 +64,6 @@ shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
|
|
|
64
64
|
updateTime_() {
|
|
65
65
|
const isSeeking = this.controls.isSeeking();
|
|
66
66
|
let displayTime = this.controls.getDisplayTime();
|
|
67
|
-
const duration = this.video.duration;
|
|
68
67
|
const seekRange = this.player.seekRange();
|
|
69
68
|
const seekRangeSize = seekRange.end - seekRange.start;
|
|
70
69
|
const Utils = shaka.ui.Utils;
|
|
@@ -89,11 +88,12 @@ shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
|
|
|
89
88
|
this.currentTime_.disabled = true;
|
|
90
89
|
}
|
|
91
90
|
} else {
|
|
92
|
-
const showHour =
|
|
91
|
+
const showHour = seekRangeSize >= 3600;
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
const currentTime = Math.max(0, displayTime - seekRange.start);
|
|
94
|
+
let value = Utils.buildTimeString(currentTime, showHour);
|
|
95
|
+
if (seekRangeSize) {
|
|
96
|
+
value += ' / ' + Utils.buildTimeString(seekRangeSize, showHour);
|
|
97
97
|
}
|
|
98
98
|
this.setValue_(value);
|
|
99
99
|
this.currentTime_.disabled = true;
|
package/ui/small_play_button.js
CHANGED
|
@@ -38,7 +38,7 @@ shaka.ui.SmallPlayButton = class extends shaka.ui.PlayButton {
|
|
|
38
38
|
/** @override */
|
|
39
39
|
updateIcon() {
|
|
40
40
|
const Icons = shaka.ui.Enums.MaterialDesignIcons;
|
|
41
|
-
if (this.
|
|
41
|
+
if (this.isEnded()) {
|
|
42
42
|
this.button.textContent = Icons.REPLAY;
|
|
43
43
|
} else {
|
|
44
44
|
this.button.textContent = this.isPaused() ? Icons.PLAY : Icons.PAUSE;
|
|
@@ -48,7 +48,7 @@ shaka.ui.SmallPlayButton = class extends shaka.ui.PlayButton {
|
|
|
48
48
|
/** @override */
|
|
49
49
|
updateAriaLabel() {
|
|
50
50
|
const LocIds = shaka.ui.Locales.Ids;
|
|
51
|
-
if (this.
|
|
51
|
+
if (this.isEnded()) {
|
|
52
52
|
this.button.ariaLabel = this.localization.resolve(LocIds.REPLAY);
|
|
53
53
|
} else {
|
|
54
54
|
const label = this.isPaused() ? LocIds.PLAY : LocIds.PAUSE;
|
package/ui/volume_bar.js
CHANGED
|
@@ -32,6 +32,10 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
|
|
|
32
32
|
/** @private {!shaka.extern.UIConfiguration} */
|
|
33
33
|
this.config_ = this.controls.getConfig();
|
|
34
34
|
|
|
35
|
+
// We use a range of 100 to avoid problems with Firefox.
|
|
36
|
+
// See https://github.com/shaka-project/shaka-player/issues/3987
|
|
37
|
+
this.setRange(0, 100);
|
|
38
|
+
|
|
35
39
|
this.eventManager.listen(this.video,
|
|
36
40
|
'volumechange',
|
|
37
41
|
() => this.onPresentationVolumeChange_());
|
|
@@ -74,9 +78,9 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
|
|
|
74
78
|
*/
|
|
75
79
|
onChange() {
|
|
76
80
|
if (this.ad && this.ad.isLinear()) {
|
|
77
|
-
this.ad.setVolume(this.getValue());
|
|
81
|
+
this.ad.setVolume(this.getValue() / 100);
|
|
78
82
|
} else {
|
|
79
|
-
this.video.volume = this.getValue();
|
|
83
|
+
this.video.volume = this.getValue() / 100;
|
|
80
84
|
if (this.video.volume == 0) {
|
|
81
85
|
this.video.muted = true;
|
|
82
86
|
} else {
|
|
@@ -90,7 +94,7 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
|
|
|
90
94
|
if (this.video.muted) {
|
|
91
95
|
this.setValue(0);
|
|
92
96
|
} else {
|
|
93
|
-
this.setValue(this.video.volume);
|
|
97
|
+
this.setValue(this.video.volume * 100);
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
this.updateColors_();
|
|
@@ -102,7 +106,7 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
|
|
|
102
106
|
'This.ad should exist at this point!');
|
|
103
107
|
|
|
104
108
|
const volume = this.ad.getVolume();
|
|
105
|
-
this.setValue(volume);
|
|
109
|
+
this.setValue(volume * 100);
|
|
106
110
|
this.updateColors_();
|
|
107
111
|
}
|
|
108
112
|
|
|
@@ -110,8 +114,8 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
|
|
|
110
114
|
updateColors_() {
|
|
111
115
|
const colors = this.config_.volumeBarColors;
|
|
112
116
|
const gradient = ['to right'];
|
|
113
|
-
gradient.push(colors.level +
|
|
114
|
-
gradient.push(colors.base +
|
|
117
|
+
gradient.push(colors.level + this.getValue() + '%');
|
|
118
|
+
gradient.push(colors.base + this.getValue() + '%');
|
|
115
119
|
gradient.push(colors.base + '100%');
|
|
116
120
|
|
|
117
121
|
this.container.style.background =
|
|
File without changes
|