您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动歌词显示
// ==UserScript== // @name 在B站(Bilibili)网页版自动显示歌词 // @version 1.0.1 // @description 自动歌词显示 // @author Tian // @namespace BilibiliMusicLRC // @license MIT // @match https://www.bilibili.com/video/* // @require https://static.hdslb.com/js/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @connect ark.cn-beijing.volces.com // @connect api.52vmy.cn // ==/UserScript== (function () { 'use strict'; // 存储密钥(建议通过脚本设置页面输入,不要直接硬编码) // 首次使用请在控制台执行: // GM_setValue('tencentSecretId', '你的SecretId') // GM_setValue('tencentSecretKey', '你的SecretKey') const SECRET_ID = 'AKIDToxtgHj03va2HNHzUmtnUxFMG6jAPakl'; const SECRET_KEY = 'tYzlMlz0sfOzOgu0ufDXdVCgz62sUt54'; const TOKEN = ""; // API配置 const host = "ark.cn-beijing.volces.com/api/v3/chat/completions"; // 添加所有的DOM元素 // 创建主要容器 const mainBox = document.createElement('div'); // 创建标题 const title = document.createElement('div'); // 创建最小化按钮 const minimizeButton = document.createElement('button'); // 创建关闭按钮 const closeButton = document.createElement('button'); // 创建调用API按钮 const apiButton = document.createElement('button'); // 创建输入框 const resultInput = document.createElement('input'); // 创建结果显示区域 const resultBox = document.createElement('div'); // 创建歌词显示区域 const resultMusicLrc = document.createElement('div'); // 常量配置 let music_Name = []; let music_Msg = []; let music_Msg_Time = []; let music_Chapter = []; let api_lock = false; // 防止重复请求锁 /** * 初始化 */ function init() { // 关键步骤:注入 placeholder 样式(必须在输入框创建前执行,确保样式生效) const style = document.createElement('style'); style.textContent = ` .music-lyric-input::placeholder { color: #14ffec !important; opacity: 1; } `; document.head.appendChild(style); // 添加主盒子 mainBox.id = 'music-lyric-main-box'; mainBox.style.position = 'fixed'; mainBox.style.width = '300px'; mainBox.style.minHeight = '30px'; mainBox.style.padding = '10px 15px'; mainBox.style.top = '10px'; mainBox.style.left = '10px'; mainBox.style.zIndex = '9998'; mainBox.style.backgroundColor = 'rgb(33, 33, 33)'; mainBox.style.display = 'flex'; mainBox.style.flexDirection = 'column'; mainBox.style.alignItems = 'flex-start'; mainBox.style.borderRadius = '8px'; mainBox.style.fontSize = '14px'; mainBox.style.lineHeight = '1.5'; // 按住拖动 mainBox.style.cursor = 'move'; mainBox.onmousedown = function (event) { const shiftX = event.clientX - mainBox.getBoundingClientRect().left const shiftY = event.clientY - mainBox.getBoundingClientRect().top function moveAt(pageX, pageY) { mainBox.style.left = pageX - shiftX + 'px' mainBox.style.top = pageY - shiftY + 'px' } function onMouseMove(event) { moveAt(event.pageX, event.pageY) } document.addEventListener('mousemove', onMouseMove) mainBox.onmouseup = function () { document.removeEventListener('mousemove', onMouseMove) mainBox.onmouseup = null } mainBox.ondragstart = function () { return false } } document.body.appendChild(mainBox); // 添加标题 title.textContent = '歌词助手'; title.style.fontSize = '16px'; title.style.fontWeight = 'bold'; title.style.color = '#14ffec'; title.style.position = 'absolute'; title.style.top = '15px'; title.style.left = '15px'; title.style.userSelect = 'none'; mainBox.appendChild(title); // 添加最小化 minimizeButton.id = 'minimize-button'; minimizeButton.textContent = '-'; minimizeButton.style.position = 'absolute'; minimizeButton.style.top = '10px'; minimizeButton.style.right = '40px'; minimizeButton.style.zIndex = '9999'; minimizeButton.style.padding = '5px 10px'; minimizeButton.style.cursor = 'pointer'; minimizeButton.style.border = 'none'; minimizeButton.style.borderRadius = '5px'; minimizeButton.style.backgroundColor = '#323232'; minimizeButton.style.color = '#14ffec'; minimizeButton.addEventListener('click', () => { apiButton.style.display = apiButton.style.display === 'none' ? 'block' : 'none'; resultInput.style.display = resultInput.style.display === 'none' ? 'block' : 'none'; resultBox.style.display = resultBox.style.display === 'none' ? 'block' : 'none'; minimizeButton.textContent = minimizeButton.textContent === '-' ? '+' : '-'; }); mainBox.appendChild(minimizeButton); // 添加关闭 closeButton.id = 'close-button'; closeButton.textContent = '×'; closeButton.style.position = 'absolute'; closeButton.style.top = '10px'; closeButton.style.right = '10px'; closeButton.style.zIndex = '9999'; closeButton.style.padding = '5px 10px'; closeButton.style.cursor = 'pointer'; closeButton.style.border = 'none'; closeButton.style.borderRadius = '5px'; closeButton.style.backgroundColor = '#323232'; closeButton.style.color = '#14ffec'; closeButton.addEventListener('click', () => { mainBox.remove(); }); mainBox.appendChild(closeButton); // 也可以添加一个按钮,点击时调用API apiButton.id = 'call-nlp-api-button'; apiButton.textContent = '重新查找歌词!'; apiButton.style.padding = '10px 15px'; apiButton.style.zIndex = '9998'; apiButton.style.cursor = 'pointer'; apiButton.style.border = 'none'; apiButton.style.borderRadius = '5px'; apiButton.style.backgroundColor = '#323232'; apiButton.style.color = '#14ffec'; apiButton.style.marginBottom = '10px'; apiButton.style.marginTop = '40px'; apiButton.addEventListener('click', callNlpApi); mainBox.appendChild(apiButton); // 输入框 resultInput.type = 'text'; resultInput.placeholder = '输入歌名获取歌词'; resultInput.disabled = false; resultInput.readOnly = false; resultInput.autocomplete = 'off'; // 避免自动填充干扰 // 添加input样式 resultInput.className = 'music-lyric-input'; resultInput.style.width = '150px'; resultInput.style.padding = '5px'; resultInput.style.paddingLeft = '13px'; // 确保placeholder有内边距 resultInput.style.borderRadius = '5px'; resultInput.style.border = '1px solid #323232'; // 原代码border: none可能导致视觉上不可见 resultInput.style.boxSizing = 'border-box'; resultInput.style.fontSize = '14px'; resultInput.style.outline = 'none'; // 可选:去除聚焦边框 resultInput.style.zIndex = '9999'; // 确保在最上层,避免被遮挡 resultInput.style.backgroundColor = '#323232'; resultInput.style.color = '#14ffec'; resultInput.style.marginBottom = '10px'; resultInput.addEventListener('keydown', (e) => { e.stopPropagation(); // 阻止事件冒泡到页面 }); resultInput.addEventListener('input', (e) => { e.stopPropagation(); }); resultInput.addEventListener('blur', (e) => { getMusic(e.target.value); e.stopPropagation(); }); mainBox.appendChild(resultInput); // 结果显示区域 resultBox.className = 'music-lyric-result-box'; resultBox.style.padding = '10px 15px'; resultBox.style.backgroundColor = '#323232'; resultBox.style.color = '#14ffec'; resultBox.style.zIndex = '9999'; resultBox.style.maxWidth = '300px'; resultBox.style.maxHeight = '400px'; resultBox.style.overflowY = 'auto'; resultBox.style.borderRadius = '8px'; resultBox.style.fontSize = '14px'; resultBox.style.lineHeight = '1.5'; resultBox.style.marginBottom = '10px'; resultBox.style.fontWeight = '300'; resultBox.innerHTML = ` <strong>识别到的歌词/作品:</strong> <br> <div class="box_item"></div> `; mainBox.appendChild(resultBox); } /** * 发起API请求 */ async function callNlpApi() { if (api_lock) { return; // 如果锁定,则不执行 } api_lock = true; // 上锁 resetConstants(); const box_item = document.querySelector('.box_item'); if (box_item) { box_item.innerHTML = '识别中...'; } try { const sampleText = $('.video-title').text(); music_Chapter = []; let tempChapter = document.querySelectorAll('.bpx-player-ctrl-viewpoint-menu-item-content'); for (let i = 0; i < tempChapter.length; i++) { music_Chapter.push(tempChapter[i].textContent); } console.log(music_Chapter); const payload = JSON.stringify({ "model": "doubao-1-5-thinking-pro-250415", "messages": [ { "role": "system", "content": "你是人工智能助手." }, { "role": "user", "content": `请从以下文本中识别出歌词和作品名称,文本内容为:${sampleText + music_Chapter.join(',')}。只需要返回歌词和作品名称即可,用英文逗号分割,不需要其他多余的描述。如果没有识别出歌词或作品,请返回“ ”。` } ] }); // 使用GM_xmlhttpRequest发送请求(避免跨域问题) GM_xmlhttpRequest({ method: 'POST', url: `https://${host}`, headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer 628cbe0e-210d-46e0-bd89-cee9ff9957e0` }, data: payload, onload: function (response) { console.log("API响应:", JSON.parse(response.responseText)); // 可以在这里处理返回结果,例如显示在页面上 box_item.innerHTML = ''; api_lock = false; // 解锁 showResult(JSON.parse(response.responseText).choices[0].message.content); }, onerror: function (error) { api_lock = false; // 解锁 box_item.innerHTML = '请求出错,请稍后再试.'; } }); } catch (error) { console.error("调用API时出错:", error); } } /** * 获取歌曲 */ async function getMusic(musicName) { if (api_lock) { return; // 如果锁定,则不执行 } api_lock = true; // 上锁 if (document.querySelector('.music-lyric-result-lrc')) { document.querySelector('.music-lyric-result-lrc').remove(); } try { // 使用GM_xmlhttpRequest发送请求(避免跨域问题) GM_xmlhttpRequest({ url: 'https://api.52vmy.cn/api/music/lrc?msg=' + encodeURIComponent(musicName) + '&n=1', method: 'GET', headers: { 'Content-Type': 'application/json' }, onload: function (response) { // 处理数据 正则删除[00:00.35] const cleanedLyric = response.responseText.replace(/\[.*?\]/g, ''); // 提取歌词 music_Msg = cleanedLyric .split(/[\r\n]+/) // 按任意换行符拆分(兼容所有系统) .filter(line => line.trim() !== ''); // 过滤空行/纯空白行 // 提取时间 music_Msg_Time = (response.responseText.match(/\[(\d{2}:\d{2}\.\d{2})\]/g) || []).map(t => t.replace(/[\[\]]/g, '')); console.log(music_Msg_Time); resultMusicLrc.className = 'music-lyric-result-lrc'; resultMusicLrc.style.position = 'fixed'; resultMusicLrc.style.top = '80px'; resultMusicLrc.style.right = '10px'; resultMusicLrc.style.padding = '10px 15px'; resultMusicLrc.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; resultMusicLrc.style.color = '#fff'; resultMusicLrc.style.zIndex = '9999'; resultMusicLrc.style.maxWidth = '200px'; resultMusicLrc.style.maxHeight = '300px'; resultMusicLrc.style.overflowY = 'auto'; resultMusicLrc.style.borderRadius = '8px'; resultMusicLrc.style.fontSize = '14px'; resultMusicLrc.style.lineHeight = '1.5'; // 隐藏滑动条 resultMusicLrc.style.scrollbarWidth = 'none'; // Firefox resultMusicLrc.style.msOverflowStyle = 'none'; // IE 10+ // 按住拖动 resultMusicLrc.style.cursor = 'move'; resultMusicLrc.onmousedown = function (event) { const shiftX = event.clientX - resultMusicLrc.getBoundingClientRect().left const shiftY = event.clientY - resultMusicLrc.getBoundingClientRect().top function moveAt(pageX, pageY) { resultMusicLrc.style.left = pageX - shiftX + 'px' resultMusicLrc.style.top = pageY - shiftY + 'px' } function onMouseMove(event) { moveAt(event.pageX, event.pageY) } document.addEventListener('mousemove', onMouseMove) resultMusicLrc.onmouseup = function () { document.removeEventListener('mousemove', onMouseMove) resultMusicLrc.onmouseup = null } resultMusicLrc.ondragstart = function () { return false } } document.body.appendChild(resultMusicLrc); for (let i = 0; i < music_Msg.length; i++) { // 创建歌词行元素 const lineDiv = document.createElement('div'); lineDiv.textContent = music_Msg[i]; lineDiv.style.padding = '5px'; lineDiv.style.fontSize = '16px'; resultMusicLrc.appendChild(lineDiv); } apiButton.style.display = apiButton.style.display === 'none' ? 'block' : 'none'; resultInput.style.display = resultInput.style.display === 'none' ? 'block' : 'none'; resultBox.style.display = resultBox.style.display === 'none' ? 'block' : 'none'; minimizeButton.textContent = minimizeButton.textContent === '-' ? '+' : '-'; scrollLyric(); api_lock = false; // 解锁 }, onerror: function (error) { console.error("API请求错误:", error); api_lock = false; // 解锁 } }); } catch (error) { console.error("调用API时出错:", error); api_lock = false; // 解锁 } } /** * 在页面上显示结果 * @param {object} result API返回的结果 */ function showResult(result) { const resultBoxItem = document.querySelector('.box_item'); // 先处理数据 按照,分割 music_Name = result.split(','); // 去重 music_Name = Array.from(new Set(music_Name)); // 去除空格 music_Name = music_Name.map(name => name.trim()).filter(name => name !== ''); // 显示在页面上 resultBoxItem.innerHTML = ''; for (let i = 0; i < music_Name.length; i++) { const resultNameItem = document.createElement('div'); resultNameItem.style.display = 'inline-block'; resultNameItem.style.backgroundColor = 'rgba(255, 255, 255, 0.1)'; resultNameItem.style.padding = '5px 10px'; resultNameItem.style.borderRadius = '5px'; resultNameItem.style.margin = '2px 5px 2px 0'; resultNameItem.style.userSelect = 'none'; resultNameItem.style.cursor = 'pointer'; resultNameItem.innerHTML = music_Name[i]; resultNameItem.addEventListener('click', function () { getMusic(music_Name[i]); }); resultBoxItem.appendChild(resultNameItem); } if (music_Name.length === 0) { resultBoxItem.innerHTML = '未识别到歌词或作品'; } } /** * 歌词滚动 */ function scrollLyric() { // 时间格式为 mm:ss.xx 转换为毫秒 function timeToSeconds(time) { const parts = time.split(':'); const minutes = parseInt(parts[0], 10); const seconds = parseFloat(parts[1]); return (minutes * 60 + seconds) * 1000; } // 转换所有时间为毫秒 music_Msg_Time = music_Msg_Time.map(timeToSeconds); // 到达时间后滚动到对应位置,打印对应歌词 const interval = setInterval(() => { const currentTime = document.querySelector('video').currentTime * 1000; // 当前时间 毫秒 for (let i = 0; i < music_Msg_Time.length; i++) { // 提前5毫秒 if (currentTime >= (music_Msg_Time[i] - 5) && currentTime < ((music_Msg_Time[i + 1] || Infinity) - 5)) { // 滚动到对应位置 const lines = resultMusicLrc.querySelectorAll('div'); if (lines[i]) { lines[i].scrollIntoView({ behavior: 'smooth', block: 'center' }); // 高亮当前行 lines[i].style.color = '#ff0'; // 取消上一个高亮 if (i > 0 && lines[i - 1]) { lines[i - 1].style.color = '#fff'; } } break; } } }, 100); } /** * 重置常量 */ function resetConstants() { music_Name = []; const resultBoxItem = document.querySelector('.box_item'); if (resultBoxItem) { resultBoxItem.innerHTML = ''; } } // 页面加载完成后执行 $(document).ready(function () { init(); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址