@stremio/stremio-video 0.0.72 → 0.0.74
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
|
@@ -401,8 +401,8 @@ function HTMLVideo(options) {
|
|
|
401
401
|
.find(function(track) {
|
|
402
402
|
return track.id === propValue;
|
|
403
403
|
});
|
|
404
|
+
onPropChanged('selectedSubtitlesTrackId');
|
|
404
405
|
if (selecterdSubtitlesTrack) {
|
|
405
|
-
onPropChanged('selectedSubtitlesTrackId');
|
|
406
406
|
events.emit('subtitlesTrackLoaded', selecterdSubtitlesTrack);
|
|
407
407
|
}
|
|
408
408
|
}
|
|
@@ -12,6 +12,7 @@ var stremioToMPVProps = {
|
|
|
12
12
|
'time': 'time-pos',
|
|
13
13
|
'duration': 'duration',
|
|
14
14
|
'buffering': 'buffering',
|
|
15
|
+
'buffered': 'demuxer-cache-time',
|
|
15
16
|
'volume': 'volume',
|
|
16
17
|
'muted': 'mute',
|
|
17
18
|
'playbackSpeed': 'speed',
|
|
@@ -73,6 +74,7 @@ function ShellVideo(options) {
|
|
|
73
74
|
|
|
74
75
|
ipc.send('mpv-observe-prop', 'paused-for-cache');
|
|
75
76
|
ipc.send('mpv-observe-prop', 'cache-buffering-state');
|
|
77
|
+
ipc.send('mpv-observe-prop', 'demuxer-cache-time');
|
|
76
78
|
|
|
77
79
|
ipc.send('mpv-observe-prop', 'aid');
|
|
78
80
|
ipc.send('mpv-observe-prop', 'vid');
|
|
@@ -177,6 +179,12 @@ function ShellVideo(options) {
|
|
|
177
179
|
}
|
|
178
180
|
break;
|
|
179
181
|
}
|
|
182
|
+
case 'demuxer-cache-time': {
|
|
183
|
+
var cacheTime = args.data || 0;
|
|
184
|
+
props[args.name] = cacheTime > 0 ? Math.floor(cacheTime * 1000) : null;
|
|
185
|
+
onPropChanged('buffered');
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
180
188
|
case 'aid':
|
|
181
189
|
case 'sid':
|
|
182
190
|
case 'vid': {
|
|
@@ -397,6 +405,7 @@ function ShellVideo(options) {
|
|
|
397
405
|
onPropChanged('time');
|
|
398
406
|
onPropChanged('duration');
|
|
399
407
|
onPropChanged('buffering');
|
|
408
|
+
onPropChanged('buffered');
|
|
400
409
|
onPropChanged('muted');
|
|
401
410
|
onPropChanged('subtitlesTracks');
|
|
402
411
|
onPropChanged('selectedSubtitlesTrackId');
|
|
@@ -418,6 +427,7 @@ function ShellVideo(options) {
|
|
|
418
427
|
subtitlesTracks: [],
|
|
419
428
|
audioTracks: [],
|
|
420
429
|
buffering: false,
|
|
430
|
+
buffered: null,
|
|
421
431
|
aid: null,
|
|
422
432
|
sid: null,
|
|
423
433
|
};
|
|
@@ -429,6 +439,7 @@ function ShellVideo(options) {
|
|
|
429
439
|
onPropChanged('time');
|
|
430
440
|
onPropChanged('duration');
|
|
431
441
|
onPropChanged('buffering');
|
|
442
|
+
onPropChanged('buffered');
|
|
432
443
|
onPropChanged('muted');
|
|
433
444
|
onPropChanged('subtitlesTracks');
|
|
434
445
|
onPropChanged('selectedSubtitlesTrackId');
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
var VTTJS = require('vtt.js');
|
|
2
|
-
var binarySearchUpperBound = require('./binarySearchUpperBound');
|
|
3
2
|
|
|
4
|
-
function render(cuesByTime,
|
|
3
|
+
function render(cuesByTime, timeIndex) {
|
|
5
4
|
var nodes = [];
|
|
6
|
-
var timeIndex = binarySearchUpperBound(cuesByTime.times, time);
|
|
7
5
|
if (timeIndex !== -1) {
|
|
8
6
|
var cuesForTime = cuesByTime[cuesByTime.times[timeIndex]];
|
|
9
7
|
for (var i = 0; i < cuesForTime.length; i++) {
|
|
@@ -3,6 +3,7 @@ var cloneDeep = require('lodash.clonedeep');
|
|
|
3
3
|
var deepFreeze = require('deep-freeze');
|
|
4
4
|
var Color = require('color');
|
|
5
5
|
var ERROR = require('../error');
|
|
6
|
+
var binarySearchUpperBound = require('./binarySearchUpperBound');
|
|
6
7
|
var subtitlesParser = require('./subtitlesParser');
|
|
7
8
|
var subtitlesRenderer = require('./subtitlesRenderer');
|
|
8
9
|
var subtitlesConverter = require('./subtitlesConverter');
|
|
@@ -40,8 +41,14 @@ function withHTMLSubtitles(Video) {
|
|
|
40
41
|
containerElement.appendChild(subtitlesElement);
|
|
41
42
|
|
|
42
43
|
var videoState = {
|
|
43
|
-
time: null
|
|
44
|
+
time: null,
|
|
45
|
+
paused: false,
|
|
46
|
+
lastSyncAt: null,
|
|
47
|
+
playbackSpeed: 1
|
|
44
48
|
};
|
|
49
|
+
var rafId = null;
|
|
50
|
+
var lastTimeIndex = null;
|
|
51
|
+
var forceRender = false;
|
|
45
52
|
var cuesByTime = null;
|
|
46
53
|
var events = new EventEmitter();
|
|
47
54
|
var destroyed = false;
|
|
@@ -67,18 +74,62 @@ function withHTMLSubtitles(Video) {
|
|
|
67
74
|
extraSubtitlesOpacity: false
|
|
68
75
|
};
|
|
69
76
|
|
|
77
|
+
function getCurrentTime() {
|
|
78
|
+
if (videoState.time === null || !isFinite(videoState.time)) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
if (videoState.paused || videoState.lastSyncAt === null) {
|
|
82
|
+
return videoState.time;
|
|
83
|
+
}
|
|
84
|
+
return videoState.time + (Date.now() - videoState.lastSyncAt) * videoState.playbackSpeed;
|
|
85
|
+
}
|
|
86
|
+
function startRenderLoop() {
|
|
87
|
+
if (rafId !== null) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
(function loop() {
|
|
91
|
+
renderSubtitles();
|
|
92
|
+
rafId = requestAnimationFrame(loop);
|
|
93
|
+
})();
|
|
94
|
+
}
|
|
95
|
+
function stopRenderLoop() {
|
|
96
|
+
if (rafId !== null) {
|
|
97
|
+
cancelAnimationFrame(rafId);
|
|
98
|
+
rafId = null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
70
101
|
function renderSubtitles() {
|
|
102
|
+
var time = getCurrentTime();
|
|
103
|
+
|
|
104
|
+
if (cuesByTime === null || time === null) {
|
|
105
|
+
if (lastTimeIndex !== null) {
|
|
106
|
+
while (subtitlesElement.hasChildNodes()) {
|
|
107
|
+
subtitlesElement.removeChild(subtitlesElement.lastChild);
|
|
108
|
+
}
|
|
109
|
+
lastTimeIndex = null;
|
|
110
|
+
}
|
|
111
|
+
forceRender = false;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
var timeIndex = binarySearchUpperBound(cuesByTime.times, time - delay);
|
|
116
|
+
if (timeIndex === lastTimeIndex && !forceRender) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
lastTimeIndex = timeIndex;
|
|
120
|
+
forceRender = false;
|
|
121
|
+
|
|
71
122
|
while (subtitlesElement.hasChildNodes()) {
|
|
72
123
|
subtitlesElement.removeChild(subtitlesElement.lastChild);
|
|
73
124
|
}
|
|
74
125
|
|
|
75
|
-
if (
|
|
126
|
+
if (timeIndex === -1) {
|
|
76
127
|
return;
|
|
77
128
|
}
|
|
78
129
|
|
|
79
130
|
subtitlesElement.style.bottom = offset + '%';
|
|
80
131
|
subtitlesElement.style.opacity = opacity;
|
|
81
|
-
subtitlesRenderer.render(cuesByTime,
|
|
132
|
+
subtitlesRenderer.render(cuesByTime, timeIndex).forEach(function(cueNode) {
|
|
82
133
|
cueNode.style.display = 'inline-block';
|
|
83
134
|
cueNode.style.padding = '0.2em';
|
|
84
135
|
cueNode.style.whiteSpace = 'pre-wrap';
|
|
@@ -101,7 +152,27 @@ function withHTMLSubtitles(Video) {
|
|
|
101
152
|
switch (propName) {
|
|
102
153
|
case 'time': {
|
|
103
154
|
videoState.time = propValue;
|
|
104
|
-
|
|
155
|
+
videoState.lastSyncAt = Date.now();
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case 'paused': {
|
|
159
|
+
if (propValue && !videoState.paused && videoState.lastSyncAt !== null && videoState.time !== null) {
|
|
160
|
+
videoState.time = videoState.time + (Date.now() - videoState.lastSyncAt) * videoState.playbackSpeed;
|
|
161
|
+
videoState.lastSyncAt = Date.now();
|
|
162
|
+
} else if (!propValue && videoState.paused) {
|
|
163
|
+
videoState.lastSyncAt = Date.now();
|
|
164
|
+
}
|
|
165
|
+
videoState.paused = propValue;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case 'playbackSpeed': {
|
|
169
|
+
if (propValue !== null && isFinite(propValue)) {
|
|
170
|
+
if (!videoState.paused && videoState.lastSyncAt !== null && videoState.time !== null) {
|
|
171
|
+
videoState.time = videoState.time + (Date.now() - videoState.lastSyncAt) * videoState.playbackSpeed;
|
|
172
|
+
videoState.lastSyncAt = Date.now();
|
|
173
|
+
}
|
|
174
|
+
videoState.playbackSpeed = propValue;
|
|
175
|
+
}
|
|
105
176
|
break;
|
|
106
177
|
}
|
|
107
178
|
}
|
|
@@ -224,6 +295,9 @@ function withHTMLSubtitles(Video) {
|
|
|
224
295
|
var selectedTrack = tracks.find(function(track) {
|
|
225
296
|
return track.id === propValue;
|
|
226
297
|
});
|
|
298
|
+
if (!selectedTrack) {
|
|
299
|
+
stopRenderLoop();
|
|
300
|
+
}
|
|
227
301
|
if (selectedTrack) {
|
|
228
302
|
selectedTrackId = selectedTrack.id;
|
|
229
303
|
delay = 0;
|
|
@@ -269,7 +343,7 @@ function withHTMLSubtitles(Video) {
|
|
|
269
343
|
}
|
|
270
344
|
|
|
271
345
|
cuesByTime = result;
|
|
272
|
-
|
|
346
|
+
startRenderLoop();
|
|
273
347
|
events.emit('extraSubtitlesTrackLoaded', selectedTrack);
|
|
274
348
|
})
|
|
275
349
|
.catch(function(error) {
|
|
@@ -299,6 +373,7 @@ function withHTMLSubtitles(Video) {
|
|
|
299
373
|
case 'extraSubtitlesDelay': {
|
|
300
374
|
if (selectedTrackId !== null && propValue !== null && isFinite(propValue)) {
|
|
301
375
|
delay = parseInt(propValue, 10);
|
|
376
|
+
forceRender = true;
|
|
302
377
|
renderSubtitles();
|
|
303
378
|
onPropChanged('extraSubtitlesDelay');
|
|
304
379
|
}
|
|
@@ -308,6 +383,7 @@ function withHTMLSubtitles(Video) {
|
|
|
308
383
|
case 'extraSubtitlesSize': {
|
|
309
384
|
if (propValue !== null && isFinite(propValue)) {
|
|
310
385
|
size = Math.max(0, parseInt(propValue, 10));
|
|
386
|
+
forceRender = true;
|
|
311
387
|
renderSubtitles();
|
|
312
388
|
onPropChanged('extraSubtitlesSize');
|
|
313
389
|
}
|
|
@@ -317,6 +393,7 @@ function withHTMLSubtitles(Video) {
|
|
|
317
393
|
case 'extraSubtitlesOffset': {
|
|
318
394
|
if (propValue !== null && isFinite(propValue)) {
|
|
319
395
|
offset = Math.max(0, Math.min(100, parseInt(propValue, 10)));
|
|
396
|
+
forceRender = true;
|
|
320
397
|
renderSubtitles();
|
|
321
398
|
onPropChanged('extraSubtitlesOffset');
|
|
322
399
|
}
|
|
@@ -332,6 +409,7 @@ function withHTMLSubtitles(Video) {
|
|
|
332
409
|
console.error('withHTMLSubtitles', error);
|
|
333
410
|
}
|
|
334
411
|
|
|
412
|
+
forceRender = true;
|
|
335
413
|
renderSubtitles();
|
|
336
414
|
onPropChanged('extraSubtitlesTextColor');
|
|
337
415
|
}
|
|
@@ -347,6 +425,7 @@ function withHTMLSubtitles(Video) {
|
|
|
347
425
|
console.error('withHTMLSubtitles', error);
|
|
348
426
|
}
|
|
349
427
|
|
|
428
|
+
forceRender = true;
|
|
350
429
|
renderSubtitles();
|
|
351
430
|
onPropChanged('extraSubtitlesBackgroundColor');
|
|
352
431
|
}
|
|
@@ -362,6 +441,7 @@ function withHTMLSubtitles(Video) {
|
|
|
362
441
|
console.error('withHTMLSubtitles', error);
|
|
363
442
|
}
|
|
364
443
|
|
|
444
|
+
forceRender = true;
|
|
365
445
|
renderSubtitles();
|
|
366
446
|
onPropChanged('extraSubtitlesOutlineColor');
|
|
367
447
|
}
|
|
@@ -377,6 +457,7 @@ function withHTMLSubtitles(Video) {
|
|
|
377
457
|
console.error('withHTMLSubtitles', error);
|
|
378
458
|
}
|
|
379
459
|
|
|
460
|
+
forceRender = true;
|
|
380
461
|
renderSubtitles();
|
|
381
462
|
onPropChanged('extraSubtitlesOpacity');
|
|
382
463
|
}
|
|
@@ -450,6 +531,8 @@ function withHTMLSubtitles(Video) {
|
|
|
450
531
|
return false;
|
|
451
532
|
}
|
|
452
533
|
case 'unload': {
|
|
534
|
+
stopRenderLoop();
|
|
535
|
+
lastTimeIndex = null;
|
|
453
536
|
cuesByTime = null;
|
|
454
537
|
tracks = [];
|
|
455
538
|
selectedTrackId = null;
|