@stremio/stremio-video 0.0.39-beta.3 → 0.0.41

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.39-beta.3",
3
+ "version": "0.0.41",
4
4
  "description": "Abstraction layer on top of different media players",
5
5
  "author": "Smart Code OOD",
6
6
  "main": "src/index.js",
@@ -23,7 +23,7 @@
23
23
  "magnet-uri": "6.2.0",
24
24
  "url": "0.11.0",
25
25
  "video-name-parser": "1.4.6",
26
- "vtt.js": "github:jaruba/vtt.js#e4f5f5603730866bacb174a93f51b734c9f29e6a"
26
+ "vtt.js": "github:jaruba/vtt.js#84d33d157848407d790d78423dacc41a096294f0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "eslint": "7.32.0"
@@ -100,9 +100,6 @@ function TizenVideo(options) {
100
100
  oncurrentplaytime: function() {
101
101
  onPropChanged('time');
102
102
  },
103
- onerror: function() {
104
- onVideoError();
105
- },
106
103
  onsubtitlechange: function(duration, text) {
107
104
  renderSubtitle(duration, text);
108
105
  },
@@ -128,8 +125,12 @@ function TizenVideo(options) {
128
125
  var events = new EventEmitter();
129
126
  var destroyed = false;
130
127
  var stream = null;
128
+ var retries = 0;
129
+ var maxRetries = 5;
130
+ var isLoaded = null;
131
131
  var observedProps = {
132
132
  stream: false,
133
+ loaded: false,
133
134
  paused: false,
134
135
  time: false,
135
136
  duration: false,
@@ -152,6 +153,9 @@ function TizenVideo(options) {
152
153
  case 'stream': {
153
154
  return stream;
154
155
  }
156
+ case 'loaded': {
157
+ return isLoaded;
158
+ }
155
159
  case 'paused': {
156
160
  if (stream === null) {
157
161
  return null;
@@ -350,18 +354,6 @@ function TizenVideo(options) {
350
354
  }
351
355
  }
352
356
  }
353
- function onVideoError() {
354
- if (destroyed) {
355
- return;
356
- }
357
-
358
- var error;
359
- error = ERROR.UNKNOWN_ERROR;
360
- onError(Object.assign({}, error, {
361
- critical: true,
362
- error: error
363
- }));
364
- }
365
357
  function onError(error) {
366
358
  events.emit('error', error);
367
359
  if (error.critical) {
@@ -593,19 +585,35 @@ function TizenVideo(options) {
593
585
  window.webapis.avplay.setDisplayRect(0, 0, window.innerWidth, window.innerHeight);
594
586
  window.webapis.avplay.setDisplayMethod('PLAYER_DISPLAY_MODE_LETTER_BOX');
595
587
  window.webapis.avplay.seekTo(commandArgs.time !== null && isFinite(commandArgs.time) ? parseInt(commandArgs.time, 10) : 0);
596
- window.webapis.avplay.prepare();
597
- onPropChanged('duration');
598
- window.webapis.avplay.play();
599
-
600
- onPropChanged('stream');
601
- onPropChanged('paused');
602
- onPropChanged('time');
603
- onPropChanged('duration');
604
- onPropChanged('subtitlesTracks');
605
- onPropChanged('selectedSubtitlesTrackId');
606
- onPropChanged('audioTracks');
607
- onPropChanged('selectedAudioTrackId');
588
+ window.webapis.avplay.prepareAsync(function() {
589
+ onPropChanged('duration');
590
+ window.webapis.avplay.play();
608
591
 
592
+ isLoaded = true;
593
+ onPropChanged('loaded');
594
+ onPropChanged('stream');
595
+ onPropChanged('paused');
596
+ onPropChanged('time');
597
+ onPropChanged('duration');
598
+ onPropChanged('subtitlesTracks');
599
+ onPropChanged('selectedSubtitlesTrackId');
600
+ onPropChanged('audioTracks');
601
+ onPropChanged('selectedAudioTrackId');
602
+ }, function(error) {
603
+ if (retries < maxRetries) {
604
+ retries++;
605
+ try {
606
+ window.webapis.avplay.stop();
607
+ } catch(e) {}
608
+ command('load', commandArgs);
609
+ } else {
610
+ onError(Object.assign({}, ERROR.STREAM_FAILED_TO_LOAD, {
611
+ critical: true,
612
+ stream: commandArgs ? commandArgs.stream : null,
613
+ error: error,
614
+ }));
615
+ }
616
+ });
609
617
  } else {
610
618
  onError(Object.assign({}, ERROR.UNSUPPORTED_STREAM, {
611
619
  critical: true,
@@ -617,6 +625,8 @@ function TizenVideo(options) {
617
625
  case 'unload': {
618
626
  stream = null;
619
627
  window.webapis.avplay.stop();
628
+ isLoaded = false;
629
+ onPropChanged('loaded');
620
630
  onPropChanged('stream');
621
631
  onPropChanged('paused');
622
632
  onPropChanged('time');
@@ -686,7 +696,7 @@ TizenVideo.canPlayStream = function() {
686
696
  TizenVideo.manifest = {
687
697
  name: 'TizenVideo',
688
698
  external: false,
689
- props: ['stream', 'paused', 'time', 'duration', 'buffering', 'audioTracks', 'selectedAudioTrackId', 'subtitlesTracks', 'selectedSubtitlesTrackId', 'subtitlesOffset', 'subtitlesSize', 'subtitlesTextColor', 'subtitlesBackgroundColor', 'subtitlesOutlineColor', 'subtitlesOpacity', 'playbackSpeed'],
699
+ props: ['stream', 'loaded', 'paused', 'time', 'duration', 'buffering', 'audioTracks', 'selectedAudioTrackId', 'subtitlesTracks', 'selectedSubtitlesTrackId', 'subtitlesOffset', 'subtitlesSize', 'subtitlesTextColor', 'subtitlesBackgroundColor', 'subtitlesOutlineColor', 'subtitlesOpacity', 'playbackSpeed'],
690
700
  commands: ['load', 'unload', 'destroy'],
691
701
  events: ['propValue', 'propChanged', 'ended', 'error', 'subtitlesTrackLoaded', 'audioTrackLoaded']
692
702
  };
@@ -6,8 +6,12 @@ var ERROR = require('../error');
6
6
  function luna(params, call, fail, method) {
7
7
  if (call) params.onSuccess = call || function() {};
8
8
 
9
- params.onFailure = function () { // function(result)
10
- // console.log('WebOS',(params.method || method) + ' [fail][' + result.errorCode + '] ' + result.errorText );
9
+ params.onFailure = function (result) {
10
+ // eslint-disable-next-line no-console
11
+ console.log('WebOS', (params.method || method) + ' [fail][' + result.errorCode + '] ' + result.errorText );
12
+
13
+ // eslint-disable-next-line no-console
14
+ console.log('fail result', JSON.stringify(result));
11
15
 
12
16
  if (fail) fail();
13
17
  };
@@ -61,9 +65,10 @@ function launchVideoApp(params, success, failure) {
61
65
  });
62
66
  }
63
67
 
64
- var webOsColors = ['black', 'white', 'yellow', 'red', 'green', 'blue'];
68
+ var webOsColors = ['none', 'black', 'white', 'yellow', 'red', 'green', 'blue'];
65
69
  var stremioColors = {
66
70
  // rgba
71
+ 'rgba(0, 0, 0, 0)': 'none',
67
72
  'rgba(0, 0, 0, 255)': 'black',
68
73
  'rgba(255, 255, 255, 255)': 'white',
69
74
  'rgba(255, 255, 0, 255)': 'yellow',
@@ -78,12 +83,12 @@ var stremioColors = {
78
83
  'rgba(0, 255, 0, 1)': 'green',
79
84
  'rgba(0, 0, 255, 1)': 'blue',
80
85
  // rgb
81
- 'rgba(0, 0, 0)': 'black',
82
- 'rgba(255, 255, 255)': 'white',
83
- 'rgba(255, 255, 0)': 'yellow',
84
- 'rgba(255, 0, 0)': 'red',
85
- 'rgba(0, 255, 0)': 'green',
86
- 'rgba(0, 0, 255)': 'blue',
86
+ 'rgb(0, 0, 0)': 'black',
87
+ 'rgb(255, 255, 255)': 'white',
88
+ 'rgb(255, 255, 0)': 'yellow',
89
+ 'rgb(255, 0, 0)': 'red',
90
+ 'rgb(0, 255, 0)': 'green',
91
+ 'rgb(0, 0, 255)': 'blue',
87
92
  // 8-digit hex
88
93
  '#000000FF': 'black',
89
94
  '#FFFFFFFF': 'white',
@@ -101,21 +106,15 @@ var stremioColors = {
101
106
  };
102
107
 
103
108
  function stremioSubOffsets(offset) {
104
- if (offset === 0) {
109
+ if (offset <= 0) {
105
110
  return -3;
106
- } else if (offset <= 2) {
107
- return -2;
108
- } else if (offset <= 3) {
109
- return -1;
110
111
  } else if (offset <= 5) {
111
- return 0;
112
+ return -2;
112
113
  } else if (offset <= 10) {
113
- return 1;
114
- } else if (offset <= 25) {
114
+ return 0;
115
+ } else if (offset <= 15) {
115
116
  return 2;
116
- } else if (offset <= 50) {
117
- return 3;
118
- } else if (offset <= 100) {
117
+ } else if (offset <= 20) {
119
118
  return 4;
120
119
  }
121
120
  return false;
@@ -123,14 +122,14 @@ function stremioSubOffsets(offset) {
123
122
 
124
123
  function stremioSubSizes(size) {
125
124
  // there is also: 0 (tiny)
126
- // adding zero will break the logic
127
- if (size <= 75) {
125
+ if (size <= 100) {
128
126
  return 1;
129
- } else if (size <= 100) {
127
+ } else if (size <= 125) {
128
+ // not used because of 50% step
130
129
  return 2;
131
130
  } else if (size <= 150) {
132
131
  return 3;
133
- } else if (size <= 250) {
132
+ } else if (size <= 200) {
134
133
  return 4;
135
134
  }
136
135
  return false;
@@ -145,6 +144,8 @@ function WebOsVideo(options) {
145
144
  throw new Error('Container element required to be instance of HTMLElement');
146
145
  }
147
146
 
147
+ var isLoaded = false;
148
+
148
149
  var knownMediaId = false;
149
150
 
150
151
  var subSize = 75;
@@ -163,22 +164,22 @@ function WebOsVideo(options) {
163
164
 
164
165
  var count_message = 0;
165
166
 
166
- var subtitleOffset = 5;
167
+ var subStyles = {
168
+ color: 'white',
169
+ font_size: 1,
170
+ bg_color: 'none',
171
+ position: -1,
172
+ bg_opacity: 0,
173
+ char_opacity: 255
174
+ };
167
175
 
168
176
  var setSubs = function (info) {
169
177
  textTracks = [];
170
- // console.log('sub tracks 1, nr of sub tracks: ', info.numSubtitleTracks);
171
178
  if (info.numSubtitleTracks) {
172
-
173
- // console.log('sub tracks 2');
174
-
175
- // try {
176
- // console.log('got sub info', JSON.stringify(info.subtitleTrackInfo));
177
- // } catch(e) {};
178
179
  for (var i = 0; i < info.subtitleTrackInfo.length; i++) {
179
180
  var textTrack = info.subtitleTrackInfo[i];
180
181
  textTrack.index = i;
181
- var textTrackLang = textTrack.language === '(null)' ? '' : textTrack.language;
182
+ var textTrackLang = textTrack.language === '(null)' ? null : textTrack.language;
182
183
 
183
184
  var textTrackId = 'EMBEDDED_' + textTrack.index;
184
185
 
@@ -196,9 +197,6 @@ function WebOsVideo(options) {
196
197
  });
197
198
 
198
199
  }
199
-
200
- // console.log('sub tracks all', textTracks);
201
-
202
200
  onPropChanged('subtitlesTracks');
203
201
  onPropChanged('selectedSubtitlesTrackId');
204
202
 
@@ -207,14 +205,7 @@ function WebOsVideo(options) {
207
205
 
208
206
  var setTracks = function (info) {
209
207
  audioTracks = [];
210
- // console.log('audio tracks 1, nr of audio tracks: ', info.numAudioTracks);
211
208
  if (info.numAudioTracks) {
212
-
213
- //console.log('audio tracks 2');
214
-
215
- // try {
216
- // console.log('got audio info', JSON.stringify(info.audioTrackInfo));
217
- // } catch(e) {};
218
209
  for (var i = 0; i < info.audioTrackInfo.length; i++) {
219
210
  var audioTrack = info.audioTrackInfo[i];
220
211
  audioTrack.index = i;
@@ -222,7 +213,7 @@ function WebOsVideo(options) {
222
213
  if (!currentAudioTrack && !audioTracks.length) {
223
214
  currentAudioTrack = audioTrackId;
224
215
  }
225
- var audioTrackLang = audioTrack.language === '(null)' ? '' : audioTrack.language;
216
+ var audioTrackLang = audioTrack.language === '(null)' ? null : audioTrack.language;
226
217
  audioTracks.push({
227
218
  id: audioTrackId,
228
219
  lang: audioTrackLang,
@@ -232,7 +223,6 @@ function WebOsVideo(options) {
232
223
  mode: audioTrackId === currentAudioTrack ? 'showing' : 'disabled',
233
224
  });
234
225
  }
235
- // console.log('audio tracks all', audioTracks);
236
226
  onPropChanged('audioTracks');
237
227
  onPropChanged('selectedAudioTrackId');
238
228
 
@@ -243,7 +233,6 @@ function WebOsVideo(options) {
243
233
  if (subscribed) return;
244
234
  subscribed = true;
245
235
  var answered = false;
246
- // console.log('subscribing');
247
236
  luna({
248
237
  method: 'subscribe',
249
238
  parameters: {
@@ -253,9 +242,6 @@ function WebOsVideo(options) {
253
242
  }, function (result) {
254
243
  if (result.sourceInfo && !answered) {
255
244
  answered = true;
256
- // try {
257
- // console.log('got source info', JSON.stringify(result.sourceInfo.programInfo[0]));
258
- // } catch(e) {};
259
245
  var info = result.sourceInfo.programInfo[0];
260
246
 
261
247
  setSubs(info);
@@ -282,7 +268,6 @@ function WebOsVideo(options) {
282
268
  return;
283
269
  }
284
270
 
285
- // console.log('WebOS', 'subscribe', JSON.stringify(result));
286
271
  count_message++;
287
272
 
288
273
  if (count_message === 30 && !answered) {
@@ -323,16 +308,14 @@ function WebOsVideo(options) {
323
308
  // };
324
309
 
325
310
  var toggleSubtitles = function (status) {
326
- if (!knownMediaId) return;
311
+ if (!videoElement.mediaId) return;
327
312
 
328
313
  disabledSubs = !status;
329
314
 
330
- // console.log('enable subs: ' + status);
331
-
332
315
  luna({
333
316
  method: 'setSubtitleEnable',
334
317
  parameters: {
335
- 'mediaId': knownMediaId,
318
+ 'mediaId': videoElement.mediaId,
336
319
  'enable': status
337
320
  }
338
321
  });
@@ -385,6 +368,10 @@ function WebOsVideo(options) {
385
368
  videoElement.onplaying = function() {
386
369
  onPropChanged('buffering');
387
370
  onPropChanged('buffered');
371
+ if (!isLoaded) {
372
+ isLoaded = true;
373
+ onPropChanged('loaded');
374
+ }
388
375
  };
389
376
  videoElement.oncanplay = function() {
390
377
  onPropChanged('buffering');
@@ -422,7 +409,6 @@ function WebOsVideo(options) {
422
409
 
423
410
  var lastSubColor = null;
424
411
  var lastSubBgColor = null;
425
- var lastSubBgOpacity = 0;
426
412
  var lastPlaybackSpeed = 1;
427
413
 
428
414
  var events = new EventEmitter();
@@ -430,9 +416,10 @@ function WebOsVideo(options) {
430
416
  var stream = null;
431
417
  var startTime = null;
432
418
  var subtitlesOffset = 0;
433
- var subtitlesOpacity = 255;
419
+ var subtitlesOpacity = 100;
434
420
  var observedProps = {
435
421
  stream: false,
422
+ loaded: false,
436
423
  paused: false,
437
424
  time: false,
438
425
  duration: false,
@@ -457,6 +444,9 @@ function WebOsVideo(options) {
457
444
  case 'stream': {
458
445
  return stream;
459
446
  }
447
+ case 'loaded': {
448
+ return isLoaded;
449
+ }
460
450
  case 'paused': {
461
451
  if (stream === null) {
462
452
  return null;
@@ -532,21 +522,21 @@ function WebOsVideo(options) {
532
522
  return null;
533
523
  }
534
524
 
535
- return lastSubColor || 'rgba(255, 255, 255, 255)';
525
+ return lastSubColor || 'rgb(255, 255, 255)';
536
526
  }
537
527
  case 'subtitlesBackgroundColor': {
538
528
  if (destroyed) {
539
529
  return null;
540
530
  }
541
531
 
542
- return lastSubBgColor || 'rgba(255, 255, 255, 0)';
532
+ return lastSubBgColor || 'rgba(0, 0, 0, 0)';
543
533
  }
544
534
  case 'subtitlesOpacity': {
545
535
  if (destroyed) {
546
536
  return null;
547
537
  }
548
538
 
549
- return subtitlesOpacity || 255;
539
+ return subtitlesOpacity || 100;
550
540
  }
551
541
  case 'audioTracks': {
552
542
  return audioTracks;
@@ -681,62 +671,93 @@ function WebOsVideo(options) {
681
671
  break;
682
672
  }
683
673
  case 'selectedSubtitlesTrackId': {
684
- if (stream !== null) {
674
+ if (videoElement.mediaId && stream !== null) {
685
675
  if ((propValue || '').indexOf('EMBEDDED_') === 0) {
686
- if (disabledSubs) {
687
- toggleSubtitles(true);
688
- }
676
+ toggleSubtitles(true);
677
+
678
+ subStyles.bg_opacity = subStyles.bg_color === 'none' ? 0 : 255;
679
+
680
+ [
681
+ 'setSubtitleCharacterColor',
682
+ 'setSubtitleBackgroundColor',
683
+ 'setSubtitlePosition',
684
+ 'setSubtitleFontSize',
685
+ 'setSubtitleBackgroundOpacity',
686
+ 'setSubtitleCharacterOpacity'
687
+ ].forEach(function(key) {
688
+ luna({
689
+ method: key,
690
+ parameters: {
691
+ mediaId: videoElement.mediaId,
692
+ charColor: subStyles.color,
693
+ bgColor: subStyles.bg_color === 'none' ? 'black' : subStyles.bg_color,
694
+ position: subStyles.position,
695
+ fontSize: subStyles.font_size,
696
+ bgOpacity: subStyles.bg_opacity,
697
+ charOpacity: subStyles.char_opacity
698
+ }
699
+ });
700
+ });
689
701
 
690
- // console.log('WebOS', 'change subtitles for id: ', knownMediaId, ' index:', propValue);
702
+ // eslint-disable-next-line no-console
703
+ console.log('WebOS', 'change subtitles for id: ', videoElement.mediaId, ' index:', propValue);
691
704
 
692
705
  currentSubTrack = propValue;
693
706
  var trackIndex = parseInt(propValue.replace('EMBEDDED_', ''));
694
- // console.log('set subs to track idx: ' + trackIndex);
695
- luna({
696
- method: 'selectTrack',
697
- parameters: {
698
- 'type': 'text',
699
- 'mediaId': knownMediaId,
700
- 'index': trackIndex
701
- }
702
- }, function() {
703
- // console.log('changed subs track successfully');
704
- var selectedSubtitlesTrack = getProp('subtitlesTracks')
705
- .find(function(track) {
706
- return track.id === propValue;
707
+ // eslint-disable-next-line no-console
708
+ console.log('set subs to track idx: ' + trackIndex);
709
+ setTimeout(function() {
710
+ var successCb = function() {
711
+ var selectedSubtitlesTrack = getProp('subtitlesTracks')
712
+ .find(function(track) {
713
+ return track.id === propValue;
714
+ });
715
+ textTracks = textTracks.map(function(track) {
716
+ track.mode = track.id === currentSubTrack ? 'showing' : 'disabled';
717
+ return track;
707
718
  });
708
- textTracks = textTracks.map(function(track) {
709
- track.mode = track.id === currentSubTrack ? 'showing' : 'disabled';
710
- return track;
711
- });
712
- if (selectedSubtitlesTrack) {
713
- events.emit('subtitlesTrackLoaded', selectedSubtitlesTrack);
714
- onPropChanged('selectedSubtitlesTrackId');
715
- }
716
- });
717
- } else if (!propValue) {
718
- toggleSubtitles(false);
719
+ if (selectedSubtitlesTrack) {
720
+ events.emit('subtitlesTrackLoaded', selectedSubtitlesTrack);
721
+ onPropChanged('selectedSubtitlesTrackId');
722
+ }
723
+ };
724
+ luna({
725
+ method: 'selectTrack',
726
+ parameters: {
727
+ 'type': 'text',
728
+ 'mediaId': videoElement.mediaId,
729
+ 'index': trackIndex
730
+ }
731
+ }, successCb, successCb);
732
+ }, 500);
719
733
  }
720
734
  }
721
735
 
736
+ if ((propValue || '').indexOf('EMBEDDED_') === -1) {
737
+ currentSubTrack = null;
738
+ onPropChanged('selectedSubtitlesTrackId');
739
+ toggleSubtitles(false);
740
+ }
741
+
722
742
  break;
723
743
  }
724
744
  case 'subtitlesOffset': {
725
745
  if (propValue !== null && isFinite(propValue)) {
726
- subtitlesOffset = Math.max(0, Math.min(100, parseInt(propValue, 10)));
727
- var nextOffset = stremioSubOffsets(subtitleOffset);
746
+ subtitlesOffset = propValue;
747
+ var nextOffset = stremioSubOffsets(Math.max(0, Math.min(100, parseInt(subtitlesOffset, 10))));
728
748
  if (nextOffset === false) { // use default
729
- nextOffset = 0;
749
+ nextOffset = -2;
750
+ }
751
+ subStyles.position = nextOffset;
752
+ if (videoElement.mediaId) {
753
+ luna({
754
+ method: 'setSubtitlePosition',
755
+ parameters: {
756
+ 'mediaId': videoElement.mediaId,
757
+ 'position': nextOffset,
758
+ }
759
+ });
730
760
  }
731
- luna({
732
- method: 'setSubtitlePosition',
733
- parameters: {
734
- 'mediaId': knownMediaId,
735
- 'position': nextOffset,
736
- }
737
- }, function() {
738
- // console.log('successfully changed sub offset to: ' + nextOffset);
739
- });
740
761
 
741
762
  onPropChanged('subtitlesOffset');
742
763
  }
@@ -745,20 +766,21 @@ function WebOsVideo(options) {
745
766
  }
746
767
  case 'subtitlesSize': {
747
768
  if (propValue !== null && isFinite(propValue)) {
748
- subSize = Math.max(0, parseInt(propValue, 10));
749
- var nextSubSize = stremioSubSizes(subSize);
769
+ subSize = propValue;
770
+ var nextSubSize = stremioSubSizes(Math.max(0, parseInt(subSize, 10)));
750
771
  if (nextSubSize === false) { // use default
751
- nextSubSize = 2;
772
+ nextSubSize = 1;
773
+ }
774
+ subStyles.font_size = nextSubSize;
775
+ if (videoElement.mediaId) {
776
+ luna({
777
+ method: 'setSubtitleFontSize',
778
+ parameters: {
779
+ 'mediaId': videoElement.mediaId,
780
+ 'fontSize': nextSubSize,
781
+ }
782
+ });
752
783
  }
753
- luna({
754
- method: 'setSubtitleFontSize',
755
- parameters: {
756
- 'mediaId': knownMediaId,
757
- 'fontSize': nextSubSize,
758
- }
759
- }, function() {
760
- // console.log('successfully changed sub size to: ' + nextSubSize);
761
- });
762
784
 
763
785
  onPropChanged('subtitlesSize');
764
786
  }
@@ -773,15 +795,16 @@ function WebOsVideo(options) {
773
795
  if (stremioColors[propValue] && webOsColors.indexOf(stremioColors[propValue]) > -1) {
774
796
  nextColor = stremioColors[propValue];
775
797
  }
776
- luna({
777
- method: 'setSubtitleCharacterColor',
778
- parameters: {
779
- 'mediaId': knownMediaId,
780
- 'charColor': nextColor,
781
- }
782
- }, function() {
783
- // console.log('changed subtitle color successfully to: ' + nextColor);
784
- });
798
+ subStyles.color = nextColor;
799
+ if (videoElement.mediaId) {
800
+ luna({
801
+ method: 'setSubtitleCharacterColor',
802
+ parameters: {
803
+ 'mediaId': videoElement.mediaId,
804
+ 'charColor': nextColor,
805
+ }
806
+ });
807
+ }
785
808
  lastSubColor = propValue;
786
809
  onPropChanged('subtitlesTextColor');
787
810
  }
@@ -791,39 +814,33 @@ function WebOsVideo(options) {
791
814
  case 'subtitlesBackgroundColor': {
792
815
  if (typeof propValue === 'string') {
793
816
  if (stremioColors[propValue] && webOsColors.indexOf(stremioColors[propValue]) > -1) {
794
- luna({
795
- method: 'setSubtitleBackgroundColor',
796
- parameters: {
797
- 'mediaId': knownMediaId,
798
- 'color': stremioColors[propValue],
799
- }
800
- }, function() {
801
- // console.log('changed subtitle background color successfully to: ' + stremioColors[propValue]);
802
- if (!lastSubBgOpacity) {
817
+ subStyles.bg_color = stremioColors[propValue];
818
+ if (videoElement.mediaId) {
819
+ luna({
820
+ method: 'setSubtitleBackgroundColor',
821
+ parameters: {
822
+ 'mediaId': videoElement.mediaId,
823
+ 'bgColor': stremioColors[propValue] === 'none' ? 'black' : stremioColors[propValue],
824
+ }
825
+ });
826
+ if (stremioColors[propValue] === 'none') {
827
+ luna({
828
+ method: 'setSubtitleBackgroundOpacity',
829
+ parameters: {
830
+ 'mediaId': videoElement.mediaId,
831
+ 'bgOpacity': 0,
832
+ }
833
+ });
834
+ } else {
803
835
  luna({
804
836
  method: 'setSubtitleBackgroundOpacity',
805
837
  parameters: {
806
- 'mediaId': knownMediaId,
838
+ 'mediaId': videoElement.mediaId,
807
839
  'bgOpacity': 255,
808
840
  }
809
- }, function() {
810
- // console.log('changed subtitle background opacity successfully to: ' + 255);
811
- lastSubBgOpacity = 255;
812
841
  });
813
842
  }
814
- });
815
- } else {
816
- // we don't know this color, set sub background opacity to 0
817
- luna({
818
- method: 'setSubtitleBackgroundOpacity',
819
- parameters: {
820
- 'mediaId': knownMediaId,
821
- 'bgOpacity': 0,
822
- }
823
- }, function() {
824
- // console.log('changed subtitle background opacity successfully to: ' + 0);
825
- lastSubBgOpacity = 0;
826
- });
843
+ }
827
844
  }
828
845
  lastSubBgColor = propValue;
829
846
  onPropChanged('subtitlesBackgroundColor');
@@ -833,13 +850,17 @@ function WebOsVideo(options) {
833
850
  }
834
851
  case 'subtitlesOpacity': {
835
852
  if (typeof propValue === 'number') {
836
- luna({
837
- method: 'setSubtitleBackgroundOpacity',
838
- parameters: {
839
- 'mediaId': knownMediaId,
840
- 'bgOpacity': Math.min(Math.max(propValue / 0.4, 0), 255),
841
- }
842
- });
853
+ var nextSubOpacity = Math.floor(propValue / 100 * 255);
854
+ subStyles.char_opacity = nextSubOpacity;
855
+ if (videoElement.mediaId) {
856
+ luna({
857
+ method: 'setSubtitleCharacterOpacity',
858
+ parameters: {
859
+ 'mediaId': videoElement.mediaId,
860
+ 'charOpacity': nextSubOpacity,
861
+ }
862
+ });
863
+ }
843
864
 
844
865
  subtitlesOpacity = propValue;
845
866
  onPropChanged('subtitlesOpacity');
@@ -848,44 +869,41 @@ function WebOsVideo(options) {
848
869
  break;
849
870
  }
850
871
  case 'selectedAudioTrackId': {
851
- // console.log('WebOS', 'change audio track for id: ', knownMediaId, ' index:', propValue);
852
-
853
872
  if ((propValue || '').indexOf('EMBEDDED_') === 0) {
854
873
  currentAudioTrack = propValue;
855
874
  var trackIndex = parseInt(propValue.replace('EMBEDDED_', ''));
856
- luna({
857
- method: 'selectTrack',
858
- parameters: {
859
- 'type': 'audio',
860
- 'mediaId': knownMediaId,
861
- 'index': trackIndex
862
- }
863
- }, function() {
864
- // console.log('changed audio track successfully');
865
- var selectedAudioTrack = getProp('audioTracks')
866
- .find(function(track) {
867
- return track.id === propValue;
875
+ if (videoElement.mediaId) {
876
+ luna({
877
+ method: 'selectTrack',
878
+ parameters: {
879
+ 'type': 'audio',
880
+ 'mediaId': videoElement.mediaId,
881
+ 'index': trackIndex
882
+ }
883
+ }, function() {
884
+ var selectedAudioTrack = getProp('audioTracks')
885
+ .find(function(track) {
886
+ return track.id === propValue;
887
+ });
888
+
889
+ audioTracks = audioTracks.map(function(track) {
890
+ track.mode = track.id === currentAudioTrack ? 'showing' : 'disabled';
891
+ return track;
868
892
  });
869
893
 
870
- audioTracks = audioTracks.map(function(track) {
871
- track.mode = track.id === currentAudioTrack ? 'showing' : 'disabled';
872
- return track;
894
+ if (selectedAudioTrack) {
895
+ events.emit('audioTrackLoaded', selectedAudioTrack);
896
+ onPropChanged('selectedAudioTrackId');
897
+ }
873
898
  });
874
-
875
- if (selectedAudioTrack) {
876
- events.emit('audioTrackLoaded', selectedAudioTrack);
877
- onPropChanged('selectedAudioTrackId');
878
- }
879
- });
880
- if (videoElement.audioTracks) {
899
+ }
900
+ if (videoElement && videoElement.audioTracks) {
881
901
  for (var i = 0; i < videoElement.audioTracks.length; i++) {
882
902
  videoElement.audioTracks[i].enabled = false;
883
903
  }
884
904
 
885
905
  if(videoElement.audioTracks[trackIndex]) {
886
906
  videoElement.audioTracks[trackIndex].enabled = true;
887
-
888
- // console.log('WebOS', 'change audio two method:', trackIndex);
889
907
  }
890
908
  }
891
909
 
@@ -906,22 +924,18 @@ function WebOsVideo(options) {
906
924
  break;
907
925
  }
908
926
  case 'playbackSpeed': {
909
- // console.log('start change play rate to: ' + propValue);
910
- // console.log(typeof propValue);
911
927
  if (propValue !== null && isFinite(propValue)) {
912
928
  lastPlaybackSpeed = parseFloat(propValue);
913
- luna({
914
- method: 'setPlayRate',
915
- parameters: {
916
- 'mediaId': knownMediaId,
917
- 'playRate': lastPlaybackSpeed,
918
- 'audioOutput': true,
919
- }
920
- }, function() {
921
- // console.log('set playback rate success: ', lastPlaybackSpeed);
922
- }, function() {
923
- // console.log('failed setting playback rate success: ', lastPlaybackSpeed);
924
- });
929
+ if (videoElement.mediaId) {
930
+ luna({
931
+ method: 'setPlayRate',
932
+ parameters: {
933
+ 'mediaId': videoElement.mediaId,
934
+ 'playRate': lastPlaybackSpeed,
935
+ 'audioOutput': true,
936
+ }
937
+ });
938
+ }
925
939
  onPropChanged('playbackSpeed');
926
940
  }
927
941
 
@@ -941,6 +955,7 @@ function WebOsVideo(options) {
941
955
  onPropChanged('stream');
942
956
  videoElement.autoplay = typeof commandArgs.autoplay === 'boolean' ? commandArgs.autoplay : true;
943
957
 
958
+ onPropChanged('loaded');
944
959
  onPropChanged('paused');
945
960
  onPropChanged('time');
946
961
  onPropChanged('duration');
@@ -957,7 +972,6 @@ function WebOsVideo(options) {
957
972
  function retrieveMediaId() {
958
973
  if (videoElement.mediaId) {
959
974
  knownMediaId = videoElement.mediaId;
960
- // console.log('got media id: ', videoElement.mediaId);
961
975
  clearInterval(timer);
962
976
  subscribe(cb);
963
977
  return;
@@ -1111,7 +1125,7 @@ WebOsVideo.canPlayStream = function() { // function(stream)
1111
1125
  WebOsVideo.manifest = {
1112
1126
  name: 'WebOsVideo',
1113
1127
  external: false,
1114
- props: ['stream', 'paused', 'time', 'duration', 'buffering', 'buffered', 'audioTracks', 'selectedAudioTrackId', 'subtitlesTracks', 'selectedSubtitlesTrackId', 'subtitlesOffset', 'subtitlesSize', 'subtitlesTextColor', 'subtitlesBackgroundColor', 'subtitlesOpacity', 'volume', 'muted', 'playbackSpeed'],
1128
+ props: ['stream', 'loaded', 'paused', 'time', 'duration', 'buffering', 'buffered', 'audioTracks', 'selectedAudioTrackId', 'subtitlesTracks', 'selectedSubtitlesTrackId', 'subtitlesOffset', 'subtitlesSize', 'subtitlesTextColor', 'subtitlesBackgroundColor', 'subtitlesOpacity', 'volume', 'muted', 'playbackSpeed'],
1115
1129
  commands: ['load', 'unload', 'destroy'],
1116
1130
  events: ['propValue', 'propChanged', 'ended', 'error', 'subtitlesTrackLoaded', 'audioTrackLoaded']
1117
1131
  };
package/src/error.js CHANGED
@@ -68,6 +68,10 @@ var ERROR = {
68
68
  UNSUPPORTED_STREAM: {
69
69
  code: 2,
70
70
  message: 'Stream is not supported'
71
+ },
72
+ STREAM_FAILED_TO_LOAD: {
73
+ code: 3,
74
+ message: 'Stream failed to load'
71
75
  }
72
76
  };
73
77
 
@@ -0,0 +1,24 @@
1
+ function isPlayerLoaded(video, props) {
2
+ if (!props.includes('loaded')) {
3
+ return Promise.resolve(true);
4
+ }
5
+ return new Promise(function(resolve, reject) {
6
+ var isLoaded = null;
7
+ video.on('propChanged', function(propName, propValue) {
8
+ if (propName === 'loaded' && propValue !== null && isLoaded === null) {
9
+ isLoaded = propValue;
10
+ if (propValue === true) {
11
+ resolve(true);
12
+ } else if (propValue === false) {
13
+ reject(Error('Player failed to load, will not retrieve video params'));
14
+ }
15
+ }
16
+ });
17
+ video.dispatch({
18
+ type: 'observeProp',
19
+ propName: 'loaded'
20
+ });
21
+ });
22
+ }
23
+
24
+ module.exports = isPlayerLoaded;
@@ -6,7 +6,7 @@ var deepFreeze = require('deep-freeze');
6
6
  var mediaCapabilities = require('../mediaCapabilities');
7
7
  var convertStream = require('./convertStream');
8
8
  var fetchVideoParams = require('./fetchVideoParams');
9
- var destroyHLSConverter = require('./destroyHLSConverter');
9
+ var isPlayerLoaded = require('./isPlayerLoaded');
10
10
  var supportsTranscoding = require('../supportsTranscoding');
11
11
  var ERROR = require('../error');
12
12
 
@@ -28,7 +28,6 @@ function withStreamingServer(Video) {
28
28
 
29
29
  var self = this;
30
30
  var loadArgs = null;
31
- var hlsConverterId = null;
32
31
  var loaded = false;
33
32
  var actionsQueue = [];
34
33
  var videoParams = null;
@@ -143,7 +142,6 @@ function withStreamingServer(Video) {
143
142
  mediaURL: mediaURL,
144
143
  infoHash: infoHash,
145
144
  fileIdx: fileIdx,
146
- hlsConverterId: null,
147
145
  stream: {
148
146
  url: mediaURL
149
147
  }
@@ -170,7 +168,6 @@ function withStreamingServer(Video) {
170
168
  mediaURL: mediaURL,
171
169
  infoHash: infoHash,
172
170
  fileIdx: fileIdx,
173
- hlsConverterId: id,
174
171
  stream: {
175
172
  url: url.resolve(commandArgs.streamingServerURL, '/hlsv2/' + id + '/master.m3u8?' + queryParams.toString()),
176
173
  subtitles: Array.isArray(commandArgs.stream.subtitles) ?
@@ -205,10 +202,13 @@ function withStreamingServer(Video) {
205
202
  stream: result.stream
206
203
  })
207
204
  });
208
- hlsConverterId = result.hlsConverterId;
209
205
  loaded = true;
210
206
  flushActionsQueue();
211
- fetchVideoParams(commandArgs.streamingServerURL, result.mediaURL, result.infoHash, result.fileIdx, commandArgs.stream.behaviorHints)
207
+
208
+ isPlayerLoaded(video, Video.manifest.props)
209
+ .then(function() {
210
+ return fetchVideoParams(commandArgs.streamingServerURL, result.mediaURL, result.infoHash, result.fileIdx, commandArgs.stream.behaviorHints);
211
+ })
212
212
  .then(function(result) {
213
213
  if (commandArgs !== loadArgs) {
214
214
  return;
@@ -279,13 +279,6 @@ function withStreamingServer(Video) {
279
279
  return true;
280
280
  }
281
281
  case 'unload': {
282
- if (loadArgs && hlsConverterId !== null) {
283
- destroyHLSConverter(loadArgs.streamingServerURL, hlsConverterId).catch(function(error) {
284
- // eslint-disable-next-line no-console
285
- console.error(error);
286
- });
287
- }
288
- hlsConverterId = null;
289
282
  loadArgs = null;
290
283
  loaded = false;
291
284
  actionsQueue = [];
@@ -1,7 +0,0 @@
1
- var url = require('url');
2
-
3
- function destroyHLSConverter(streamingServerURL, id) {
4
- return fetch(url.resolve(streamingServerURL, '/hlsv2/' + encodeURIComponent(id) + '/destroy'));
5
- }
6
-
7
- module.exports = destroyHLSConverter;