From 16674571881d3b6d8ceb698150367f0a9c67cd41 Mon Sep 17 00:00:00 2001 From: Harvey Zack Date: Fri, 23 Nov 2018 16:23:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AD=97=E5=B9=95=E6=8F=92?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/lab/css/artplayer-plugin-subtitle.css | 1 + docs/lab/css/artplayer.css | 2 +- docs/lab/index.html | 1 + docs/lab/js/artplayer-plugin-subtitle.js | 68 +++++ docs/lab/js/artplayer-plugin-subtitle.js.map | 1 + docs/lab/js/artplayer.js | 102 +++---- docs/lab/js/artplayer.js.map | 2 +- docs/lab/js/index.js | 252 +++++++++--------- .../src/contextmenuMix.js | 3 - .../artplayer-plugin-danmu/src/controlMix.js | 3 - .../artplayer-plugin-danmu/src/i18nMix.js | 3 - packages/artplayer-plugin-danmu/src/index.js | 21 +- .../artplayer-plugin-danmu/src/settingMix.js | 3 - packages/artplayer-plugin-subtitle/.babelrc | 11 + packages/artplayer-plugin-subtitle/.npmignore | 9 + packages/artplayer-plugin-subtitle/.npmrc | 1 + packages/artplayer-plugin-subtitle/README.md | 51 ++++ .../artplayer-plugin-subtitle/package.json | 50 ++++ .../rollup.config.js | 63 +++++ .../artplayer-plugin-subtitle/src/index.js | 33 +++ packages/artplayer/src/index.js | 27 +- packages/artplayer/src/scheme/index.js | 6 + packages/artplayer/src/style/artplayer.scss | 4 - packages/artplayer/src/subtitle.js | 22 +- 24 files changed, 492 insertions(+), 247 deletions(-) create mode 100644 docs/lab/css/artplayer-plugin-subtitle.css create mode 100644 docs/lab/js/artplayer-plugin-subtitle.js create mode 100644 docs/lab/js/artplayer-plugin-subtitle.js.map delete mode 100644 packages/artplayer-plugin-danmu/src/contextmenuMix.js delete mode 100644 packages/artplayer-plugin-danmu/src/controlMix.js delete mode 100644 packages/artplayer-plugin-danmu/src/i18nMix.js delete mode 100644 packages/artplayer-plugin-danmu/src/settingMix.js create mode 100644 packages/artplayer-plugin-subtitle/.babelrc create mode 100644 packages/artplayer-plugin-subtitle/.npmignore create mode 100644 packages/artplayer-plugin-subtitle/.npmrc create mode 100644 packages/artplayer-plugin-subtitle/README.md create mode 100644 packages/artplayer-plugin-subtitle/package.json create mode 100644 packages/artplayer-plugin-subtitle/rollup.config.js create mode 100644 packages/artplayer-plugin-subtitle/src/index.js diff --git a/docs/lab/css/artplayer-plugin-subtitle.css b/docs/lab/css/artplayer-plugin-subtitle.css new file mode 100644 index 000000000..21f9dd122 --- /dev/null +++ b/docs/lab/css/artplayer-plugin-subtitle.css @@ -0,0 +1 @@ +.artplayerPluginDanmu{display:flex} \ No newline at end of file diff --git a/docs/lab/css/artplayer.css b/docs/lab/css/artplayer.css index 17bb67296..f4288d2ef 100644 --- a/docs/lab/css/artplayer.css +++ b/docs/lab/css/artplayer.css @@ -1,4 +1,4 @@ -.artplayer-video-player{position:relative;width:100%;height:100%;overflow:hidden;outline:0;font-family:Roboto,Arial,Helvetica,sans-serif;color:#eee;text-align:left;direction:ltr;font-size:14px;line-height:1.3;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);touch-action:manipulation;-ms-high-contrast-adjust:none}.artplayer-video-player *{box-sizing:border-box}.artplayer-video-player .art-icon{display:inline-block;line-height:1.5}.artplayer-video-player .art-icon svg{fill:#fff}.artplayer-video-player .art-hide{display:none!important} +.artplayer-video-player{position:relative;width:100%;height:100%;overflow:hidden;outline:0;font-family:Roboto,Arial,Helvetica,sans-serif;color:#eee;text-align:left;direction:ltr;font-size:14px;line-height:1.3;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);touch-action:manipulation;-ms-high-contrast-adjust:none}.artplayer-video-player *{box-sizing:border-box}.artplayer-video-player .art-icon{display:inline-block;line-height:1.5}.artplayer-video-player .art-icon svg{fill:#fff} .artplayer-video-player .artplayer-video{position:absolute;z-index:10;left:0;top:0;right:0;bottom:0;width:100%;height:100%;background-color:#000;outline:0;cursor:pointer} .artplayer-video-player .artplayer-subtitle{position:absolute;z-index:20;bottom:40px;width:100%;padding:0 20px;text-align:center;color:#fff;text-shadow:.5px .5px .5px rgba(0,0,0,.5);font-size:20px;pointer-events:none}.artplayer-video-player .artplayer-subtitle p{margin:5px 0} .artplayer-video-player .artplayer-layers{position:absolute;z-index:30;left:0;top:0;right:0;bottom:0;width:100%;height:100%;pointer-events:none}.artplayer-video-player .artplayer-layers .art-layer{pointer-events:all} diff --git a/docs/lab/index.html b/docs/lab/index.html index b994a2aae..183eff7bb 100644 --- a/docs/lab/index.html +++ b/docs/lab/index.html @@ -41,6 +41,7 @@ + +``` + +Will expose the global variable to `window.artplayerPluginSubtitle`. + +## Usage + +```html +
+``` + +```js +var art = new Artplayer({ + container: '.artplayer-app', + url: 'path/to/video.mp4', + plugins: [ + artplayerPluginSubtitle({ + time: -1, // Subtitle delay time, ranging from -10 to 10 + }), + ], +}); +``` + +## License + +MIT © [Harvey Zack](https://www.zhw-island.com/) diff --git a/packages/artplayer-plugin-subtitle/package.json b/packages/artplayer-plugin-subtitle/package.json new file mode 100644 index 000000000..08ff02624 --- /dev/null +++ b/packages/artplayer-plugin-subtitle/package.json @@ -0,0 +1,50 @@ +{ + "name": "artplayer-plugin-subtitle", + "version": "1.0.3", + "description": "Danmu plugin for ArtPlayer", + "main": "dist/artplayer-plugin-subtitle.js", + "style": "dist/artplayer-plugin-subtitle.css", + "scripts": { + "dev": "cross-env NODE_ENV=development rollup -c -m -w", + "build": "cross-env NODE_ENV=production rollup -c", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "keywords": [ + "video", + "player" + ], + "author": "Harvey Zack ", + "license": "MIT", + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "homepage": "https://github.com/zhw2590582/ArtPlayer#readme", + "devDependencies": { + "@babel/core": "^7.1.2", + "@babel/plugin-external-helpers": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.1.0", + "@babel/preset-env": "^7.1.0", + "@babel/runtime": "^7.1.2", + "autoprefixer": "^9.3.1", + "browser-env": "^3.2.5", + "cross-env": "^5.2.0", + "cssnano": "^4.1.7", + "node-sass": "^4.9.4", + "rollup": "^0.67.0", + "rollup-plugin-babel": "^4.0.3", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-eslint": "^5.0.0", + "rollup-plugin-node-resolve": "^3.4.0", + "rollup-plugin-postcss": "^1.6.2", + "rollup-plugin-replace": "^2.1.0", + "rollup-plugin-svgo": "^1.0.1", + "rollup-plugin-uglify": "^6.0.0" + }, + "dependencies": { + "vtt-adjust": "^1.0.2" + } +} diff --git a/packages/artplayer-plugin-subtitle/rollup.config.js b/packages/artplayer-plugin-subtitle/rollup.config.js new file mode 100644 index 000000000..5848aba0d --- /dev/null +++ b/packages/artplayer-plugin-subtitle/rollup.config.js @@ -0,0 +1,63 @@ +const path = require('path'); +const babel = require('rollup-plugin-babel'); +const commonjs = require('rollup-plugin-commonjs'); +const nodeResolve = require('rollup-plugin-node-resolve'); +const postcss = require('rollup-plugin-postcss'); +const { eslint } = require('rollup-plugin-eslint'); +const autoprefixer = require('autoprefixer'); +const cssnano = require('cssnano'); +const replace = require('rollup-plugin-replace'); +const svgo = require('rollup-plugin-svgo'); +const { uglify } = require('rollup-plugin-uglify'); +const { version, homepage, name } = require('./package.json'); + +const isProd = process.env.NODE_ENV === 'production'; + +const banner = + '/*!\n' + + ` * ${name}.js v${version}\n` + + ` * Github: ${homepage}\n` + + ` * (c) 2017-${new Date().getFullYear()} Harvey Zack\n` + + ' * Released under the MIT License.\n' + + ' */\n'; + +export default { + input: 'src/index.js', + output: { + name, + file: isProd ? `dist/${name}.js` : path.join(process.cwd(), '../../', `docs/lab/js/${name}.js`), + format: 'umd', + exports: 'named', + }, + plugins: [ + eslint({ + exclude: ['node_modules/**', 'src/**/*.scss', 'src/**/*.svg'], + }), + postcss({ + plugins: [autoprefixer, cssnano], + extract: isProd ? `dist/${name}.css` : path.join(process.cwd(), '../../', `docs/lab/css/${name}.css`), + }), + nodeResolve(), + commonjs(), + babel({ + runtimeHelpers: true, + exclude: 'node_modules/**', + presets: [['@babel/env', { modules: false }]], + plugins: ['@babel/plugin-external-helpers', '@babel/plugin-transform-runtime'], + }), + svgo({ + raw: true, + }), + replace({ + exclude: 'node_modules/**', + __ENV__: JSON.stringify(process.env.NODE_ENV || 'development'), + __VERSION__: version, + }), + isProd && + uglify({ + output: { + preamble: banner, + }, + }), + ], +}; diff --git a/packages/artplayer-plugin-subtitle/src/index.js b/packages/artplayer-plugin-subtitle/src/index.js new file mode 100644 index 000000000..31f0e47e5 --- /dev/null +++ b/packages/artplayer-plugin-subtitle/src/index.js @@ -0,0 +1,33 @@ +function artplayerPluginSubtitle(option) { + return art => { + const { errorHandle, clamp, sleep } = art.constructor.utils; + + errorHandle( + option && typeof option.time === 'number', + `The plugin 'artplayerPluginSubtitle': 'option.time' require 'number' type, but got '${typeof option.time}'`, + ); + + let retry = 0; + const maxRetry = 10; + const time = clamp(option.time, -10, 10); + + function adjust() { + errorHandle(retry < maxRetry, 'It seems that something wrong for reading subtitle'); + retry += 1; + const cues = Array.from(art.refs.$track.track.cues); + if (cues.length === 0) { + sleep(100).then(adjust); + } else { + cues.forEach(cue => { + cue.startTime += time; + cue.endTime += time; + }); + } + } + + art.on('subtitle:load', adjust); + }; +} + +window.artplayerPluginSubtitle = artplayerPluginSubtitle; +export default artplayerPluginSubtitle; diff --git a/packages/artplayer/src/index.js b/packages/artplayer/src/index.js index 4307728b9..0aef2f85c 100644 --- a/packages/artplayer/src/index.js +++ b/packages/artplayer/src/index.js @@ -71,6 +71,7 @@ class Artplayer extends Emitter { quality: [], controls: [], highlight: [], + plugins: [], thumbnails: { url: '', number: 60, @@ -90,18 +91,6 @@ class Artplayer extends Emitter { }; } - static use(...args) { - const plugin = args[0]; - const installedPlugins = this.plugins || (this.plugins = []); - if (installedPlugins.indexOf === -1) { - installedPlugins.push(plugin); - args.unshift(this); - plugin(...args.slice(1)); - this.prototype.emit('use', plugin); - } - return this; - } - init() { this.isFocus = false; this.isPlaying = false; @@ -136,6 +125,20 @@ class Artplayer extends Emitter { id += 1; this.id = id; Artplayer.instances.push(this); + + this.plugins = []; + this.option.plugins.forEach((plugin, index) => { + const resule = plugin(this); + let pluginName = ''; + if (resule && resule.name) { + pluginName = resule.name; + } else if (plugin.name) { + pluginName = plugin.name; + } else { + pluginName = `plugin${index}`; + } + this.plugins[pluginName] = resule; + }); } destroy(removeHtml = false) { diff --git a/packages/artplayer/src/scheme/index.js b/packages/artplayer/src/scheme/index.js index 1c5c0a4c4..9c52c9742 100644 --- a/packages/artplayer/src/scheme/index.js +++ b/packages/artplayer/src/scheme/index.js @@ -32,6 +32,12 @@ export default { mutex: 'boolean', fullscreen: 'boolean', fullscreenWeb: 'boolean', + plugins: { + type: 'array', + child: { + type: 'function', + }, + }, layers: { type: 'array', child: { diff --git a/packages/artplayer/src/style/artplayer.scss b/packages/artplayer/src/style/artplayer.scss index 0bbba3bba..53f8bfe32 100644 --- a/packages/artplayer/src/style/artplayer.scss +++ b/packages/artplayer/src/style/artplayer.scss @@ -26,8 +26,4 @@ fill: #fff; } } - - .art-hide { - display: none !important; - } } \ No newline at end of file diff --git a/packages/artplayer/src/subtitle.js b/packages/artplayer/src/subtitle.js index b96dd1f10..9bb66c547 100644 --- a/packages/artplayer/src/subtitle.js +++ b/packages/artplayer/src/subtitle.js @@ -5,7 +5,6 @@ export default class Subtitle { constructor(art) { this.art = art; this.state = true; - this.vttText = ''; const { url } = this.art.option.subtitle; if (url) { this.init(); @@ -22,10 +21,11 @@ export default class Subtitle { const $track = document.createElement('track'); $track.default = true; $track.kind = 'metadata'; - this.load(subtitle.url).then(data => { - $track.src = data; - $video.appendChild($track); - this.art.refs.$track = $track; + $video.appendChild($track); + this.art.refs.$track = $track; + this.load(subtitle.url).then(vttText => { + $track.src = vttToBlob(vttText); + this.art.emit('subtitle:load', vttText); if ($video.textTracks && $video.textTracks[0]) { const [track] = $video.textTracks; proxy(track, 'cuechange', () => { @@ -54,12 +54,13 @@ export default class Subtitle { return response.text(); }) .then(text => { + let vttText = ''; if (/x-subrip/gi.test(type)) { - this.vttText = srtToVtt(text); + vttText = srtToVtt(text); } else { - this.vttText = text; + vttText = text; } - return vttToBlob(this.vttText); + return vttText; }) .catch(err => { notice.show(err); @@ -103,8 +104,9 @@ export default class Subtitle { switch(url) { const { $track } = this.art.refs; errorHandle($track, 'You need to initialize the subtitle option first.'); - this.load(url).then(data => { - $track.src = data; + this.load(url).then(vttText => { + $track.src = vttToBlob(vttText); + this.art.emit('subtitle:load', vttText); this.art.emit('subtitle:switch', url); }); }