Я разрабатываю веб-приложение, которое передает аудио от администратора нескольким пользователям в режиме реального времени с использованием WebRTC и Socket.IO. Однако я столкнулся с проблемой, при которой воспроизведение звука на стороне пользователя прерывается или периодически останавливается. Вот краткий обзор установки и проблемы:
Настраивать: Администратор записывает звук с микрофона с помощью getUserMedia и MediaRecorder. Аудио кодируется из WAV в MP3 с помощью lamejs и передается пользователям через Socket.IO. Пользователи получают аудиофрагменты и пытаются воспроизвести их с помощью элемента.
Проблема:
Хотя воспроизведение звука начинается успешно, оно часто прерывается или останавливается через короткое время.
Код со стороны администратора:
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Admin Broadcasting</title>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lamejs/1.2.0/lame.min.js"></script>
</head>
<body>
<h1>Admin Broadcasting</h1>
<button id = "startBroadcastBtn">Start Broadcasting</button>
<script src = "/socket.io/socket.io.js"></script>
<script>
const startBroadcastBtn = document.getElementById('startBroadcastBtn');
const socket = io('ws://localhost:9000');
let mediaRecorder;
startBroadcastBtn.addEventListener('click', async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
if (!stream) {
console.error('getUserMedia failed to return a valid stream');
return;
}
// Initialize MediaRecorder with WAV format
mediaRecorder = new MediaRecorder(stream);
// Create WAV to MP3 converter using lamejs
const mp3Encoder = new lamejs.Mp3Encoder(1, 44100, 128);
// Add event listener for data availability
mediaRecorder.ondataavailable = async (event) => {
try {
if (event.data.size > 0) {
console.info('Audio chunk captured:', event.data);
// Convert WAV audio data to MP3
const reader = new FileReader();
reader.onload = async () => {
const arrayBuffer = reader.result;
const buffer = new Int8Array(arrayBuffer);
const length = buffer.length;
const pcm = new Int16Array(length / 2);
// Convert Int8Array to Int16Array (PCM data)
for (let i = 0; i < length; i += 2) {
pcm[i / 2] = buffer[i] | (buffer[i + 1] << 8);
}
const mp3Data = mp3Encoder.encodeBuffer(pcm);
const mp3Blob = new Blob([mp3Data], { type: 'audio/mp3' });
console.info('Created MP3 blob:', mp3Blob);
socket.emit('admin-audio-chunk', mp3Blob);
};
reader.readAsArrayBuffer(event.data);
}
} catch (error) {
console.error('Error processing audio data:', error);
}
};
// Start recording
console.info('Starting recording...');
mediaRecorder.start(1000);
console.info('Recording started.');
} catch (error) {
console.error('Error accessing media devices:', error);
}
});
</script>
</body>
</html>
код на стороне пользователя:
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>User Listening</title>
</head>
<body>
<h1>User Listening</h1>
<audio id = "audioPlayer" controls preload = "auto"></audio>
<script src = "/socket.io/socket.io.js"></script>
<script>
const audioPlayer = document.getElementById('audioPlayer');
const socket = io('ws://localhost:9000');
let audioChunks = [];
socket.on('user-audio-chunk', (data) => {
console.info('Received audio chunk from admin:', data);
audioChunks.push(data);
playAudioChunks();
});
function playAudioChunks() {
if (audioChunks.length > 0 && audioPlayer.paused) {
const audioBlob = new Blob(audioChunks, { type: 'audio/mp3' });
audioPlayer.src = URL.createObjectURL(audioBlob);
audioPlayer.play().catch((error) => {
console.error('Error playing audio:', error);
});
audioChunks = [];
}
}
</script>
</body>
</html>
Как плавно воспроизвести звук и решить проблему?





Настройка: администратор записывает звук с микрофона с помощью getUserMedia и MediaRecorder. Аудио кодируется из WAV в MP3 с помощью lamejs и передается пользователям через Socket.IO. Пользователи получают аудиофрагменты и пытаются воспроизвести их с помощью элемента.
Вы кодируете фрагменты и воспроизводите фрагменты... вот почему у вас прерывистое звучание звука. Если вам нужен поток аудио, вам нужно относиться к нему как к потоку.
Не создавайте экземпляр нового кодека каждый раз. Я не знаю о вашей сборке LAME, но обычный LAME будет использовать битовый резервуар, который будет переносить данные из одного кадра в другой. Итак, вам нужно настроить один экземпляр и продолжать передавать на него данные PCM.
Теперь, что касается воспроизведения, вообще не используйте веб-сокеты и все такое. Это проще. Используйте простой элемент <audio> и передавайте данные через http:
<audio src = "https://stream.example.com/something"></audio>
Ваш сервер должен брать полученные фрагменты и немедленно записывать их клиенту. Если вместо этого вы попытаетесь декодировать каждый сегмент отдельно, вы просто получите декодированные фрагменты, и они не будут волшебным образом просто воспроизводиться во времени и выстраиваться в линию.