@stremio/stremio-video 0.0.73 → 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stremio/stremio-video",
3
- "version": "0.0.73",
3
+ "version": "0.0.74",
4
4
  "description": "Abstraction layer on top of different media players",
5
5
  "author": "Smart Code OOD",
6
6
  "main": "src/index.js",
@@ -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
  }
@@ -1,9 +1,7 @@
1
1
  var VTTJS = require('vtt.js');
2
- var binarySearchUpperBound = require('./binarySearchUpperBound');
3
2
 
4
- function render(cuesByTime, time) {
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 (cuesByTime === null || videoState.time === null || !isFinite(videoState.time)) {
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, videoState.time - delay).forEach(function(cueNode) {
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
- renderSubtitles();
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
- renderSubtitles();
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;