基于Node.js的音频流服务:如何连续播放目录下音频文件?
实现Node.js音频流服务的目录遍历连续播放功能
我正在开发一个类似在线电台的Node.js音频流服务,当前app.js只能传输单个音频文件,无法遍历指定目录并逐个播放音频,需要修改代码实现该需求。原代码如下:
const express = require('express'); const path = require('path'); const fs = require('fs').promises; const app = express(); const port = 8001; // Serve static files from the 'public' directory app.use(express.static(path.join(__dirname, 'public'))); app.get('/', async (req, res) => { console.log('Port Number:', port); const folderPath = path.join(__dirname, 'public/playlists/gral/'); const totalFiles = await getTotalFiles(folderPath); console.log(totalFiles); res.sendFile(path.join(__dirname, 'public/playlists/gral/La_Mirla.mp3')); }); async function getTotalFiles(folderPath) { try { const files = await fs.readdir(folderPath); const totalFiles = files.length; console.log(`Total files in ${folderPath}: ${totalFiles}`); return totalFiles; // Return the total number of files } catch (err) { console.error('Error reading folder:', err); return 0; // Return 0 in case of an error } } app.listen(port, () => { console.log(`Server is running on port ${port}`); });
修改方案与完整代码
要实现目录遍历连续播放,需要维护播放队列、流式传输音频并自动切换文件,以下是修改后的代码:
const express = require('express'); const path = require('path'); const fs = require('fs'); const fsPromises = require('fs').promises; const app = express(); const port = 8001; // 静态文件服务 app.use(express.static(path.join(__dirname, 'public'))); // 全局播放状态:音频列表、当前播放索引 let audioFiles = []; let currentIndex = 0; const audioFolder = path.join(__dirname, 'public/playlists/gral/'); // 初始化音频文件列表(只保留MP3格式) async function initAudioList() { try { const files = await fsPromises.readdir(audioFolder); // 过滤出MP3文件,可根据需要添加其他音频格式 audioFiles = files.filter(file => file.toLowerCase().endsWith('.mp3')) .map(file => path.join(audioFolder, file)); console.log(`加载 ${audioFiles.length} 个音频文件`); } catch (err) { console.error('读取音频目录失败:', err); } } // 流式传输下一个音频文件 function streamNextAudio(res) { if (audioFiles.length === 0) { res.end('没有可播放的音频文件'); return; } // 循环播放:索引超出后重置为0 currentIndex = currentIndex % audioFiles.length; const currentFile = audioFiles[currentIndex]; console.log(`正在播放: ${path.basename(currentFile)}`); // 创建文件流 const stream = fs.createReadStream(currentFile); // 设置响应头,告诉客户端这是音频流 res.setHeader('Content-Type', 'audio/mpeg'); res.setHeader('Transfer-Encoding', 'chunked'); // 流结束后切换到下一个文件 stream.on('end', () => { currentIndex++; // 继续流式传输下一个文件 streamNextAudio(res); }); // 处理流错误 stream.on('error', (err) => { console.error('播放音频出错:', err); currentIndex++; streamNextAudio(res); }); // 将流管道到响应 stream.pipe(res); } // 根路由返回播放页面(如果有public/index.html的话),否则直接启动流 app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public/index.html')); }); // 音频流路由,提供连续播放的音频内容 app.get('/stream', (req, res) => { streamNextAudio(res); }); // 启动服务器前先初始化音频列表 initAudioList().then(() => { app.listen(port, () => { console.log(`Server is running on port ${port}`); console.log(`访问 http://localhost:${port}/stream 收听音频流`); }); });
关键修改说明
- 全局播放状态管理:用
audioFiles存储目录下的有效音频文件路径,currentIndex记录当前播放位置,实现连续播放和循环。 - 音频文件过滤:通过
filter方法只保留MP3文件,避免加载无效内容。 - 流式传输:使用
fs.createReadStream替代res.sendFile,实现大文件的流式传输,避免内存占用过高。 - 自动切换逻辑:监听流的
end事件,播放完成后自动切换到下一个文件,实现类似电台的连续播放效果。 - 专用流路由:新增
/stream路由专门提供音频流,根路由可返回前端页面(需自行创建public/index.html)。
内容的提问来源于stack exchange,提问作者el_sas
相关产品推荐
相关产品推荐

