senza-sdk 4.2.64-70c0747.0 → 4.2.65-4527e57.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/dist/bundle.js +1 -1
- package/dist/bundle.js.LICENSE.txt +4 -0
- package/package.json +9 -16
- package/src/{implementation/alarmManager.js → alarmManager.js} +52 -15
- package/src/api.js +350 -183
- package/src/{interface/devSequence.js → devSequence.js} +35 -0
- package/src/{implementation/deviceManager.js → deviceManager.js} +65 -4
- package/src/{implementation/lifecycle.js → lifecycle.js} +182 -5
- package/src/{implementation/messageManager.js → messageManager.js} +6 -6
- package/src/{implementation/platformManager.js → platformManager.js} +4 -5
- package/src/{implementation/remotePlayer.js → remotePlayer.js} +139 -7
- package/src/{implementation/senzaShakaPlayer.js → senzaShakaPlayer.js} +114 -25
- package/src/{implementation/utils.js → utils.js} +6 -15
- package/src/implementation/api.js +0 -367
- package/src/interface/alarmManager.js +0 -69
- package/src/interface/api.js +0 -8
- package/src/interface/deviceManager.js +0 -133
- package/src/interface/lifecycle.js +0 -278
- package/src/interface/messageManager.js +0 -46
- package/src/interface/platformManager.js +0 -35
- package/src/interface/remotePlayer.js +0 -441
- package/src/interface/senzaShakaPlayer.js +0 -171
- package/src/interface/utils.js +0 -45
- /package/src/{implementation/SessionInfo.js → SessionInfo.js} +0 -0
- /package/src/{implementation/devHelper.js → devHelper.js} +0 -0
- /package/src/{implementation/eventListenersManager.js → eventListenersManager.js} +0 -0
- /package/src/{implementation/subtitlesUtils.js → subtitlesUtils.js} +0 -0
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
import { noop } from "./utils";
|
|
2
|
-
export class RemotePlayerError extends Error {
|
|
3
|
-
constructor(code, message) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.code = code;
|
|
6
|
-
this.msg = message; // For backwards compatibility
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {Object} Config
|
|
12
|
-
* @property {string} preferredAudioLanguage
|
|
13
|
-
* @property {string} preferredSubtitlesLanguage
|
|
14
|
-
* @property {boolean} autoPlay - (Not implemented yet) upon loading start playing automatically
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* RemotePlayer a singleton class to communicate with remote player
|
|
19
|
-
* @class RemotePlayer
|
|
20
|
-
* @fires timeupdate
|
|
21
|
-
* @fires tracksupdate
|
|
22
|
-
* @fires ended
|
|
23
|
-
* @fires error
|
|
24
|
-
* @fires onloadmodechange
|
|
25
|
-
* @fires seeking (Not implemented yet)
|
|
26
|
-
* @fires seeked (Not implemented yet)
|
|
27
|
-
* @fires loadedmetadata (Not implemented yet)
|
|
28
|
-
* @fires canplay
|
|
29
|
-
* @fires license-request
|
|
30
|
-
*/
|
|
31
|
-
export class RemotePlayer extends EventTarget {
|
|
32
|
-
constructor() {
|
|
33
|
-
super();
|
|
34
|
-
this.LoadMode = Object.freeze({
|
|
35
|
-
NOT_LOADED: "notLoaded",
|
|
36
|
-
LOADING: "loading",
|
|
37
|
-
LOADED: "loaded",
|
|
38
|
-
UNLOADING: "unloading"
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @event RemotePlayer#canplay
|
|
43
|
-
* @description canplay event will be dispatched when the remote player can start play the event
|
|
44
|
-
* @example
|
|
45
|
-
* remotePlayer.addEventListener("canplay", () => {
|
|
46
|
-
* console.info("remotePlayer canplay");
|
|
47
|
-
* remotePlayer.play();
|
|
48
|
-
* });
|
|
49
|
-
*/
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @event RemotePlayer#loadedmetadata
|
|
53
|
-
* @description loadedmetadata event will be dispatched when the remote player metadata is loaded
|
|
54
|
-
* and the audio/video tracks are available
|
|
55
|
-
* @example
|
|
56
|
-
* remotePlayer.addEventListener("loadedmetadata", () => {
|
|
57
|
-
* console.info("remotePlayer loadedmetadata", remotePlayer.getAudioTracks(), remotePlayer.getTextTracks());
|
|
58
|
-
* });
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @event RemotePlayer#timeupdate
|
|
63
|
-
* @example
|
|
64
|
-
* remotePlayer.addEventListener("timeupdate", () => {
|
|
65
|
-
* console.info("remotePlayer timeupdate", remotePlayer.currentTime);
|
|
66
|
-
* localPlayer.getMediaElement().currentTime = remotePlayer.currentTime || 0;
|
|
67
|
-
* });
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @event RemotePlayer#tracksupdate
|
|
72
|
-
* @example
|
|
73
|
-
* remotePlayer.addEventListener("tracksupdate", () => {
|
|
74
|
-
* console.info("remotePlayer tracksupdate", remotePlayer.getAudioTracks(), remotePlayer.getTextTracks());
|
|
75
|
-
* });
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* @event RemotePlayer#ended
|
|
80
|
-
* @example
|
|
81
|
-
* remotePlayer.addEventListener("ended", () => {
|
|
82
|
-
* console.info("remotePlayer ended");
|
|
83
|
-
* });
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @event RemotePlayer#onloadmodechange
|
|
88
|
-
* @example
|
|
89
|
-
* remotePlayer.addEventListener("onloadmodechange", () => {
|
|
90
|
-
* console.info("remotePlayer load mode changed to", remotePlayer.getLoadMode());
|
|
91
|
-
* });
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* @event RemotePlayer#error
|
|
96
|
-
* @type {object}
|
|
97
|
-
* @property {int} detail.errorCode
|
|
98
|
-
* @property {string} detail.message
|
|
99
|
-
*
|
|
100
|
-
* @see Possible error codes:
|
|
101
|
-
*
|
|
102
|
-
* | Code | Domain | Description |
|
|
103
|
-
* | :-------- | :---------------- | :-----------------------------------------------------------------------------------------------|
|
|
104
|
-
* | 23 | Player | load() failed due to remote player initialization error |
|
|
105
|
-
* | 98 | Player | load() failed due to remote player failure to send message to the client |
|
|
106
|
-
* | 99 | Player | load() failed due to remote player reporting invalid message |
|
|
107
|
-
* | 1000 | Encrypted content | Failed to create or initialise the CDM |
|
|
108
|
-
* | 1001 | Encrypted content | Failed to create a CDM session |
|
|
109
|
-
* | 1002 | Encrypted content | CDM failed to generate a license request |
|
|
110
|
-
* | 1003 | Encrypted content | The CDM rejected the license server response |
|
|
111
|
-
* | 1004 | Encrypted content | The CDM rejected the license server certificate |
|
|
112
|
-
* | 1005 | Encrypted content | All keys in the license have expired |
|
|
113
|
-
* | 1006 | Encrypted content | Output device is incompatible with the license requirements (HDCP) |
|
|
114
|
-
* | 1007 | Encrypted content | The device has been revoked |
|
|
115
|
-
* | 1008 | Encrypted content | The device secrets aren't available |
|
|
116
|
-
* | 1009 | Encrypted content | Keys are loaded but the KID requested by playback isn't found. The app has likely issued a license for the wrong content or there is a mismatch between the KIDs in the license and the data plane |
|
|
117
|
-
* | 1010 | Encrypted content | The CDM failed to provision, therefore it is not possible to play encrypted content |
|
|
118
|
-
* | 1100 | Encrypted content | The CDM session has already received a license response. The app has likely issued 2, or more, license responses for the same request. The subsequent licenses will be ignored so this error is informational only |
|
|
119
|
-
* | 1101 | Encrypted content | The license has been rejected since an error was received by the CDM. The app has likely sent a non-200 code to `WriteLicenseResponse` |
|
|
120
|
-
* | 1102 | Encrypted content | A license response wasn't received from the app within a pre-defined timeout |
|
|
121
|
-
* | 1103 | Encrypted content | The CDM session associated with this license response is in an invalid state. This is an internal Senza platform error |
|
|
122
|
-
* | 1104 | Encrypted content | The CDM failed to send a license request to the app. This is an internal Senza platform error |
|
|
123
|
-
* | 1999 | Encrypted content | An unknown encrypted content error |
|
|
124
|
-
* | 2000 | Player | Content makes reference to no or unsupported key system |
|
|
125
|
-
* | 3000 | Player | Unexpected problem with playback, only used if no more specific code in 3xxx range applies |
|
|
126
|
-
* | 3001 | Player | Problem accessing content manifest, only used if no more specific code in 8xxx range applies |
|
|
127
|
-
* | 3002 | Player | Unexpectedly stopped playback |
|
|
128
|
-
* | 3100 | Player | Problem parsing MP4 content |
|
|
129
|
-
* | 3200 | Player | Problem with decoder |
|
|
130
|
-
* | 3300 | Player | DRM keys unavailable, player waited for keys but none arrived |
|
|
131
|
-
* | 3400 | Player | Problem accessing segments, only used if no more specific code in 34xx range applies |
|
|
132
|
-
* | 3401 | Player | Problem accessing segments, connection issue or timeout |
|
|
133
|
-
* | 3402 | Player | Problem accessing segments, server returned HTTP error code |
|
|
134
|
-
* | 3403 | Player | Problem accessing segments, server authentication issue |
|
|
135
|
-
* | 3404 | Player | Problem accessing segments, server returned not found |
|
|
136
|
-
* | 3900-3999 | Player | Internal player error |
|
|
137
|
-
* | 6000 | Player | The remote player api call has reached the configurable timeout with no response from the remote player |
|
|
138
|
-
* | 6001 | Player | play() was called while the remote player is not loaded |
|
|
139
|
-
* | 6002 | Player | load() was called while the application was in state 'background' or 'inTransitionToBackground' |
|
|
140
|
-
* | 6500 | Player | remotePlayer api was called before initializing remotePlayer |
|
|
141
|
-
* | 6501 | Player | load() was called while previous load/unload was still in progress |
|
|
142
|
-
* | 6502 | Player | unload() was called while previous unload/load was still in progress |
|
|
143
|
-
* | 8001 | Player | Error pulling manifest. bad parameters |
|
|
144
|
-
* | 8002 | Player | Error pulling manifest. filters returned no data |
|
|
145
|
-
* | 8003 | Player | Error pulling manifest. fetch error |
|
|
146
|
-
* | 8004 | Player | Error pulling manifest. parse error |
|
|
147
|
-
* | 8005 | Player | Error pulling manifest. stale manifest detected |
|
|
148
|
-
* | 8006 | Player | Error updating manifest. internal cache error |
|
|
149
|
-
* | 8007 | Player | Error updating manifest. internal error during backoff |
|
|
150
|
-
* | 8008 | Player | Error pulling manifest. sidx parsing error |
|
|
151
|
-
* | 8009 | Player | Error pulling manifest. internal error |
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
* remotePlayer.addEventListener("error", (event) => {
|
|
155
|
-
* console.error("received remotePlayer error:", event.detail.errorCode, event.detail.message);
|
|
156
|
-
* });
|
|
157
|
-
*/
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @event RemotePlayer#license-request
|
|
161
|
-
* @description Fired whenever the platform requires a license to play encrypted content.
|
|
162
|
-
* The Web App is responsible for passing the (opaque) license request blob to the license server and passing the (opaque) license server response to the CDM by calling the `writeLicenseResponse` method on the event.
|
|
163
|
-
* @type {LicenseRequestEvent}
|
|
164
|
-
* @property {object} detail - Object containing ievent data
|
|
165
|
-
* @property {string} detail.licenseRequest - Base64 coded opaque license request. The app is responsible for decoding the request before sending to the license server. Note that after decoding, the request may still be in Base64 form and this form should be sent to the license server without further decoding
|
|
166
|
-
* @property {writeLicenseResponse} writeLicenseResponse - Write the license server response to the platform
|
|
167
|
-
* @example
|
|
168
|
-
* Whilst the payload structure and access controls are specific to each license server implementation, the Widevine UAT license server requires no authentication and minimal payload formatting and therefore serves as a useful case study that may be adapted.
|
|
169
|
-
*
|
|
170
|
-
* remotePlayer.addEventListener("license-request", async (event) => {
|
|
171
|
-
* console.log("Got license-request event");
|
|
172
|
-
* const requestBuffer = event?.detail?.licenseRequest;
|
|
173
|
-
* const requestBufferStr = String.fromCharCode.apply(null, new Uint8Array(requestBuffer));
|
|
174
|
-
* console.log("License Request in base64:", requestBufferStr);
|
|
175
|
-
* const decodedLicenseRequest = window.atob(requestBufferStr); // from base 64
|
|
176
|
-
* const licenseRequestBytes = Uint8Array.from(decodedLicenseRequest, (l) => l.charCodeAt(0));
|
|
177
|
-
* // call Google API
|
|
178
|
-
* const res = await getLicenseFromServer(licenseRequestBytes.buffer);
|
|
179
|
-
* console.log("Writing response to platform ", res.code, res.responseBody);
|
|
180
|
-
* event.writeLicenseResponse(res.code, res.responseBody);
|
|
181
|
-
* });
|
|
182
|
-
|
|
183
|
-
* async function getLicenseFromServer(licenseRequest) {
|
|
184
|
-
* console.log("Requesting License from Widevine server");
|
|
185
|
-
* const response = await fetch("https://proxy.uat.widevine.com/proxy", {
|
|
186
|
-
* "method": "POST",
|
|
187
|
-
* "body": licenseRequest,
|
|
188
|
-
* "headers" : {
|
|
189
|
-
* "Content-Type": "application/octet-stream"
|
|
190
|
-
* }
|
|
191
|
-
* });
|
|
192
|
-
* const code = response.status;
|
|
193
|
-
* if (code !== 200) {
|
|
194
|
-
* console.error("failed to to get response from widevine:", code);
|
|
195
|
-
* const responseBody = await response.text();
|
|
196
|
-
* console.error(responseBody);
|
|
197
|
-
* return {code, responseBody};
|
|
198
|
-
* }
|
|
199
|
-
* const responseBody = await response.arrayBuffer();
|
|
200
|
-
* console.info("Got response: ");
|
|
201
|
-
* return {code, responseBody};
|
|
202
|
-
* }
|
|
203
|
-
*/
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/** get the player configuration.
|
|
207
|
-
* @returns {Config}
|
|
208
|
-
* */
|
|
209
|
-
getConfiguration() {
|
|
210
|
-
return { preferredAudioLanguage: "", preferredSubtitlesLanguage: "" };
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/** setting values for properties in the player configuration using an object.
|
|
214
|
-
* If the config does not support a property this is a no-op.
|
|
215
|
-
* @param {Object} props the object with all the different properties to change
|
|
216
|
-
* @example
|
|
217
|
-
* remotePlayer.configure({ preferredAudioLanguage: 'en-US' })
|
|
218
|
-
*
|
|
219
|
-
* */
|
|
220
|
-
configure(props) {
|
|
221
|
-
noop("RemotePlayer.configure", props);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** In order to support a seamless switch between the video in the UI and ABR, the web application must
|
|
225
|
-
* register the video element being used for the currently played video before calling the load and play apis.
|
|
226
|
-
* @param {object} video The video element currently playing video in the web application
|
|
227
|
-
* @deprecated use attach function instead
|
|
228
|
-
* */
|
|
229
|
-
registerVideoElement(video) {
|
|
230
|
-
this.attach(video);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/** In order to support a seamless switch between the video in the UI and ABR, the web application must
|
|
234
|
-
* attach the video element being used for the currently played video before calling the load and play apis.
|
|
235
|
-
* @param {object} video The video element currently playing video in the web application
|
|
236
|
-
* */
|
|
237
|
-
attach(video) {
|
|
238
|
-
noop("RemotePlayer.attach", video);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** Detach the video element from the remote player
|
|
242
|
-
*/
|
|
243
|
-
detach() {
|
|
244
|
-
noop("RemotePlayer.detach");
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/** Tell the remote player to load the given URL.
|
|
248
|
-
* @param {string} url url to load
|
|
249
|
-
* @param {number} [position] start position in seconds (if not provided, start from beginning (VOD) or current time (LTV))
|
|
250
|
-
* @returns {Promise}
|
|
251
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
252
|
-
*
|
|
253
|
-
* */
|
|
254
|
-
async load(url, position) {
|
|
255
|
-
return noop("RemotePlayer.load", url, position);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Play loaded URL. Assuming load was called before.
|
|
260
|
-
* Need to call lifecycle.moveToBackground() in order to move the ui to the background and display the remote player playback in full screen
|
|
261
|
-
* @example
|
|
262
|
-
* remotePlayer.load("https://example.com/video.mp4", 0);
|
|
263
|
-
* remotePlayer.play();
|
|
264
|
-
* lifecycle.moveToBackground();
|
|
265
|
-
*
|
|
266
|
-
* @returns {Promise}
|
|
267
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
268
|
-
*/
|
|
269
|
-
async play() {
|
|
270
|
-
return noop("RemotePlayer.play");
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/** Pauses the currently playing audio or video
|
|
274
|
-
* When pausing in background, it will pause all streams (audio, video, subtitles) to support pausing in background.
|
|
275
|
-
* When pausing in foreground, if audio in ui enabled, it will only pause audio stream.
|
|
276
|
-
* When pausing in foreground, if audio is not enabled, remote player is not playing and therefore no call is sent.
|
|
277
|
-
* @returns {Promise}
|
|
278
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
279
|
-
*
|
|
280
|
-
* */
|
|
281
|
-
async pause() {
|
|
282
|
-
return noop("RemotePlayer.pause");
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/** Stop playback
|
|
286
|
-
* @returns {Promise}
|
|
287
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
288
|
-
* */
|
|
289
|
-
async stop() {
|
|
290
|
-
return noop("RemotePlayer.stop");
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/** Get the currently loaded uri, or empty string is player is not loaded.
|
|
294
|
-
* @returns {string} loaded uri
|
|
295
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
296
|
-
*
|
|
297
|
-
* */
|
|
298
|
-
getAssetUri() {
|
|
299
|
-
return "";
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/** Get the current load mode (either NOT_LOADED or LOADING or LOADED).
|
|
303
|
-
* @returns {LoadMode} current load mode
|
|
304
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
305
|
-
* @example
|
|
306
|
-
* import { remotePlayer } from "senza-sdk";
|
|
307
|
-
* const loadMode = remotePlayer.getLoadMode();
|
|
308
|
-
* if (loadMode === remotePlayer.LoadMode.LOADED) {
|
|
309
|
-
* console.log("remote player is currently loaded");
|
|
310
|
-
* }
|
|
311
|
-
*
|
|
312
|
-
* */
|
|
313
|
-
getLoadMode() {
|
|
314
|
-
return this.LoadMode.NOT_LOADED;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* @typedef {Object} TextTrack
|
|
319
|
-
* @property {string} id - A unique ID for the track
|
|
320
|
-
* @property {string} lang - The track's language
|
|
321
|
-
* @property {boolean} selected - Whether the track is selected
|
|
322
|
-
* @property {boolean} autoTranslate - (Optional) Whether the track is an auto-translated language
|
|
323
|
-
*/
|
|
324
|
-
/** Get all the text (subtitles) tracks.
|
|
325
|
-
* Text tracks are available only after playing content and returning to the UI.
|
|
326
|
-
* When text tracks are updated, the @event tracksupdate if fired.
|
|
327
|
-
* Auto Translation languages are returned only for VOD assets where there is at least one text track in the manifest to be used for translation.
|
|
328
|
-
* The list of tracks is sorted ascending to two parts by the lang key in the following order:
|
|
329
|
-
* 1. The actual text tracks which is available in the asset manifest and the selected track
|
|
330
|
-
* 2. Auto-Translation tracks
|
|
331
|
-
* @returns {TextTrack[]} an array of TextTracks if available, otherwise - empty array
|
|
332
|
-
*
|
|
333
|
-
* */
|
|
334
|
-
getTextTracks() {
|
|
335
|
-
return [];
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* @typedef {Object} AudioTrack
|
|
340
|
-
* @property {string} id - A unique ID for the track
|
|
341
|
-
* @property {string} lang - The track's language
|
|
342
|
-
* @property {boolean} selected - Whether the track is selected
|
|
343
|
-
*/
|
|
344
|
-
/** Get all the audio tracks.
|
|
345
|
-
* Text tracks are available only after playing content and returning to the UI.
|
|
346
|
-
* When audio tracks are updated, the @event tracksupdate is fired.
|
|
347
|
-
* @returns {AudioTrack[]} an array of objects if available, otherwise - empty array
|
|
348
|
-
*
|
|
349
|
-
* */
|
|
350
|
-
getAudioTracks() {
|
|
351
|
-
return [];
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** Select a specific audio track.
|
|
355
|
-
* Track id should come from a call to getAudioTracks.
|
|
356
|
-
* If no tracks exist - this is a no-op.
|
|
357
|
-
* If the id does not match the id of any of the existing tracks - this is a no-op.
|
|
358
|
-
* @param {string} audioTrackId - The ID of the audio track to select.
|
|
359
|
-
* @returns {Promise<void>} A Promise that resolves once the selection process is complete.
|
|
360
|
-
* @throws {RemotePlayerError} If the player is not initialized or not loaded.
|
|
361
|
-
**/
|
|
362
|
-
async selectAudioTrack(audioTrackId) {
|
|
363
|
-
return noop("RemotePlayer.selectAudioTrack", audioTrackId);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/** Select a specific text (subtitle) track.
|
|
367
|
-
* Track id should come from a call to getTextTracks.
|
|
368
|
-
* If no tracks exist - this is a no-op.
|
|
369
|
-
* If the id does not match the id of any of the existing tracks - this is a no-op.
|
|
370
|
-
* @param {string} textTrackId - The ID of the text track to select.
|
|
371
|
-
* @returns {Promise<void>} A Promise that resolves once the selection process is complete.
|
|
372
|
-
* @throws {RemotePlayerError} If the player is not initialized or not loaded.
|
|
373
|
-
* */
|
|
374
|
-
async selectTextTrack(textTrackId) {
|
|
375
|
-
return noop("RemotePlayer.selectTextTrack", textTrackId);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/**
|
|
379
|
-
* Enable or disable the subtitles.
|
|
380
|
-
* If the player is in an unloaded state, the request will be applied next time content is played.
|
|
381
|
-
* @param {boolean} visible whether the subtitles are visible or not
|
|
382
|
-
* @throws {TypeError} if visible is not a boolean variable
|
|
383
|
-
*/
|
|
384
|
-
setTextTrackVisibility(visible) {
|
|
385
|
-
return noop("RemotePlayer.setTextTrackVisibility", visible);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Getter/Setter for currentTime
|
|
390
|
-
*/
|
|
391
|
-
get currentTime() {
|
|
392
|
-
return 0;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
set currentTime(playbackPosition) {
|
|
396
|
-
noop("RemotePlayer.currentTime", playbackPosition);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* For VOD asset, the duration of the asset
|
|
401
|
-
* @readonly
|
|
402
|
-
*/
|
|
403
|
-
get duration() {
|
|
404
|
-
return 0;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Whether the subtitles are visible or not.
|
|
409
|
-
* @readonly
|
|
410
|
-
*/
|
|
411
|
-
get textTrackVisibility() {
|
|
412
|
-
return false;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
/** Get the presentation start time as a date. This should only be called when the player has loaded a live stream.
|
|
416
|
-
* If the player has not loaded a live stream, this will return null.
|
|
417
|
-
* @returns {Date} presentation start time
|
|
418
|
-
*
|
|
419
|
-
* */
|
|
420
|
-
getPresentationStartTimeAsDate() {
|
|
421
|
-
return null;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/** Tell the remote player to unload the loaded URL.
|
|
425
|
-
* @returns {Promise}
|
|
426
|
-
* @throws {RemotePlayerError} error object contains code & msg
|
|
427
|
-
* @alpha API has not yet been released
|
|
428
|
-
*
|
|
429
|
-
* */
|
|
430
|
-
async unload() {
|
|
431
|
-
return noop("RemotePlayer.unload");
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* @function writeLicenseResponse
|
|
436
|
-
* @param {number} statusCode - License server HTTP response code, e.g. 200, 401, etc. Must be 200 to indicate a successful license exchange.
|
|
437
|
-
* @param {string} response - License server response as opaque binary data in an ArrayBuffer.
|
|
438
|
-
* @private
|
|
439
|
-
*/
|
|
440
|
-
}
|
|
441
|
-
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import * as shaka from "shaka-player";
|
|
2
|
-
|
|
3
|
-
// Define custom error category
|
|
4
|
-
shaka.util.Error.Category.SENZA_PLAYER_ERROR = 50;
|
|
5
|
-
shaka.util.Error.Code.SENZA_PLAYER_ERROR = 10500;
|
|
6
|
-
|
|
7
|
-
// Copy the shaka module and replace the Player class with SenzaShakaPlayer
|
|
8
|
-
// if we don't Copy the shaka module, the Player class will be replaced for all the other modules that import shaka
|
|
9
|
-
const senzaShaka = { ...shaka };
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* SenzaShakaPlayer subclass of Shaka that handles both local and remote playback.
|
|
14
|
-
*
|
|
15
|
-
* @class SenzaShakaPlayer
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* import { SenzaShakaPlayer } from "./senzaShakaPlayer.js";
|
|
19
|
-
*
|
|
20
|
-
* try {
|
|
21
|
-
* const videoElement = document.getElementById("video");
|
|
22
|
-
* const player = new SenzaShakaPlayer(videoElement);
|
|
23
|
-
* await player.load("http://playable.url/file.mpd");
|
|
24
|
-
* await videoElement.play(); // will start the playback
|
|
25
|
-
*
|
|
26
|
-
* } catch (err) {
|
|
27
|
-
* console.error("SenzaShakaPlayer failed with error", err);
|
|
28
|
-
* }
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
export class SenzaShakaPlayer extends shaka.Player {
|
|
32
|
-
/**
|
|
33
|
-
* Creates an instance of SenzaShakaPlayer, which is a subclass of shaka.Player.
|
|
34
|
-
*
|
|
35
|
-
* @param {HTMLVideoElement} videoElement - The video element to be used for local playback. This parameter is optional. If not provided, the video element can be attached later using the attach method.
|
|
36
|
-
* @param {HTMLElement=} videoContainer - The videoContainer to construct UITextDisplayer
|
|
37
|
-
* @param {function(shaka.Player)=} dependencyInjector Optional callback
|
|
38
|
-
* which is called to inject mocks into the Player. Used for testing.
|
|
39
|
-
*/
|
|
40
|
-
constructor(videoElement, videoContainer, dependencyInjector) {
|
|
41
|
-
super(videoElement, videoContainer, dependencyInjector);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Overrides the attach method of shaka.Player to attach the video element.
|
|
46
|
-
*
|
|
47
|
-
* @param {HTMLVideoElement} videoElement - The video element to be used for local playback.
|
|
48
|
-
* @param {boolean} [initializeMediaSource=true] - Whether to initialize the media source.
|
|
49
|
-
*/
|
|
50
|
-
async attach(videoElement, initializeMediaSource = true) {
|
|
51
|
-
await super.attach(videoElement, initializeMediaSource);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Detach the player from the current media element. Leaves the player in a
|
|
56
|
-
* state where it cannot play media, until it has been attached to something
|
|
57
|
-
* else.
|
|
58
|
-
*
|
|
59
|
-
* @param {boolean=} keepAdManager
|
|
60
|
-
*
|
|
61
|
-
* @return {!Promise}
|
|
62
|
-
* @export
|
|
63
|
-
*/
|
|
64
|
-
async detach(keepAdManager = false) {
|
|
65
|
-
return super.detach(keepAdManager);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Unloads the currently playing stream, if any.
|
|
70
|
-
*
|
|
71
|
-
* @param {boolean=} initializeMediaSource
|
|
72
|
-
* @param {boolean=} keepAdManager
|
|
73
|
-
* @return {!Promise}
|
|
74
|
-
* @export
|
|
75
|
-
*/
|
|
76
|
-
async unload(initializeMediaSource = true, keepAdManager = false) {
|
|
77
|
-
return super.unload(initializeMediaSource, keepAdManager);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Overrides the getTextTracks method to use the remote player's text tracks.
|
|
82
|
-
* @returns {Array} An array of text tracks.
|
|
83
|
-
*/
|
|
84
|
-
getTextLanguages() {
|
|
85
|
-
return super.getTextLanguages();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Overrides the getAudioTracks method to use the remote player's audio tracks.
|
|
90
|
-
* @returns {Array} An array of audio tracks.
|
|
91
|
-
*/
|
|
92
|
-
getAudioLanguages() {
|
|
93
|
-
return super.getAudioLanguages();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Overrides the selectAudioLanguage method to use the remote player's audio track selection.
|
|
98
|
-
* @param {string} language - The language to select.
|
|
99
|
-
* @param {string=} role - The role of the track to select. (e.g. 'main', 'caption', or 'commentary')
|
|
100
|
-
*/
|
|
101
|
-
selectAudioLanguage(language, role) {
|
|
102
|
-
super.selectAudioLanguage(language, role);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Overrides the selectTextLanguage method to use the remote player's text track selection.
|
|
107
|
-
* @param {string} language - The language to select.
|
|
108
|
-
* @param {string=} role - The role of the track to select.
|
|
109
|
-
*/
|
|
110
|
-
selectTextLanguage(language, role) {
|
|
111
|
-
super.selectTextLanguage(language, role);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Overrides the setTextTrackVisibility method to use the remote player's text track visibility settings.
|
|
116
|
-
* @param {boolean} visible - Whether the text tracks should be visible.
|
|
117
|
-
*/
|
|
118
|
-
setTextTrackVisibility(visible) {
|
|
119
|
-
super.setTextTrackVisibility(visible);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Helper function that makes it easier to check if lifecycle.state is
|
|
124
|
-
* either background or inTransitionToBackground.
|
|
125
|
-
*/
|
|
126
|
-
get isInRemotePlayback() {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Loads a media URL into both local and remote players.
|
|
132
|
-
*
|
|
133
|
-
* @param {string} url - The URL of the media to load.
|
|
134
|
-
* @returns {Promise<void>}
|
|
135
|
-
*/
|
|
136
|
-
async load(url, startTime, mimeType) {
|
|
137
|
-
return super.load(url, startTime, mimeType);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/***
|
|
141
|
-
*
|
|
142
|
-
* Configure the Player instance.
|
|
143
|
-
* @param {Object} config the configuration object
|
|
144
|
-
* @returns {Boolean}
|
|
145
|
-
*/
|
|
146
|
-
|
|
147
|
-
async destroy() {
|
|
148
|
-
return super.destroy();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Override the configure method to add custom configuration handling
|
|
153
|
-
* Supports the following additional configuration options:
|
|
154
|
-
* - shouldStopRemotePlayerOnError: boolean - If true, remote player will be stopped on error
|
|
155
|
-
*
|
|
156
|
-
* @override
|
|
157
|
-
* @param {Object} config - Configuration object to be merged with existing config
|
|
158
|
-
* @param {boolean} [config.shouldStopRemotePlayerOnError=true] - Whether to stop remote player on error
|
|
159
|
-
* @example
|
|
160
|
-
* player.configure({
|
|
161
|
-
* shouldStopRemotePlayerOnError: false, // Don't stop remote player on error
|
|
162
|
-
* // ... other shaka configurations
|
|
163
|
-
* });
|
|
164
|
-
*/
|
|
165
|
-
configure(config) {
|
|
166
|
-
return super.configure(config);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
senzaShaka.Player = SenzaShakaPlayer;
|
|
171
|
-
export { senzaShaka as shaka };
|
package/src/interface/utils.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import pack from "../../package.json";
|
|
2
|
-
const { version } = pack;
|
|
3
|
-
|
|
4
|
-
/* eslint-disable no-console */
|
|
5
|
-
class SdkLogger {
|
|
6
|
-
|
|
7
|
-
constructor(logFields) {
|
|
8
|
-
this.logFields = logFields;
|
|
9
|
-
}
|
|
10
|
-
debug(...data) {
|
|
11
|
-
console.debug(this.formatLogString(data));
|
|
12
|
-
}
|
|
13
|
-
log(...data) {
|
|
14
|
-
console.log(this.formatLogString(data));
|
|
15
|
-
}
|
|
16
|
-
info(...data) {
|
|
17
|
-
console.info(this.formatLogString(data));
|
|
18
|
-
}
|
|
19
|
-
warn(...data) {
|
|
20
|
-
console.warn(this.formatLogString(data));
|
|
21
|
-
}
|
|
22
|
-
error(...data) {
|
|
23
|
-
console.error(this.formatLogString(data));
|
|
24
|
-
}
|
|
25
|
-
metrics(metricObj) {
|
|
26
|
-
console.info(`[hs-sdk] [metrics] ${JSON.stringify(metricObj)}`);
|
|
27
|
-
}
|
|
28
|
-
withFields(logFields) {
|
|
29
|
-
return new SdkLogger({ ...this.logFields, ...logFields });
|
|
30
|
-
}
|
|
31
|
-
formatLogString(data) {
|
|
32
|
-
let logString = "[hs-sdk] " + data.join(" ");
|
|
33
|
-
if (this.logFields) {
|
|
34
|
-
logString += " [log-fields] " + JSON.stringify(this.logFields);
|
|
35
|
-
}
|
|
36
|
-
return logString;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const sdkLogger = new SdkLogger({ sdkVersion: version });
|
|
41
|
-
|
|
42
|
-
export function noop(functionname, ...args) {
|
|
43
|
-
console.log(`Called "${functionname}" with args:`, ...args || [], "This feature is only supported E2E.");
|
|
44
|
-
return Promise.resolve();
|
|
45
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|