shaka-player 4.1.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build-and-test.yaml +67 -15
- package/.github/workflows/compute-incremental-coverage.py +251 -0
- package/.github/workflows/report-incremental-coverage.yaml +39 -0
- package/.github/workflows/selenium-lab-tests.yaml +44 -1
- package/AUTHORS +1 -0
- package/CHANGELOG.md +36 -8
- package/CONTRIBUTORS +3 -0
- package/README.md +20 -6
- package/demo/common/assets.js +25 -0
- package/demo/common/message_ids.js +2 -0
- package/demo/config.js +5 -1
- package/demo/index.html +1 -3
- package/demo/locales/en.json +2 -0
- package/demo/locales/source.json +8 -0
- package/dist/controls.css +1 -1
- package/dist/demo.compiled.debug.js +25 -23
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +25 -23
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +6 -5
- package/dist/locales.js +30 -30
- package/dist/receiver.compiled.debug.js +24 -22
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +24 -22
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +69 -5
- package/dist/shaka-player.compiled.debug.d.ts +69 -5
- package/dist/shaka-player.compiled.debug.externs.js +111 -42
- package/dist/shaka-player.compiled.debug.js +352 -301
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +111 -42
- package/dist/shaka-player.compiled.js +823 -802
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +69 -5
- package/dist/shaka-player.ui.debug.d.ts +69 -5
- package/dist/shaka-player.ui.debug.externs.js +111 -42
- package/dist/shaka-player.ui.debug.js +360 -310
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +111 -42
- package/dist/shaka-player.ui.js +980 -957
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/fairplay.md +149 -0
- package/docs/tutorials/ui.md +6 -6
- package/docs/tutorials/upgrade.md +1 -0
- package/docs/tutorials/welcome.md +6 -3
- package/externs/shaka/abr_manager.js +8 -0
- package/externs/shaka/manifest.js +43 -0
- package/externs/shaka/player.js +13 -2
- package/karma.conf.js +3 -11
- package/lib/abr/simple_abr_manager.js +72 -4
- package/lib/ads/client_side_ad_manager.js +1 -1
- package/lib/dash/dash_parser.js +5 -0
- package/lib/hls/hls_parser.js +123 -27
- package/lib/media/drm_engine.js +1 -3
- package/lib/media/media_source_engine.js +57 -24
- package/lib/media/presentation_timeline.js +24 -1
- package/lib/media/segment_index.js +8 -0
- package/lib/media/segment_reference.js +7 -1
- package/lib/media/streaming_engine.js +42 -6
- package/lib/media/time_ranges_utils.js +46 -0
- package/lib/net/networking_engine.js +1 -0
- package/lib/player.js +8 -6
- package/lib/polyfill/media_capabilities.js +9 -0
- package/lib/polyfill/patchedmediakeys_apple.js +729 -0
- package/lib/polyfill/videoplaybackquality.js +3 -1
- package/lib/text/cue.js +0 -5
- package/lib/text/simple_text_displayer.js +21 -9
- package/lib/text/ui_text_displayer.js +83 -19
- package/lib/text/vtt_text_parser.js +61 -4
- package/lib/util/buffer_utils.js +3 -0
- package/lib/util/error.js +21 -1
- package/lib/util/fairplay_utils.js +100 -2
- package/lib/util/object_utils.js +1 -0
- package/lib/util/platform.js +30 -1
- package/lib/util/player_configuration.js +3 -10
- package/lib/util/stream_utils.js +23 -3
- package/lib/util/string_utils.js +102 -13
- package/maintained-branches.md +15 -0
- package/package.json +3 -5
- package/shaka-player.uncompiled.js +1 -0
- package/test/hls/hls_parser_unit.js +49 -33
- package/test/media/drm_engine_integration.js +24 -8
- package/test/media/media_source_engine_integration.js +24 -10
- package/test/media/media_source_engine_unit.js +53 -38
- package/test/media/streaming_engine_unit.js +107 -32
- package/test/test/util/fake_media_source_engine.js +10 -9
- package/test/test/util/simple_fakes.js +4 -0
- package/test/test/util/streaming_engine_util.js +10 -2
- package/test/text/simple_text_displayer_unit.js +27 -0
- package/test/text/ui_text_displayer_unit.js +65 -0
- package/test/text/vtt_text_parser_unit.js +26 -0
- package/test/util/string_utils_unit.js +46 -8
- package/ui/text_selection.js +2 -2
- package/app-engine/README.md +0 -9
- package/app-engine/demo-version-index/README.md +0 -14
- package/app-engine/demo-version-index/app.yaml +0 -28
- package/app-engine/demo-version-index/generate.py +0 -164
- package/app-engine/demo-version-index/main.py +0 -11
- package/app-engine/demo-version-index/requirements.txt +0 -5
- package/app-engine/demo-version-index/templates/index.html +0 -114
- package/app-engine/shaka-player-demo/README.md +0 -18
- package/app-engine/shaka-player-demo/app.yaml +0 -61
- package/app-engine/shaka-player-demo/main.py +0 -95
- package/app-engine/shaka-player-demo/posters/10yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/10yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/1yo.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/2yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/2yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/3yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/3yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/4yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/4yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/5yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/5yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/6yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/6yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/7yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/7yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/8yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/8yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/9yo.png +0 -0
- package/app-engine/shaka-player-demo/posters/9yo.xcf +0 -0
- package/app-engine/shaka-player-demo/posters/audioOnly.gif +0 -0
- package/app-engine/shaka-player-demo/posters/audioRickRoll.gif +0 -0
- package/app-engine/shaka-player-demo/posters/colorbars.gif +0 -0
- package/app-engine/shaka-player-demo/posters/fireworks.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/party-hat.png +0 -0
- package/app-engine/shaka-player-demo/posters/sources.txt +0 -46
- package/app-engine/shaka-player-demo/posters/standard.png +0 -0
- package/app-engine/shaka-player-demo/posters/trek.jpg +0 -0
- package/app-engine/shaka-player-demo/posters/valentines.png +0 -0
- package/app-engine/shaka-player-demo/posters/zombie.jpg +0 -0
- package/app-engine/shaka-player-demo/posters.py +0 -110
- package/app-engine/shaka-player-demo/requirements.txt +0 -5
- package/app-engine/shaka-player-demo/time.txt +0 -1
- package/build/README.md +0 -127
- package/build/__init__.py +0 -0
- package/build/all.py +0 -150
- package/build/apps.py +0 -186
- package/build/build.py +0 -392
- package/build/check.py +0 -354
- package/build/checkversion.py +0 -84
- package/build/compiler.py +0 -513
- package/build/conformance.textproto +0 -335
- package/build/docker/Dockerfile +0 -20
- package/build/docker/docker-compose.yml +0 -10
- package/build/docs.py +0 -54
- package/build/eslint-plugin-shaka-rules/arg-comment-spacing.js +0 -72
- package/build/eslint-plugin-shaka-rules/index.js +0 -24
- package/build/eslint-plugin-shaka-rules/package.json +0 -7
- package/build/eslint-plugin-shaka-rules/private.js +0 -109
- package/build/gendeps.py +0 -71
- package/build/generateExterns.js +0 -867
- package/build/generateLocalizations.py +0 -262
- package/build/generateTsDefs.py +0 -137
- package/build/install-linux-prereqs.sh +0 -136
- package/build/license-header +0 -5
- package/build/misspellings.txt +0 -39
- package/build/pixelsChanged.js +0 -35
- package/build/shaka-lab.yaml +0 -161
- package/build/shakaBuildHelpers.py +0 -356
- package/build/stats.py +0 -816
- package/build/subprocessWindowsPatch.py +0 -103
- package/build/test.py +0 -541
- package/build/types/ads +0 -8
- package/build/types/cast +0 -6
- package/build/types/cea +0 -13
- package/build/types/complete +0 -9
- package/build/types/core +0 -108
- package/build/types/dash +0 -8
- package/build/types/hls +0 -9
- package/build/types/manifests +0 -5
- package/build/types/networking +0 -6
- package/build/types/offline +0 -22
- package/build/types/polyfill +0 -18
- package/build/types/text +0 -11
- package/build/types/ui +0 -39
- package/build/updateScreenshots.py +0 -85
- package/build/wrapper.template.js +0 -52
|
@@ -149,11 +149,13 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
149
149
|
* ranges for each type of init segment.
|
|
150
150
|
* @param {!Object.<string,number>=} timestampOffsets The timestamp offset
|
|
151
151
|
* for each type of segment
|
|
152
|
+
* @param {shaka.extern.HlsAes128Key=} hlsAes128Key The AES-128 key to provide
|
|
153
|
+
* to streams, if desired.
|
|
152
154
|
* @return {shaka.extern.Manifest}
|
|
153
155
|
*/
|
|
154
156
|
static createManifest(
|
|
155
157
|
presentationTimeline, periodStartTimes, presentationDuration,
|
|
156
|
-
segmentDurations, initSegmentRanges, timestampOffsets) {
|
|
158
|
+
segmentDurations, initSegmentRanges, timestampOffsets, hlsAes128Key) {
|
|
157
159
|
const Util = shaka.test.Util;
|
|
158
160
|
|
|
159
161
|
/**
|
|
@@ -255,7 +257,7 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
255
257
|
const appendWindowEnd = periodIndex == periodStartTimes.length - 1?
|
|
256
258
|
presentationDuration : periodStartTimes[periodIndex + 1];
|
|
257
259
|
|
|
258
|
-
|
|
260
|
+
const ref = new shaka.media.SegmentReference(
|
|
259
261
|
/* startTime= */ periodStart + positionWithinPeriod * d,
|
|
260
262
|
/* endTime= */ periodStart + (positionWithinPeriod + 1) * d,
|
|
261
263
|
getUris,
|
|
@@ -265,6 +267,12 @@ shaka.test.StreamingEngineUtil = class {
|
|
|
265
267
|
timestampOffset,
|
|
266
268
|
appendWindowStart,
|
|
267
269
|
appendWindowEnd);
|
|
270
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
271
|
+
if (hlsAes128Key &&
|
|
272
|
+
(type == ContentType.AUDIO || type == ContentType.VIDEO)) {
|
|
273
|
+
ref.hlsAes128Key = hlsAes128Key;
|
|
274
|
+
}
|
|
275
|
+
return ref;
|
|
268
276
|
};
|
|
269
277
|
|
|
270
278
|
/** @type {shaka.extern.Manifest} */
|
|
@@ -127,6 +127,33 @@ describe('SimpleTextDisplayer', () => {
|
|
|
127
127
|
[shakaCue]);
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
+
it('flattens nested cue payloads correctly', () => {
|
|
131
|
+
const level0ContainerCue = new shaka.text.Cue(10, 30, '');
|
|
132
|
+
level0ContainerCue.isContainer = true;
|
|
133
|
+
|
|
134
|
+
const level1NonContainerCueA = new shaka.text.Cue(10, 20, '');
|
|
135
|
+
const level1NonContainerCueB = new shaka.text.Cue(20, 30, '');
|
|
136
|
+
|
|
137
|
+
// Add a trailing whitespace character to get a space-delimited expected
|
|
138
|
+
// result.
|
|
139
|
+
const cueANestedCue0 = new shaka.text.Cue(10, 20, 'Cue A Test0 ');
|
|
140
|
+
const cueANestedCue1 = new shaka.text.Cue(10, 20, 'Cue A Test1');
|
|
141
|
+
const cueBNestedCue0 = new shaka.text.Cue(20, 30, 'Cue B Test0 ');
|
|
142
|
+
const cueBNestedCue1 = new shaka.text.Cue(20, 30, 'Cue B Test1');
|
|
143
|
+
|
|
144
|
+
level1NonContainerCueA.nestedCues = [cueANestedCue0, cueANestedCue1];
|
|
145
|
+
level1NonContainerCueB.nestedCues = [cueBNestedCue0, cueBNestedCue1];
|
|
146
|
+
level0ContainerCue.nestedCues =
|
|
147
|
+
[level1NonContainerCueA, level1NonContainerCueB];
|
|
148
|
+
|
|
149
|
+
verifyHelper(
|
|
150
|
+
[
|
|
151
|
+
{startTime: 10, endTime: 20, text: 'Cue A Test0 Cue A Test1'},
|
|
152
|
+
{startTime: 20, endTime: 30, text: 'Cue B Test0 Cue B Test1'},
|
|
153
|
+
],
|
|
154
|
+
[level0ContainerCue]);
|
|
155
|
+
});
|
|
156
|
+
|
|
130
157
|
// Regression test for b/159050711
|
|
131
158
|
it('maintains the styles of the parent cue', () => {
|
|
132
159
|
const shakaCue = new shaka.text.Cue(10, 20, '');
|
|
@@ -50,6 +50,7 @@ describe('UITextDisplayer', () => {
|
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
beforeEach(() => {
|
|
53
|
+
video.currentTime = 0;
|
|
53
54
|
textDisplayer = new shaka.text.UITextDisplayer(video, videoContainer);
|
|
54
55
|
});
|
|
55
56
|
|
|
@@ -396,4 +397,68 @@ describe('UITextDisplayer', () => {
|
|
|
396
397
|
expect(parentCueElements.length).toBe(1);
|
|
397
398
|
expect(parentCueElements[0].textContent).toBe('');
|
|
398
399
|
});
|
|
400
|
+
|
|
401
|
+
it('creates separate elements for cue regions', () => {
|
|
402
|
+
const cueRegion = new shaka.text.CueRegion();
|
|
403
|
+
cueRegion.id = 'regionId';
|
|
404
|
+
cueRegion.height = 80;
|
|
405
|
+
cueRegion.heightUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
406
|
+
cueRegion.width = 80;
|
|
407
|
+
cueRegion.widthUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
408
|
+
cueRegion.viewportAnchorX = 10;
|
|
409
|
+
cueRegion.viewportAnchorY = 10;
|
|
410
|
+
cueRegion.viewportAnchorUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
411
|
+
|
|
412
|
+
// These all attach to the same region, but only one region element should
|
|
413
|
+
// be created.
|
|
414
|
+
const cues = [
|
|
415
|
+
new shaka.text.Cue(0, 100, ''),
|
|
416
|
+
new shaka.text.Cue(0, 100, ''),
|
|
417
|
+
new shaka.text.Cue(0, 100, ''),
|
|
418
|
+
];
|
|
419
|
+
for (const cue of cues) {
|
|
420
|
+
cue.displayAlign = shaka.text.Cue.displayAlign.CENTER;
|
|
421
|
+
cue.region = cueRegion;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
textDisplayer.setTextVisibility(true);
|
|
425
|
+
textDisplayer.append(cues);
|
|
426
|
+
updateCaptions();
|
|
427
|
+
|
|
428
|
+
const textContainer = videoContainer.querySelector('.shaka-text-container');
|
|
429
|
+
const allRegionElements = textContainer.querySelectorAll(
|
|
430
|
+
'.shaka-text-region');
|
|
431
|
+
|
|
432
|
+
// Verify that the nested cues are all attached to a single region element.
|
|
433
|
+
expect(allRegionElements.length).toBe(1);
|
|
434
|
+
const regionElement = allRegionElements[0];
|
|
435
|
+
const children = Array.from(regionElement.childNodes).filter(
|
|
436
|
+
(e) => e.nodeType == Node.ELEMENT_NODE);
|
|
437
|
+
expect(children.length).toBe(3);
|
|
438
|
+
|
|
439
|
+
// Verify styles applied to the region element.
|
|
440
|
+
const regionCssObj = parseCssText(regionElement.style.cssText);
|
|
441
|
+
const expectRegionCssObj = {
|
|
442
|
+
'position': 'absolute',
|
|
443
|
+
'height': '80%',
|
|
444
|
+
'width': '80%',
|
|
445
|
+
'top': '10%',
|
|
446
|
+
'left': '10%',
|
|
447
|
+
'display': 'flex',
|
|
448
|
+
'flex-direction': 'column',
|
|
449
|
+
'align-items': 'center',
|
|
450
|
+
'justify-content': 'center',
|
|
451
|
+
};
|
|
452
|
+
expect(regionCssObj).toEqual(jasmine.objectContaining(expectRegionCssObj));
|
|
453
|
+
|
|
454
|
+
for (const caption of children) {
|
|
455
|
+
// Verify that styles applied to the nested cues _DO NOT_ include region
|
|
456
|
+
// placement.
|
|
457
|
+
const cueCssObj = parseCssText(caption.style.cssText);
|
|
458
|
+
expect(Object.keys(cueCssObj)).not.toContain('height');
|
|
459
|
+
expect(Object.keys(cueCssObj)).not.toContain('width');
|
|
460
|
+
expect(Object.keys(cueCssObj)).not.toContain('top');
|
|
461
|
+
expect(Object.keys(cueCssObj)).not.toContain('left');
|
|
462
|
+
}
|
|
463
|
+
});
|
|
399
464
|
});
|
|
@@ -1008,6 +1008,32 @@ describe('VttTextParser', () => {
|
|
|
1008
1008
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1009
1009
|
});
|
|
1010
1010
|
|
|
1011
|
+
it('supports karaoke style text', () => {
|
|
1012
|
+
verifyHelper(
|
|
1013
|
+
[
|
|
1014
|
+
{
|
|
1015
|
+
startTime: 20, endTime: 40,
|
|
1016
|
+
payload: '',
|
|
1017
|
+
nestedCues: [
|
|
1018
|
+
{
|
|
1019
|
+
startTime: 20,
|
|
1020
|
+
endTime: 40,
|
|
1021
|
+
payload: 'Test',
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
startTime: 25,
|
|
1025
|
+
endTime: 40,
|
|
1026
|
+
payload: ' 1',
|
|
1027
|
+
},
|
|
1028
|
+
],
|
|
1029
|
+
},
|
|
1030
|
+
],
|
|
1031
|
+
'WEBVTT\n\n' +
|
|
1032
|
+
'00:00:20.00 --> 00:00:40.00\n' +
|
|
1033
|
+
'Test<00:00:25.00> 1',
|
|
1034
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1011
1037
|
it('supports default color overriding', () => {
|
|
1012
1038
|
verifyHelper(
|
|
1013
1039
|
[
|
|
@@ -5,6 +5,29 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
describe('StringUtils', () => {
|
|
8
|
+
describe('with TextDecoder', () => {
|
|
9
|
+
if (window.TextDecoder) {
|
|
10
|
+
defineStringUtilTests();
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('without TextDecoder', () => {
|
|
15
|
+
let originalTextDecoder;
|
|
16
|
+
|
|
17
|
+
beforeAll(() => {
|
|
18
|
+
originalTextDecoder = window.TextDecoder;
|
|
19
|
+
window['TextDecoder'] = null;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterAll(() => {
|
|
23
|
+
window.TextDecoder = originalTextDecoder;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
defineStringUtilTests();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function defineStringUtilTests() {
|
|
8
31
|
const StringUtils = shaka.util.StringUtils;
|
|
9
32
|
|
|
10
33
|
it('parses fromUTF8', () => {
|
|
@@ -16,19 +39,34 @@ describe('StringUtils', () => {
|
|
|
16
39
|
});
|
|
17
40
|
|
|
18
41
|
it('won\'t break if given cut-off UTF8 character', () => {
|
|
19
|
-
|
|
20
|
-
// at the very end of the string.
|
|
21
|
-
const arr1 = [0x53, 0x61, 0x6e, 0x20, 0x4a, 0x6f, 0x73, 0x81];
|
|
42
|
+
const arr1 = [0x53, 0x61, 0x6e, 0x20, 0x4a, 0x6f, 0x73, 0xc3, 0xa9];
|
|
22
43
|
expect(StringUtils.fromUTF8(new Uint8Array(arr1)))
|
|
44
|
+
.toBe('San Jos\u00E9');
|
|
45
|
+
|
|
46
|
+
// This array contains the first half of a 2-byte UTF8 character
|
|
47
|
+
// (0xc3 0xa9 = é). The half-character is stranded at the very end of the
|
|
48
|
+
// string.
|
|
49
|
+
const arr = [0x53, 0x61, 0x6e, 0x20, 0x4a, 0x6f, 0x73, 0xc3];
|
|
50
|
+
expect(StringUtils.fromUTF8(new Uint8Array(arr)))
|
|
23
51
|
.toBe('San Jos\uFFFD');
|
|
52
|
+
});
|
|
24
53
|
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
const
|
|
28
|
-
expect(StringUtils.fromUTF8(new Uint8Array(
|
|
54
|
+
it('won\'t break if given an invalid UTF-8 sequence', () => {
|
|
55
|
+
// 0xe9 0x33 0x33 is an invalid UTF-8 sequence.
|
|
56
|
+
const arr = [0x4a, 0x6f, 0x73, 0xE9, 0x33, 0x33, 0x20, 0x53, 0x61, 0x6e];
|
|
57
|
+
expect(StringUtils.fromUTF8(new Uint8Array(arr)))
|
|
29
58
|
.toBe('Jos\uFFFD33 San');
|
|
30
59
|
});
|
|
31
60
|
|
|
61
|
+
it('can handle an 8-byte character', () => {
|
|
62
|
+
// This is the UTF-8 encoding of the US flag emoji.
|
|
63
|
+
// It decodes into two Unicode codepoints, which becomes 4 JavaScript
|
|
64
|
+
// UTF-16 characters.
|
|
65
|
+
const arr = [0xf0, 0x9f, 0x87, 0xba, 0xf0, 0x9f, 0x87, 0xb8];
|
|
66
|
+
expect(StringUtils.fromUTF8(new Uint8Array(arr)))
|
|
67
|
+
.toBe('\uD83C\uDDFA\uD83C\uDDF8');
|
|
68
|
+
});
|
|
69
|
+
|
|
32
70
|
it('strips the BOM in fromUTF8', () => {
|
|
33
71
|
// This is 4 Unicode characters, the last will be split into a surrogate
|
|
34
72
|
// pair.
|
|
@@ -125,4 +163,4 @@ describe('StringUtils', () => {
|
|
|
125
163
|
expect(StringUtils.fromUTF16(buffer, true).length)
|
|
126
164
|
.toBe(buffer.byteLength / 2);
|
|
127
165
|
});
|
|
128
|
-
}
|
|
166
|
+
}
|
package/ui/text_selection.js
CHANGED
|
@@ -111,11 +111,11 @@ shaka.ui.TextSelection = class extends shaka.ui.SettingsMenu {
|
|
|
111
111
|
onCaptionStateChange_() {
|
|
112
112
|
if (this.player.isTextTrackVisible()) {
|
|
113
113
|
this.icon.textContent =
|
|
114
|
-
shaka.ui.Enums.MaterialDesignIcons.
|
|
114
|
+
shaka.ui.Enums.MaterialDesignIcons.CLOSED_CAPTIONS;
|
|
115
115
|
this.button.ariaPressed = 'true';
|
|
116
116
|
} else {
|
|
117
117
|
this.icon.textContent =
|
|
118
|
-
shaka.ui.Enums.MaterialDesignIcons.
|
|
118
|
+
shaka.ui.Enums.MaterialDesignIcons.CLOSED_CAPTIONS_OFF;
|
|
119
119
|
this.button.ariaPressed = 'false';
|
|
120
120
|
}
|
|
121
121
|
|
package/app-engine/README.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Google App Engine Code
|
|
2
|
-
|
|
3
|
-
This folder contains source code for the services we run on Google App Engine
|
|
4
|
-
(appspot.com).
|
|
5
|
-
|
|
6
|
-
- shaka-player-demo: Our hosted demo on https://shaka-player-demo.appspot.com/
|
|
7
|
-
|
|
8
|
-
- demo-version-index: An index of Shaka Player releases and demos, hosted at
|
|
9
|
-
https://index-dot-shaka-player-demo.appspot.com/
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Google App Engine Version Index
|
|
2
|
-
|
|
3
|
-
This folder contains everything necessary to host an index of Shaka Player
|
|
4
|
-
releases and demos at https://index-dot-shaka-player-demo.appspot.com/
|
|
5
|
-
|
|
6
|
-
- app.yaml: App Engine config file. Defines the runtime (Python 3).
|
|
7
|
-
|
|
8
|
-
- generate.py: A python script that generates the index's static content from
|
|
9
|
-
a template.
|
|
10
|
-
|
|
11
|
-
- requirements.txt: Used by App Engine to install the necessary Python server
|
|
12
|
-
requirements (Flask).
|
|
13
|
-
|
|
14
|
-
- templates/index.html: A Jinja2 template used to generate the index HTML.
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# Copyright 2022 Google LLC
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
runtime: python39
|
|
16
|
-
default_expiration: 1h
|
|
17
|
-
|
|
18
|
-
handlers:
|
|
19
|
-
# Server static/index.html as the root.
|
|
20
|
-
- url: /
|
|
21
|
-
secure: always
|
|
22
|
-
static_files: static/index.html
|
|
23
|
-
upload: static/index.html
|
|
24
|
-
# Any other requests are served from the static/ folder.
|
|
25
|
-
- url: /(.+)
|
|
26
|
-
secure: always
|
|
27
|
-
static_files: static/\1
|
|
28
|
-
upload: static/.+
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
# Shaka Player Version Index Generator
|
|
4
|
-
# Copyright 2022 Google LLC
|
|
5
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
-
|
|
7
|
-
# Generate an index of Shaka Player versions on appspot.
|
|
8
|
-
|
|
9
|
-
import collections
|
|
10
|
-
import jinja2
|
|
11
|
-
import os
|
|
12
|
-
import re
|
|
13
|
-
import subprocess
|
|
14
|
-
|
|
15
|
-
DEMO_URL_TEMPLATE = 'https://{0}-dot-shaka-player-demo.appspot.com/'
|
|
16
|
-
|
|
17
|
-
# In Google Hosted Libraries
|
|
18
|
-
HOSTED_URL_TEMPLATE = 'https://ajax.googleapis.com/ajax/libs/shaka-player/{0}/shaka-player.{1}'
|
|
19
|
-
|
|
20
|
-
# Before Google Hosted Libraries, v1 appspot URLs
|
|
21
|
-
V1_URL_TEMPLATE = 'https://{0}-dot-shaka-player-demo.appspot.com/shaka-player.{1}'
|
|
22
|
-
# Before Google Hosted Libraries, v2 appspot URLs
|
|
23
|
-
V2_URL_TEMPLATE = 'https://{0}-dot-shaka-player-demo.appspot.com/dist/shaka-player.{1}'
|
|
24
|
-
|
|
25
|
-
def version_to_demo_url(v):
|
|
26
|
-
return DEMO_URL_TEMPLATE.format(v.replace('.', '-'))
|
|
27
|
-
|
|
28
|
-
def version_to_lib_url(v):
|
|
29
|
-
if v == 'nightly':
|
|
30
|
-
return V2_URL_TEMPLATE.format(v, 'compiled.js')
|
|
31
|
-
elif (version_key(v) == version_key('v1.6.5') or
|
|
32
|
-
version_key(v) >= version_key('v2.0.6')):
|
|
33
|
-
return HOSTED_URL_TEMPLATE.format(v.replace('v', ''), 'compiled.js')
|
|
34
|
-
elif version_key(v) >= version_key('v2.0.0-beta'):
|
|
35
|
-
return V2_URL_TEMPLATE.format(v.replace('.', '-'), 'compiled.js')
|
|
36
|
-
else:
|
|
37
|
-
return V1_URL_TEMPLATE.format(v.replace('.', '-'), 'compiled.js')
|
|
38
|
-
|
|
39
|
-
def version_to_ui_lib_url(v):
|
|
40
|
-
if v == 'nightly':
|
|
41
|
-
return V2_URL_TEMPLATE.format(v, 'ui.js')
|
|
42
|
-
elif version_key(v) >= version_key('v2.5.0'):
|
|
43
|
-
return HOSTED_URL_TEMPLATE.format(v.replace('v', ''), 'ui.js')
|
|
44
|
-
else:
|
|
45
|
-
return None
|
|
46
|
-
|
|
47
|
-
def version_to_lib_externs_url(v):
|
|
48
|
-
if v == 'nightly':
|
|
49
|
-
return V2_URL_TEMPLATE.format(v, 'compiled.externs.js')
|
|
50
|
-
elif version_key(v) >= version_key('v2.0.6'):
|
|
51
|
-
return HOSTED_URL_TEMPLATE.format(v.replace('v', ''), 'compiled.externs.js')
|
|
52
|
-
else:
|
|
53
|
-
return None
|
|
54
|
-
|
|
55
|
-
def version_to_ui_lib_externs_url(v):
|
|
56
|
-
if v == 'nightly':
|
|
57
|
-
return V2_URL_TEMPLATE.format(v, 'ui.externs.js')
|
|
58
|
-
elif version_key(v) >= version_key('v2.5.0'):
|
|
59
|
-
return HOSTED_URL_TEMPLATE.format(v.replace('v', ''), 'ui.externs.js')
|
|
60
|
-
else:
|
|
61
|
-
return None
|
|
62
|
-
|
|
63
|
-
def version_to_lib_defs_url(v):
|
|
64
|
-
if v == 'nightly':
|
|
65
|
-
return V2_URL_TEMPLATE.format(v, 'compiled.d.ts')
|
|
66
|
-
elif version_key(v) >= version_key('v3.0.6'):
|
|
67
|
-
return HOSTED_URL_TEMPLATE.format(v.replace('v', ''), 'compiled.d.ts')
|
|
68
|
-
else:
|
|
69
|
-
return None
|
|
70
|
-
|
|
71
|
-
def version_to_ui_lib_defs_url(v):
|
|
72
|
-
if v == 'nightly':
|
|
73
|
-
return V2_URL_TEMPLATE.format(v, 'ui.d.ts')
|
|
74
|
-
elif version_key(v) >= version_key('v3.0.6'):
|
|
75
|
-
return HOSTED_URL_TEMPLATE.format(v.replace('v', ''), 'ui.d.ts')
|
|
76
|
-
else:
|
|
77
|
-
return None
|
|
78
|
-
|
|
79
|
-
def version_to_metadata(v):
|
|
80
|
-
return {
|
|
81
|
-
'version': v,
|
|
82
|
-
'best': False, # Corrected later in another loop
|
|
83
|
-
'demo': version_to_demo_url(v),
|
|
84
|
-
'lib': version_to_lib_url(v),
|
|
85
|
-
'ui_lib': version_to_ui_lib_url(v),
|
|
86
|
-
'lib_externs': version_to_lib_externs_url(v),
|
|
87
|
-
'ui_lib_externs': version_to_ui_lib_externs_url(v),
|
|
88
|
-
'lib_defs': version_to_lib_defs_url(v),
|
|
89
|
-
'ui_lib_defs': version_to_ui_lib_defs_url(v),
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
def is_release_tag(name):
|
|
93
|
-
matches = re.match(r'v\d+\.\d+\.\d+(-.+)?', name)
|
|
94
|
-
# Doesn't match, not a version tag.
|
|
95
|
-
if not matches:
|
|
96
|
-
return False
|
|
97
|
-
# A "master" (old) or "main" (new) tag, indicating the state of the main
|
|
98
|
-
# branch at the time of a release. Not an actual version in itself, though.
|
|
99
|
-
if matches.group(1) == '-master' or matches.group(1) == '-main':
|
|
100
|
-
return False
|
|
101
|
-
# For historical reasons, these oldest few tags are not currently deployed to
|
|
102
|
-
# appengine. All other matching tags are, though.
|
|
103
|
-
if name in ['v1.2.0', 'v1.2.1', 'v1.2.2', 'v1.2.3']:
|
|
104
|
-
return False
|
|
105
|
-
return True
|
|
106
|
-
|
|
107
|
-
def version_key(version):
|
|
108
|
-
if version == 'nightly':
|
|
109
|
-
# A false version number for nightly, greater than any actual release
|
|
110
|
-
# version.
|
|
111
|
-
return [float('inf')]
|
|
112
|
-
|
|
113
|
-
assert version[0] == 'v'
|
|
114
|
-
main_version, _, suffix = version[1:].partition('-')
|
|
115
|
-
if not suffix:
|
|
116
|
-
suffix = '}}}' # this puts main releases after prerelease versions
|
|
117
|
-
version_tuple = [int(x) for x in main_version.split('.')]
|
|
118
|
-
return version_tuple + [suffix]
|
|
119
|
-
|
|
120
|
-
def get_release_tags():
|
|
121
|
-
output = subprocess.check_output(['git', 'tag'], text=True)
|
|
122
|
-
return list(filter(is_release_tag, output.split('\n')))
|
|
123
|
-
|
|
124
|
-
def generate():
|
|
125
|
-
# Get all release tags.
|
|
126
|
-
versions = get_release_tags()
|
|
127
|
-
# Now sort, putting prerelease versions ahead of the corresponding release.
|
|
128
|
-
versions.sort(key=version_key)
|
|
129
|
-
|
|
130
|
-
version_metadata = collections.OrderedDict()
|
|
131
|
-
latest_by_branch = {}
|
|
132
|
-
for v in versions:
|
|
133
|
-
version_metadata[v] = version_to_metadata(v)
|
|
134
|
-
|
|
135
|
-
# Because |versions| is already sorted, we can just overwrite the entry
|
|
136
|
-
# in the latest_by_branch dictionary.
|
|
137
|
-
branch_key = tuple(version_key(v)[0:2])
|
|
138
|
-
latest_by_branch[branch_key] = v
|
|
139
|
-
|
|
140
|
-
for v in latest_by_branch.values():
|
|
141
|
-
version_metadata[v]['best'] = True
|
|
142
|
-
|
|
143
|
-
# Append nightly rather than filter for it, so that it always appears at the
|
|
144
|
-
# end of the list.
|
|
145
|
-
version_metadata['nightly'] = version_to_metadata('nightly')
|
|
146
|
-
version_metadata['nightly']['best'] = True
|
|
147
|
-
|
|
148
|
-
# Debug: uncomment to see a list of version metadata objects.
|
|
149
|
-
#for i in version_metadata.values(): print(i)
|
|
150
|
-
|
|
151
|
-
script_path = os.path.dirname(__file__)
|
|
152
|
-
template_path = os.path.join(script_path, 'templates', 'index.html')
|
|
153
|
-
output_path = os.path.join(script_path, 'static', 'index.html')
|
|
154
|
-
|
|
155
|
-
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
156
|
-
|
|
157
|
-
with open(template_path, 'r') as template_file:
|
|
158
|
-
with open(output_path, 'w') as output_file:
|
|
159
|
-
template = jinja2.Template(template_file.read())
|
|
160
|
-
output = template.render(versions=version_metadata.values())
|
|
161
|
-
output_file.write(output)
|
|
162
|
-
|
|
163
|
-
if __name__ == '__main__':
|
|
164
|
-
generate()
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# Shaka Player Version Index - Appspot Entrypoint
|
|
2
|
-
# Copyright 2022 Google LLC
|
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
|
|
5
|
-
# In the App Engine Python 3 runtime, you must have an entrypoint, even if all
|
|
6
|
-
# content is static and no routes are defined. This seems pretty weird, and
|
|
7
|
-
# wasn't required in the Python 2 runtime.
|
|
8
|
-
|
|
9
|
-
from flask import Flask
|
|
10
|
-
|
|
11
|
-
app = Flask(__name__)
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>Shaka Player Demo - Version Index</title>
|
|
5
|
-
<style>
|
|
6
|
-
|
|
7
|
-
#background {
|
|
8
|
-
top: 0;
|
|
9
|
-
left: 0;
|
|
10
|
-
bottom: 0;
|
|
11
|
-
right: 0;
|
|
12
|
-
position: fixed;
|
|
13
|
-
z-index: -1;
|
|
14
|
-
|
|
15
|
-
background:
|
|
16
|
-
url(https://shaka-player-demo.appspot.com/assets/poster.jpg)
|
|
17
|
-
no-repeat center center fixed;
|
|
18
|
-
background-size: contain;
|
|
19
|
-
|
|
20
|
-
opacity: 0.4;
|
|
21
|
-
filter: sepia(50%);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
#links {
|
|
25
|
-
margin: 20px;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
#links a {
|
|
29
|
-
margin: 0.5em;
|
|
30
|
-
padding: 0.5em;
|
|
31
|
-
|
|
32
|
-
border: 2px solid black;
|
|
33
|
-
background-color: #006;
|
|
34
|
-
|
|
35
|
-
font-size: 110%;
|
|
36
|
-
color: white;
|
|
37
|
-
font-weight: bold;
|
|
38
|
-
text-decoration: none;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
table.best tr.old {
|
|
42
|
-
display: none;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
th, td {
|
|
46
|
-
border: 1px solid black;
|
|
47
|
-
padding: 0.2em 2em;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
table.best tr.best-even,
|
|
51
|
-
table.all tr:nth-child(2n) {
|
|
52
|
-
background-color: rgba(0,0,0,0.1);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
</style>
|
|
56
|
-
<script>
|
|
57
|
-
function display(which) {
|
|
58
|
-
table.class = 'which';
|
|
59
|
-
}
|
|
60
|
-
</script>
|
|
61
|
-
</head>
|
|
62
|
-
<body>
|
|
63
|
-
<div id="background"></div>
|
|
64
|
-
|
|
65
|
-
<h1>Shaka Player release demos on appspot</h1>
|
|
66
|
-
|
|
67
|
-
<div id="links">
|
|
68
|
-
<a href="#" onclick="table.className = 'best'">Best versions</a>
|
|
69
|
-
<a href="#" onclick="table.className = 'all'">All versions</a>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<table id="table" class="best">
|
|
73
|
-
<tr><th>Version</th></tr>
|
|
74
|
-
{% set best_counter = 0 %}
|
|
75
|
-
{% for v in versions %}
|
|
76
|
-
{% if v.best %}
|
|
77
|
-
<tr class="best {{'best-even' if best_counter % 2 == 0 else ''}}">
|
|
78
|
-
{% set best_counter = best_counter + 1 %}
|
|
79
|
-
{% else %}
|
|
80
|
-
<tr class="old">
|
|
81
|
-
{% endif %}
|
|
82
|
-
<th>{{ v.version }}</th>
|
|
83
|
-
<td><a href="{{ v.demo }}">demo</a></td>
|
|
84
|
-
<td><a href="{{ v.lib }}">non-UI library</a></td>
|
|
85
|
-
<td>
|
|
86
|
-
{% if v.ui_lib %}
|
|
87
|
-
<a href="{{ v.ui_lib }}">UI-enabled library</a>
|
|
88
|
-
{% endif %}
|
|
89
|
-
</td>
|
|
90
|
-
<td>
|
|
91
|
-
{% if v.lib_externs %}
|
|
92
|
-
<a href="{{ v.lib_externs }}">non-UI externs</a>
|
|
93
|
-
{% endif %}
|
|
94
|
-
</td>
|
|
95
|
-
<td>
|
|
96
|
-
{% if v.ui_lib_externs %}
|
|
97
|
-
<a href="{{ v.ui_lib_externs }}">UI-enabled externs</a>
|
|
98
|
-
{% endif %}
|
|
99
|
-
</td>
|
|
100
|
-
<td>
|
|
101
|
-
{% if v.lib_defs %}
|
|
102
|
-
<a href="{{ v.lib_defs }}">non-UI typescript defs</a>
|
|
103
|
-
{% endif %}
|
|
104
|
-
</td>
|
|
105
|
-
<td>
|
|
106
|
-
{% if v.ui_lib_defs %}
|
|
107
|
-
<a href="{{ v.ui_lib_defs }}">UI-enabled typescript defs</a>
|
|
108
|
-
{% endif %}
|
|
109
|
-
</td>
|
|
110
|
-
</tr>
|
|
111
|
-
{% endfor %}
|
|
112
|
-
</table>
|
|
113
|
-
</body>
|
|
114
|
-
</html>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# Google App Engine Demo
|
|
2
|
-
|
|
3
|
-
This folder contains everything necessary to host our demo on
|
|
4
|
-
https://shaka-player-demo.appspot.com/
|
|
5
|
-
|
|
6
|
-
- app.yaml: App Engine config file. Defines cache expiration and how specific
|
|
7
|
-
URLs are mapped to specific files.
|
|
8
|
-
|
|
9
|
-
- main.py: A catch-all python service to serve any non-static files. This
|
|
10
|
-
handles HTTP redirects for the root path (this is the only way to
|
|
11
|
-
do HTTP redirects in App Engine) and the poster service (which
|
|
12
|
-
returns special poster images on certain days).
|
|
13
|
-
|
|
14
|
-
- requirements.txt: Used by App Engine to install the necessary Python server
|
|
15
|
-
requirements (Flask).
|
|
16
|
-
|
|
17
|
-
- time.txt: A static file used for time sync in the client. Configured with
|
|
18
|
-
special response headers for cross-origin access.
|