mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-20 12:11:20 -08:00
添加字幕本地预览
This commit is contained in:
1 parent
2878705e72
commit
9cf1571ef8
15 files changed
+279
-81
No files matched your search
@@ -30,5 +30,5 @@
|
||||
"Web fullscreen": "网页全屏",
|
||||
"Exit web fullscreen": "退出网页全屏",
|
||||
"Mini player": "迷你播放器",
|
||||
"This does not seem to support full screen functionality": "似乎不支持全屏功能"
|
||||
}
|
||||
"Does not support fullscreen": "不支持全屏"
|
||||
}
|
||||
@@ -30,5 +30,5 @@
|
||||
"Web fullscreen": "網頁全屏",
|
||||
"Exit web fullscreen": "退出網頁全屏",
|
||||
"Mini player": "迷你播放器",
|
||||
"This does not seem to support full screen functionality": "似乎不支持全屏功能"
|
||||
"Does not support fullscreen": "不支持全屏"
|
||||
}
|
||||
@@ -123,7 +123,8 @@ class Artplayer extends Emitter {
|
||||
fullscreenWeb: false,
|
||||
subtitleOffset: false,
|
||||
miniProgressBar: false,
|
||||
localPreview: false,
|
||||
localVideo: false,
|
||||
localSubtitle: false,
|
||||
autoPip: false,
|
||||
networkMonitor: false,
|
||||
layers: [],
|
||||
|
||||
@@ -14,7 +14,7 @@ export default function fullscreenMix(art, player) {
|
||||
};
|
||||
|
||||
const screenfullError = () => {
|
||||
notice.show(i18n.get('This does not seem to support full screen functionality'));
|
||||
notice.show(i18n.get('Does not support fullscreen'));
|
||||
};
|
||||
|
||||
if (player.fullscreenIsEnabled) {
|
||||
|
||||
@@ -4,6 +4,7 @@ export default function switchMix(art, player) {
|
||||
Object.defineProperty(player, 'switchQuality', {
|
||||
value: (url, name = 'unknown') => {
|
||||
if (url !== template.$video.src) {
|
||||
URL.revokeObjectURL(template.$video.src);
|
||||
const { currentTime, playing } = player;
|
||||
return player.attachUrl(url).then(() => {
|
||||
option.url = url;
|
||||
@@ -26,6 +27,7 @@ export default function switchMix(art, player) {
|
||||
Object.defineProperty(player, 'switchUrl', {
|
||||
value: (url, name = 'unknown') => {
|
||||
if (url !== template.$video.src) {
|
||||
URL.revokeObjectURL(template.$video.src);
|
||||
const { playing } = player;
|
||||
return player.attachUrl(url).then(() => {
|
||||
option.url = url;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { errorHandle, hasOwnProperty } from '../utils';
|
||||
import subtitleOffset from './subtitleOffset';
|
||||
import localPreview from './localPreview';
|
||||
import localVideo from './localVideo';
|
||||
import localSubtitle from './localSubtitle';
|
||||
import miniProgressBar from './miniProgressBar';
|
||||
import networkMonitor from './networkMonitor';
|
||||
import autoPip from './autoPip';
|
||||
@@ -20,8 +21,12 @@ export default class Plugins {
|
||||
this.add(miniProgressBar);
|
||||
}
|
||||
|
||||
if (option.localPreview) {
|
||||
this.add(localPreview);
|
||||
if (option.localVideo) {
|
||||
this.add(localVideo);
|
||||
}
|
||||
|
||||
if (option.localSubtitle) {
|
||||
this.add(localSubtitle);
|
||||
}
|
||||
|
||||
if (option.networkMonitor) {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { append, setStyle, setStyles, errorHandle, getExt, vttToBlob, srtToVtt, assToVtt } from '../utils';
|
||||
|
||||
export default function localSubtitle(art) {
|
||||
const {
|
||||
events: { proxy },
|
||||
notice,
|
||||
i18n,
|
||||
subtitle,
|
||||
} = art;
|
||||
|
||||
const notSupport = 'Only supports subtitle files in .ass, .vtt and .srt format';
|
||||
i18n.update({
|
||||
'zh-cn': {
|
||||
[notSupport]: '只支持 .ass、.vtt 和 .srt 格式的字幕文件',
|
||||
},
|
||||
'zh-tw': {
|
||||
[notSupport]: '只支持 .ass、.vtt 和 .srt 格式的字幕文件',
|
||||
},
|
||||
});
|
||||
|
||||
function loadSubtitle(file) {
|
||||
if (file) {
|
||||
const type = getExt(file.name);
|
||||
if (['ass', 'vtt', 'srt'].includes(type)) {
|
||||
const reader = new FileReader();
|
||||
proxy(reader, 'load', event => {
|
||||
const text = event.target.result;
|
||||
switch (type) {
|
||||
case 'srt': {
|
||||
const url = vttToBlob(srtToVtt(text));
|
||||
subtitle.switch(url, file.name);
|
||||
break;
|
||||
}
|
||||
case 'ass': {
|
||||
const url = vttToBlob(assToVtt(text));
|
||||
subtitle.switch(url, file.name);
|
||||
break;
|
||||
}
|
||||
case 'vtt': {
|
||||
const url = vttToBlob(text);
|
||||
subtitle.switch(url, file.name);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
reader.readAsText(file);
|
||||
} else {
|
||||
const tip = i18n.get(notSupport);
|
||||
notice.show(tip, true, 3000);
|
||||
errorHandle(false, tip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'localSubtitle',
|
||||
attach(target) {
|
||||
const $input = append(target, '<input type="file">');
|
||||
setStyle(target, 'position', 'relative');
|
||||
setStyles($input, {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
left: '0',
|
||||
top: '0',
|
||||
opacity: '0',
|
||||
});
|
||||
proxy($input, 'change', () => {
|
||||
const file = $input.files[0];
|
||||
loadSubtitle(file);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
+10
-19
@@ -1,41 +1,33 @@
|
||||
export default function localPreview(art) {
|
||||
const { append, setStyle, setStyles, sleep, errorHandle } = art.constructor.utils;
|
||||
import { append, setStyle, setStyles, errorHandle, getExt } from '../utils';
|
||||
|
||||
export default function localVideo(art) {
|
||||
const {
|
||||
events: { proxy },
|
||||
option,
|
||||
notice,
|
||||
i18n,
|
||||
template,
|
||||
player,
|
||||
} = art;
|
||||
|
||||
const notSupport = 'Playback of this file format is not supported';
|
||||
i18n.update({
|
||||
'zh-cn': {
|
||||
'Playback of this file format is not supported': '不支持播放该文件格式',
|
||||
'Load local video successfully': '加载本地视频成功',
|
||||
[notSupport]: '不支持播放该文件格式',
|
||||
},
|
||||
'zh-tw': {
|
||||
'Playback of this file format is not supported': '不支持播放該文件格式',
|
||||
'Load local video successfully': '加載本地視頻成功',
|
||||
[notSupport]: '不支持播放該文件格式',
|
||||
},
|
||||
});
|
||||
|
||||
function loadVideo(file) {
|
||||
if (file) {
|
||||
const type = getExt(file.name);
|
||||
const canPlayType = template.$video.canPlayType(file.type);
|
||||
if (canPlayType === 'maybe' || canPlayType === 'probably') {
|
||||
const url = URL.createObjectURL(file);
|
||||
player.playbackRate = false;
|
||||
player.aspectRatio = false;
|
||||
template.$video.src = url;
|
||||
sleep(1000).then(() => {
|
||||
player.currentTime = 0;
|
||||
});
|
||||
option.url = url;
|
||||
art.emit('switch', url);
|
||||
notice.show(i18n.get('Load local video successfully'));
|
||||
player.switchUrl(url, file.name);
|
||||
} else {
|
||||
const tip = `${i18n.get('Playback of this file format is not supported')}: ${file.type}`;
|
||||
const tip = `${i18n.get(notSupport)}: ${file.type || type}`;
|
||||
notice.show(tip, true, 3000);
|
||||
errorHandle(false, tip);
|
||||
}
|
||||
@@ -44,7 +36,6 @@ export default function localPreview(art) {
|
||||
|
||||
proxy(template.$player, 'dragover', e => {
|
||||
e.preventDefault();
|
||||
notice.show(i18n.get('Load local video successfully'));
|
||||
});
|
||||
|
||||
proxy(template.$player, 'drop', e => {
|
||||
@@ -54,7 +45,7 @@ export default function localPreview(art) {
|
||||
});
|
||||
|
||||
return {
|
||||
name: 'localPreview',
|
||||
name: 'localVideo',
|
||||
attach(target) {
|
||||
const $input = append(target, '<input type="file">');
|
||||
setStyle(target, 'position', 'relative');
|
||||
@@ -32,7 +32,8 @@ export default {
|
||||
fullscreenWeb: 'boolean',
|
||||
subtitleOffset: 'boolean',
|
||||
miniProgressBar: 'boolean',
|
||||
localPreview: 'boolean',
|
||||
localVideo: 'boolean',
|
||||
localSubtitle: 'boolean',
|
||||
autoPip: 'boolean',
|
||||
networkMonitor: 'boolean',
|
||||
plugins: ['function'],
|
||||
@@ -46,6 +47,7 @@ export default {
|
||||
style: 'object|undefined',
|
||||
click: 'function|undefined',
|
||||
mounted: 'function|undefined',
|
||||
tooltip: 'string|undefined',
|
||||
},
|
||||
],
|
||||
contextmenu: [
|
||||
@@ -57,6 +59,7 @@ export default {
|
||||
style: 'object|undefined',
|
||||
click: 'function|undefined',
|
||||
mounted: 'function|undefined',
|
||||
tooltip: 'string|undefined',
|
||||
},
|
||||
],
|
||||
quality: [
|
||||
@@ -75,6 +78,7 @@ export default {
|
||||
style: 'object|undefined',
|
||||
click: 'function|undefined',
|
||||
mounted: 'function|undefined',
|
||||
tooltip: 'string|undefined',
|
||||
position: (value, type, paths) => {
|
||||
const position = ['top', 'left', 'right'];
|
||||
return errorHandle(
|
||||
|
||||
@@ -19,10 +19,10 @@ export default class Subtitle {
|
||||
return '';
|
||||
}
|
||||
|
||||
switch(url) {
|
||||
switch(url, name = 'unknown') {
|
||||
const { i18n, notice } = this.art;
|
||||
return this.init(url).then(blobUrl => {
|
||||
notice.show(i18n.get('Switch subtitle'));
|
||||
notice.show(`${i18n.get('Switch subtitle')}: ${name}`);
|
||||
return blobUrl;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { append, setStyles, setStyle, remove, errorHandle, hasOwnProperty } from './index';
|
||||
import { append, setStyles, setStyle, remove, errorHandle, hasOwnProperty, tooltip } from './index';
|
||||
|
||||
export default function component(art, parent, target, getOption, callback, title) {
|
||||
const option = typeof getOption === 'function' ? getOption(art) : getOption;
|
||||
@@ -20,6 +20,10 @@ export default function component(art, parent, target, getOption, callback, titl
|
||||
setStyles($element, option.style);
|
||||
}
|
||||
|
||||
if (option.tooltip) {
|
||||
tooltip($element, option.tooltip);
|
||||
}
|
||||
|
||||
const childs = Array.from(target.children);
|
||||
$element.dataset.index = option.index || componentID;
|
||||
const nextChild = childs.find(item => Number(item.dataset.index) >= Number($element.dataset.index));
|
||||
|
||||
Reference in new issue
Block a user