// ==UserScript== // @name Bilibili显示当前视频字幕 // @namespace Scipline // @version 2.2 // @description 获取当前视频的字幕,弹窗显示出来 // @match https://www.bilibili.com/video/av* // @match https://www.bilibili.com/video/BV* // @icon data:image/x-icon;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A1qEAANahAADWoQAG1qEAb9ahAMvWoQD01qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD01qEAy9ahAG/WoQAG1qEAANahAADWoQAA1qEAG9ahAM/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahANDWoQAb1qEAANahAAfWoQDQ1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahANHWoQAH1qEAbtahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAG7WoQDH1qEA/9ahAP/WoQD/1qEAtdahABjWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahABvWoQC11qEA/9ahAP/WoQD/1qEAx9ahAPnWoQD/1qEA/9ahAP/WoQAZ1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahABjWoQD/1qEA/9ahAP/WoQDz1qEA/9ahAP/WoQD/1qEA/9ahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEAANahAADWoQAA1qEAANahAErWoQDn1qEA5NahAErWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAErWoQDn1qEA5NahAErWoQAA1qEAANahAADWoQAA1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQAA1qEAANahAADWoQAA1qEA5tahAP/WoQD/1qEA59ahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEA5tahAP/WoQD/1qEA59ahAADWoQAA1qEAANahAADWoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAADWoQAA1qEAANahAADWoQD/1qEA/9ahAP/WoQD/1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQD/1qEA/9ahAP/WoQD/1qEAANahAADWoQAA1qEAANahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEAANahAADWoQAA1qEAANahAP/WoQD/1qEA/9ahAP/WoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAP/WoQD/1qEA/9ahAP/WoQAA1qEAANahAADWoQAA1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQAA1qEAANahAADWoQAA1qEA5tahAP/WoQD/1qEA5tahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEA5tahAP/WoQD/1qEA5tahAADWoQAA1qEAANahAADWoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAADWoQAA1qEAANahAADWoQBJ1qEA5tahAObWoQBJ1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQBJ1qEA5tahAObWoQBJ1qEAANahAADWoQAA1qEAANahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQD/1qEA/9ahAP/WoQD/1qEA+dahAP/WoQD/1qEA/9ahABnWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAGdahAP/WoQD/1qEA/9ahAPjWoQDH1qEA/9ahAP/WoQD/1qEAttahABnWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahABnWoQC21qEA/9ahAP/WoQD/1qEAx9ahAG3WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQBt1qEABtahAM/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA0NahAAfWoQAA1qEAG9ahAM/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAM/WoQAb1qEAANahAADWoQAA1qEABtahAG7WoQDH1qEA89ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA/9ahAP/WoQD/1qEA89ahAMfWoQBu1qEABtahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEADtahAMXWoQD/1qEA/9ahAP/WoQD/1qEAxdahAA/WoQAA1qEAANahAADWoQAA1qEADtahAMXWoQD/1qEA/9ahAP/WoQD/1qEAxdahAA/WoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAAbWoQDF1qEA/9ahAP/WoQD/1qEA/9ahAMXWoQAP1qEAANahAADWoQAA1qEAANahAADWoQAA1qEADtahAMXWoQD/1qEA/9ahAP/WoQD/1qEAxdahAAbWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAYtahAP/WoQD/1qEA/9ahAP/WoQDF1qEADtahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEADtahAMXWoQD/1qEA/9ahAP/WoQD/1qEAY9ahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQBf1qEA/9ahAP/WoQD/1qEAxdahAA7WoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEADtahAMXWoQD/1qEA/9ahAP/WoQBf1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAATWoQCg1qEA6tahAKjWoQAO1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEAANahAADWoQAA1qEADtahAKjWoQDr1qEAoNahAATWoQAA1qEAANahAADWoQAA1qEAAP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A///////////AAAADgAAAAQAAAAAAAAAAA///wAf//+AP///wD///8A////AP///wDw/w8A8P8PAPD/DwDw/w8A8P8PAPD/DwD///8A////AH///gA///wAAAAAAAAAAAgAAAAcAAAAP8A8A/+AfgH/gP8B/4H/gf+D/8H/////8= // @author Scipline // @connect api.bilibili.com // @connect i0.hdslb.com // @grant GM_addStyle // @grant GM_download // @grant GM_xmlhttpRequest // @license Apache License 2.0 // @downloadURL none // ==/UserScript== GM_addStyle(` button { background-color: #008CBA; color: white; border: none; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; } #summary { position: fixed; top: 50px; left: 20px; max-height: 400px; width: 300px; background-color: white; border: 1px solid gray; padding: 10px; box-shadow: 5px 5px 5px gray; z-index: 999; overflow-y: auto; } #summary a { color: #008CBA; text-decoration: underline; } `); (async function () { 'use strict'; // 创建按钮并绑定点击事件 var button = document.createElement("button"); button.innerHTML = "生成摘要"; button.style.position = "fixed"; button.style.top = "50px"; button.style.right = "20px"; document.body.appendChild(button); // 创建弹窗内容 var summary = document.createElement('div'); summary.id = 'summary'; summary.style.display = 'none'; summary.style.position = 'fixed'; // summary.style.top = '60px'; // summary.style.right = '20px'; // summary.style.width = '260px'; // summary.style.height = '350px'; summary.style.overflow = 'auto'; // 添加弹窗到页面 document.body.appendChild(summary); // 定义全局变量 let subtitleText = []; let avid = null; let bvid = null; let title = null; // 绑定按钮点击事件 button.addEventListener('click', async function () { if (summary.style.display === 'none') { if (subtitleText.length > 0 && document.querySelector("#viewbox_report > h1").innerText === title) { // 如果已经获取过字幕内容,则直接显示 summary.style.display = 'block'; button.innerHTML = "关闭摘要"; } else { try { // 获取所有字幕 const subtitleJson = await getSubtitleJSON(); const subtitles = subtitleJson.data.subtitle.subtitles; const tabCount = subtitles.length; // 创建选项卡和字幕内容到弹窗 const tabsHTML = []; const subtitlesHTML = []; if (tabCount === 0) { alert("当前视频没有找到字幕"); return; } for (let i = 0; i < tabCount; i++) { tabsHTML.push(``); subtitleText = await getSubtitleText(subtitles[i].subtitle_url); subtitlesHTML.push(`
${subtitleText}
`); title = document.querySelector("#viewbox_report > h1").innerText; } summary.innerHTML = `
${tabsHTML.join('')}
${subtitlesHTML.join('')} `; // 显示弹窗和第一个字幕 summary.style.display = 'block'; button.innerHTML = "关闭摘要"; // 绑定超链接点击事件 const video = document.querySelector('video'); // 超链接方式刷新当前页面打开 // window.open(link.getAttribute('href'), '_self'); summary.querySelectorAll('a') .forEach(function (link) { link.addEventListener('click', function (e) { // 阻止默认行为 e.preventDefault(); // 如果链接的 href 属性包含 "?t=",说明有指定时间点 if (this.href.indexOf("?t=") !== -1) { // 使用正则表达式匹配 t= 后面的数字并取出 const regex = /\?t=(\d+)/; const match = regex.exec(this.href); // 如果成功匹配到了数字,就将其赋值给 startTime 变量,并打印输出 if (match !== null && match[1] !== undefined) { const startTime = parseInt(match[1]); // 执行 JavaScript 代码 eval(`video.currentTime=${startTime};`); } } }); }); } catch (error) { // 显示错误信息 alert(error.message); } } } else { // 隐藏弹窗 summary.style.display = 'none'; button.innerHTML = "生成摘要"; } }); // 获取视频所有字幕的 JSON 数据 async function getSubtitleJSON() { return new Promise((resolve, reject) => { const url = window.location.href; const avidRegex = /\/av([0-9]+)\//; const bvidRegex = /\/(BV[0-9a-zA-Z]+)\/?/; const avidMatch = url.match(avidRegex); const bvidMatch = url.match(bvidRegex); avid = avidMatch ? avidMatch[1] : null; bvid = bvidMatch ? bvidMatch[1] : null; // 构造获取视频信息的 API 链接 let apiLink; if (avid) { apiLink = 'https://api.bilibili.com/x/player/pagelist?aid=' + avid; } else if (bvid) { apiLink = 'https://api.bilibili.com/x/player/pagelist?bvid=' + bvid; } // 发送获取视频信息的请求 GM_xmlhttpRequest({ method: 'GET', url: apiLink, onload: function (response) { if (response.status === 200) { const responseJson = JSON.parse(response.responseText); const cid = responseJson.data[0].cid; // 构造获取字幕链接的 API 链接 let subtitleLink = 'https://api.bilibili.com/x/player/v2?'; subtitleLink += 'cid=' + cid; if (avid) { subtitleLink += '&aid=' + avid; } else if (bvid) { subtitleLink += '&bvid=' + bvid; } subtitleLink += '&qn=32&type=&otype=json&ep_id=&fourk=1&fnver=0&fnval=16'; // 发送获取字幕链接的请求 GM_xmlhttpRequest({ method: 'GET', url: subtitleLink, onload: function (subtitleResponse) { if (subtitleResponse.status === 200) { const subtitleJson = JSON.parse(subtitleResponse.responseText); resolve(subtitleJson); } else { reject(new Error('获取字幕链接失败')); } } }); } else { reject(new Error('获取视频信息失败')); } } }); }); } // 发送获取字幕文件内容的请求 function getSubtitleText(subtitleUrl) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: subtitleUrl, responseType: 'json', onload: function (response) { if (response.status === 200) { let count = 1; const subtitles = response.response.body; // 全部字幕内容 // const subtitleContent = subtitles.map(subtitle => subtitle.content).join(','); // console.log(subtitleContent) const subtitleText = subtitles.map(subtitle => { // 部分字幕可能没有subtitle.sid参数,手动编号 const sid = count++; const startTime = formatTime(subtitle.from); const endTime = formatTime(subtitle.to); const videourl = `https://www.bilibili.com/video/${avid ? 'av' + avid : bvid}?t=${Math.floor(subtitle.from)}`; return `

字幕序号:${sid}

字幕内容:${subtitle.content}

时间点:${startTime} - ${endTime}
`; }) .join(''); resolve(subtitleText); } else { reject(new Error('获取字幕文件内容失败')); } } }); }); } // 格式化时间,将秒数转化为分钟 function formatTime(time) { const minutes = Math.floor(time / 60); let seconds = Math.floor(time % 60); seconds = seconds < 10 ? '0' + seconds : seconds; return minutes + ':' + seconds; } })(); // 切换选项卡显示对应的字幕 unsafeWindow.openTab = function (evt, tabName) { var i, tabcontent, tablinks; tabcontent = document.getElementsByClassName("tabcontent-container"); for (i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } tablinks = document.getElementsByClassName("tablinks"); for (i = 0; i < tablinks.length; i++) { tablinks[i].className = tablinks[i].className.replace(" active", ""); } document.getElementById(tabName) .style.display = "block"; evt.currentTarget.className += " active"; };