@stremio/stremio-video 0.0.45 → 0.0.47

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.45",
3
+ "version": "0.0.47",
4
4
  "description": "Abstraction layer on top of different media players",
5
5
  "author": "Smart Code OOD",
6
6
  "main": "src/index.js",
@@ -6,6 +6,7 @@ var ERROR = require('../error');
6
6
  var SUBS_SCALE_FACTOR = 0.0066;
7
7
 
8
8
  var stremioToMPVProps = {
9
+ 'loaded': 'loaded',
9
10
  'stream': null,
10
11
  'paused': 'pause',
11
12
  'time': 'time-pos',
@@ -24,17 +25,35 @@ var stremioToMPVProps = {
24
25
  'subtitlesOutlineColor': 'sub-border-color',
25
26
  };
26
27
 
28
+ function parseVersion(version) {
29
+ return version.split('.').slice(0, 2).map(function (v) { return parseInt(v); });
30
+ }
31
+
32
+ function versionGTE(a, b) {
33
+ var versionA = parseVersion(a);
34
+ var versionB = parseVersion(b);
35
+ if (versionA[0] > versionB[0]) return true;
36
+ if (versionA[0] < versionB[0]) return false;
37
+ return versionA[1] >= versionB[1];
38
+ }
39
+
27
40
  function ShellVideo(options) {
28
41
  options = options || {};
29
42
 
30
43
  var ipc = options.shellTransport;
31
-
44
+ var observedProps = {};
45
+ var props = {};
32
46
  var stremioProps = {};
33
47
  Object.keys(stremioToMPVProps).forEach(function(key) {
34
48
  if(stremioToMPVProps[key]) {
35
49
  stremioProps[stremioToMPVProps[key]] = key;
36
50
  }
37
51
  });
52
+ var resolveMPVVersion;
53
+ var waitForMPVVersion = new Promise(function (resolve) {
54
+ resolveMPVVersion = resolve;
55
+ });
56
+ command('unload');
38
57
 
39
58
  ipc.send('mpv-command', ['stop']);
40
59
  ipc.send('mpv-observe-prop', 'path');
@@ -66,13 +85,9 @@ function ShellVideo(options) {
66
85
  var events = new EventEmitter();
67
86
  var destroyed = false;
68
87
  var stream = null;
69
- // var selectedSubtitlesTrackId = null;
70
- var observedProps = {};
71
- var continueFrom = 0;
72
88
 
73
89
  var avgDuration = 0;
74
90
  var minClipDuration = 30;
75
- var props = { };
76
91
 
77
92
  function setBackground(visible) {
78
93
  // This is a bit of a hack but there is no better way so far
@@ -93,11 +108,15 @@ function ShellVideo(options) {
93
108
  ipc.on('mpv-prop-change', function(args) {
94
109
  switch (args.name) {
95
110
  case 'mpv-version':
111
+ resolveMPVVersion(args.data);
112
+ props[args.name] = logProp(args);
113
+ break;
96
114
  case 'ffmpeg-version': {
97
115
  props[args.name] = logProp(args);
98
116
  break;
99
117
  }
100
118
  case 'duration': {
119
+ setBackground(false);
101
120
  var intDuration = args.data | 0;
102
121
  // Accumulate average duration over time. if it is greater than minClipDuration
103
122
  // and equal to the currently reported duration, it is returned as video length.
@@ -111,15 +130,12 @@ function ShellVideo(options) {
111
130
  // for bitwise maths so the maximum supported video duration is 1073741823 (2 ^ 30 - 1)
112
131
  // which is around 34 years of playback time.
113
132
  avgDuration = avgDuration ? (avgDuration + intDuration) >> 1 : intDuration;
133
+ props.loaded = intDuration > 0;
134
+ if(props.loaded) onPropChanged('loaded');
114
135
  break;
115
136
  }
116
137
  case 'time-pos': {
117
138
  props[args.name] = Math.round(args.data*1000);
118
- if(continueFrom) {
119
- ipc.send('mpv-set-prop', ['time-pos', continueFrom]);
120
- props[args.name] = Math.round(continueFrom);
121
- continueFrom = 0;
122
- }
123
139
  break;
124
140
  }
125
141
  case 'sub-scale': {
@@ -306,60 +322,76 @@ function ShellVideo(options) {
306
322
  case 'load': {
307
323
  command('unload');
308
324
  if (commandArgs && commandArgs.stream && typeof commandArgs.stream.url === 'string') {
309
- stream = commandArgs.stream;
310
- onPropChanged('stream');
311
- continueFrom = commandArgs.time !== null && isFinite(commandArgs.time) ? parseInt(commandArgs.time, 10) / 1000 : 0;
325
+ waitForMPVVersion.then(function (mpvVersion) {
326
+ stream = commandArgs.stream;
327
+ onPropChanged('stream');
312
328
 
313
- setBackground(false);
329
+ ipc.send('mpv-set-prop', ['no-sub-ass']);
314
330
 
315
- ipc.send('mpv-set-prop', ['no-sub-ass']);
331
+ // opengl-cb is an alias for the new name "libmpv", as shown in mpv's video/out/vo.c aliases
332
+ // opengl is an alias for the new name "gpu"
333
+ // When on Windows we use d3d for the rendering in separate window
334
+ var windowRenderer = navigator.platform === 'Win32' ? 'direct3d' : 'opengl';
335
+ var videoOutput = options.mpvSeparateWindow ? windowRenderer : 'opengl-cb';
336
+ var separateWindow = options.mpvSeparateWindow ? 'yes' : 'no';
337
+ ipc.send('mpv-set-prop', ['vo', videoOutput]);
338
+ ipc.send('mpv-set-prop', ['osc', separateWindow]);
339
+ ipc.send('mpv-set-prop', ['input-defalt-bindings', separateWindow]);
340
+ ipc.send('mpv-set-prop', ['input-vo-keyboard', separateWindow]);
316
341
 
317
- // opengl-cb is an alias for the new name "libmpv", as shown in mpv's video/out/vo.c aliases
318
- // opengl is an alias for the new name "gpu"
319
- // When on Windows we use d3d for the rendering in separate window
320
- var windowRenderer = navigator.platform === 'Win32' ? 'direct3d' : 'opengl';
321
- var videoOutput = options.mpvSeparateWindow ? windowRenderer : 'opengl-cb';
322
- var separateWindow = options.mpvSeparateWindow ? 'yes' : 'no';
323
- ipc.send('mpv-set-prop', ['vo', videoOutput]);
324
- ipc.send('mpv-set-prop', ['osc', separateWindow]);
325
- ipc.send('mpv-set-prop', ['input-defalt-bindings', separateWindow]);
326
- ipc.send('mpv-set-prop', ['input-vo-keyboard', separateWindow]);
342
+ var startAt = Math.floor(parseInt(commandArgs.time, 10) / 1000) || 0;
343
+ if (startAt !== 0) {
344
+ if (versionGTE(mpvVersion, '0.39')) {
345
+ ipc.send('mpv-command', ['loadfile', stream.url, 'replace', '-1', 'start=+' + startAt]);
346
+ } else {
347
+ ipc.send('mpv-command', ['loadfile', stream.url, 'replace', 'start=+' + startAt]);
348
+ }
349
+ } else {
350
+ ipc.send('mpv-command', ['loadfile', stream.url]);
351
+ }
352
+ ipc.send('mpv-set-prop', ['pause', false]);
353
+ ipc.send('mpv-set-prop', ['speed', props.speed]);
354
+ if (props.aid) {
355
+ if (typeof props.aid === 'string' && props.aid.startsWith('EMBEDDED_')) {
356
+ ipc.send('mpv-set-prop', ['aid', props.aid.slice('EMBEDDED_'.length)]);
357
+ } else {
358
+ ipc.send('mpv-set-prop', ['aid', props.aid]);
359
+ }
360
+ }
361
+ ipc.send('mpv-set-prop', ['mute', 'no']);
327
362
 
328
- ipc.send('mpv-command', ['loadfile', stream.url]);
329
- ipc.send('mpv-set-prop', ['pause', false]);
330
- ipc.send('mpv-set-prop', ['speed', props.speed]);
331
- ipc.send('mpv-set-prop', ['aid', props.aid]);
332
- ipc.send('mpv-set-prop', ['mute', 'no']);
333
-
334
- onPropChanged('paused');
335
- onPropChanged('time');
336
- onPropChanged('duration');
337
- onPropChanged('buffering');
338
- onPropChanged('volume');
339
- onPropChanged('muted');
340
- onPropChanged('subtitlesTracks');
341
- onPropChanged('selectedSubtitlesTrackId');
363
+ onPropChanged('paused');
364
+ onPropChanged('time');
365
+ onPropChanged('duration');
366
+ onPropChanged('buffering');
367
+ onPropChanged('volume');
368
+ onPropChanged('muted');
369
+ onPropChanged('subtitlesTracks');
370
+ onPropChanged('selectedSubtitlesTrackId');
371
+ });
342
372
  } else {
343
373
  onError(Object.assign({}, ERROR.UNSUPPORTED_STREAM, {
344
374
  critical: true,
345
375
  stream: commandArgs ? commandArgs.stream : null
346
376
  }));
347
377
  }
348
-
349
378
  break;
350
379
  }
351
380
  case 'unload': {
352
381
  props = {
382
+ loaded: false,
383
+ pause: false,
353
384
  mute: false,
354
385
  speed: 1,
355
386
  subtitlesTracks: [],
356
- buffering: true,
387
+ audioTracks: [],
388
+ buffering: false,
357
389
  aid: null,
358
390
  sid: null,
359
391
  };
360
- continueFrom = 0;
361
392
  avgDuration = 0;
362
393
  ipc.send('mpv-command', ['stop']);
394
+ onPropChanged('loaded');
363
395
  onPropChanged('stream');
364
396
  onPropChanged('paused');
365
397
  onPropChanged('time');
@@ -6,6 +6,8 @@ var ERROR = require('../error');
6
6
  var getTracksData = require('../tracksData');
7
7
  var createAVPlay = require('./AVPlay');
8
8
 
9
+ var SSA_DESCRIPTORS_REGEX = /^\{(\\an[1-8])+\}/i;
10
+
9
11
  function TizenVideo(options) {
10
12
  options = options || {};
11
13
 
@@ -50,10 +52,12 @@ function TizenVideo(options) {
50
52
  async function renderSubtitle(duration, text) {
51
53
  if (disabledSubs) return;
52
54
  var now = await getProp('time');
55
+ var cleanedText = text.replace(SSA_DESCRIPTORS_REGEX, '');
56
+
53
57
  // we ignore custom delay here, it's not needed for embedded subs
54
58
  lastSub = {
55
59
  duration: duration,
56
- text: text,
60
+ text: cleanedText,
57
61
  now: now,
58
62
  };
59
63
  if (subtitleTimeout) {
@@ -69,7 +73,7 @@ function TizenVideo(options) {
69
73
  subtitlesElement.style.opacity = subtitlesOpacity;
70
74
 
71
75
  var cueNode = document.createElement('span');
72
- cueNode.innerHTML = text;
76
+ cueNode.innerHTML = cleanedText;
73
77
  cueNode.style.display = 'inline-block';
74
78
  cueNode.style.padding = '0.2em';
75
79
  cueNode.style.fontSize = Math.floor(size / 25) + 'vmin';
@@ -1,5 +1,5 @@
1
1
  function supportsTranscoding() {
2
- if (typeof global.tizen !== 'undefined' || typeof global.webOS !== 'undefined') {
2
+ if (typeof global.tizen !== 'undefined' || typeof global.webOS !== 'undefined' || typeof window.qt !== 'undefined') {
3
3
  return Promise.resolve(false);
4
4
  }
5
5
  return Promise.resolve(true);