diff --git a/package.json b/package.json
index edcdeed..e2f57ad 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,8 @@
"vuedraggable": "^2.24.3",
"vuex": "^3.6.0",
"xgplayer": "^2.16.0",
- "xgplayer-hls.js": "^2.3.0"
+ "xgplayer-hls.js": "^2.3.0",
+ "xgplayer-mp4": "^1.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.9",
diff --git a/src/components/Play.vue b/src/components/Play.vue
index 70f15d4..50f6ec6 100644
--- a/src/components/Play.vue
+++ b/src/components/Play.vue
@@ -181,7 +181,7 @@
- - 导出
+ - 导出
- 无数据
- {{i | ftName(j)}}
@@ -244,6 +244,7 @@ import { star, history, setting, shortcut, mini, channelList, sites } from '../l
import zy from '../lib/site/tools'
import Player from 'xgplayer'
import HlsJsPlayer from 'xgplayer-hls.js'
+import 'xgplayer-mp4'
import mt from 'mousetrap'
import Clickoutside from 'element-ui/src/utils/clickoutside'
import { exec, execFile } from 'child_process'
@@ -332,7 +333,7 @@ export default {
videoTitle: true,
airplay: true,
closeVideoTouch: true,
- ignores: ['cssFullscreen', 'replay'],
+ ignores: ['cssFullscreen', 'replay', 'error'], // 为了切换播放器类型时避免显示错误刷新,暂时忽略错误
preloadTime: 300
},
state: {
@@ -361,7 +362,8 @@ export default {
endPosition: { min: '00', sec: '00' },
skipendStatus: false, // 是否跳过了片尾
currentShortcutList: [],
- onlineUrl: ''
+ onlineUrl: '',
+ playerType: 'hls'
}
},
filters: {
@@ -557,6 +559,16 @@ export default {
},
playChannel (channel) {
this.isLive = true
+ if (this.playerType !== 'hls') {
+ this.xg.src = ''
+ this.config.url = ''
+ this.xg.destroy()
+ this.xg = null
+ this.xg = new HlsJsPlayer(this.config)
+ this.playerInstall()
+ this.bindEvent()
+ this.playerType = 'hls'
+ }
if (channel.channels) {
this.right.sources = channel.channels.filter(e => e.isActive)
channel = channel.prefer ? channel.channels.find(e => e.id === channel.prefer) : channel.channels.filter(e => e.isActive)[0]
@@ -576,40 +588,59 @@ export default {
},
playVideo (index = 0, time = 0) {
this.isLive = false
- if (document.querySelector('xg-btn-showhistory')) document.querySelector('xg-btn-showhistory').style.display = 'block'
- if (document.querySelector('.xgplayer-playbackrate')) document.querySelector('.xgplayer-playbackrate').style.display = 'inline-block'
- this.fetchM3u8List().then(async (m3u8Arr) => {
- const url = m3u8Arr[index]
- if (!url.endsWith('.m3u8')) {
+ this.fetchPlaylist().then(async (playlistUrls) => {
+ const url = playlistUrls[index]
+ if (!url.endsWith('.m3u8') && !url.endsWith('.mp4')) {
const currentSite = await sites.find({ key: this.video.key })
if (currentSite.jiexiUrl) {
this.onlineUrl = currentSite.jiexiUrl + url
} else {
this.onlineUrl = 'https://jx.7kjx.com/?url=' + url
}
- } else {
- this.xg.src = m3u8Arr[index]
- const key = this.video.key + '@' + this.video.info.id
- const startTime = VIDEO_DETAIL_CACHE[key].startPosition || 0
- this.xg.play()
- this.xg.once('playing', () => {
- this.xg.currentTime = time > startTime ? time : startTime
- if (VIDEO_DETAIL_CACHE[key].startPosition) this.xg.addProgressDot(VIDEO_DETAIL_CACHE[key].startPosition, '片头')
- if (VIDEO_DETAIL_CACHE[key].endPosition) this.xg.addProgressDot(this.xg.duration - VIDEO_DETAIL_CACHE[key].endPosition, '片尾')
- })
- this.videoPlaying()
- this.skipendStatus = false
- this.xg.once('ended', () => {
- if (m3u8Arr.length > 1 && (m3u8Arr.length - 1 > index)) {
- this.video.info.time = 0
- this.video.info.index++
- }
- this.xg.off('ended') // 明明是once为何会触发多次,得注销掉以真正只执行一次
- })
+ return
}
+ if (url.endsWith('.mp4') && this.playerType !== 'mp4') {
+ this.xg.src = ''
+ this.config.url = ''
+ this.xg.destroy()
+ this.xg = null
+ this.xg = new Player(this.config)
+ this.playerInstall()
+ this.bindEvent()
+ this.playerType = 'mp4'
+ } else if (url.endsWith('.m3u8') && this.playerType !== 'hls') {
+ this.xg.src = ''
+ this.config.url = ''
+ this.xg.destroy()
+ this.xg = null
+ this.xg = new HlsJsPlayer(this.config)
+ this.playerInstall()
+ this.bindEvent()
+ this.playerType = 'hls'
+ }
+ this.xg.src = url
+ const key = this.video.key + '@' + this.video.info.id
+ const startTime = VIDEO_DETAIL_CACHE[key].startPosition || 0
+ this.xg.play()
+ if (document.querySelector('xg-btn-showhistory')) document.querySelector('xg-btn-showhistory').style.display = 'block'
+ if (document.querySelector('.xgplayer-playbackrate')) document.querySelector('.xgplayer-playbackrate').style.display = 'inline-block'
+ this.xg.once('playing', () => {
+ this.xg.currentTime = time > startTime ? time : startTime
+ if (VIDEO_DETAIL_CACHE[key].startPosition) this.xg.addProgressDot(VIDEO_DETAIL_CACHE[key].startPosition, '片头')
+ if (VIDEO_DETAIL_CACHE[key].endPosition) this.xg.addProgressDot(this.xg.duration - VIDEO_DETAIL_CACHE[key].endPosition, '片尾')
+ })
+ this.videoPlaying()
+ this.skipendStatus = false
+ this.xg.once('ended', () => {
+ if (playlistUrls.length > 1 && (playlistUrls.length - 1 > index)) {
+ this.video.info.time = 0
+ this.video.info.index++
+ }
+ this.xg.off('ended') // 明明是once为何会触发多次,得注销掉以真正只执行一次
+ })
})
},
- fetchM3u8List () {
+ fetchPlaylist () {
return new Promise((resolve) => {
const cacheKey = this.video.key + '@' + this.video.info.id
if (VIDEO_DETAIL_CACHE[cacheKey] && VIDEO_DETAIL_CACHE[cacheKey].list && VIDEO_DETAIL_CACHE[cacheKey].list.length) {
@@ -618,28 +649,28 @@ export default {
}
zy.detail(this.video.key, this.video.info.id).then(res => {
this.name = res.name
- const m3u8Txt = res.m3u8List
- this.right.list = m3u8Txt
- const m3u8Arr = []
- for (const i of m3u8Txt) {
+ const playlist = res.m3u8List.length ? res.m3u8List : res.mp4List
+ this.right.list = playlist
+ const playlistUrls = []
+ for (const i of playlist) {
const j = i.split('$')
if (j.length > 1) {
for (let m = 0; m < j.length; m++) {
if (j[m].startsWith('http')) {
- m3u8Arr.push(j[m])
+ playlistUrls.push(j[m])
break
}
}
} else {
- m3u8Arr.push(j[0])
+ playlistUrls.push(j[0])
}
}
VIDEO_DETAIL_CACHE[cacheKey] = Object.assign(VIDEO_DETAIL_CACHE[cacheKey] || {}, {
- list: m3u8Arr,
+ list: playlistUrls,
name: res.name
})
- resolve(m3u8Arr)
+ resolve(playlistUrls)
})
})
},
@@ -892,20 +923,27 @@ export default {
}
return
}
- this.fetchM3u8List().then(m3u8Arr => {
+ this.fetchPlaylist().then(playlistUrls => {
var externalPlayer = this.setting.externalPlayer
if (!externalPlayer) {
this.$message.error('请设置第三方播放器路径')
// 在线播放该视频
- var link = 'https://www.m3u8play.com/?play=' + m3u8Arr[this.video.info.index]
- const open = require('open')
- open(link)
+ if (playlistUrls[this.video.info.index].endsWith('.m3u8')) {
+ var link = 'https://www.m3u8play.com/?play=' + playlistUrls[this.video.info.index]
+ const open = require('open')
+ open(link)
+ }
} else {
- var m3uFile = this.generateM3uFile(this.video.info.name, m3u8Arr, this.video.info.index)
- if (fs.existsSync(externalPlayer)) {
- execFile(externalPlayer, [m3uFile])
+ let playlist
+ if (playlistUrls.every(e => e.endsWith('.m3u8'))) {
+ playlist = this.generateM3uFile(this.video.info.name, playlistUrls, this.video.info.index)
} else {
- exec(externalPlayer, [m3uFile])
+ playlist = playlistUrls[this.video.info.index]
+ }
+ if (fs.existsSync(externalPlayer)) {
+ execFile(externalPlayer, [playlist])
+ } else {
+ exec(externalPlayer, [playlist])
}
}
})
@@ -1456,7 +1494,7 @@ export default {
this.video.key = ''
this.xg.src = ''
this.config.url = ''
- this.xg.destroy(false)
+ this.xg.destroy()
this.xg = null
this.name = ''
this.isLive = false
diff --git a/src/lib/site/tools.js b/src/lib/site/tools.js
index 5625d1e..74207ac 100644
--- a/src/lib/site/tools.js
+++ b/src/lib/site/tools.js
@@ -238,6 +238,7 @@ const zy = {
const videoList = jsondata.list.video
// Parse m3u8List
var m3u8List = []
+ let mp4List = []
const dd = videoList.dl.dd
const type = Object.prototype.toString.call(dd)
if (type === '[object Array]') {
@@ -245,12 +246,18 @@ const zy = {
// 如果含有多个视频列表的话, 仅获取m3u8列表
if (i._flag.includes('m3u8') || i._t.includes('.m3u8')) {
m3u8List = i._t.split('#')
+ break
+ // 获取不到m3u8时,尝试获取mp4列表
+ } else if (i._flag.includes('mp4') || i._t.includes('.mp4')) {
+ mp4List = i._t.split('#')
+ break
}
}
} else {
m3u8List = dd._t.split('#')
}
videoList.m3u8List = m3u8List
+ if (mp4List.length) videoList.mp4List = mp4List
resolve(videoList)
}).catch(err => {
reject(err)