You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:06:36