feat: 视频播放器增加m3u8和flv格式的支持
This commit is contained in:
parent
570f47003f
commit
1770bc8005
@ -20,6 +20,7 @@
|
||||
"clipboard": "^2.0.6",
|
||||
"cropperjs": "^1.5.6",
|
||||
"e-vue-contextmenu": "^0.1.3",
|
||||
"flv.js": "^1.6.2",
|
||||
"gsap": "^3.2.6",
|
||||
"highlightjs-line-numbers.js": "^2.7.0",
|
||||
"hls.js": "^1.4.0",
|
||||
|
||||
@ -16,6 +16,9 @@
|
||||
<script>
|
||||
import fileConfig from '@/utils/file-config'
|
||||
import Artplayer from "@/components/preview/Artplayer.vue";
|
||||
import Hls from "hls.js";
|
||||
import FlvJs from "flv.js";
|
||||
|
||||
export default {
|
||||
name: 'VideoPreview',
|
||||
components: {
|
||||
@ -46,14 +49,14 @@ export default {
|
||||
url: '',
|
||||
title: '', // 视频标题,目前会出现在 视频截图 和 迷你模式 下
|
||||
fullscreen: true,
|
||||
fullscreenWeb: true,
|
||||
fullscreenWeb: this.$pc,
|
||||
//pip: true, // 是否在底部控制栏里显示 画中画 的开关按钮
|
||||
flip: true, // 是否显示视频翻转功能,目前只出现在 设置面板 和 右键菜单 里
|
||||
playbackRate: true, // 是否显示视频播放速度功能,会出现在 设置面板 和 右键菜单 里
|
||||
aspectRatio: true, // 是否显示视频长宽比功能,会出现在 设置面板 和 右键菜单 里
|
||||
screenshot: true, // 是否在底部控制栏里显示 视频截图 功能
|
||||
setting: true, // 是否在底部控制栏里显示 设置面板 的开关按钮
|
||||
autoplay: false, // 是否自动播放
|
||||
autoplay: true, // 是否自动播放
|
||||
autoPlayback: true, // 是否使用自动 回放功能
|
||||
theme: '#23ade5',
|
||||
hotkey: true, // 是否使用快捷键
|
||||
@ -63,7 +66,8 @@ export default {
|
||||
position: 'right',
|
||||
tooltip: 'IINA',
|
||||
style: {
|
||||
marginRight: '20px',
|
||||
marginRight: this.$pc ? '20px' : '0px',
|
||||
display: this.$pc ? 'block' : 'none'
|
||||
},
|
||||
html: `<a><img style="width: 1.9rem;height: 1.9rem;line-height: 1.9rem" src="${require("@/assets/img/iina.webp")}"></a>`,
|
||||
index: 1,
|
||||
@ -73,7 +77,7 @@ export default {
|
||||
position: 'right',
|
||||
tooltip: 'nPlayer',
|
||||
style: {
|
||||
marginRight: '20px',
|
||||
marginRight: this.$pc ? '20px' : '0px',
|
||||
},
|
||||
html: `<a href="nplayer-videLink"><img style="width: 1.9rem;height: 1.9rem;line-height: 1.9rem" src="${require("@/assets/img/nplayer.webp")}"></a>`,
|
||||
index: 2,
|
||||
@ -83,7 +87,7 @@ export default {
|
||||
position: 'right',
|
||||
tooltip: 'Infuse',
|
||||
style: {
|
||||
marginRight: '20px',
|
||||
marginRight: this.$pc ? '20px' : '0px',
|
||||
},
|
||||
html: `<a href="infuse://x-callback-url/play?url=videLink"><img style="width: 1.9rem;height: 1.9rem;line-height: 1.9rem" src="${require("@/assets/img/infuse.webp")}"></a>`,
|
||||
index: 3,
|
||||
@ -94,7 +98,7 @@ export default {
|
||||
html: '复制链接',
|
||||
index: 5,
|
||||
style: {
|
||||
marginRight: '20px',
|
||||
marginRight: this.$pc ? '20px' : '0px',
|
||||
},
|
||||
click: () => this.copyToClipboard(this.videoLink),
|
||||
}
|
||||
@ -121,11 +125,30 @@ export default {
|
||||
watch: {
|
||||
status: function (visible) {
|
||||
if (visible) {
|
||||
this.option.url = fileConfig.previewUrl(this.$store.state.user.name, this.file, this.$store.getters.token)
|
||||
let videoUrl = fileConfig.previewUrl(this.$store.state.user.name, this.file, this.$store.getters.token)
|
||||
if (this.shareId) {
|
||||
this.option.url = fileConfig.publicPreviewUrl(this.file.id, window.shareId, this.$store.getters.shareToken)
|
||||
videoUrl = fileConfig.publicPreviewUrl(this.file, window.shareId, this.$store.getters.shareToken)
|
||||
}
|
||||
this.videoLink = window.location.origin + this.option.url
|
||||
if (this.file.m3u8) {
|
||||
videoUrl = `${fileConfig.baseUrl}/video/hls/${this.file.m3u8}`
|
||||
if (this.shareId) {
|
||||
videoUrl = `${fileConfig.baseUrl}/public/video/hls/${this.file.m3u8}?share-token=${this.$store.getters.shareToken}`
|
||||
}
|
||||
}
|
||||
this.option.url = videoUrl
|
||||
console.log('this.option.url', this.option.url)
|
||||
if (this.file.m3u8) {
|
||||
this.option.customType = {
|
||||
m3u8: this.playM3u8
|
||||
}
|
||||
}
|
||||
if (this.file.contentType.indexOf('flv') > -1) {
|
||||
this.option.customType = {
|
||||
flv: this.playFlv
|
||||
}
|
||||
}
|
||||
|
||||
this.videoLink = window.location.origin + videoUrl
|
||||
this.title = this.file.name
|
||||
this.option.id = this.file.id
|
||||
this.show = true
|
||||
@ -134,25 +157,18 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
copyToClipboard(text) {
|
||||
const type = "text/plain";
|
||||
const blob = new Blob([text], { type });
|
||||
const data = [new ClipboardItem({ [type]: blob })];
|
||||
navigator.clipboard.write(data).then(
|
||||
() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success',
|
||||
duration: 1000,
|
||||
});
|
||||
},
|
||||
() => {
|
||||
this.$message({
|
||||
message: '复制失败',
|
||||
type: 'error',
|
||||
duration: 1000,
|
||||
});
|
||||
}
|
||||
);
|
||||
// 复制文本
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand("copy");
|
||||
textArea.remove();
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success',
|
||||
duration: 1000,
|
||||
});
|
||||
},
|
||||
escape(event) {
|
||||
// 监听ESC键
|
||||
@ -166,19 +182,47 @@ export default {
|
||||
},
|
||||
getInstance(art) {
|
||||
this.art = art
|
||||
art.on('ready', () => {
|
||||
let doc = this.art.controls.$parent
|
||||
// iina
|
||||
const iina = doc.querySelector('[data-index="1"]').querySelector('a');
|
||||
iina.href = `iina://weblink?url=${this.videoLink}`
|
||||
// nplayer
|
||||
const nplayer = doc.querySelector('[data-index="2"]').querySelector('a');
|
||||
nplayer.href = `nplayer-${this.videoLink}`
|
||||
// infuse
|
||||
const infuse = doc.querySelector('[data-index="3"]').querySelector('a');
|
||||
infuse.href = `infuse://x-callback-url/play?url==${this.videoLink}`
|
||||
});
|
||||
let doc = this.art.controls.$parent
|
||||
// iina
|
||||
const iina = doc.querySelector('[data-index="1"]').querySelector('a');
|
||||
iina.href = `iina://weblink?url=${this.videoLink}`
|
||||
console.log('iina.href', iina.href)
|
||||
// nplayer
|
||||
const nplayer = doc.querySelector('[data-index="2"]').querySelector('a');
|
||||
let link = `nplayer-${this.videoLink}`
|
||||
nplayer.href = link
|
||||
// infuse
|
||||
const infuse = doc.querySelector('[data-index="3"]').querySelector('a');
|
||||
infuse.href = `infuse://x-callback-url/play?url=${this.videoLink}`
|
||||
},
|
||||
playM3u8(video, url, art) {
|
||||
if (Hls.isSupported()) {
|
||||
if (art.hls) art.hls.destroy();
|
||||
const hls = new Hls();
|
||||
hls.loadSource(url);
|
||||
hls.attachMedia(video);
|
||||
art.hls = hls;
|
||||
console.log('Hls')
|
||||
art.on('destroy', () => hls.destroy());
|
||||
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
video.src = url;
|
||||
console.log('Hls1')
|
||||
} else {
|
||||
art.notice.show = 'Unsupported playback format: m3u8';
|
||||
}
|
||||
},
|
||||
playFlv(video, url, art) {
|
||||
if (FlvJs.isSupported()) {
|
||||
if (art.flv) art.flv.destroy();
|
||||
const flv = FlvJs.createPlayer({ type: 'flv', url });
|
||||
flv.attachMediaElement(video);
|
||||
flv.load();
|
||||
art.flv = flv;
|
||||
art.on('destroy', () => flv.destroy());
|
||||
} else {
|
||||
art.notice.show = 'Unsupported playback format: flv';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
width="50"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<icon-file :item="scope.row" :image-url="imageUrl" :public="true"></icon-file>
|
||||
<icon-file v-if="sharer" :item="scope.row" :image-url="imageUrl" :audio-cover-url="audioUrl" :public="true"></icon-file>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@ -204,7 +204,7 @@
|
||||
<van-checkbox v-show="gridHoverItemIndex === index || indexList.includes(index)"
|
||||
class="grid-item-checkbox" :name="item" @click.stop="clickGridItemCheckBox(item,index)"/>
|
||||
<div class="grid-item-icon">
|
||||
<icon-file :item="item" :image-url="imageUrl" :grid="true" :grid-width="gridColumnWidth"
|
||||
<icon-file v-if="sharer" :item="item" :image-url="imageUrl" :audio-cover-url="audioUrl" :grid="true" :grid-width="gridColumnWidth"
|
||||
:public="true"></icon-file>
|
||||
</div>
|
||||
<span class="grid-item-text">{{ item.name }}</span>
|
||||
@ -220,8 +220,8 @@
|
||||
|
||||
<div v-if="showShareCode" class="share-content">
|
||||
<div class="share-icon">
|
||||
<icon-file class="share-icon-font" :item="shareData" :grid="true" :details="true"
|
||||
:image-url="imageUrl"></icon-file>
|
||||
<icon-file v-if="sharer" class="share-icon-font" :item="shareData" :grid="true" :details="true"
|
||||
:image-url="imageUrl" :audio-cover-url="audioUrl"></icon-file>
|
||||
</div>
|
||||
<div class="share-filename">
|
||||
<span>{{ shareData.fileName }}</span>
|
||||
@ -405,7 +405,7 @@ export default {
|
||||
audioPreviewVisible: false,
|
||||
showUpdateDateItem: this.$pc,// 列表模式下是否显示修改时间
|
||||
showSizeItem: this.$pc,// 列表模式下是否显示文件大小
|
||||
sharer: {},//分享者信息
|
||||
sharer: undefined,//分享者信息
|
||||
sharerAvatarUrl: '',
|
||||
netdiskName: 'JmalCloud',
|
||||
netdiskLogo: '',
|
||||
@ -428,6 +428,11 @@ export default {
|
||||
return this.$store.getters.shareToken === undefined ?
|
||||
`${process.env.VUE_APP_BASE_API}/public/s/view/thumbnail?id=` :
|
||||
`${process.env.VUE_APP_BASE_API}/public/s/view/thumbnail?share-token=${this.$store.getters.shareToken}&id=`
|
||||
},
|
||||
audioUrl() {
|
||||
return this.$store.getters.shareToken === undefined ?
|
||||
`${process.env.VUE_APP_BASE_API}/public/s/view/cover?name=${this.sharer.username}&id=` :
|
||||
`${process.env.VUE_APP_BASE_API}/public/s/view/cover?name=${this.sharer.username}&share-token=${this.$store.getters.shareToken}&id=`
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -678,6 +683,9 @@ export default {
|
||||
if (this.sharer.netdiskLogo) {
|
||||
this.netdiskLogo = this.sharer.netdiskLogo
|
||||
}
|
||||
|
||||
this.audioUrl = `${process.env.VUE_APP_BASE_API}/public/s/view/cover?name=${this.sharer.username}&id=`
|
||||
|
||||
this.$store.dispatch('user/setLogo', {netdiskName: this.netdiskName, netdiskLogo: this.netdiskLogo})
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user