NodeJS потоковое mp3 не работает в браузерах - PullRequest
0 голосов
/ 30 сентября 2019

Я бы хотел транслировать аудиофайлы MP3 из серверной части NodeJS / ExpressJS. Для начала я нашел некоторый код в форумах (например, здесь потоковый mp3-файл, экспресс-сервер с возможностью быстрой перемотки вперед / назад ), однако он мне не подходит. У меня есть следующий код:

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 "и т. Д. Я всегда получаю правильный ответ с правильным количеством байтов (например, 101 байт для" 100-200 "). Так почему же браузер не может загрузить аудио? Даже когда я открываю URL / api / play напрямую, я получаю только автоматически сгенерированный тег «video», но он не воспроизводится, происходит то же самое.

Я также пробовал MP3 без пробелов или специальных символов вимя файла, попытался загрузить его из каталога без пробелов и специальных символов, загрузить с локального диска (Z: сетевое хранилище), попытался загрузить из того же каталога, что и HTML, он всегда одинаков.

Пожалуйста, помогитеесли у вас есть идеяЯ не уверен, что это проблема или что-то отсутствует на стороне NodeJS, или что-то еще полностью.

1 Ответ

0 голосов
/ 30 сентября 2019

Ах, я нашел это. Похоже, что ответом 206 «Частичное содержание» был виновник. Я изменил его на 200, и теперь он работает. Можно ли возвращать 200, если запрашивается полный диапазон, и использовать 206 только при возвращении части полного файла?

...