You've already forked bilibili-subtitle
245 lines
6.9 KiB
JavaScript
245 lines
6.9 KiB
JavaScript
const {TOTAL_HEIGHT_DEF, HEADER_HEIGHT, TOTAL_HEIGHT_MIN, TOTAL_HEIGHT_MAX, IFRAME_ID} = require("../const");
|
|
var totalHeight = TOTAL_HEIGHT_DEF
|
|
|
|
const getVideoElement = () => {
|
|
const videoWrapper = document.getElementById('bilibili-player')
|
|
return videoWrapper.querySelector('video')
|
|
}
|
|
|
|
let danmukuBox = null
|
|
const timerIframe = setInterval(function () {
|
|
if (danmukuBox) return clearInterval(timerIframe)
|
|
|
|
danmukuBox = document.getElementById('danmukuBox')
|
|
if (danmukuBox) {
|
|
var vKey = ''
|
|
for (const key in danmukuBox?.dataset) {
|
|
if (key.startsWith('v-')) {
|
|
vKey = key
|
|
break
|
|
}
|
|
}
|
|
|
|
const iframe = document.createElement('iframe')
|
|
iframe.id = IFRAME_ID
|
|
iframe.src = chrome.runtime.getURL('index.html')
|
|
iframe.style = 'border: none; width: 100%; height: 44px;'
|
|
iframe.allow = 'clipboard-read; clipboard-write;'
|
|
if (vKey) {
|
|
iframe.dataset[vKey] = danmukuBox?.dataset[vKey]
|
|
}
|
|
//insert before first child
|
|
danmukuBox?.insertBefore(iframe, danmukuBox?.firstChild)
|
|
}
|
|
}, 1000)
|
|
|
|
let aid = 0
|
|
let title = ''
|
|
let pages = []
|
|
let pagesMap = {}
|
|
|
|
let lastAidOrBvid = null
|
|
const refreshVideoInfo = async () => {
|
|
const iframe = document.getElementById(IFRAME_ID)
|
|
if (!iframe) return
|
|
|
|
// fix: https://github.com/IndieKKY/bilibili-subtitle/issues/5
|
|
// 处理稍后再看的url( https://www.bilibili.com/list/watchlater?bvid=xxx&oid=xxx )
|
|
const pathSearchs = {}
|
|
location.search.slice(1).replace(/([^=&]*)=([^=&]*)/g, (matchs, a, b, c) => pathSearchs[a] = b)
|
|
|
|
// bvid
|
|
let aidOrBvid = pathSearchs.bvid // 默认为稍后再看
|
|
if (!aidOrBvid) {
|
|
let path = location.pathname
|
|
if (path.endsWith('/')) {
|
|
path = path.slice(0, -1)
|
|
}
|
|
const paths = path.split('/')
|
|
aidOrBvid = paths[paths.length - 1]
|
|
}
|
|
|
|
if (aidOrBvid !== lastAidOrBvid) {
|
|
// console.debug('refreshVideoInfo')
|
|
|
|
lastAidOrBvid = aidOrBvid
|
|
if (aidOrBvid) {
|
|
//aid,pages
|
|
let cid
|
|
let subtitles
|
|
if (aidOrBvid.toLowerCase().startsWith('av')) {//avxxx
|
|
title = ''
|
|
aid = aidOrBvid.slice(2)
|
|
cid = 1
|
|
pages = await fetch(`https://api.bilibili.com/x/player/pagelist?aid=${aid}`, {credentials: 'include'}).then(res => res.json()).then(res => res.data)
|
|
subtitles = await fetch(`https://api.bilibili.com/x/player/v2?aid=${aid}&cid=${cid}`, {credentials: 'include'}).then(res => res.json()).then(res => res.data.subtitle.subtitles)
|
|
} else {//bvxxx
|
|
pages = await fetch(`https://api.bilibili.com/x/web-interface/view?bvid=${aidOrBvid}`, {credentials: 'include'}).then(res => res.json()).then(res => {
|
|
title = res.data.title
|
|
aid = res.data.aid
|
|
cid = res.data.cid
|
|
subtitles = res.data.subtitle.list
|
|
return res.data.pages
|
|
})
|
|
}
|
|
|
|
//pagesMap
|
|
pagesMap = {}
|
|
pages.forEach(page => {
|
|
pagesMap[page.page + ''] = page
|
|
})
|
|
|
|
console.debug('refreshVideoInfo: ', aid, cid, pages, subtitles)
|
|
|
|
//send setVideoInfo
|
|
iframe.contentWindow.postMessage({
|
|
type: 'setVideoInfo',
|
|
title,
|
|
aid,
|
|
pages,
|
|
infos: subtitles,
|
|
}, '*')
|
|
}
|
|
}
|
|
}
|
|
|
|
let lastAid = null
|
|
let lastCid = null
|
|
const refreshSubtitles = () => {
|
|
const iframe = document.getElementById(IFRAME_ID)
|
|
if (!iframe) return
|
|
|
|
const urlSearchParams = new URLSearchParams(window.location.search)
|
|
const p = urlSearchParams.get('p') || 1
|
|
const page = pagesMap[p]
|
|
if (!page) return
|
|
const cid = page.cid
|
|
|
|
if (aid !== lastAid || cid !== lastCid) {
|
|
console.debug('refreshSubtitles', aid, cid)
|
|
|
|
lastAid = aid
|
|
lastCid = cid
|
|
if (aid && cid) {
|
|
fetch(`https://api.bilibili.com/x/player/v2?aid=${aid}&cid=${cid}`, {
|
|
credentials: 'include',
|
|
})
|
|
.then(res => res.json())
|
|
.then(res => {
|
|
// console.log('refreshSubtitles: ', aid, cid, res)
|
|
iframe.contentWindow.postMessage({
|
|
type: 'setInfos',
|
|
infos: res.data.subtitle.subtitles
|
|
}, '*')
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 监听消息
|
|
window.addEventListener("message", (event) => {
|
|
const {data} = event
|
|
|
|
if (data.type === 'fold') {
|
|
const iframe = document.getElementById(IFRAME_ID)
|
|
iframe.style.height = (data.fold ? HEADER_HEIGHT : totalHeight) + 'px'
|
|
}
|
|
|
|
if (data.type === 'move') {
|
|
const video = getVideoElement()
|
|
if (video) {
|
|
video.currentTime = data.time
|
|
}
|
|
}
|
|
|
|
//刷新视频信息
|
|
if (data.type === 'refreshVideoInfo') {
|
|
refreshVideoInfo().catch(console.error)
|
|
}
|
|
//刷新字幕
|
|
if (data.type === 'refreshSubtitles') {
|
|
refreshSubtitles()
|
|
}
|
|
if (data.type === 'getSubtitle') {
|
|
let url = data.info.subtitle_url
|
|
if (url.startsWith('http://')) {
|
|
url = url.replace('http://', 'https://')
|
|
}
|
|
fetch(url).then(res => res.json()).then(res => {
|
|
event.source.postMessage({
|
|
data: {
|
|
info: data.info,
|
|
data: res,
|
|
}, type: 'setSubtitle'
|
|
}, '*')
|
|
})
|
|
}
|
|
|
|
if (data.type === 'getCurrentTime') {
|
|
const video = getVideoElement()
|
|
if (video) {
|
|
event.source.postMessage({
|
|
data: {
|
|
currentTime: video.currentTime
|
|
}, type: 'setCurrentTime'
|
|
}, '*')
|
|
}
|
|
}
|
|
|
|
if (data.type === 'getSettings') {
|
|
const videoElement = getVideoElement()
|
|
totalHeight = videoElement ? Math.min(Math.max(videoElement.offsetHeight, TOTAL_HEIGHT_MIN), TOTAL_HEIGHT_MAX) : TOTAL_HEIGHT_DEF
|
|
event.source.postMessage({
|
|
data: {
|
|
noVideo: !videoElement,
|
|
totalHeight,
|
|
}, type: 'setSettings'
|
|
}, '*')
|
|
}
|
|
|
|
if (data.type === 'downloadAudio') {
|
|
const html = document.getElementsByTagName('html')[0].innerHTML
|
|
const playInfo = JSON.parse(html.match(/window.__playinfo__=(.+?)<\/script/)[1])
|
|
const audioUrl = playInfo.data.dash.audio[0].baseUrl
|
|
|
|
fetch(audioUrl).then(res => res.blob()).then(blob => {
|
|
const a = document.createElement('a')
|
|
a.href = URL.createObjectURL(blob)
|
|
a.download = `${title}.m4s`
|
|
a.click()
|
|
})
|
|
}
|
|
|
|
if (data.type === 'updateTransResult') {
|
|
const trans = data.result??''
|
|
let text = document.getElementById('trans-result-text')
|
|
if (text) {
|
|
text.innerHTML = trans
|
|
} else {
|
|
const container = document.getElementsByClassName('bpx-player-subtitle-panel-wrap')?.[0]
|
|
if (container) {
|
|
const div = document.createElement('div')
|
|
div.style.display = 'flex'
|
|
div.style.justifyContent = 'center'
|
|
div.style.margin = '2px'
|
|
text = document.createElement('text')
|
|
text.id = 'trans-result-text'
|
|
text.innerHTML = trans
|
|
text.style.fontSize = '1rem'
|
|
text.style.padding = '5px'
|
|
text.style.color = 'white'
|
|
text.style.background = 'rgba(0, 0, 0, 0.4)'
|
|
div.append(text)
|
|
|
|
container.append(div)
|
|
}
|
|
}
|
|
text && (text.style.display = trans ? 'block' : 'none')
|
|
}
|
|
}, false);
|
|
|
|
setInterval(() => {
|
|
refreshVideoInfo().catch(console.error)
|
|
refreshSubtitles()
|
|
}, 1000)
|