Skip to content

Commit f5b2c5e

Browse files
authored
Merge pull request #75 from Stremio/extended-tracks-data
Retrieve Extended Tracks Data from Streaming Server
2 parents f01a6c0 + 41e2283 commit f5b2c5e

File tree

3 files changed

+170
-140
lines changed

3 files changed

+170
-140
lines changed

src/TizenVideo/TizenVideo.js

+47
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ var cloneDeep = require('lodash.clonedeep');
33
var deepFreeze = require('deep-freeze');
44
var Color = require('color');
55
var ERROR = require('../error');
6+
var getTracksData = require('../tracksData');
67

78
function TizenVideo(options) {
89
options = options || {};
@@ -148,6 +149,26 @@ function TizenVideo(options) {
148149
playbackSpeed: false
149150
};
150151

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+
151172
function getProp(propName) {
152173
switch (propName) {
153174
case 'stream': {
@@ -213,6 +234,14 @@ function TizenVideo(options) {
213234
extra = JSON.parse(textTrack.extra_info);
214235
} catch(e) {}
215236
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+
}
216245
textTracks.push({
217246
id: textTrackId,
218247
lang: textTrackLang,
@@ -307,6 +336,14 @@ function TizenVideo(options) {
307336
extra = JSON.parse(audioTrack.extra_info);
308337
} catch(e) {}
309338
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+
}
310347
audioTracks.push({
311348
id: audioTrackId,
312349
lang: audioTrackLang,
@@ -581,6 +618,16 @@ function TizenVideo(options) {
581618
}
582619
onPropChanged('buffering');
583620

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+
584631
window.webapis.avplay.open(stream.url);
585632
window.webapis.avplay.setDisplayRect(0, 0, window.innerWidth, window.innerHeight);
586633
window.webapis.avplay.setDisplayMethod('PLAYER_DISPLAY_MODE_LETTER_BOX');

src/WebOsVideo/WebOsVideo.js

+110-140
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var EventEmitter = require('eventemitter3');
22
var cloneDeep = require('lodash.clonedeep');
33
var deepFreeze = require('deep-freeze');
44
var ERROR = require('../error');
5+
var getTracksData = require('../tracksData');
56

67
function luna(params, call, fail, method) {
78
if (call) params.onSuccess = call || function() {};
@@ -135,6 +136,47 @@ function stremioSubSizes(size) {
135136
return false;
136137
}
137138

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+
138180
function WebOsVideo(options) {
139181

140182
options = options || {};
@@ -146,14 +188,10 @@ function WebOsVideo(options) {
146188

147189
var isLoaded = null;
148190

149-
var knownMediaId = false;
150-
151191
var subSize = 75;
152192

153193
var disabledSubs = true;
154194

155-
var subscribed = false;
156-
157195
var currentSubTrack = false;
158196

159197
var currentAudioTrack = false;
@@ -173,140 +211,6 @@ function WebOsVideo(options) {
173211
char_opacity: 255
174212
};
175213

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-
310214
var toggleSubtitles = function (status) {
311215
if (!videoElement.mediaId) return;
312216

@@ -439,6 +343,69 @@ function WebOsVideo(options) {
439343
playbackSpeed: false
440344
};
441345

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+
442409
function getProp(propName) {
443410
switch (propName) {
444411
case 'stream': {
@@ -971,15 +938,18 @@ function WebOsVideo(options) {
971938
var initMediaId = function (cb) {
972939
function retrieveMediaId() {
973940
if (videoElement.mediaId) {
974-
knownMediaId = videoElement.mediaId;
975941
clearInterval(timer);
976-
subscribe(cb);
942+
retrieveExtendedTracks();
943+
retrieveDeviceInfo();
944+
cb();
977945
return;
978946
}
979947
count++;
980948
if (count > 4) {
981949
// console.log('failed to get media id');
982950
clearInterval(timer);
951+
retrieveExtendedTracks();
952+
retrieveDeviceInfo();
983953
cb();
984954
}
985955
}

src/tracksData.js

+13
Original file line numberDiff line numberDiff line change
@@ -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+
};

0 commit comments

Comments
 (0)