如何从指定音乐流获取歌曲名?解决CORS及代码不更新问题
解决方案
1. 前端直接用fetch能否实现?
不行。这些音乐流服务器几乎都未配置CORS跨域允许头,浏览器的同源策略会直接阻止前端fetch请求,必须通过后端代理获取元数据后再返回给前端。
2. 后端歌曲切换后不更新的问题修复
你的代码能获取初始歌曲名,但歌曲切换时前端无法自动更新,原因有两个:一是前端只有刷新页面或重新请求接口才能拿到最新的name值;二是代码里require语句存在语法错误,'icecast-parser"'应改为'icecast-parser'。以下提供两种修复方案:
方案一:前端定时轮询获取最新歌曲名
修改后端代码,新增单独的歌曲名接口:
const { Parser } = require('icecast-parser'); let currentSong = ''; const radioStation = new Parser({ url: 'http://strm112.1.fm/dubstep_mobile_mp3' }); radioStation.on('metadata', (metadata) => { currentSong = metadata.get('StreamTitle') || '未知歌曲'; }); // 主页面接口 app.get("/", (req, res) => { res.render("index", { song: currentSong }); }); // 单独返回歌曲名的接口 app.get("/current-song", (req, res) => { res.json({ song: currentSong }); });
前端页面(index模板)添加定时请求逻辑:
<script> function updateSong() { fetch('/current-song') .then(res => res.json()) .then(data => { document.getElementById('current-song').textContent = data.song; }); } // 页面加载时先获取一次,之后每5秒更新 updateSong(); setInterval(updateSong, 5000); </script> <div id="current-song"></div>
方案二:用WebSocket实时推送(更高效)
如果希望歌曲切换时立即更新,WebSocket是更优选择,步骤如下:
- 安装ws模块:
npm install ws - 修改后端代码:
const { Parser } = require('icecast-parser'); const WebSocket = require('ws'); let currentSong = ''; const radioStation = new Parser({ url: 'http://strm112.1.fm/dubstep_mobile_mp3' }); radioStation.on('metadata', (metadata) => { currentSong = metadata.get('StreamTitle') || '未知歌曲'; // 将更新推送给所有连接的客户端 wss.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(JSON.stringify({ song: currentSong })); } }); }); app.get("/", (req, res) => { res.render("index", { song: currentSong }); }); // 启动WebSocket服务 const wss = new WebSocket.Server({ port: 8080 });
前端页面添加WebSocket监听:
<script> const ws = new WebSocket('ws://localhost:8080'); ws.onmessage = function(event) { const data = JSON.parse(event.data); document.getElementById('current-song').textContent = data.song; }; // 渲染初始歌曲名 document.getElementById('current-song').textContent = '<%= song %>'; </script> <div id="current-song"></div>
3. 支持多个音乐流链接
如果需要处理你列出的所有5个电台,可以修改后端代码,按ID区分不同电台:
const { Parser } = require('icecast-parser'); // 存储每个电台的当前歌曲 const stationSongs = {}; const stations = [ { id: 'zeno1', url: 'https://stream-27.zeno.fm/0r0xa792kwzuv?zs=of2rNL4EQaKONauS-rWZdQ' }, { id: 'zeno2', url: 'https://stream-61.zeno.fm/0r0xa792kwzuv?zs=SyKyJJtSQvSmEQObk_ymow' }, { id: 'dubstep', url: 'http://strm112.1.fm/dubstep_mobile_mp3' }, { id: 'generations', url: 'http://gene-rgton.ice.infomaniak.ch/generations-rgton.mp3' }, { id: 'iloveradio', url: 'https://streams.ilovemusic.de/iloveradio21.mp3' } ]; // 初始化每个电台的元数据监听 stations.forEach(station => { stationSongs[station.id] = '加载中...'; const parser = new Parser({ url: station.url }); parser.on('metadata', (metadata) => { stationSongs[station.id] = metadata.get('StreamTitle') || '未知歌曲'; }); }); // 根据电台ID返回对应歌曲名 app.get("/current-song/:stationId", (req, res) => { const { stationId } = req.params; res.json({ song: stationSongs[stationId] || '无效电台ID' }); });
前端可通过请求/current-song/dubstep这类接口获取对应电台的歌曲名。
内容的提问来源于stack exchange,提问作者Vεκρός
相关产品推荐
相关产品推荐

