Я хотел поэкспериментировать с чем-то за пределами моей зоны комфорта и создать прототип "приложения для онлайн-радио".
Затем я попал в кроличью нору потоковой передачи WebRTC, медиасерверов, шлюзов WebRTC, сетевых графиков P2P ...
Кажется, WebRTC не подходит для подобных задач. В большинстве браузеров он ограничен 10 пирами. Масштабирование WebRTC также требует большой работы для большого количества зрителей.
Пример:
WebRTC - масштабируемая прямая трансляция / многоадресная передача
Тогда мне пришло в голову, что простые живые аудиопотоки без JavaScript уже некоторое время существуют в такой форме:
http://stream.radioreklama.bg/radio1.opus
Клиентом для таких потоков могут быть просто html <audio>
тэги.
Теперь все, что мне нужно сделать, это создать этот «волшебный» URL, где доступен живой аудиопоток. Можно ли это сделать с помощью Node.js?
Недостающие части для создания моего прототипа:
1: Отправка «живого» аудиопотока от клиента (вещателя) на сервер (используя getUserMedia и socket.io).
2: передать этот аудиопоток на URL-адрес «/stream.mp3» с правильными кодировками.
Если это возможно, я думаю, что это был бы интересный подход для решения крупномасштабной потоковой задачи со звуком «один ко многим», но, возможно, мне не хватает некоторой основной информации.
Идеальный клиент:
import io from 'socket.io-client';
const socket = io.connect('//localhost:8888');
// Broadcasting code
navigator.mediaDevices
.getUserMedia({ audio: true, video: false })
.then(userMediaStream => {
const mediaRecorder = new MediaRecorder(userMediaStream, {mimeType: 'audio/webm'});
mediaRecorder.ondataavailable = event => {
socket.emit('sound-blob', event.data);
}
mediaRecorder.start();
})
// Could be just a static html file
const App = () => (
<div>
<h1>Audio streaming client</h1>
<audio>
<source src="http://example.com/stream.mp3" type="audio/webm" />
</audio>
</div>
)
Идеальный сервер:
const app = express();
const io = require('socket.io').listen(8888);
const stream = require('stream');
const audioStream = new stream.Readable();
var app = express();
app.get('/stream.mp3', (req, res) => {
audioStream.pipe(res);
})
io.on('connection', (socket) => {
socket.on('sound-blob', (blob) => {
audioStream.push(blob);
})
})
server = http.createServer(app);
server.listen(8080);
В данный момент событие ondataavailable
запускается только после окончания потока, но я думаю, что было бы возможно разделить запись на куски и транслировать ее в режиме реального времени. Я не уверен в подходящем подходе для этого.
Как только поток будет отправлен на сервер, вероятно, будет необходимо выполнить некоторое кодирование / преобразование перед передачей его в конечную точку /stream.mp3. Я тоже не знаю, нужно ли это.
Это вообще возможно сделать? Каких ловушек я не вижу?
Спасибо, что поделились своими мыслями!