【问题标题】:NodeJS mp3 streaming not working in browsersNodeJS mp3 流在浏览器中不起作用
【发布时间】:2019-09-30 18:11:46
【问题描述】:

我想从 NodeJS / ExpressJS 后端流式传输 MP3 音频文件。我在论坛中找到了一些代码(例如这里stream mp3 file express server with ability to fast forward/rewind),但它似乎对我不起作用。我有以下代码:

const express = require('express');
const path = require('path');
const fs = require('fs');

const app = express();

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'index.html'));
});

app.get('/api/play', (req, res) => {
    var music = path.join('Z:', 'Music', 'Metallica', "Kill 'Em All", '01 - Hit the Lights.mp3');
    var stat = fs.statSync(music);
    var range = req.headers.range;
    var readStream;

    if (range != undefined) {
        var parts = range.replace(/bytes=/, '').split('-');
        var partialStart = parts[0];
        var partialEnd = parts[1];

        if (isNaN(partialStart) || partialStart == '') {
            partialStart = '0';
        }

        if (isNaN(partialEnd) || partialEnd == '') {
            partialEnd = stat.size - 1;
        }

        var start = parseInt(partialStart, 10);
        var end = parseInt(partialEnd, 10);
        var contentLength = end - start + 1;

        console.log(`Streaming ${music} as ${contentLength} bytes from ${start} to ${end}`);

        res.writeHead(206, {
            'Content-Type': 'audio/mpeg',
            'Content-Length': contentLength,
            'Content-Range': 'bytes=' + start + '-' + end + '/' + stat.size,
            'Accept-Ranges': 'bytes'
        });

        readStream = fs.createReadStream(music, { start: start, end: end });
    } else {
        console.log(`Streaming ${music} as ${stat.size} bytes`);

        res.header({
            'Content-Type': 'audio/mpeg',
            'Content-Length': stat.size
        });

        readStream = fs.createReadStream(music);
    }

    readStream.pipe(res);

    console.log('Done');
});

const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

index.html 基本上只是一个音频标签:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <audio controls="controls" preload="all">
        <source src="http://localhost:5000/api/play" type="audio/mpeg" />
        Your browser does not support the audio element.
    </audio>
</body>

</html>

当我从浏览器打开页面时,我得到了音频标签,但它没有播放。控制台没有错误,在网络选项卡中我看到 /api/play 请求只有 229 个字节,响应头如下:

Accept-Ranges: bytes
Connection: keep-alive
Content-Length: 4108683
Content-Range: bytes=0-4108682/4108683
Content-Type: audio/mpeg
Date: Mon, 30 Sep 2019 18:01:02 GMT
X-Powered-By: Express

但是,当我从 RestMan 扩展中尝试相同的操作时,我得到了完整的 4MB 文件作为响应,其中包含以下标题:

date: Mon, 30 Sep 2019 17:41:01 GMT
connection: keep-alive
x-powered-by: Express
content-length: 15987040
content-type: audio/mpeg

我尝试从 RestMan 客户端手动执行,使用不同的“Accept”标头、“0-”和浏览器一样、“0-2”、“0-200”、“100-200”等,我总是以正确的字节数获得正确的响应(例如,“100-200”为 101 个字节)。那么为什么浏览器无法加载音频呢?即使我直接打开 /api/play URL,我也只会得到一个自动生成的“视频”标签,但它没有播放,同样的事情也会发生。

我还尝试了文件名中没有空格或特殊字符的 MP3,尝试从没有空格或特殊字符的目录加载它,从本地驱动器加载(Z:是网络附加存储),尝试从与 html 相同的目录加载,总是一样的。

如果您有任何想法,请提供帮助。我不确定这是否是 NodeJS 方面的问题或缺少的东西,或者完全是其他的东西。

【问题讨论】:

    标签: node.js express stream


    【解决方案1】:

    啊,我找到了。似乎 206“部分内容”响应是罪魁祸首。我将其更改为 200,现在它可以工作了。如果请求完整范围,是否可以返回 200,仅在返回完整文件的一部分时使用 206?

    【讨论】:

      猜你喜欢
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 2012-02-04
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 2021-04-02
      相关资源
      最近更新 更多