您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
下载汽水音乐歌词(LRC逐字格式)
// ==UserScript== // @name 汽水音乐歌词下载 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 下载汽水音乐歌词(LRC逐字格式) // @author Yanice537 // @match https://music.douyin.com/qishui/share/track* // @grant none // ==/UserScript== (function() { 'use strict'; // 创建下载按钮 function createDownloadButton() { const btn = document.createElement('button'); btn.innerHTML = '下载LRC歌词'; btn.style.position = 'fixed'; btn.style.bottom = '20px'; btn.style.right = '20px'; btn.style.zIndex = '9999'; btn.style.padding = '12px 24px'; btn.style.background = 'linear-gradient(45deg, #ff2a55, #ff8a00)'; btn.style.color = 'white'; btn.style.border = 'none'; btn.style.borderRadius = '30px'; btn.style.fontWeight = 'bold'; btn.style.fontSize = '16px'; btn.style.cursor = 'pointer'; btn.style.boxShadow = '0 4px 15px rgba(255, 42, 85, 0.4)'; btn.style.transition = 'all 0.3s ease'; btn.onmouseover = () => { btn.style.transform = 'translateY(-3px)'; btn.style.boxShadow = '0 6px 20px rgba(255, 42, 85, 0.6)'; }; btn.onmouseout = () => { btn.style.transform = 'translateY(0)'; btn.style.boxShadow = '0 4px 15px rgba(255, 42, 85, 0.4)'; }; btn.onclick = downloadLyrics; document.body.appendChild(btn); return btn; } // 下载歌词 async function downloadLyrics() { const btn = this; const originalText = btn.innerHTML; btn.innerHTML = '获取歌词中...'; btn.disabled = true; try { // 获取当前页面URL参数 const urlParams = new URLSearchParams(window.location.search); const track_id = urlParams.get('track_id'); if (!track_id) { throw new Error('无法获取歌曲ID'); } // 构建API请求URL const apiUrl = `https://music.douyin.com/qishui/share/track?${urlParams.toString()}`; // 发送请求获取歌词数据 const response = await fetch(apiUrl); const responseText = await response.text(); // 获取歌曲元数据 const { artistName, songTitle, composer, lyricist } = extractMetadata(responseText); // 创建文件名 const filename = `${artistName}-${songTitle}.lrc`.replace(/[\\/:*?"<>|]/g, ''); // 解析歌词 let lrcContent = parseLyrics(responseText); // 添加元数据到歌词开头 lrcContent = addMetadataToLyrics(lrcContent, composer, lyricist); // 下载文件 downloadFile(lrcContent, filename); btn.innerHTML = '下载成功!'; setTimeout(() => { btn.innerHTML = originalText; btn.disabled = false; }, 2000); } catch (error) { console.error('歌词下载失败:', error); btn.innerHTML = '失败,点击重试'; btn.disabled = false; // 显示错误提示 showErrorToast(`歌词下载失败: ${error.message}`); } } // 提取歌曲元数据 function extractMetadata(responseText) { // 歌曲名 const songTitleMatch = responseText.match(/"trackName":"(.*?)"/); const songTitle = songTitleMatch ? songTitleMatch[1] : '未知歌曲'; // 歌手名 const artistNameMatch = responseText.match(/"artistName":"(.*?)"/); const artistName = artistNameMatch ? artistNameMatch[1] : '未知歌手'; // 作曲 const composerMatch = responseText.match(/"text":"作曲:(.*?)","startMs":(\d+),"endMs":(\d+)/); const composer = composerMatch ? composerMatch[1] : '未知作曲'; // 作词 const lyricistMatch = responseText.match(/"text":"作词:(.*?)","startMs":(\d+),"endMs":(\d+)/); const lyricist = lyricistMatch ? lyricistMatch[1] : '未知作词'; return { songTitle, artistName, composer, lyricist }; } // 添加元数据到歌词开头 function addMetadataToLyrics(lyrics, composer, lyricist) { return `[ar:${composer}]\n` + `[ti:${lyricist}]\n\n` + lyrics; } // 解析歌词 function parseLyrics(responseText) { // 使用正则表达式提取逐行歌词 const lineLyrics = []; const lineRegex = /{"text":"(.*?)","startMs":(\d+),"endMs":(\d+)(?=,"words":)/g; let lineMatch; while ((lineMatch = lineRegex.exec(responseText)) !== null) { lineLyrics.push({ text: lineMatch[1], startMs: parseInt(lineMatch[2]), endMs: parseInt(lineMatch[3]) }); } // 提取逐字歌词信息 const wordLyrics = []; const wordRegex = /{"startMs":(\d+),"endMs":(\d+),"text":"(.*?)"}/g; let wordMatch; while ((wordMatch = wordRegex.exec(responseText)) !== null) { wordLyrics.push({ startMs: parseInt(wordMatch[1]), endMs: parseInt(wordMatch[2]), text: wordMatch[3] }); } // 准备LRC内容 const lrcContent = []; // 处理每一行歌词 for (const line of lineLyrics) { const lineStartMs = line.startMs; const lineEndMs = line.endMs; const lineText = line.text; // 收集属于当前行的逐字歌词 const lineWords = []; for (const word of wordLyrics) { if (word.startMs >= lineStartMs && word.startMs <= lineEndMs) { lineWords.push({ startMs: word.startMs, text: word.text }); } } // 如果没有逐字歌词,使用整行文本 if (lineWords.length === 0) { const timeTag = formatTime(lineStartMs); lrcContent.push(`${timeTag}${lineText}`); } else { // 按时间排序逐字歌词 lineWords.sort((a, b) => a.startMs - b.startMs); // 生成逐字LRC行 let lineStr = ''; for (const word of lineWords) { const timeTag = formatTime(word.startMs); lineStr += `${timeTag}${word.text}`; } lrcContent.push(lineStr); } } return lrcContent.join('\n'); } // 格式化时间标签 function formatTime(ms) { const minutes = Math.floor(ms / 60000); const seconds = Math.floor((ms % 60000) / 1000); const centiseconds = Math.floor((ms % 1000) / 10); return `[${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}.${centiseconds.toString().padStart(2, '0')}]`; } // 下载文件 function downloadFile(content, filename) { const blob = new Blob([content], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); // 清理 setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 100); } // 显示错误提示 function showErrorToast(message) { let toast = document.getElementById('lyrics-error-toast'); if (!toast) { toast = document.createElement('div'); toast.id = 'lyrics-error-toast'; toast.style.position = 'fixed'; toast.style.top = '20px'; toast.style.left = '50%'; toast.style.transform = 'translateX(-50%)'; toast.style.backgroundColor = '#ff2a55'; toast.style.color = 'white'; toast.style.padding = '15px 25px'; toast.style.borderRadius = '8px'; toast.style.zIndex = '10000'; toast.style.fontWeight = 'bold'; toast.style.boxShadow = '0 4px 15px rgba(0, 0, 0, 0.3)'; toast.style.transition = 'opacity 0.3s'; document.body.appendChild(toast); } toast.textContent = message; toast.style.opacity = '1'; setTimeout(() => { toast.style.opacity = '0'; }, 3000); } // 初始化 window.addEventListener('load', () => { createDownloadButton(); }); })();