@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
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
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;
|