@stremio/stremio-video 0.0.42 → 0.0.44

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.42",
3
+ "version": "0.0.44",
4
4
  "description": "Abstraction layer on top of different media players",
5
5
  "author": "Smart Code OOD",
6
6
  "main": "src/index.js",
@@ -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 getTracksData = require('../tracksData');
6
7
 
7
8
  function TizenVideo(options) {
8
9
  options = options || {};
@@ -148,6 +149,26 @@ function TizenVideo(options) {
148
149
  playbackSpeed: false
149
150
  };
150
151
 
152
+ var gotTraktData = false;
153
+ var tracksData = { audio: [], subs: [] };
154
+
155
+ function retrieveExtendedTracks() {
156
+ if (!gotTraktData && stream !== null) {
157
+ gotTraktData = true;
158
+ getTracksData(stream.url, function(resp) {
159
+ if (resp) {
160
+ tracksData = resp;
161
+ }
162
+ if (((tracksData || {}).subs || []).length) {
163
+ onPropChanged('subtitlesTracks');
164
+ }
165
+ if (((tracksData || {}).audio || []).length) {
166
+ onPropChanged('audioTracks');
167
+ }
168
+ });
169
+ }
170
+ }
171
+
151
172
  function getProp(propName) {
152
173
  switch (propName) {
153
174
  case 'stream': {
@@ -213,6 +234,14 @@ function TizenVideo(options) {
213
234
  extra = JSON.parse(textTrack.extra_info);
214
235
  } catch(e) {}
215
236
  var textTrackLang = typeof extra.track_lang === 'string' && extra.track_lang.length > 0 ? extra.track_lang.trim() : null;
237
+ if (((tracksData || {}).subs || []).length) {
238
+ var extendedTrackData = tracksData.subs.find(function(el) {
239
+ return (el || {}).id-1 === textTrack.index;
240
+ });
241
+ if (extendedTrackData) {
242
+ textTrackLang = extendedTrackData.lang || 'eng';
243
+ }
244
+ }
216
245
  textTracks.push({
217
246
  id: textTrackId,
218
247
  lang: textTrackLang,
@@ -307,6 +336,14 @@ function TizenVideo(options) {
307
336
  extra = JSON.parse(audioTrack.extra_info);
308
337
  } catch(e) {}
309
338
  var audioTrackLang = typeof extra.language === 'string' && extra.language.length > 0 ? extra.language : null;
339
+ if (((tracksData || {}).audio || []).length) {
340
+ var extendedTrackData = tracksData.audio.find(function(el) {
341
+ return (el || {}).id-1 === audioTrack.index;
342
+ });
343
+ if (extendedTrackData) {
344
+ audioTrackLang = extendedTrackData.lang || 'eng';
345
+ }
346
+ }
310
347
  audioTracks.push({
311
348
  id: audioTrackId,
312
349
  lang: audioTrackLang,
@@ -581,6 +618,16 @@ function TizenVideo(options) {
581
618
  }
582
619
  onPropChanged('buffering');
583
620
 
621
+ var tizenVersion = false;
622
+
623
+ try {
624
+ tizenVersion = parseFloat(global.tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version'));
625
+ } catch(e) {}
626
+
627
+ if (!tizenVersion || tizenVersion >= 6) {
628
+ retrieveExtendedTracks();
629
+ }
630
+
584
631
  window.webapis.avplay.open(stream.url);
585
632
  window.webapis.avplay.setDisplayRect(0, 0, window.innerWidth, window.innerHeight);
586
633
  window.webapis.avplay.setDisplayMethod('PLAYER_DISPLAY_MODE_LETTER_BOX');
@@ -2,6 +2,7 @@ var EventEmitter = require('eventemitter3');
2
2
  var cloneDeep = require('lodash.clonedeep');
3
3
  var deepFreeze = require('deep-freeze');
4
4
  var ERROR = require('../error');
5
+ var getTracksData = require('../tracksData');
5
6
 
6
7
  function luna(params, call, fail, method) {
7
8
  if (call) params.onSuccess = call || function() {};
@@ -135,6 +136,47 @@ function stremioSubSizes(size) {
135
136
  return false;
136
137
  }
137
138
 
139
+ var device = {
140
+ unsupportedAudio: ['DTS', 'TRUEHD'],
141
+ unsupportedSubs: ['HDMV/PGS', 'VOBSUB']
142
+ };
143
+
144
+ var fetchedDeviceInfo = false;
145
+
146
+ function retrieveDeviceInfo() {
147
+ if (fetchedDeviceInfo) {
148
+ return;
149
+ }
150
+ window.webOS.service.request('luna://com.webos.service.config', {
151
+ method: 'getConfigs',
152
+ parameters: {
153
+ 'configNames': [
154
+ 'tv.model.edidType'
155
+ ]
156
+ },
157
+ onSuccess: function (result) {
158
+ if (((result || {}).configs || {})['tv.model.edidType']) {
159
+ fetchedDeviceInfo = true;
160
+ var edidType = result.configs['tv.model.edidType'].toLowerCase();
161
+ if (edidType.includes('dts')) {
162
+ device.unsupportedAudio = device.unsupportedAudio.filter(function(e) {
163
+ return e !== 'DTS';
164
+ });
165
+ }
166
+ if (edidType.includes('truehd')) {
167
+ device.unsupportedAudio = device.unsupportedAudio.filter(function(e) {
168
+ return e !== 'TRUEHD';
169
+ });
170
+ }
171
+ }
172
+ },
173
+ onFailure: function (err) {
174
+ // eslint-disable-next-line no-console
175
+ console.log('could not get deviceInfo', err);
176
+ }
177
+ });
178
+ }
179
+
138
180
  function WebOsVideo(options) {
139
181
 
140
182
  options = options || {};
@@ -146,14 +188,10 @@ function WebOsVideo(options) {
146
188
 
147
189
  var isLoaded = null;
148
190
 
149
- var knownMediaId = false;
150
-
151
191
  var subSize = 75;
152
192
 
153
193
  var disabledSubs = true;
154
194
 
155
- var subscribed = false;
156
-
157
195
  var currentSubTrack = false;
158
196
 
159
197
  var currentAudioTrack = false;
@@ -173,140 +211,6 @@ function WebOsVideo(options) {
173
211
  char_opacity: 255
174
212
  };
175
213
 
176
- var setSubs = function (info) {
177
- textTracks = [];
178
- if (info.numSubtitleTracks) {
179
- for (var i = 0; i < info.subtitleTrackInfo.length; i++) {
180
- var textTrack = info.subtitleTrackInfo[i];
181
- textTrack.index = i;
182
- var textTrackLang = textTrack.language === '(null)' ? null : textTrack.language;
183
-
184
- var textTrackId = 'EMBEDDED_' + textTrack.index;
185
-
186
- if (!currentSubTrack && !textTracks.length) {
187
- currentSubTrack = textTrackId;
188
- }
189
-
190
- textTracks.push({
191
- id: textTrackId,
192
- lang: textTrackLang,
193
- label: textTrackLang,
194
- origin: 'EMBEDDED',
195
- embedded: true,
196
- mode: textTrackId === currentSubTrack ? 'showing' : 'disabled',
197
- });
198
-
199
- }
200
- onPropChanged('subtitlesTracks');
201
- onPropChanged('selectedSubtitlesTrackId');
202
-
203
- }
204
- };
205
-
206
- var setTracks = function (info) {
207
- audioTracks = [];
208
- if (info.numAudioTracks) {
209
- for (var i = 0; i < info.audioTrackInfo.length; i++) {
210
- var audioTrack = info.audioTrackInfo[i];
211
- audioTrack.index = i;
212
- var audioTrackId = 'EMBEDDED_' + audioTrack.index;
213
- if (!currentAudioTrack && !audioTracks.length) {
214
- currentAudioTrack = audioTrackId;
215
- }
216
- var audioTrackLang = audioTrack.language === '(null)' ? null : audioTrack.language;
217
- audioTracks.push({
218
- id: audioTrackId,
219
- lang: audioTrackLang,
220
- label: audioTrackLang,
221
- origin: 'EMBEDDED',
222
- embedded: true,
223
- mode: audioTrackId === currentAudioTrack ? 'showing' : 'disabled',
224
- });
225
- }
226
- onPropChanged('audioTracks');
227
- onPropChanged('selectedAudioTrackId');
228
-
229
- }
230
- };
231
-
232
- var subscribe = function (cb) {
233
- if (subscribed) return;
234
- subscribed = true;
235
- var answered = false;
236
- luna({
237
- method: 'subscribe',
238
- parameters: {
239
- 'mediaId': knownMediaId,
240
- 'subscribe': true
241
- }
242
- }, function (result) {
243
- if (result.sourceInfo && !answered) {
244
- answered = true;
245
- var info = result.sourceInfo.programInfo[0];
246
-
247
- setSubs(info);
248
-
249
- setTracks(info);
250
-
251
- unsubscribe(cb);
252
- }
253
-
254
- if ((result.error || {}).errorCode) {
255
- answered = true;
256
- // console.error('luna playback error', result.error);
257
- unsubscribe(cb);
258
- // unsubscribe();
259
- // onVideoError();
260
- return;
261
- }
262
-
263
- if ((result.unloadCompleted || {}).mediaId === knownMediaId && (result.unloadCompleted || {}).state) {
264
- // strange case where it just.. ends? without ever getting result.sourceInfo
265
- // onEnded();
266
- // console.log('strange case of end');
267
- // unsubscribe(cb);
268
- return;
269
- }
270
-
271
- count_message++;
272
-
273
- if (count_message === 30 && !answered) {
274
- // cb();
275
- unsubscribe(cb);
276
- }
277
- }, function() { // function(err)
278
- // console.log('luna error log 2');
279
- // console.error(err);
280
- });
281
- };
282
-
283
- var unsubscribe = function (cb) {
284
- if (!subscribed) return;
285
- subscribed = false;
286
- luna({
287
- method: 'unsubscribe',
288
- parameters: {
289
- 'mediaId': knownMediaId
290
- }
291
- }, function () { // function(result)
292
- // console.log('unsubscribe result', JSON.stringify(result));
293
- cb();
294
- }, function () { // function(err)
295
- // console.log('unsubscribe error', JSON.stringify(err));
296
- cb();
297
- });
298
- cb();
299
- };
300
-
301
- // var unload = function (cb) {
302
- // luna({
303
- // method: 'unload',
304
- // parameters: {
305
- // 'mediaId': knownMediaId
306
- // }
307
- // }, cb, cb);
308
- // };
309
-
310
214
  var toggleSubtitles = function (status) {
311
215
  if (!videoElement.mediaId) return;
312
216
 
@@ -439,6 +343,69 @@ function WebOsVideo(options) {
439
343
  playbackSpeed: false
440
344
  };
441
345
 
346
+ var gotTraktData = false;
347
+ var tracksData = { audio: [], subs: [] };
348
+
349
+ function retrieveExtendedTracks() {
350
+ if (!gotTraktData && stream !== null) {
351
+ gotTraktData = true;
352
+ getTracksData(stream.url, function(resp) {
353
+ var nrSubs = 0;
354
+ var nrAudio = 0;
355
+ textTracks = [];
356
+ audioTracks = [];
357
+ if (resp) {
358
+ tracksData = resp;
359
+ }
360
+ if (((tracksData || {}).subs || []).length) {
361
+ tracksData.subs.forEach(function(track) {
362
+ if (device.unsupportedSubs.includes(track.codec || '')) {
363
+ return;
364
+ }
365
+ var textTrackId = nrSubs;
366
+ nrSubs++;
367
+ if (!currentSubTrack && !textTracks.length) {
368
+ currentSubTrack = textTrackId;
369
+ }
370
+ textTracks.push({
371
+ id: 'EMBEDDED_' + textTrackId,
372
+ lang: track.lang || 'eng',
373
+ label: track.lang || 'eng',
374
+ origin: 'EMBEDDED',
375
+ embedded: true,
376
+ mode: textTrackId === currentSubTrack ? 'showing' : 'disabled',
377
+ });
378
+ });
379
+ onPropChanged('subtitlesTracks');
380
+ onPropChanged('selectedSubtitlesTrackId');
381
+ }
382
+ if (((tracksData || {}).audio || []).length) {
383
+ tracksData.audio.forEach(function(track) {
384
+ if (device.unsupportedAudio.includes(track.codec || '')) {
385
+ return;
386
+ }
387
+ var audioTrackId = nrAudio;
388
+ nrAudio++;
389
+ if (!currentAudioTrack && !audioTracks.length) {
390
+ currentAudioTrack = audioTrackId;
391
+ }
392
+ audioTracks.push({
393
+ id: 'EMBEDDED_' + audioTrackId,
394
+ lang: track.lang || 'eng',
395
+ label: track.lang || 'eng',
396
+ origin: 'EMBEDDED',
397
+ embedded: true,
398
+ mode: audioTrackId === currentAudioTrack ? 'showing' : 'disabled',
399
+ });
400
+ });
401
+ currentAudioTrack = 'EMBEDDED_0';
402
+ onPropChanged('audioTracks');
403
+ onPropChanged('selectedAudioTrackId');
404
+ }
405
+ });
406
+ }
407
+ }
408
+
442
409
  function getProp(propName) {
443
410
  switch (propName) {
444
411
  case 'stream': {
@@ -971,15 +938,18 @@ function WebOsVideo(options) {
971
938
  var initMediaId = function (cb) {
972
939
  function retrieveMediaId() {
973
940
  if (videoElement.mediaId) {
974
- knownMediaId = videoElement.mediaId;
975
941
  clearInterval(timer);
976
- subscribe(cb);
942
+ retrieveExtendedTracks();
943
+ retrieveDeviceInfo();
944
+ cb();
977
945
  return;
978
946
  }
979
947
  count++;
980
948
  if (count > 4) {
981
949
  // console.log('failed to get media id');
982
950
  clearInterval(timer);
951
+ retrieveExtendedTracks();
952
+ retrieveDeviceInfo();
983
953
  cb();
984
954
  }
985
955
  }
@@ -0,0 +1,13 @@
1
+ module.exports = function(url, cb) {
2
+ fetch('http://127.0.0.1:11470/tracks/'+encodeURIComponent(url)).then(function(resp) {
3
+ return resp.json();
4
+ }).then(function(tracks) {
5
+ var audioTracks = tracks.filter(function(el) { return (el || {}).type === 'audio'; });
6
+ var subsTracks = tracks.filter(function(el) { return (el || {}).type === 'text'; });
7
+ cb({ audio: audioTracks, subs: subsTracks });
8
+ }).catch(function(err) {
9
+ // eslint-disable-next-line no-console
10
+ console.error(err);
11
+ cb(false);
12
+ });
13
+ };
@@ -1,7 +1,21 @@
1
+ var url = require('url');
1
2
  var magnet = require('magnet-uri');
2
3
  var createTorrent = require('./createTorrent');
3
4
 
4
- function convertStream(streamingServerURL, stream, seriesInfo) {
5
+ function buildProxyUrl(streamingServerURL, streamURL, requestHeaders, responseHeaders) {
6
+ var parsedStreamURL = new URL(streamURL);
7
+ var proxyOptions = new URLSearchParams();
8
+ proxyOptions.set('d', parsedStreamURL.origin);
9
+ Object.entries(requestHeaders).forEach(function(entry) {
10
+ proxyOptions.append('h', entry[0] + ':' + entry[1]);
11
+ });
12
+ Object.entries(responseHeaders).forEach(function(entry) {
13
+ proxyOptions.append('r', entry[0] + ':' + entry[1]);
14
+ });
15
+ return url.resolve(streamingServerURL, '/proxy/' + proxyOptions.toString() + parsedStreamURL.pathname) + parsedStreamURL.search;
16
+ }
17
+
18
+ function convertStream(streamingServerURL, stream, seriesInfo, streamingServerSettings) {
5
19
  return new Promise(function(resolve, reject) {
6
20
  if (typeof stream.url === 'string') {
7
21
  if (stream.url.indexOf('magnet:') === 0) {
@@ -30,7 +44,15 @@ function convertStream(streamingServerURL, stream, seriesInfo) {
30
44
  reject(error);
31
45
  });
32
46
  } else {
33
- resolve({ url: stream.url });
47
+ var proxyStreamsEnabled = streamingServerSettings && streamingServerSettings.proxyStreamsEnabled;
48
+ var proxyHeaders = stream.behaviorHints && stream.behaviorHints.proxyHeaders;
49
+ if (proxyStreamsEnabled || proxyHeaders) {
50
+ var requestHeaders = proxyHeaders && proxyHeaders.request ? proxyHeaders.request : {};
51
+ var responseHeaders = proxyHeaders && proxyHeaders.response ? proxyHeaders.response : {};
52
+ resolve({ url: buildProxyUrl(streamingServerURL, stream.url, requestHeaders, responseHeaders) });
53
+ } else {
54
+ resolve({ url: stream.url });
55
+ }
34
56
  }
35
57
 
36
58
  return;
@@ -104,7 +104,7 @@ function withStreamingServer(Video) {
104
104
  video.dispatch({ type: 'command', commandName: 'unload' });
105
105
  loadArgs = commandArgs;
106
106
  onPropChanged('stream');
107
- convertStream(commandArgs.streamingServerURL, commandArgs.stream, commandArgs.seriesInfo)
107
+ convertStream(commandArgs.streamingServerURL, commandArgs.stream, commandArgs.seriesInfo, commandArgs.streamingServerSettings)
108
108
  .then(function(result) {
109
109
  var mediaURL = result.url;
110
110
  var infoHash = result.infoHash;