Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Stremio/stremio-video int…
Browse files Browse the repository at this point in the history
…o feat/local-subtitles
tymmesyde committed Jan 17, 2025
2 parents 9c6a4a5 + 41cf05b commit 1537a0e
Showing 12 changed files with 747 additions and 42 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stremio/stremio-video",
"version": "0.0.48",
"version": "0.0.50",
"description": "Abstraction layer on top of different media players",
"author": "Smart Code OOD",
"main": "src/index.js",
2 changes: 1 addition & 1 deletion src/HTMLVideo/HTMLVideo.js
Original file line number Diff line number Diff line change
@@ -189,7 +189,7 @@ function HTMLVideo(options) {
return Object.freeze({
id: 'EMBEDDED_' + String(index),
lang: track.language,
label: track.label,
label: track.label || null,
origin: 'EMBEDDED',
embedded: true
});
4 changes: 4 additions & 0 deletions src/StremioVideo/StremioVideo.js
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ var EventEmitter = require('eventemitter3');
var cloneDeep = require('lodash.clonedeep');
var deepFreeze = require('deep-freeze');
var selectVideoImplementation = require('./selectVideoImplementation');
var platform = require('../platform');
var ERROR = require('../error');

function StremioVideo() {
@@ -25,6 +26,9 @@ function StremioVideo() {
action = deepFreeze(cloneDeep(action));
options = options || {};
if (action.type === 'command' && action.commandName === 'load' && action.commandArgs) {
if (action.commandArgs.platform) {
platform.set(action.commandArgs.platform);
}
var Video = selectVideoImplementation(action.commandArgs, options);
if (video !== null && video.constructor !== Video) {
video.dispatch({ type: 'command', commandName: 'destroy' });
7 changes: 7 additions & 0 deletions src/StremioVideo/selectVideoImplementation.js
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ var ChromecastSenderVideo = require('../ChromecastSenderVideo');
var ShellVideo = require('../ShellVideo');
var HTMLVideo = require('../HTMLVideo');
var TizenVideo = require('../TizenVideo');
var TitanVideo = require('../TitanVideo');
var WebOsVideo = require('../WebOsVideo');
var IFrameVideo = require('../IFrameVideo');
var YouTubeVideo = require('../YouTubeVideo');
@@ -37,6 +38,9 @@ function selectVideoImplementation(commandArgs, options) {
if (commandArgs.platform === 'webOS') {
return withStreamingServer(withHTMLSubtitles(WebOsVideo));
}
if (commandArgs.platform === 'Titan' || commandArgs.platform === 'NetTV') {
return withStreamingServer(withHTMLSubtitles(TitanVideo));
}
return withStreamingServer(withHTMLSubtitles(HTMLVideo));
}

@@ -47,6 +51,9 @@ function selectVideoImplementation(commandArgs, options) {
if (commandArgs.platform === 'webOS') {
return withVideoParams(withHTMLSubtitles(WebOsVideo));
}
if (commandArgs.platform === 'Titan' || commandArgs.platform === 'NetTV') {
return withVideoParams(withHTMLSubtitles(TitanVideo));
}
return withVideoParams(withHTMLSubtitles(HTMLVideo));
}

667 changes: 667 additions & 0 deletions src/TitanVideo/TitanVideo.js

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/TitanVideo/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var TitanVideo = require('./TitanVideo');

module.exports = TitanVideo;
16 changes: 11 additions & 5 deletions src/TizenVideo/TizenVideo.js
Original file line number Diff line number Diff line change
@@ -244,18 +244,20 @@ function TizenVideo(options) {
extra = JSON.parse(textTrack.extra_info);
} catch(e) {}
var textTrackLang = typeof extra.track_lang === 'string' && extra.track_lang.length > 0 ? extra.track_lang.trim() : null;
var textTrackLabel = null;
if (((tracksData || {}).subs || []).length) {
var extendedTrackData = tracksData.subs.find(function(el) {
return (el || {}).id-1 === textTrack.index;
});
if (extendedTrackData) {
textTrackLang = extendedTrackData.lang || 'eng';
textTrackLabel = extendedTrackData.label || null;
}
}
textTracks.push({
id: textTrackId,
lang: textTrackLang,
label: textTrackLang,
label: textTrackLabel,
origin: 'EMBEDDED',
embedded: true,
mode: !disabledSubs && textTrackId === currentSubTrack ? 'showing' : 'disabled',
@@ -346,18 +348,20 @@ function TizenVideo(options) {
extra = JSON.parse(audioTrack.extra_info);
} catch(e) {}
var audioTrackLang = typeof extra.language === 'string' && extra.language.length > 0 ? extra.language : null;
var audioTrackLabel = null;
if (((tracksData || {}).audio || []).length) {
var extendedTrackData = tracksData.audio.find(function(el) {
return (el || {}).id-1 === audioTrack.index;
});
if (extendedTrackData) {
audioTrackLang = extendedTrackData.lang || 'eng';
audioTrackLabel = extendedTrackData.label || null;
}
}
audioTracks.push({
id: audioTrackId,
lang: audioTrackLang,
label: audioTrackLang,
label: audioTrackLabel,
origin: 'EMBEDDED',
embedded: true,
mode: audioTrackId === currentAudioTrack ? 'showing' : 'disabled',
@@ -633,9 +637,11 @@ function TizenVideo(options) {

var tizenVersion = false;

try {
tizenVersion = parseFloat(global.tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version'));
} catch(e) {}
var TIZEN_MATCHES = navigator.userAgent.match(/Tizen (\d+\.\d+)/i);

if (TIZEN_MATCHES && TIZEN_MATCHES[1]) {
tizenVersion = parseFloat(TIZEN_MATCHES[1]);
}

if (!tizenVersion || tizenVersion >= 6) {
retrieveExtendedTracks();
4 changes: 2 additions & 2 deletions src/WebOsVideo/WebOsVideo.js
Original file line number Diff line number Diff line change
@@ -370,7 +370,7 @@ function WebOsVideo(options) {
textTracks.push({
id: 'EMBEDDED_' + textTrackId,
lang: track.lang || 'eng',
label: track.lang || 'eng',
label: track.label || null,
origin: 'EMBEDDED',
embedded: true,
mode: textTrackId === currentSubTrack ? 'showing' : 'disabled',
@@ -392,7 +392,7 @@ function WebOsVideo(options) {
audioTracks.push({
id: 'EMBEDDED_' + audioTrackId,
lang: track.lang || 'eng',
label: track.lang || 'eng',
label: track.label || null,
origin: 'EMBEDDED',
embedded: true,
mode: audioTrackId === currentAudioTrack ? 'showing' : 'disabled',
6 changes: 6 additions & 0 deletions src/platform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var platform = null;

module.exports = {
set: function(val) { platform = val; },
get: function() { return platform; }
};
4 changes: 3 additions & 1 deletion src/supportsTranscoding.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var platform = require('./platform');

function supportsTranscoding() {
if (typeof global.tizen !== 'undefined' || typeof global.webOS !== 'undefined' || typeof window.qt !== 'undefined') {
if (['Tizen', 'webOS', 'Titan', 'NetTV'].includes(platform.get()) || typeof window.qt !== 'undefined') {
return Promise.resolve(false);
}
return Promise.resolve(true);
72 changes: 40 additions & 32 deletions src/withHTMLSubtitles/withHTMLSubtitles.js
Original file line number Diff line number Diff line change
@@ -226,9 +226,9 @@ function withHTMLSubtitles(Video) {
selectedTrackId = selectedTrack.id;
delay = 0;

function getSubtitlesData() {
if (typeof selectedTrack.url === 'string') {
return fetch(selectedTrack.url)
function getSubtitlesData(track) {
if (typeof track.url === 'string') {
return fetch(track.url)
.then(function(resp) {
if (resp.ok) {
return resp.text();
@@ -238,9 +238,9 @@ function withHTMLSubtitles(Video) {
});
}

if (selectedTrack.buffer instanceof ArrayBuffer) {
if (track.buffer instanceof ArrayBuffer) {
try {
const uInt8Array = new Uint8Array(selectedTrack.buffer);
const uInt8Array = new Uint8Array(track.buffer);
const text = new TextDecoder().decode(uInt8Array);
return Promise.resolve(text);
} catch(e) {
@@ -251,33 +251,41 @@ function withHTMLSubtitles(Video) {
return Promise.reject('No `url` or `buffer` field available for this track');
}

getSubtitlesData()
.then(function(text) {
return subtitlesConverter.convert(text);
})
.then(function(text) {
return subtitlesParser.parse(text);
})
.then(function(result) {
if (selectedTrackId !== selectedTrack.id) {
return;
}

cuesByTime = result;
renderSubtitles();
events.emit('extraSubtitlesTrackLoaded', selectedTrack);
})
.catch(function(error) {
if (selectedTrackId !== selectedTrack.id) {
return;
}

onError(Object.assign({}, ERROR.WITH_HTML_SUBTITLES.LOAD_FAILED, {
error: error,
track: selectedTrack,
critical: false
}));
});
function loadSubtitles(track, isFallback) {
getSubtitlesData(track)
.then(function(text) {
return subtitlesConverter.convert(text);
})
.then(function(text) {
return subtitlesParser.parse(text);
})
.then(function(result) {
if (selectedTrackId !== selectedTrack.id) {
return;
}

cuesByTime = result;
renderSubtitles();
events.emit('extraSubtitlesTrackLoaded', selectedTrack);
})
.catch(function(error) {
if (selectedTrackId !== selectedTrack.id) {
return;
}

if (!isFallback && typeof selectedTrack.fallbackUrl === 'string') {
loadSubtitles(selectedTrack, true);
return;
}

onError(Object.assign({}, ERROR.WITH_HTML_SUBTITLES.LOAD_FAILED, {
error: error,
track: selectedTrack,
critical: false
}));
});
}
loadSubtitles(selectedTrack);
}
renderSubtitles();
onPropChanged('selectedExtraSubtitlesTrackId');
2 changes: 2 additions & 0 deletions src/withStreamingServer/withStreamingServer.js
Original file line number Diff line number Diff line change
@@ -259,6 +259,8 @@ function withStreamingServer(Video) {
commandArgs: Object.assign({}, commandArgs, {
tracks: commandArgs.tracks.map(function(track) {
return Object.assign({}, track, {
// fallback is used in case server conversion fails (if server is offline)
fallbackUrl: track.url,
url: typeof track.url === 'string' ?
url.resolve(loadArgs.streamingServerURL, '/subtitles.vtt?' + new URLSearchParams([['from', track.url]]).toString())
:

0 comments on commit 1537a0e

Please sign in to comment.