shaka-player 3.1.4 → 3.3.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/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/.github/ISSUE_TEMPLATE/question.md +1 -1
- package/AUTHORS +6 -5
- package/CHANGELOG.md +363 -0
- package/CONTRIBUTORS +4 -2
- package/README.md +4 -4
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +2 -0
- package/build/types/ui +2 -0
- package/demo/common/asset.js +9 -7
- package/demo/common/assets.js +28 -1
- package/demo/common/message_ids.js +15 -2
- package/demo/config.js +35 -2
- package/demo/index.html +1 -1
- package/demo/locales/en.json +14 -1
- package/demo/locales/source.json +56 -4
- package/demo/main.js +2 -1
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +24 -21
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +24 -21
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +33 -25
- package/dist/locales.js +31 -29
- package/dist/receiver.compiled.debug.js +14 -12
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +14 -12
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.externs.js +1005 -695
- package/dist/shaka-player.compiled.debug.js +720 -640
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1005 -695
- package/dist/shaka-player.compiled.js +850 -817
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +274 -21
- package/dist/shaka-player.ui.debug.d.ts +274 -21
- package/dist/shaka-player.ui.debug.externs.js +766 -429
- package/dist/shaka-player.ui.debug.js +863 -765
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +766 -429
- package/dist/shaka-player.ui.js +1042 -996
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/bg-fetch-after.gv +29 -0
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +18 -0
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +134 -0
- package/docs/tutorials/blob-url.md +15 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/aria.js +6 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +29 -1
- package/externs/shaka/manifest.js +18 -2
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +36 -2
- package/externs/shaka/player.js +182 -13
- package/externs/shaka/text.js +24 -10
- package/externs/texttrack.js +3 -0
- package/externs/webcrypto.js +18 -0
- package/lib/abr/ewma.js +14 -0
- package/lib/abr/ewma_bandwidth_estimator.js +16 -2
- package/lib/abr/simple_abr_manager.js +6 -0
- package/lib/ads/ad_manager.js +16 -15
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +14 -6
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +19 -2
- package/lib/cast/cast_proxy.js +8 -0
- package/lib/cast/cast_utils.js +7 -1
- package/lib/cea/cea608_data_channel.js +56 -56
- package/lib/cea/cea608_memory.js +33 -33
- package/lib/cea/cea708_service.js +43 -43
- package/lib/cea/cea708_window.js +38 -38
- package/lib/cea/cea_decoder.js +13 -14
- package/lib/cea/cea_utils.js +23 -23
- package/lib/cea/dtvcc_packet_builder.js +7 -7
- package/lib/cea/i_caption_decoder.js +2 -3
- package/lib/cea/i_cea_parser.js +2 -2
- package/lib/cea/mp4_cea_parser.js +6 -6
- package/lib/dash/dash_parser.js +53 -14
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +18 -9
- package/lib/dash/segment_template.js +23 -10
- package/lib/hls/hls_parser.js +210 -30
- package/lib/media/closed_caption_parser.js +1 -2
- package/lib/media/drm_engine.js +162 -192
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +9 -1
- package/lib/media/segment_reference.js +37 -5
- package/lib/media/streaming_engine.js +48 -10
- package/lib/net/http_fetch_plugin.js +31 -11
- package/lib/net/http_plugin_utils.js +1 -0
- package/lib/net/http_xhr_plugin.js +40 -14
- package/lib/net/networking_engine.js +82 -18
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +14 -7
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/manifest_converter.js +3 -1
- package/lib/offline/storage.js +404 -297
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +622 -153
- package/lib/polyfill/aria.js +82 -0
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/routing/walker.js +2 -3
- package/lib/text/cue.js +12 -0
- package/lib/text/srt_text_parser.js +4 -4
- package/lib/text/text_engine.js +2 -2
- package/lib/text/ttml_text_parser.js +25 -2
- package/lib/text/ui_text_displayer.js +2 -2
- package/lib/text/vtt_text_parser.js +2 -2
- package/lib/text/web_vtt_generator.js +55 -12
- package/lib/util/cmcd_manager.js +826 -0
- package/lib/util/error.js +12 -0
- package/lib/util/language_utils.js +12 -0
- package/lib/util/manifest_parser_utils.js +1 -0
- package/lib/util/mp4_box_parsers.js +20 -20
- package/lib/util/multi_map.js +8 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +98 -64
- package/lib/util/player_configuration.js +31 -1
- package/lib/util/stream_utils.js +140 -85
- package/lib/util/xml_utils.js +31 -12
- package/package.json +1 -1
- package/roadmap.md +24 -22
- package/shaka-player.uncompiled.js +4 -0
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/cea/cea608_memory_unit.js +1 -1
- package/test/cea/cea708_service_unit.js +8 -8
- package/test/cea/cea708_window_unit.js +6 -6
- package/test/cea/cea_decoder_unit.js +1 -1
- package/test/cea/dtvcc_packet_builder_unit.js +2 -2
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +101 -1
- package/test/dash/dash_parser_manifest_unit.js +78 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -1
- package/test/dash/dash_parser_segment_template_unit.js +2 -1
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +252 -0
- package/test/media/drm_engine_integration.js +86 -12
- package/test/media/drm_engine_unit.js +310 -450
- package/test/media/quality_observer_unit.js +139 -0
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +2 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/manifest_convert_unit.js +2 -0
- package/test/offline/storage_integration.js +117 -23
- package/test/player_integration.js +151 -0
- package/test/player_src_equals_integration.js +52 -0
- package/test/player_unit.js +11 -33
- package/test/test/assets/chapters.srt +11 -0
- package/test/test/assets/chapters.vtt +10 -0
- package/test/test/util/cea_utils.js +12 -12
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_ad_manager.js +7 -0
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +5 -2
- package/test/test/util/manifest_parser_util.js +3 -1
- package/test/test/util/test_scheme.js +14 -1
- package/test/text/ttml_text_parser_unit.js +47 -0
- package/test/text/web_vtt_generator_unit.js +81 -7
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +277 -0
- package/test/util/stream_utils_unit.js +118 -10
- package/ui/airplay_button.js +2 -1
- package/ui/audio_language_selection.js +9 -5
- package/ui/cast_button.js +5 -6
- package/ui/constants.js +0 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +41 -7
- package/ui/controls.less +1 -0
- package/ui/enums.js +4 -0
- package/ui/externs/ui.js +28 -1
- package/ui/fast_forward_button.js +16 -8
- package/ui/fullscreen_button.js +2 -3
- package/ui/language_utils.js +1 -1
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +74 -0
- package/ui/less/overflow_menu.less +0 -10
- package/ui/less/tooltip.less +97 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/loop_button.js +6 -3
- package/ui/mute_button.js +3 -4
- package/ui/overflow_menu.js +7 -28
- package/ui/pip_button.js +10 -7
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +11 -15
- package/ui/presentation_time.js +1 -3
- package/ui/resolution_selection.js +11 -7
- package/ui/rewind_button.js +17 -9
- package/ui/seek_bar.js +6 -6
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/spacer.js +1 -1
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +19 -15
- package/ui/ui.js +30 -0
- package/ui/ui_utils.js +1 -1
- package/ui/volume_bar.js +2 -4
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
goog.provide('shaka.polyfill.Aria');
|
|
8
|
+
|
|
9
|
+
goog.require('shaka.log');
|
|
10
|
+
goog.require('shaka.polyfill');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @summary A polyfill to add support for the ARIAMixin interface mixin, for
|
|
14
|
+
* browsers that do not implement it (e.g. Firefox).
|
|
15
|
+
* Note that IE also does not support ARIAMixin, but this polyfill does not work
|
|
16
|
+
* for that platform, as it relies on getters and setters.
|
|
17
|
+
* @see https://w3c.github.io/aria/#ARIAMixin
|
|
18
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element
|
|
19
|
+
* @export
|
|
20
|
+
*/
|
|
21
|
+
shaka.polyfill.Aria = class {
|
|
22
|
+
/**
|
|
23
|
+
* Install the polyfill if needed.
|
|
24
|
+
* @export
|
|
25
|
+
*/
|
|
26
|
+
static install() {
|
|
27
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
28
|
+
if (Object.getOwnPropertyDescriptor(Element.prototype, 'ariaHidden')) {
|
|
29
|
+
shaka.log.info('Using native ARIAMixin interface.');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
shaka.log.info('ARIAMixin interface not detected. Installing polyfill.');
|
|
33
|
+
|
|
34
|
+
// Define a list of all of the ARIAMixin properties that we have externs
|
|
35
|
+
// for.
|
|
36
|
+
const attributes = [
|
|
37
|
+
'ariaHidden',
|
|
38
|
+
'ariaLabel',
|
|
39
|
+
'ariaPressed',
|
|
40
|
+
'ariaSelected',
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// Add each attribute, one by one.
|
|
44
|
+
for (const attribute of attributes) {
|
|
45
|
+
shaka.polyfill.Aria.addARIAMixinAttribute_(attribute);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Adds an attribute with the given name.
|
|
51
|
+
* @param {string} name The name of the attribute, in camelCase.
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
static addARIAMixinAttribute_(name) {
|
|
55
|
+
const baseName = name.toLowerCase().replace(/^aria/, '');
|
|
56
|
+
// NOTE: All the attributes listed in the method above begin with "aria".
|
|
57
|
+
// However, to add extra protection against the possibility of XSS attacks
|
|
58
|
+
// through this method, this enforces "aria-" at the beginning of the
|
|
59
|
+
// snake-case name, even if somehow "aria" were missing from the input.
|
|
60
|
+
const snakeCaseName = `aria-${baseName}`;
|
|
61
|
+
|
|
62
|
+
/* eslint-disable no-restricted-syntax */
|
|
63
|
+
Object.defineProperty(Element.prototype, name, {
|
|
64
|
+
get() {
|
|
65
|
+
const element = /** @type {!Element} */ (this);
|
|
66
|
+
return element.getAttribute(snakeCaseName);
|
|
67
|
+
},
|
|
68
|
+
set(value) {
|
|
69
|
+
const element = /** @type {!Element} */ (this);
|
|
70
|
+
if (value == null || value == undefined) {
|
|
71
|
+
element.removeAttribute(snakeCaseName);
|
|
72
|
+
} else {
|
|
73
|
+
element.setAttribute(snakeCaseName, value);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
/* eslint-enable no-restricted-syntax */
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
shaka.polyfill.register(shaka.polyfill.Aria.install);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
goog.provide('shaka.polyfill.RandomUUID');
|
|
7
|
+
|
|
8
|
+
goog.require('shaka.log');
|
|
9
|
+
goog.require('shaka.polyfill');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @summary A polyfill to provide window.crypto.randomUUID in all browsers.
|
|
13
|
+
* @export
|
|
14
|
+
*/
|
|
15
|
+
shaka.polyfill.RandomUUID = class {
|
|
16
|
+
/**
|
|
17
|
+
* Install the polyfill if needed.
|
|
18
|
+
* @export
|
|
19
|
+
*/
|
|
20
|
+
static install() {
|
|
21
|
+
shaka.log.debug('randomUUID.install');
|
|
22
|
+
|
|
23
|
+
if (!window.crypto) {
|
|
24
|
+
// See: https://caniuse.com/cryptography
|
|
25
|
+
shaka.log.debug(
|
|
26
|
+
'window.crypto must be available to install randomUUID polyfill.');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if ('randomUUID' in window.crypto) {
|
|
31
|
+
shaka.log.debug(
|
|
32
|
+
'RandomUUID: Native window.crypto.randomUUID() support found.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
window.crypto.randomUUID = shaka.polyfill.RandomUUID.randomUUID_;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @return {string}
|
|
41
|
+
* @private
|
|
42
|
+
*/
|
|
43
|
+
static randomUUID_() {
|
|
44
|
+
const url = URL.createObjectURL(new Blob());
|
|
45
|
+
const uuid = url.toString();
|
|
46
|
+
URL.revokeObjectURL(url);
|
|
47
|
+
return uuid.substr(uuid.lastIndexOf('/') + 1);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
shaka.polyfill.register(shaka.polyfill.RandomUUID.install);
|
package/lib/routing/walker.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.routing.Walker');
|
|
8
|
-
goog.provide('shaka.routing.Walker.Implementation');
|
|
9
8
|
|
|
10
9
|
goog.require('goog.asserts');
|
|
11
10
|
goog.require('shaka.routing.Node');
|
|
@@ -81,7 +80,7 @@ shaka.routing.Walker = class {
|
|
|
81
80
|
* new work is added (and this is not null) it can be resolved. The only
|
|
82
81
|
* time when this should be non-null is when we are waiting for more work.
|
|
83
82
|
*
|
|
84
|
-
* @private {shaka.util.PublicPromise}
|
|
83
|
+
* @private {?shaka.util.PublicPromise}
|
|
85
84
|
*/
|
|
86
85
|
this.waitForWork_ = null;
|
|
87
86
|
|
|
@@ -91,7 +90,7 @@ shaka.routing.Walker = class {
|
|
|
91
90
|
/** @private {?shaka.routing.Walker.ActiveRoute_} */
|
|
92
91
|
this.currentRoute_ = null;
|
|
93
92
|
|
|
94
|
-
/** @private {shaka.util.AbortableOperation} */
|
|
93
|
+
/** @private {?shaka.util.AbortableOperation} */
|
|
95
94
|
this.currentStep_ = null;
|
|
96
95
|
|
|
97
96
|
/**
|
package/lib/text/cue.js
CHANGED
|
@@ -144,6 +144,18 @@ shaka.text.Cue = class {
|
|
|
144
144
|
*/
|
|
145
145
|
this.border = '';
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* @override
|
|
149
|
+
* @exportInterface
|
|
150
|
+
*/
|
|
151
|
+
this.textStrokeColor = '';
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* @override
|
|
155
|
+
* @exportInterface
|
|
156
|
+
*/
|
|
157
|
+
this.textStrokeWidth = '';
|
|
158
|
+
|
|
147
159
|
/**
|
|
148
160
|
* @override
|
|
149
161
|
* @exportInterface
|
|
@@ -57,8 +57,8 @@ shaka.text.SrtTextParser = class {
|
|
|
57
57
|
/**
|
|
58
58
|
* Convert a SRT format to WebVTT
|
|
59
59
|
*
|
|
60
|
-
* @param {
|
|
61
|
-
* @return {
|
|
60
|
+
* @param {string} data
|
|
61
|
+
* @return {string}
|
|
62
62
|
* @export
|
|
63
63
|
*/
|
|
64
64
|
static srt2webvtt(data) {
|
|
@@ -87,8 +87,8 @@ shaka.text.SrtTextParser = class {
|
|
|
87
87
|
/**
|
|
88
88
|
* Convert a SRT cue into WebVTT cue
|
|
89
89
|
*
|
|
90
|
-
* @param {
|
|
91
|
-
* @return {
|
|
90
|
+
* @param {string} caption
|
|
91
|
+
* @return {string}
|
|
92
92
|
* @private
|
|
93
93
|
*/
|
|
94
94
|
static convertSrtCue_(caption) {
|
package/lib/text/text_engine.js
CHANGED
|
@@ -12,7 +12,7 @@ goog.require('shaka.util.BufferUtils');
|
|
|
12
12
|
goog.require('shaka.util.Functional');
|
|
13
13
|
goog.require('shaka.util.IDestroyable');
|
|
14
14
|
goog.require('shaka.util.MimeUtils');
|
|
15
|
-
goog.requireType('shaka.cea.ICaptionDecoder
|
|
15
|
+
goog.requireType('shaka.cea.ICaptionDecoder');
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
// TODO: revisit this when Closure Compiler supports partially-exported classes.
|
|
@@ -24,7 +24,7 @@ goog.requireType('shaka.cea.ICaptionDecoder.ClosedCaption');
|
|
|
24
24
|
shaka.text.TextEngine = class {
|
|
25
25
|
/** @param {shaka.extern.TextDisplayer} displayer */
|
|
26
26
|
constructor(displayer) {
|
|
27
|
-
/** @private {shaka.extern.TextParser} */
|
|
27
|
+
/** @private {?shaka.extern.TextParser} */
|
|
28
28
|
this.parser_ = null;
|
|
29
29
|
|
|
30
30
|
/** @private {shaka.extern.TextDisplayer} */
|
|
@@ -531,7 +531,6 @@ shaka.text.TtmlTextParser = class {
|
|
|
531
531
|
|
|
532
532
|
const color = TtmlTextParser.getStyleAttribute_(
|
|
533
533
|
cueElement, region, styles, 'color', shouldInheritRegionStyles);
|
|
534
|
-
|
|
535
534
|
if (color) {
|
|
536
535
|
cue.color = color;
|
|
537
536
|
}
|
|
@@ -584,7 +583,6 @@ shaka.text.TtmlTextParser = class {
|
|
|
584
583
|
|
|
585
584
|
const fontSize = TtmlTextParser.getStyleAttribute_(
|
|
586
585
|
cueElement, region, styles, 'fontSize', shouldInheritRegionStyles);
|
|
587
|
-
|
|
588
586
|
if (fontSize) {
|
|
589
587
|
const isValidFontSizeUnit =
|
|
590
588
|
fontSize.match(TtmlTextParser.unitValues_) ||
|
|
@@ -622,6 +620,31 @@ shaka.text.TtmlTextParser = class {
|
|
|
622
620
|
}
|
|
623
621
|
}
|
|
624
622
|
|
|
623
|
+
const textOutline = TtmlTextParser.getStyleAttribute_(
|
|
624
|
+
cueElement, region, styles, 'textOutline', shouldInheritRegionStyles);
|
|
625
|
+
if (textOutline) {
|
|
626
|
+
// tts:textOutline isn't natively supported by browsers, but it can be
|
|
627
|
+
// mostly replicated using the non-standard -webkit-text-stroke-width and
|
|
628
|
+
// -webkit-text-stroke-color properties.
|
|
629
|
+
const split = textOutline.split(' ');
|
|
630
|
+
if (split[0].match(TtmlTextParser.unitValues_)) {
|
|
631
|
+
// There is no defined color, so default to the text color.
|
|
632
|
+
cue.textStrokeColor = cue.color;
|
|
633
|
+
} else {
|
|
634
|
+
cue.textStrokeColor = split[0];
|
|
635
|
+
split.shift();
|
|
636
|
+
}
|
|
637
|
+
if (split[0] && split[0].match(TtmlTextParser.unitValues_)) {
|
|
638
|
+
cue.textStrokeWidth = split[0];
|
|
639
|
+
} else {
|
|
640
|
+
// If there is no width, or the width is not a number, don't draw a
|
|
641
|
+
// border.
|
|
642
|
+
cue.textStrokeColor = '';
|
|
643
|
+
}
|
|
644
|
+
// There is an optional blur radius also, but we have no way of
|
|
645
|
+
// replicating that, so ignore it.
|
|
646
|
+
}
|
|
647
|
+
|
|
625
648
|
const letterSpacing = TtmlTextParser.getStyleAttribute_(
|
|
626
649
|
cueElement, region, styles, 'letterSpacing', shouldInheritRegionStyles);
|
|
627
650
|
if (letterSpacing && letterSpacing.match(TtmlTextParser.unitValues_)) {
|
|
@@ -403,8 +403,8 @@ shaka.text.UITextDisplayer = class {
|
|
|
403
403
|
return nonBreakingSpace.repeat(match.length);
|
|
404
404
|
});
|
|
405
405
|
|
|
406
|
-
style.
|
|
407
|
-
style.
|
|
406
|
+
style.webkitTextStrokeColor = cue.textStrokeColor;
|
|
407
|
+
style.webkitTextStrokeWidth = cue.textStrokeWidth;
|
|
408
408
|
style.color = cue.color;
|
|
409
409
|
style.direction = cue.direction;
|
|
410
410
|
style.opacity = cue.opacity;
|
|
@@ -464,8 +464,8 @@ shaka.text.VttTextParser = class {
|
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
/**
|
|
467
|
-
* @param {
|
|
468
|
-
* @param {
|
|
467
|
+
* @param {string} value
|
|
468
|
+
* @param {string} defaultValue
|
|
469
469
|
* @private
|
|
470
470
|
*/
|
|
471
471
|
static getOrDefault_(value, defaultValue) {
|
|
@@ -17,9 +17,10 @@ goog.require('shaka.text.Cue');
|
|
|
17
17
|
shaka.text.WebVttGenerator = class {
|
|
18
18
|
/**
|
|
19
19
|
* @param {!Array.<!shaka.text.Cue>} cues
|
|
20
|
+
* @param {!Array.<!shaka.extern.AdCuePoint>} adCuePoints
|
|
20
21
|
* @return {string}
|
|
21
22
|
*/
|
|
22
|
-
static convert(cues) {
|
|
23
|
+
static convert(cues, adCuePoints) {
|
|
23
24
|
// Flatten nested cue payloads recursively. If a cue has nested cues,
|
|
24
25
|
// their contents should be combined and replace the payload of the parent.
|
|
25
26
|
const flattenPayload = (cue) => {
|
|
@@ -64,6 +65,25 @@ shaka.text.WebVttGenerator = class {
|
|
|
64
65
|
}
|
|
65
66
|
};
|
|
66
67
|
|
|
68
|
+
const webvttTimeString = (time) => {
|
|
69
|
+
let newTime = time;
|
|
70
|
+
for (const adCuePoint of adCuePoints) {
|
|
71
|
+
if (adCuePoint.end && adCuePoint.start < time) {
|
|
72
|
+
const offset = adCuePoint.end - adCuePoint.start;
|
|
73
|
+
newTime += offset;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const hours = Math.floor(newTime / 3600);
|
|
77
|
+
const minutes = Math.floor(newTime / 60 % 60);
|
|
78
|
+
const seconds = Math.floor(newTime % 60);
|
|
79
|
+
const milliseconds = Math.floor(newTime * 1000 % 1000);
|
|
80
|
+
return (hours < 10 ? '0' : '') + hours + ':' +
|
|
81
|
+
(minutes < 10 ? '0' : '') + minutes + ':' +
|
|
82
|
+
(seconds < 10 ? '0' : '') + seconds + '.' +
|
|
83
|
+
(milliseconds < 100 ? (milliseconds < 10 ? '00' : '0') : '') +
|
|
84
|
+
milliseconds;
|
|
85
|
+
};
|
|
86
|
+
|
|
67
87
|
// We don't want to modify the array or objects passed in, since we don't
|
|
68
88
|
// technically own them. So we build a new array and replace certain items
|
|
69
89
|
// in it if they need to be flattened.
|
|
@@ -80,19 +100,42 @@ shaka.text.WebVttGenerator = class {
|
|
|
80
100
|
|
|
81
101
|
let webvttString = 'WEBVTT\n\n';
|
|
82
102
|
for (const cue of flattenedCues) {
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
(
|
|
92
|
-
|
|
103
|
+
const webvttSettings = (cue) => {
|
|
104
|
+
const settings = [];
|
|
105
|
+
const Cue = shaka.text.Cue;
|
|
106
|
+
switch (cue.textAlign) {
|
|
107
|
+
case Cue.textAlign.LEFT:
|
|
108
|
+
settings.push('align:left');
|
|
109
|
+
break;
|
|
110
|
+
case Cue.textAlign.RIGHT:
|
|
111
|
+
settings.push('align:right');
|
|
112
|
+
break;
|
|
113
|
+
case Cue.textAlign.CENTER:
|
|
114
|
+
settings.push('align:middle');
|
|
115
|
+
break;
|
|
116
|
+
case Cue.textAlign.START:
|
|
117
|
+
settings.push('align:start');
|
|
118
|
+
break;
|
|
119
|
+
case Cue.textAlign.END:
|
|
120
|
+
settings.push('align:end');
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
switch (cue.writingMode) {
|
|
124
|
+
case Cue.writingMode.VERTICAL_LEFT_TO_RIGHT:
|
|
125
|
+
settings.push('vertical:lr');
|
|
126
|
+
break;
|
|
127
|
+
case Cue.writingMode.VERTICAL_RIGHT_TO_LEFT:
|
|
128
|
+
settings.push('vertical:rl');
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (settings.length) {
|
|
133
|
+
return ' ' + settings.join(' ');
|
|
134
|
+
}
|
|
135
|
+
return '';
|
|
93
136
|
};
|
|
94
137
|
webvttString += webvttTimeString(cue.startTime) + ' --> ' +
|
|
95
|
-
webvttTimeString(cue.endTime) + '\n';
|
|
138
|
+
webvttTimeString(cue.endTime) + webvttSettings(cue) + '\n';
|
|
96
139
|
webvttString += cue.payload + '\n\n';
|
|
97
140
|
}
|
|
98
141
|
return webvttString;
|