返回首頁 

Greasy Fork is available in English.

Apple Music 歌词增强

为网页版 Apple Music 提供翻译歌词,数据来源为网易云音乐。


Installer ce script?
// ==UserScript==// @name         Apple Music 歌词增强// @namespace    https://github.com/akashiwest/AML-Enhancer// @version      1.100// @description  为网页版 Apple Music 提供翻译歌词,数据来源为网易云音乐。// @author       Akashi// @license      GNU GPL 3.0// @match        https://*.music.apple.com/*// @grant        GM_xmlhttpRequest// ==/UserScript==(function() {'use strict';// 定义扩展和缩小时容器的高度const expandedHeight = '240px';const minimizedHeight = '130px';// 全局变量保存主歌词与翻译歌词数据let currentLyrics = [];let currentTLyrics = [];// 创建固定容器(含内部内容容器)用于显示歌词function createLyricsDisplay() {const lyricsDiv = document.createElement('div');lyricsDiv.id = 'lyrics-display';// 默认缩小lyricsDiv.dataset.isMinimized = 'true';Object.assign(lyricsDiv.style, {position: 'fixed',right: '20px',top: '60px',width: '850px',height: minimizedHeight,overflow: 'hidden',borderRadius: '20px',backdropFilter: 'saturate(200%) blur(25px)',background: 'rgba(250,250,250,0.72)',zIndex: '9999',padding: '20px 30px',fontSize: '28px',color: '#565656',textAlign: 'center',boxShadow: '0 5px 30px rgba(0, 0, 0, 0.4)',fontWeight: 'bold',msOverflowStyle: 'none',scrollbarWidth: 'none',// 高度切换的动画效果,仅对 height 生效transition: 'height 0.3s ease'});// 内部容器,滚动时带平滑动画const lyricsContent = document.createElement('div');lyricsContent.id = 'lyrics-content';lyricsContent.style.transition = 'transform 0.3s ease-out';lyricsContent.style.transform = 'translateY(0)';lyricsDiv.appendChild(lyricsContent);const defaultGroup = document.createElement('div');defaultGroup.className = 'lyric-group';defaultGroup.style.height = '70px';defaultGroup.style.marginBottom = '10px';const defaultText = document.createElement('div');defaultText.className = 'main-lyric';defaultText.innerText = 'Apple Music 歌词翻译 V1.1';defaultText.style.fontSize = '32px';defaultText.style.color = '#252525';defaultText.style.fontWeight = 'bold';defaultText.style.marginTop = '25px';defaultGroup.appendChild(defaultText);lyricsContent.appendChild(defaultGroup);lyricsDiv.appendChild(lyricsContent);// 切换按钮const toggleButton = document.createElement('button');const infoButton = document.createElement('button');toggleButton.id = 'toggle-size-button';infoButton.id = 'info-button';toggleButton.innerText = '放大';Object.assign(toggleButton.style, {position: 'absolute',bottom: '10px',right: '10px',padding: '5px 10px',fontSize: '14px',border: 'none',borderRadius: '15px',background: '#ddd',cursor: 'pointer',zIndex: '10000',opacity: '0.8'});infoButton.innerText = 'O';Object.assign(infoButton.style, {position: 'absolute',bottom: '10px',right: '65px',padding: '5px 8px',fontSize: '14px',border: 'none',borderRadius: '15px',background: '#ddd',cursor: 'pointer',zIndex: '10000',opacity: '0.3'});toggleButton.addEventListener('click', function(e) {// 阻止事件向拖拽处理传播e.stopPropagation();if (lyricsDiv.dataset.isMinimized === 'true') {// 扩展lyricsDiv.style.height = expandedHeight;lyricsDiv.dataset.isMinimized = 'false';toggleButton.innerText = '缩小';} else {// 缩小lyricsDiv.style.height = minimizedHeight;lyricsDiv.dataset.isMinimized = 'true';toggleButton.innerText = '放大';}});lyricsDiv.appendChild(toggleButton);lyricsDiv.appendChild(infoButton);infoButton.addEventListener('click', function(e) {e.stopPropagation();window.open('https://github.com/akashiwest/AML-Enhancer', '_blank');});// 拖拽功能lyricsDiv.onmousedown = dragMouseDown;let pos3 = 0, pos4 = 0;function dragMouseDown(e) {// 点击按钮不触发if (e.target === toggleButton) return;e.preventDefault();pos3 = e.clientX;pos4 = e.clientY;document.onmouseup = closeDragElement;document.onmousemove = elementDrag;}function elementDrag(e) {e.preventDefault();const pos1 = pos3 - e.clientX;const pos2 = pos4 - e.clientY;pos3 = e.clientX;pos4 = e.clientY;lyricsDiv.style.top = `${lyricsDiv.offsetTop - pos2}px`;lyricsDiv.style.left = `${lyricsDiv.offsetLeft - pos1}px`;}function closeDragElement() {document.onmouseup = null;document.onmousemove = null;}document.body.appendChild(lyricsDiv);return lyricsDiv;}// 根据播放器 title 获取歌曲ID,并调用歌词接口function getSongId() {const audioPlayer = document.getElementById('apple-music-player');if (!audioPlayer) {console.log('当前页面未找到音频播放器');return;}let title = audioPlayer.title;// 取标题中第一个“-”前面的部分(可根据实际情况调整)const secondDashIndex = title.indexOf('-', title.indexOf('-') + 1);if (secondDashIndex !== -1) {title = title.substring(0, secondDashIndex).trim();}showMessage(title);const apiUrl = `https://music.163.com/api/search/pc?s=${encodeURIComponent(title)}&offset=0&limit=1&type=1`;GM_xmlhttpRequest({method: "GET",url: apiUrl,responseType: "json",onload: function(response) {if (response.status === 200) {const data = response.response;if (data.r###lt && data.r###lt.songs && data.r###lt.songs.length > 0) {const firstSongId = data.r###lt.songs[0].id;getLyrics(firstSongId);console.log(apiUrl, 'ID - ' + firstSongId);} else {showMessage("未找到歌曲");}} else {showMessage("请求失败");}},onerror: function() {console.error("未知错误");}});}// 提示信息function showMessage(msg) {const lyricsContent = document.getElementById('lyrics-content');if (lyricsContent) {const messageGroup = document.createElement('div');messageGroup.className = 'lyric-group';messageGroup.style.height = '70px';messageGroup.style.marginBottom = '10px';const messageText = document.createElement('div');messageText.className = 'main-lyric';messageText.innerText = msg;messageText.style.fontSize = '32px';messageText.style.color = '#252525';messageText.style.fontWeight = 'bold';messageText.style.filter = 'blur(0) !important';// 添加容器样式以确保垂直居中messageGroup.style.display = 'flex';messageGroup.style.alignItems = 'center';messageGroup.style.justifyContent = 'center';messageGroup.style.height = '100%';messageGroup.style.marginTop = '25px';messageGroup.appendChild(messageText);lyricsContent.innerHTML = '';lyricsContent.appendChild(messageGroup);}}// 获取歌词(同时获取主歌词和翻译歌词)并解析后渲染function getLyrics(songId) {const apiUrl = `https://music.163.com/api/song/lyric?lv=1&kv=1&tv=-1&id=${songId}`;showMessage('歌词正在加载中 ...');GM_xmlhttpRequest({method: "GET",url: apiUrl,responseType: "json",onload: function(response) {if (response.status === 200) {const data = response.response;if (!data || (!data.lrc && !data.tlyric)) {showMessage('未找到匹配歌词');currentLyrics = [];currentTLyrics = [];return;}const lyricsLines = data.lrc ? data.lrc.lyric : "";const tlyricsLines = data.tlyric ? data.tlyric.lyric : "";currentLyrics = parseLyrics(lyricsLines);currentTLyrics = parseLyrics(tlyricsLines);if (currentLyrics.length === 0) {showMessage('暂无歌词');return;}renderLyrics();const audioPlayer = document.getElementById('apple-music-player');if (audioPlayer) {audioPlayer.dataset.songId = songId;}} else {showMessage('歌词获取失败');currentLyrics = [];currentTLyrics = [];}},onerror: function(err) {console.error(err);showMessage('歌词获取失败');currentLyrics = [];currentTLyrics = [];}});}// 解析歌词文本(格式:[mm:ss.xxx]歌词内容)function parseLyrics(lyricsText) {return lyricsText.split('\n').filter(line => line.trim() !== '').map(line => {const matches = line.match(/\[(\d{2}):(\d{2})(?:\.(\d{1,3}))?\](.*)/);if (matches) {const minutes = parseInt(matches[1], 10);const seconds = parseInt(matches[2], 10);let milliseconds = matches[3] ? parseInt(matches[3], 10) : 0;if (milliseconds < 100 && milliseconds >= 10) {milliseconds *= 10;}const text = matches[4].trim();const totalSeconds = minutes * 60 + seconds + milliseconds / 1000;return { startTime: totalSeconds, text: text };}}).filter(Boolean);}// 渲染歌词:每组歌词显示为两行(主歌词及对应翻译),每组之间有间隙function renderLyrics() {const lyricsContent = document.getElementById('lyrics-content');if (!lyricsContent) return;lyricsContent.innerHTML = '';const groupHeight = 70; // 每组固定高度(包括两行与间隙)currentLyrics.forEach((lyric, index) => {const groupDiv = document.createElement('div');groupDiv.className = 'lyric-group';groupDiv.dataset.index = index;groupDiv.style.height = groupHeight + 'px';groupDiv.style.marginBottom = '10px';// 主歌词行const mainDiv = document.createElement('div');mainDiv.className = 'main-lyric';mainDiv.innerText = lyric.text;mainDiv.style.fontSize = '28px';mainDiv.style.color = '#565656';// 匹配翻译歌词let translationText = "";if (currentTLyrics && currentTLyrics.length > 0) {const tLine = currentTLyrics.find(t => Math.abs(t.startTime - lyric.startTime) < 0.5);if (tLine) {translationText = tLine.text;}}const transDiv = document.createElement('div');transDiv.className = 'translation-lyric';transDiv.innerText = translationText;transDiv.style.fontSize = '20px';transDiv.style.color = '#888';transDiv.style.marginTop = '5px';groupDiv.appendChild(mainDiv);groupDiv.appendChild(transDiv);lyricsContent.appendChild(groupDiv);});}// 当前歌词高亮function updateLyricScroll(currentTime) {if (currentLyrics.length === 0) return;let currentIndex = 0;for (let i = 0; i < currentLyrics.length; i++) {if (currentTime >= currentLyrics[i].startTime) {currentIndex = i;} else {break;}}const lyricsContent = document.getElementById('lyrics-content');if (lyricsContent === null) return;const groups = lyricsContent.getElementsByClassName('lyric-group');for (let i = 0; i < groups.length; i++) {const mainDiv = groups[i].querySelector('.main-lyric');const transDiv = groups[i].querySelector('.translation-lyric');if (!mainDiv || !transDiv) continue;if (i === currentIndex) {mainDiv.style.color = '#252525';mainDiv.style.fontWeight = 'bold';mainDiv.style.fontSize = '32px';mainDiv.style.filter = 'blur(0)';transDiv.style.filter = 'blur(0)';transDiv.style.color = '#353535';transDiv.style.fontWeight = 'bold';transDiv.style.fontSize = '24px';} else {mainDiv.style.color = '#565656';mainDiv.style.filter = 'blur(3px)';mainDiv.style.marginTop = '20px';mainDiv.style.fontWeight = 'normal';mainDiv.style.fontSize = '28px';transDiv.style.filter = 'blur(3px)';transDiv.style.color = '#888';transDiv.style.fontWeight = 'normal';transDiv.style.fontSize = '20px';}}// 计算滚动偏移(groupHeight + 下边距),不知道怎么调的,反正按照现在这样数值设置了看着还可以const groupHeight = 90;const container = document.getElementById('lyrics-display');const containerHeight = container.clientHeight;const offset = (currentIndex * groupHeight) - (containerHeight / 2 - groupHeight / 2) + 30;const lyricsContentDiv = document.getElementById('lyrics-content');lyricsContentDiv.style.transform = `translateY(-${offset}px)`;}const lyricsDisplay = createLyricsDisplay();// 更新滚动document.addEventListener('timeupdate', function(event) {const audioPlayer = event.target;if (audioPlayer.id === 'apple-music-player') {const startOffset = parseFloat(audioPlayer.dataset.startOffset) || 0;const effectiveTime = audioPlayer.currentTime - startOffset;updateLyricScroll(effectiveTime);}}, true);// 每秒检测歌曲标题变化(切歌)setInterval(function() {const audioPlayer = document.getElementById('apple-music-player');if (audioPlayer) {let title = audioPlayer.title;if (title) {const secondDashIndex = title.indexOf('-', title.indexOf('-') + 1);if (secondDashIndex !== -1) {title = title.substring(0, secondDashIndex).trim();}if (title !== audioPlayer.dataset.lastTitle) {audioPlayer.dataset.lastTitle = title;audioPlayer.dataset.startOffset = audioPlayer.currentTime;const lyricsContent = document.getElementById('lyrics-content');if (lyricsContent) {lyricsContent.innerHTML = '';}getSongId();}}}}, 1000);// 当前曲播放结束时也尝试重新获取歌词(适用于自动切换下一曲)const audioPlayer = document.getElementById('apple-music-player');if (audioPlayer) {audioPlayer.addEventListener('ended', function() {setTimeout(() => {audioPlayer.dataset.startOffset = audioPlayer.currentTime;getSongId();}, 500);});}})();