diff --git a/package.json b/package.json index bcbdd3dacc..0a3cd85085 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "libjass": "^0.11.0", "shaka-player": "^2.5.5", "sortablejs": "^1.9.0", - "swiper": "^3.4.2" + "swiper": "^3.4.2", + "libass-wasm": "^2.1.1" }, "scripts": { "serve": "webpack-dev-server --config webpack.dev.js --open", diff --git a/src/bundle.js b/src/bundle.js index 86e10aab7d..cf01bc5f1c 100644 --- a/src/bundle.js +++ b/src/bundle.js @@ -42,3 +42,7 @@ _define("sortable", function() { return sortable; }); var libjass = require("libjass"); require("libjass/libjass.css"); _define("libjass", function() { return libjass; }); + +// libass-wasm +var libass_wasm = require("libass-wasm"); +_define("JavascriptSubtitlesOctopus", function() { return libass_wasm; }); diff --git a/src/components/htmlvideoplayer/plugin.js b/src/components/htmlvideoplayer/plugin.js index 27e02349c0..938668ef72 100644 --- a/src/components/htmlvideoplayer/plugin.js +++ b/src/components/htmlvideoplayer/plugin.js @@ -27,6 +27,14 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa return _supportsTextTracks; } + function supportsCanvas() { + return !!document.createElement('canvas').getContext; + } + + function supportsWebWorkers() { + return !!window.Worker; + } + function enableNativeTrackSupport(currentSrc, track) { if (track) { @@ -185,6 +193,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa var lastCustomTrackMs = 0; var currentClock; + var currentSubtitlesOctopus; var currentAssRenderer; var customTrackIndex = -1; @@ -960,6 +969,12 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa currentClock = null; self._currentAspectRatio = null; + var octopus = currentSubtitlesOctopus; + if (octopus) { + octopus.dispose(); + } + currentSubtitlesOctopus = null; + var renderer = currentAssRenderer; if (renderer) { renderer.setEnabled(false); @@ -1024,6 +1039,21 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa lastCustomTrackMs = 0; } + function renderWithSubtitlesOctopus(videoElement, track, item) { + var options = { + video: videoElement, + subUrl: getTextTrackUrl(track, item), + fonts: [], + workerUrl: appRouter.baseUrl() + "/JavascriptSubtitlesOctopus/subtitles-octopus-worker.js", + onError: function() { + htmlMediaHelper.onErrorInternal(self, 'mediadecodeerror') + } + }; + require(['JavascriptSubtitlesOctopus'], function(SubtitlesOctopus) { + currentSubtitlesOctopus = new SubtitlesOctopus(options); + }); + } + function renderWithLibjass(videoElement, track, item) { var rendererSettings = {}; @@ -1071,6 +1101,14 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa }); } + function renderSsaAss(videoElement, track, item) { + if (supportsCanvas() && supportsWebWorkers()) { + renderWithSubtitlesOctopus(videoElement, track, item); + } else { + renderWithLibjass(videoElement, track, item); + } + } + function onVideoResize() { if (browser.iOS) { // the new sizes will be delayed for about 500ms with wkwebview @@ -1181,7 +1219,7 @@ define(['browser', 'require', 'events', 'apphost', 'loading', 'dom', 'playbackMa var format = (track.Codec || '').toLowerCase(); if (format === 'ssa' || format === 'ass') { // libjass is needed here - renderWithLibjass(videoElement, track, item); + renderSsaAss(videoElement, track, item); return; } diff --git a/src/components/htmlvideoplayer/style.css b/src/components/htmlvideoplayer/style.css index 9550f2c873..32c090eeae 100644 --- a/src/components/htmlvideoplayer/style.css +++ b/src/components/htmlvideoplayer/style.css @@ -24,6 +24,10 @@ z-index: 1000; } +.videoPlayerContainer .libassjs-canvas-parent { + order: -1; +} + video::-webkit-media-controls { display: none !important; } diff --git a/webpack.common.js b/webpack.common.js index 05b2b0cb46..00b3d0dea8 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -10,9 +10,18 @@ module.exports = { ] }, plugins: [ - new CopyPlugin([{ - from: "**/*", - to: "." - }]) + new CopyPlugin([ + { + from: "**/*", + to: "." + }, + { + from: "../node_modules/libass-wasm/dist/subtitles-octopus-worker.*", + to: "JavascriptSubtitlesOctopus", + transformPath(targetPath, absolutePath) { + return Promise.resolve(path.join("JavascriptSubtitlesOctopus", path.basename(targetPath))); + } + } + ]) ] };