@stremio/stremio-video 0.0.43 → 0.0.45
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/package.json
CHANGED
|
@@ -31,22 +31,22 @@ function selectVideoImplementation(commandArgs, options) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
if (typeof commandArgs.streamingServerURL === 'string') {
|
|
34
|
-
if (
|
|
34
|
+
if (commandArgs.platform === 'Tizen') {
|
|
35
35
|
return withStreamingServer(withHTMLSubtitles(TizenVideo));
|
|
36
36
|
}
|
|
37
|
-
if (
|
|
37
|
+
if (commandArgs.platform === 'webOS') {
|
|
38
38
|
return withStreamingServer(withHTMLSubtitles(WebOsVideo));
|
|
39
39
|
}
|
|
40
40
|
return withStreamingServer(withHTMLSubtitles(HTMLVideo));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
if (typeof commandArgs.stream.url === 'string') {
|
|
44
|
-
if (
|
|
45
|
-
return withVideoParams(withHTMLSubtitles(WebOsVideo));
|
|
46
|
-
}
|
|
47
|
-
if (typeof global.tizen !== 'undefined') {
|
|
44
|
+
if (commandArgs.platform === 'Tizen') {
|
|
48
45
|
return withVideoParams(withHTMLSubtitles(TizenVideo));
|
|
49
46
|
}
|
|
47
|
+
if (commandArgs.platform === 'webOS') {
|
|
48
|
+
return withVideoParams(withHTMLSubtitles(WebOsVideo));
|
|
49
|
+
}
|
|
50
50
|
return withVideoParams(withHTMLSubtitles(HTMLVideo));
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const SCOPE = 'AVPlay';
|
|
2
|
+
|
|
3
|
+
const createAVPlay = (transport) => {
|
|
4
|
+
const getState = () => {
|
|
5
|
+
return transport.request(SCOPE, 'getState');
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const getCurrentTime = () => {
|
|
9
|
+
return transport.request(SCOPE, 'getCurrentTime');
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const getDuration = () => {
|
|
13
|
+
return transport.request(SCOPE, 'getDuration');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const getTotalTrackInfo = () => {
|
|
17
|
+
return transport.request(SCOPE, 'getTotalTrackInfo');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getCurrentStreamInfo = () => {
|
|
21
|
+
return transport.request(SCOPE, 'getCurrentStreamInfo');
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const open = (path) => {
|
|
25
|
+
return transport.request(SCOPE, 'open', path);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const prepareAsync = async (successHandler, errorHandler) => {
|
|
29
|
+
const [handler, handlerResult] = await transport.request(SCOPE, 'prepareAsync', 'handler:success', 'handler:error');
|
|
30
|
+
if (handler === 'handler:success') successHandler();
|
|
31
|
+
if (handler === 'handler:error') errorHandler(...handlerResult);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const pause = () => {
|
|
35
|
+
return transport.request(SCOPE, 'pause');
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const play = () => {
|
|
39
|
+
return transport.request(SCOPE, 'play');
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const stop = () => {
|
|
43
|
+
return transport.request(SCOPE, 'stop');
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const seekTo = (time) => {
|
|
47
|
+
return transport.request(SCOPE, 'seekTo', time);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const setSpeed = (rate) => {
|
|
51
|
+
return transport.request(SCOPE, 'setSpeed', rate);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const setSelectTrack = (type, id) => {
|
|
55
|
+
return transport.request(SCOPE, 'setSelectTrack', type, id);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const setDisplayRect = (x, y, width, height) => {
|
|
59
|
+
return transport.request(SCOPE, 'setDisplayRect', x, y, width, height);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const setDisplayMethod = (method) => {
|
|
63
|
+
return transport.request(SCOPE, 'setDisplayMethod', method);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const setListener = (listener) => {
|
|
67
|
+
const handlers = Object.keys(listener).map((name) => `handler:${name}`);
|
|
68
|
+
const onHandlerResponse = (handler, handlerResult) => {
|
|
69
|
+
const name = handler.replace('handler:', '');
|
|
70
|
+
if (listener[name]) {
|
|
71
|
+
handlerResult ? listener[name](...handlerResult) : listener[name]();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
transport.listen(SCOPE, 'setListener', onHandlerResponse, ...handlers);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
getState,
|
|
80
|
+
getCurrentTime,
|
|
81
|
+
getDuration,
|
|
82
|
+
getTotalTrackInfo,
|
|
83
|
+
getCurrentStreamInfo,
|
|
84
|
+
open,
|
|
85
|
+
prepareAsync,
|
|
86
|
+
pause,
|
|
87
|
+
play,
|
|
88
|
+
stop,
|
|
89
|
+
seekTo,
|
|
90
|
+
setSpeed,
|
|
91
|
+
setSelectTrack,
|
|
92
|
+
setDisplayRect,
|
|
93
|
+
setDisplayMethod,
|
|
94
|
+
setListener,
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
module.exports = createAVPlay;
|
|
@@ -4,6 +4,7 @@ var deepFreeze = require('deep-freeze');
|
|
|
4
4
|
var Color = require('color');
|
|
5
5
|
var ERROR = require('../error');
|
|
6
6
|
var getTracksData = require('../tracksData');
|
|
7
|
+
var createAVPlay = require('./AVPlay');
|
|
7
8
|
|
|
8
9
|
function TizenVideo(options) {
|
|
9
10
|
options = options || {};
|
|
@@ -18,6 +19,8 @@ function TizenVideo(options) {
|
|
|
18
19
|
throw new Error('Container element required to be instance of HTMLElement');
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
var AVPlay = createAVPlay(options.transport);
|
|
23
|
+
|
|
21
24
|
var promiseAudioTrackChange = false;
|
|
22
25
|
|
|
23
26
|
var size = 100;
|
|
@@ -36,20 +39,22 @@ function TizenVideo(options) {
|
|
|
36
39
|
var lastSub;
|
|
37
40
|
var disabledSubs = false;
|
|
38
41
|
|
|
39
|
-
function refreshSubtitle() {
|
|
42
|
+
async function refreshSubtitle() {
|
|
40
43
|
if (lastSub) {
|
|
41
|
-
var
|
|
44
|
+
var currentTime = await getProp('time');
|
|
45
|
+
var lastSubDurationDiff = lastSub.duration - (currentTime - lastSub.now);
|
|
42
46
|
if (lastSubDurationDiff > 0) renderSubtitle(lastSubDurationDiff, lastSub.text);
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
function renderSubtitle(duration, text) {
|
|
50
|
+
async function renderSubtitle(duration, text) {
|
|
47
51
|
if (disabledSubs) return;
|
|
52
|
+
var now = await getProp('time');
|
|
48
53
|
// we ignore custom delay here, it's not needed for embedded subs
|
|
49
54
|
lastSub = {
|
|
50
55
|
duration: duration,
|
|
51
56
|
text: text,
|
|
52
|
-
now:
|
|
57
|
+
now: now,
|
|
53
58
|
};
|
|
54
59
|
if (subtitleTimeout) {
|
|
55
60
|
clearTimeout(subtitleTimeout);
|
|
@@ -85,7 +90,8 @@ function TizenVideo(options) {
|
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
var subtitleTimeout = false;
|
|
88
|
-
|
|
93
|
+
|
|
94
|
+
AVPlay.setListener({
|
|
89
95
|
onbufferingstart: function() {
|
|
90
96
|
isBuffering = true;
|
|
91
97
|
onPropChanged('buffering');
|
|
@@ -107,8 +113,7 @@ function TizenVideo(options) {
|
|
|
107
113
|
onstreamcompleted: function() {
|
|
108
114
|
onEnded();
|
|
109
115
|
}
|
|
110
|
-
};
|
|
111
|
-
window.webapis.avplay.setListener(Listener);
|
|
116
|
+
});
|
|
112
117
|
|
|
113
118
|
containerElement.appendChild(objElement);
|
|
114
119
|
|
|
@@ -169,7 +174,7 @@ function TizenVideo(options) {
|
|
|
169
174
|
}
|
|
170
175
|
}
|
|
171
176
|
|
|
172
|
-
function getProp(propName) {
|
|
177
|
+
async function getProp(propName) {
|
|
173
178
|
switch (propName) {
|
|
174
179
|
case 'stream': {
|
|
175
180
|
return stream;
|
|
@@ -182,17 +187,18 @@ function TizenVideo(options) {
|
|
|
182
187
|
return null;
|
|
183
188
|
}
|
|
184
189
|
|
|
185
|
-
var
|
|
190
|
+
var state = await AVPlay.getState();
|
|
191
|
+
var isPaused = !!(state === 'PAUSED');
|
|
186
192
|
|
|
187
193
|
if (!isPaused && promiseAudioTrackChange) {
|
|
188
|
-
|
|
194
|
+
AVPlay.setSelectTrack('AUDIO', parseInt(promiseAudioTrackChange.replace('EMBEDDED_', '')));
|
|
189
195
|
promiseAudioTrackChange = false;
|
|
190
196
|
}
|
|
191
197
|
|
|
192
198
|
return isPaused;
|
|
193
199
|
}
|
|
194
200
|
case 'time': {
|
|
195
|
-
var currentTime =
|
|
201
|
+
var currentTime = await AVPlay.getCurrentTime();
|
|
196
202
|
if (stream === null || currentTime === null || !isFinite(currentTime)) {
|
|
197
203
|
return null;
|
|
198
204
|
}
|
|
@@ -200,7 +206,7 @@ function TizenVideo(options) {
|
|
|
200
206
|
return Math.floor(currentTime);
|
|
201
207
|
}
|
|
202
208
|
case 'duration': {
|
|
203
|
-
var duration =
|
|
209
|
+
var duration = await AVPlay.getDuration();
|
|
204
210
|
if (stream === null || duration === null || !isFinite(duration)) {
|
|
205
211
|
return null;
|
|
206
212
|
}
|
|
@@ -219,7 +225,7 @@ function TizenVideo(options) {
|
|
|
219
225
|
return [];
|
|
220
226
|
}
|
|
221
227
|
|
|
222
|
-
var totalTrackInfo =
|
|
228
|
+
var totalTrackInfo = await AVPlay.getTotalTrackInfo();
|
|
223
229
|
var textTracks = [];
|
|
224
230
|
|
|
225
231
|
for (var i = 0; i < totalTrackInfo.length; i++) {
|
|
@@ -260,7 +266,7 @@ function TizenVideo(options) {
|
|
|
260
266
|
return null;
|
|
261
267
|
}
|
|
262
268
|
|
|
263
|
-
var currentTracks =
|
|
269
|
+
var currentTracks = await AVPlay.getCurrentStreamInfo();
|
|
264
270
|
var currentIndex;
|
|
265
271
|
|
|
266
272
|
for (var i = 0; i < currentTracks.length; i++) {
|
|
@@ -321,7 +327,7 @@ function TizenVideo(options) {
|
|
|
321
327
|
return [];
|
|
322
328
|
}
|
|
323
329
|
|
|
324
|
-
var totalTrackInfo =
|
|
330
|
+
var totalTrackInfo = await AVPlay.getTotalTrackInfo();
|
|
325
331
|
var audioTracks = [];
|
|
326
332
|
|
|
327
333
|
for (var i = 0; i < totalTrackInfo.length; i++) {
|
|
@@ -366,7 +372,7 @@ function TizenVideo(options) {
|
|
|
366
372
|
return promiseAudioTrackChange;
|
|
367
373
|
}
|
|
368
374
|
|
|
369
|
-
var currentTracks =
|
|
375
|
+
var currentTracks = await AVPlay.getCurrentStreamInfo();
|
|
370
376
|
var currentIndex = false;
|
|
371
377
|
|
|
372
378
|
for (var i = 0; i < currentTracks.length; i++) {
|
|
@@ -400,23 +406,25 @@ function TizenVideo(options) {
|
|
|
400
406
|
function onEnded() {
|
|
401
407
|
events.emit('ended');
|
|
402
408
|
}
|
|
403
|
-
function onPropChanged(propName) {
|
|
409
|
+
async function onPropChanged(propName) {
|
|
404
410
|
if (observedProps[propName]) {
|
|
405
|
-
|
|
411
|
+
var propValue = await getProp(propName);
|
|
412
|
+
events.emit('propChanged', propName, propValue);
|
|
406
413
|
}
|
|
407
414
|
}
|
|
408
|
-
function observeProp(propName) {
|
|
415
|
+
async function observeProp(propName) {
|
|
409
416
|
if (observedProps.hasOwnProperty(propName)) {
|
|
410
|
-
|
|
417
|
+
var propValue = await getProp(propName);
|
|
418
|
+
events.emit('propValue', propName, propValue);
|
|
411
419
|
observedProps[propName] = true;
|
|
412
420
|
}
|
|
413
421
|
}
|
|
414
|
-
function setProp(propName, propValue) {
|
|
422
|
+
async function setProp(propName, propValue) {
|
|
415
423
|
switch (propName) {
|
|
416
424
|
case 'paused': {
|
|
417
425
|
if (stream !== null) {
|
|
418
426
|
var willPause = !!propValue;
|
|
419
|
-
willPause ?
|
|
427
|
+
willPause ? AVPlay.pause() : AVPlay.play();
|
|
420
428
|
if (willPause) {
|
|
421
429
|
if (subtitleTimeout) {
|
|
422
430
|
clearTimeout(subtitleTimeout);
|
|
@@ -430,10 +438,10 @@ function TizenVideo(options) {
|
|
|
430
438
|
|
|
431
439
|
// the paused state is usually correct, but i have seen it not change on tizen 3
|
|
432
440
|
// which causes all kinds of issues in the UI: (only happens with some videos)
|
|
433
|
-
var lastKnownProp = getProp('paused');
|
|
441
|
+
var lastKnownProp = await getProp('paused');
|
|
434
442
|
|
|
435
|
-
setTimeout(function() {
|
|
436
|
-
if (getProp('paused') !== lastKnownProp) {
|
|
443
|
+
setTimeout(async function() {
|
|
444
|
+
if (await getProp('paused') !== lastKnownProp) {
|
|
437
445
|
onPropChanged('paused');
|
|
438
446
|
}
|
|
439
447
|
}, 1000);
|
|
@@ -442,7 +450,7 @@ function TizenVideo(options) {
|
|
|
442
450
|
}
|
|
443
451
|
case 'time': {
|
|
444
452
|
if (stream !== null && propValue !== null && isFinite(propValue)) {
|
|
445
|
-
|
|
453
|
+
AVPlay.seekTo(parseInt(propValue, 10));
|
|
446
454
|
renderSubtitle(1, '');
|
|
447
455
|
onPropChanged('time');
|
|
448
456
|
}
|
|
@@ -462,12 +470,13 @@ function TizenVideo(options) {
|
|
|
462
470
|
|
|
463
471
|
currentSubTrack = propValue;
|
|
464
472
|
|
|
465
|
-
var
|
|
473
|
+
var subtitlesTracks = await getProp('subtitlesTracks');
|
|
474
|
+
var selectedSubtitlesTrack = subtitlesTracks
|
|
466
475
|
.find(function(track) {
|
|
467
476
|
return track.id === propValue;
|
|
468
477
|
});
|
|
469
478
|
|
|
470
|
-
|
|
479
|
+
AVPlay.setSelectTrack('TEXT', parseInt(currentSubTrack.replace('EMBEDDED_', '')));
|
|
471
480
|
|
|
472
481
|
if (selectedSubtitlesTrack) {
|
|
473
482
|
events.emit('subtitlesTrackLoaded', selectedSubtitlesTrack);
|
|
@@ -565,15 +574,15 @@ function TizenVideo(options) {
|
|
|
565
574
|
}
|
|
566
575
|
case 'selectedAudioTrackId': {
|
|
567
576
|
if (stream !== null) {
|
|
568
|
-
|
|
569
577
|
currentAudioTrack = propValue;
|
|
570
578
|
|
|
571
|
-
var
|
|
579
|
+
var audioTracks = await getProp('audioTracks');
|
|
580
|
+
var selectedAudioTrack = audioTracks
|
|
572
581
|
.find(function(track) {
|
|
573
582
|
return track.id === propValue;
|
|
574
583
|
});
|
|
575
584
|
|
|
576
|
-
if (getProp('paused')) {
|
|
585
|
+
if (await getProp('paused')) {
|
|
577
586
|
// issues before this logic:
|
|
578
587
|
// tizen 3 does not allow changing audio track when paused
|
|
579
588
|
// tizen 5 does, but it will only change getProp('selectedAudioTrackId') after playback starts
|
|
@@ -582,7 +591,7 @@ function TizenVideo(options) {
|
|
|
582
591
|
promiseAudioTrackChange = propValue;
|
|
583
592
|
onPropChanged('selectedAudioTrackId');
|
|
584
593
|
} else {
|
|
585
|
-
|
|
594
|
+
AVPlay.setSelectTrack('AUDIO', parseInt(currentAudioTrack.replace('EMBEDDED_', '')));
|
|
586
595
|
}
|
|
587
596
|
if (selectedAudioTrack) {
|
|
588
597
|
events.emit('audioTrackLoaded', selectedAudioTrack);
|
|
@@ -597,7 +606,7 @@ function TizenVideo(options) {
|
|
|
597
606
|
videoSpeed = parseFloat(propValue);
|
|
598
607
|
|
|
599
608
|
try {
|
|
600
|
-
|
|
609
|
+
AVPlay.setSpeed(videoSpeed);
|
|
601
610
|
} catch (e) {}
|
|
602
611
|
|
|
603
612
|
onPropChanged('playbackSpeed');
|
|
@@ -628,13 +637,14 @@ function TizenVideo(options) {
|
|
|
628
637
|
retrieveExtendedTracks();
|
|
629
638
|
}
|
|
630
639
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
640
|
+
AVPlay.open(stream.url);
|
|
641
|
+
AVPlay.setDisplayRect(0, 0, window.innerWidth, window.innerHeight);
|
|
642
|
+
AVPlay.setDisplayMethod('PLAYER_DISPLAY_MODE_LETTER_BOX');
|
|
643
|
+
AVPlay.seekTo(commandArgs.time !== null && isFinite(commandArgs.time) ? parseInt(commandArgs.time, 10) : 0);
|
|
644
|
+
|
|
645
|
+
function onPrepareSuccess() {
|
|
636
646
|
onPropChanged('duration');
|
|
637
|
-
|
|
647
|
+
AVPlay.play();
|
|
638
648
|
|
|
639
649
|
isLoaded = true;
|
|
640
650
|
onPropChanged('loaded');
|
|
@@ -646,11 +656,13 @@ function TizenVideo(options) {
|
|
|
646
656
|
onPropChanged('selectedSubtitlesTrackId');
|
|
647
657
|
onPropChanged('audioTracks');
|
|
648
658
|
onPropChanged('selectedAudioTrackId');
|
|
649
|
-
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function onPrepareError(error) {
|
|
650
662
|
if (retries < maxRetries) {
|
|
651
663
|
retries++;
|
|
652
664
|
try {
|
|
653
|
-
|
|
665
|
+
AVPlay.stop();
|
|
654
666
|
} catch(e) {}
|
|
655
667
|
command('load', commandArgs);
|
|
656
668
|
} else {
|
|
@@ -660,7 +672,9 @@ function TizenVideo(options) {
|
|
|
660
672
|
error: error,
|
|
661
673
|
}));
|
|
662
674
|
}
|
|
663
|
-
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
AVPlay.prepareAsync(onPrepareSuccess, onPrepareError);
|
|
664
678
|
} else {
|
|
665
679
|
onError(Object.assign({}, ERROR.UNSUPPORTED_STREAM, {
|
|
666
680
|
critical: true,
|
|
@@ -671,7 +685,7 @@ function TizenVideo(options) {
|
|
|
671
685
|
}
|
|
672
686
|
case 'unload': {
|
|
673
687
|
stream = null;
|
|
674
|
-
|
|
688
|
+
AVPlay.stop();
|
|
675
689
|
isLoaded = false;
|
|
676
690
|
onPropChanged('loaded');
|
|
677
691
|
onPropChanged('stream');
|
|
@@ -688,6 +702,7 @@ function TizenVideo(options) {
|
|
|
688
702
|
case 'destroy': {
|
|
689
703
|
command('unload');
|
|
690
704
|
destroyed = true;
|
|
705
|
+
AVPlay.stop();
|
|
691
706
|
onPropChanged('subtitlesOffset');
|
|
692
707
|
onPropChanged('subtitlesSize');
|
|
693
708
|
onPropChanged('subtitlesTextColor');
|