mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-16 17:46:17 -08:00
add srt
This commit is contained in:
1 parent
1d1bf15f0d
commit
8b6258c4e5
11 files changed
+331
-169
No files matched your search
@@ -24,13 +24,15 @@ export default class Thumbnails {
|
||||
showThumbnails(event) {
|
||||
const { $progress } = this.art.refs;
|
||||
const { width: posWidth } = this.getPosFromEvent(event);
|
||||
const { url, height, width, number } = this.art.option.thumbnails;
|
||||
const { url, height, width, number, column } = this.art.option.thumbnails;
|
||||
const perWidth = $progress.clientWidth / number;
|
||||
const index = Math.ceil(posWidth / perWidth);
|
||||
const perIndex = Math.ceil(posWidth / perWidth);
|
||||
let yIndex = Math.ceil(perIndex / column);
|
||||
let xIndex = perIndex % column || column;
|
||||
this.option.ref.style.backgroundImage = `url(${url})`;
|
||||
this.option.ref.style.height = `${height}px`;
|
||||
this.option.ref.style.width = `${width}px`;
|
||||
this.option.ref.style.backgroundPosition = `-${index * width}px 0`;
|
||||
this.option.ref.style.backgroundPosition = `-${--xIndex * width}px -${--yIndex * height}px`;
|
||||
|
||||
if (posWidth <= width / 2) {
|
||||
this.option.ref.style.left = 0;
|
||||
|
||||
+5
-11
@@ -1,4 +1,5 @@
|
||||
import './style/index.scss';
|
||||
import { deepMerge } from './utils';
|
||||
import validOption from './verification/player';
|
||||
import config from './config';
|
||||
import Emitter from 'tiny-emitter';
|
||||
@@ -16,7 +17,6 @@ import Layers from './layers';
|
||||
import Loading from './loading';
|
||||
import Notice from './notice';
|
||||
import Mask from './mask';
|
||||
import plugins from './plugins';
|
||||
|
||||
let id = 0;
|
||||
export const instances = [];
|
||||
@@ -25,10 +25,9 @@ class Artplayer extends Emitter {
|
||||
constructor(option) {
|
||||
super();
|
||||
this.emit('init:start');
|
||||
this.option = Object.assign({}, Artplayer.DEFAULTS, option);
|
||||
this.option = deepMerge({}, Artplayer.DEFAULTS, option);
|
||||
validOption(this.option);
|
||||
this.init();
|
||||
this.usePlugins();
|
||||
this.emit('init:end');
|
||||
}
|
||||
|
||||
@@ -47,9 +46,10 @@ class Artplayer extends Emitter {
|
||||
poster: '',
|
||||
thumbnails: {
|
||||
url: '',
|
||||
number: 100,
|
||||
number: 60,
|
||||
width: 160,
|
||||
height: 90
|
||||
height: 90,
|
||||
column: 10
|
||||
},
|
||||
volume: 0.7,
|
||||
autoplay: false,
|
||||
@@ -116,12 +116,6 @@ class Artplayer extends Emitter {
|
||||
return this;
|
||||
}
|
||||
|
||||
usePlugins() {
|
||||
Object.keys(plugins).forEach(name => {
|
||||
Artplayer.use(plugins[name]);
|
||||
});
|
||||
}
|
||||
|
||||
destroy(removeHtml = false) {
|
||||
this.events.destroy();
|
||||
instances.splice(instances.indexOf(this), 1);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import Srt from './srt';
|
||||
import Mse from './mse';
|
||||
|
||||
export default {
|
||||
Srt,
|
||||
Mse
|
||||
};
|
||||
@@ -50,6 +50,10 @@
|
||||
color: #fff;
|
||||
text-shadow: 0.5px 0.5px 0.5px rgba(0, 0, 0, 0.5);
|
||||
font-size: 20px;
|
||||
|
||||
p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.artplayer-layers {
|
||||
|
||||
+72
-34
@@ -3,13 +3,8 @@ import { errorHandle, getExt, setStyle } from './utils';
|
||||
export default class Subtitle {
|
||||
constructor(art) {
|
||||
this.art = art;
|
||||
if (this.art.option.subtitle) {
|
||||
errorHandle(
|
||||
getExt(this.art.option.subtitle.url) === 'vtt',
|
||||
`'url' option require 'vtt' format, but got '${getExt(this.art.option.subtitle.url)}'.`
|
||||
);
|
||||
this.init();
|
||||
}
|
||||
this.checkExt(this.art.option.subtitle.url);
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
@@ -23,26 +18,71 @@ export default class Subtitle {
|
||||
const $track = document.createElement('track');
|
||||
$track.default = true;
|
||||
$track.kind = 'metadata';
|
||||
$track.src = subtitle.url;
|
||||
$video.appendChild($track);
|
||||
this.art.refs.$track = $track;
|
||||
|
||||
if ($video.textTracks && $video.textTracks[0]) {
|
||||
const [track] = $video.textTracks;
|
||||
proxy(track, 'cuechange', () => {
|
||||
const [cue] = track.activeCues;
|
||||
$subtitle.innerHTML = '';
|
||||
if (cue) {
|
||||
const template = document.createElement('div');
|
||||
template.appendChild(cue.getCueAsHTML());
|
||||
$subtitle.innerHTML = template.innerHTML
|
||||
.split(/\r?\n/)
|
||||
.map(item => `<p>${item}</p>`)
|
||||
.join('');
|
||||
this.load(subtitle.url).then(data => {
|
||||
$track.src = data;
|
||||
$video.appendChild($track);
|
||||
this.art.refs.$track = $track;
|
||||
if ($video.textTracks && $video.textTracks[0]) {
|
||||
const [track] = $video.textTracks;
|
||||
proxy(track, 'cuechange', () => {
|
||||
const [cue] = track.activeCues;
|
||||
$subtitle.innerHTML = '';
|
||||
if (cue) {
|
||||
const template = document.createElement('div');
|
||||
template.appendChild(cue.getCueAsHTML());
|
||||
$subtitle.innerHTML = template.innerHTML
|
||||
.split(/\r?\n/)
|
||||
.map(item => `<p>${item}</p>`)
|
||||
.join('');
|
||||
}
|
||||
this.art.emit('subtitle:update', $subtitle);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
load(url) {
|
||||
let type;
|
||||
return fetch(url)
|
||||
.then(response => {
|
||||
type = response.headers.get('Content-Type');
|
||||
return response.text();
|
||||
})
|
||||
.then(text => {
|
||||
if ((/x-subrip/gi).test(type)) {
|
||||
return this.srtToVtt(text);
|
||||
}
|
||||
this.art.emit('subtitle:update', $subtitle);
|
||||
return url;
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
srtToVtt(text) {
|
||||
const vttText = 'WEBVTT \r\n\r\n'.concat(
|
||||
text
|
||||
.replace(/\{\\([ibu])\}/g, '</$1>')
|
||||
.replace(/\{\\([ibu])1\}/g, '<$1>')
|
||||
.replace(/\{([ibu])\}/g, '<$1>')
|
||||
.replace(/\{\/([ibu])\}/g, '</$1>')
|
||||
.replace(/(\d\d:\d\d:\d\d),(\d\d\d)/g, '$1.$2')
|
||||
.concat('\r\n\r\n')
|
||||
);
|
||||
return URL.createObjectURL(
|
||||
new Blob([vttText], {
|
||||
type: 'text/vtt'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
checkExt(url) {
|
||||
const ext = getExt(url);
|
||||
errorHandle(
|
||||
ext === 'vtt' || ext === 'srt',
|
||||
`'url' option require 'vtt' or 'srt' format, but got '${ext}'.`
|
||||
);
|
||||
}
|
||||
|
||||
show() {
|
||||
@@ -59,15 +99,13 @@ export default class Subtitle {
|
||||
|
||||
switch(url) {
|
||||
const { $track } = this.art.refs;
|
||||
errorHandle(
|
||||
getExt(url) === 'vtt',
|
||||
`'url' option require 'vtt' format, but got '${getExt(url)}'.`
|
||||
);
|
||||
errorHandle(
|
||||
$track,
|
||||
'You need to initialize the subtitle option first.'
|
||||
);
|
||||
$track.src = url;
|
||||
this.art.emit('subtitle:switch', url);
|
||||
this.checkExt(url);
|
||||
errorHandle($track, 'You need to initialize the subtitle option first.');
|
||||
this.load(url).then(data => {
|
||||
if (url !== data) {
|
||||
$track.src = data;
|
||||
this.art.emit('subtitle:switch', url);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+24
-2
@@ -1,7 +1,8 @@
|
||||
import ArtPlayerError from './ArtPlayerError';
|
||||
|
||||
export function errorHandle(condition, msg) {
|
||||
if (!condition) {
|
||||
const isFun = typeof condition === 'function';
|
||||
if (isFun ? !isFun() : !condition) {
|
||||
throw new ArtPlayerError(msg);
|
||||
}
|
||||
}
|
||||
@@ -43,9 +44,30 @@ export function setStyle(element, styles) {
|
||||
}
|
||||
|
||||
export function secondToTime(second) {
|
||||
const add0 = num => num < 10 ? `0${num}` : String(num);
|
||||
const add0 = num => (num < 10 ? `0${num}` : String(num));
|
||||
const hour = Math.floor(second / 3600);
|
||||
const min = Math.floor((second - hour * 3600) / 60);
|
||||
const sec = Math.floor(second - hour * 3600 - min * 60);
|
||||
return (hour > 0 ? [hour, min, sec] : [min, sec]).map(add0).join(':');
|
||||
}
|
||||
|
||||
export function deepMerge(...sources) {
|
||||
const isObject = value => value !== null && typeof value === 'object';
|
||||
let returnValue = {};
|
||||
for (const source of sources) {
|
||||
if (Array.isArray(source)) {
|
||||
if (!Array.isArray(returnValue)) {
|
||||
returnValue = [];
|
||||
}
|
||||
returnValue = [...returnValue, ...source];
|
||||
} else if (isObject(source)) {
|
||||
for (let [key, value] of Object.entries(source)) {
|
||||
if (isObject(value) && Reflect.has(returnValue, key)) {
|
||||
value = deepMerge(returnValue[key], value);
|
||||
}
|
||||
returnValue = { ...returnValue, [key]: value };
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
Reference in new issue
Block a user