Симулятор Ham Radio: потоковая передача аудио с микрофона в реальном времени между 2 браузерами, подключенными через Ubuntu 22.

Вопрос или проблема

Я пытаюсь симулировать радио с кнопкой PTT. Подключенные пользователи должны иметь возможность общаться голосом в группе в реальном времени, по одному за раз, удерживая кнопку. У меня работает сервер Ubuntu 22.04 с nginx, но, к сожалению, ничего не получается. Я точно не знаю, какой метод будет хорошим. Я пытался использовать сокеты, но я продолжаю получать ошибки в консоли (в Firefox), такие как:
Медиа ресурс blob:https://mywebsite не может быть декодирован, ошибка: Код ошибки: NS_ERROR_DOM_MEDIA_METADATA_ERR (0x806e0006)

Как именно должен выглядеть протокол передачи живого аудио через браузер? Спасибо!

async function startTransmission() {
if (!mediaStream) {
    try {
        mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
        mediaRecorder = new MediaRecorder(mediaStream, { mimeType: "audio/webm;codecs=opus" });

        mediaRecorder.ondataavailable = (event) => {
            if (event.data.size > 0) {
                socket.emit("audio-stream", event.data);
            }
        };
        mediaRecorder.start(300); // Отправка аудио фрагментами по 300мс
        logMessage("🔊 Передача аудио...");
    } catch (error) {
        console.error("Доступ к микрофону отклонен:", error);
        logMessage("⚠️ Доступ к микрофону отклонен.");
    }
}}

а сервер:

socket.on("audio-stream", (audioData) => {
io.emit("receive-audio", {
    audioData,
    mimeType: "audio/webm;codecs=opus",
    senderId: socket.id // Отправка ID отправителя, чтобы они могли игнорировать свое собственное аудио
});});

Спасибо!
Джордж

Ответ или решение

Теория:

Когда речь идет о передаче звука в реальном времени между браузерами, обычно используется технология WebRTC (Web Real-Time Communication). Она позволяет обеспечивать потоковую передачу аудио и видео в реальном времени с минимальными задержками, обеспечивая взаимодействие между различными устройствами напрямую, без необходимости проходить через сервер посредника для передачи медиапотока. WebRTC поддерживается большинством современных браузеров, включая Firefox и Chrome, и является идеальным выбором для задач типа "рация", где нет необходимости в сложной архитектуре клиента и сервера.

WebRTC состоит из нескольких ключевых компонентов:

  • MediaStream API: позволяет запрашивать доступ к микрофону и камере пользователя.
  • RTCPeerConnection: обеспечивает установление и поддержание прямого подключения между узлами.
  • RTCDataChannel: позволяет передавать произвольные данные (не медиа).

Возможно, в вашей реализации также используется MediaRecorder, который предназначен для записи медиапотоков, но для задачи прямой трансляции WebRTC будет более уместным.

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

Пример:

Для начала, важно убедиться, что сервер и клиентская части системы настроены правильно для работы с WebRTC. Для этого выполните следующие шаги:

  1. Запрос доступа к микрофону на клиенте:
async function getMicrophoneStream() {
    try {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        return stream;
    } catch (error) {
        console.error('Ошибка доступа к микрофону:', error);
        return null;
    }
}
  1. Создание RTCPeerConnection на клиенте:
const peerConnection = new RTCPeerConnection({
    iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});

// Добавьте обработчики событий для уведомления об изменениях статуса соединения
peerConnection.onicecandidate = event => {
    if (event.candidate) {
        socket.emit('ice-candidate', event.candidate);
    }
};

peerConnection.ontrack = event => {
    // Добавление аудио потока в аудиоконтекст
    const audioElement = document.createElement('audio');
    audioElement.srcObject = event.streams[0];
    audioElement.play();
};

async function makeCall() {
    const stream = await getMicrophoneStream();
    if (!stream) return;

    stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));

    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);

    socket.emit('offer', offer);
}
  1. Обработка сигнала на сервере:

Ваш сервер (предположительно Node.js с использованием сокетов) должен уметь обрабатывать сигналы WebRTC:

socket.on('offer', (offer) => {
    // Отправка предложения другим пользователям
    socket.broadcast.emit('offer', offer);
});

socket.on('answer', (answer) => {
    // Отправка ответа пользователю, который предложил соединение
    socket.broadcast.emit('answer', answer);
});

socket.on('ice-candidate', (candidate) => {
    // Отправьте ICE-кандидаты другим пользователям
    socket.broadcast.emit('ice-candidate', candidate);
});

Применение:

Реализовав описанные выше шаги, вы сможете создать рабочую трансляцию аудио между браузерами с использованием WebRTC. Убедитесь, что ваш nginx-сервер правильно конфигурирован для обеспечения безопасности и соответствия сертификатам SSL, поскольку WebRTC работает только по защищённому соединению (HTTPS).

Ваш nginx-конфигурация может выглядеть следующим образом:

server {
    listen 443 ssl;
    server_name mywebsite.com;

    ssl_certificate /path/to/ssl/certificate.crt;
    ssl_certificate_key /path/to/private.key;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Убедитесь, что все модули сервера для работы с WebRTC и сокетами установлены и работают корректно. Проводите тестирование в различных условиях, чтобы убедиться в корректной обработке всех возможных ошибок и устранения потенциальных уязвимостей.

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

Оцените материал
Добавить комментарий

Капча загружается...