Потоковое аудио одновременно с источника Soundcloud с помощью узла

Я использую API Soundcloud с сервера узлов. Я хочу передавать аудиодорожку одновременно нескольким пользователям.

Я пытался что-то вроде этого (используя код по этому вопросу Потоковое аудио с сервера Node.js в тег HTML5 ;), но это не работает. Есть идеи, как я могу это сделать?

var radio = require("radio-stream");
var http = require('http');
var url = "http://api.soundcloud.com/tracks/79031167/stream?client_id=db10c5086fe237d1718f7a5184f33b51";
var stream = radio.createReadStream(url);

var clients = [];

stream.on("connect", function() {
    console.error("Radio Stream connected!");
    console.error(stream.headers);
});

stream.on("data", function (chunk) {
    if (clients.length > 0){
        for (client in clients){
            clients[client].write(chunk);
        };
    }
});

stream.on("metadata", function(title) {
    console.error(title);
});

var server = http.createServer(function(req, res){
    res.writeHead(200,{
        "Content-Type": "audio/mpeg",
        'Transfer-Encoding': 'chunked'
    });

    clients.push(res);
    console.log('Client connected; streaming');
});
server.listen("8000", "0.0.0.0");

console.log('Server running at http://127.0.0.1:8000'); 

1 ответ

Решение

Есть несколько проблем

Следуйте перенаправлениям

radio-stream используемый вами модуль не обновлялся 4 года. Это вечность во времена Node.js API. Я рекомендую не использовать его, поскольку, несомненно, существуют проблемы совместимости с текущей и будущей версиями Node.js. Как минимум, теперь есть гораздо лучшие способы справиться с этим с помощью нового API потоков.

В любом случае этот модуль не выполняет HTTP-перенаправления. SoundCloud API перенаправляет вас к реальному медиа-файлу.

Кроме radio-stream Модуль создан для демодуляции метаданных в стиле SHOUTcast/Icecast, а не данных MP3 ID3. Это тебе не поможет.

Все, что вам нужно, это простой http.get(), Затем вы можете либо самостоятельно выполнить перенаправление, либо воспользоваться request пакет. Подробнее здесь: Как вы следите за HTTP Redirect в Node.js?

Chunked Encoding

Многие потоковые клиенты не могут справиться с кодированием по частям. Node.js (правильно) добавляет его, когда у вас есть потоковый вывод. Для наших целей, однако, давайте отключим его.

res.useChunkedEncodingByDefault = false;

/questions/22736542/obsluzhivanie-otvetov-http10-s-nodejs-neizvestnaya-dlina-kontenta-kodirovka-peredachi-po-chastyam/22736552#22736552

Построение связного потока

Теоретически, вы можете просто добавить поток MPEG после потока MPEG, и все будет работать нормально. На практике это не работает. Теги ID3 повредят поток. Один файл может иметь другую частоту дискретизации, чем другой файл, и большинство программного обеспечения не сможет переключить оборудование на эту новую частоту дискретизации на лету. По сути, вы не можете надежно делать то, что вы пытаетесь сделать.

Единственное, что вы можете сделать, это перекодировать весь поток, воспроизводя эти аудиофайлы, и получая сплошной поток на другом конце. Это дает вам дополнительный бонус, который вы можете обрабатывать другие кодеки и форматы, а не только MP3.

Для решения многих проблем с кодеками вы можете использовать FFmpeg. Однако вам понадобится способ воспроизвести эти файлы в FFmpeg для кодирования.

Ограничение скорости

Вы должны передавать аудио со скоростью воспроизведения. (Вы можете отправить начальный буфер для быстрого запуска клиентов, но вы не можете продолжать отбрасывать им данные настолько быстро, насколько это возможно.) Если вы этого не сделаете, на сервере будет очень мало памяти, так как клиенты уменьшают размер окна TCP до нуля и остаются там до тех пор, пока звук не будет достаточно занят, чтобы позволить буферизовать больше данных. Поскольку вы не используете pipe, ваши потоки находятся в режиме потока и будут неограниченно буферизоваться на сервере. Теперь, на самом деле, это хорошо в некоторых отношениях, потому что это мешает одному медленному клиенту замедлять работу других. Это плохо, хотя в том, что ваш код, вы транслируете как можно быстрее, а не со скоростью воспроизведения.

Если вы воспроизводите звук на другом кодере, используйте RTC в течение нескольких секунд в качестве часов. Это не должно быть идеально, для этого нужны клиентские буферы. Если вы воспроизводите аудиоустройство, у него, конечно, есть свои часы, которые будут использоваться.

Что вы должны на самом деле делать

Вы наткнулись на огромный проект. Я настоятельно рекомендую вместо этого использовать Liquidsoap. Есть способы, которыми вы можете управлять им из Node.js. Оттуда, используйте сервер как Icecast для вашей потоковой передачи.

Другие вопросы по тегам