2014-12-11 2 views
0

У меня есть программно определенное радио, воспроизводящее аудиопоток с сервера WebSocket, и клиент, который потребляет данные и воспроизводит их с помощью AudioBufferSourceNode.Webaudio Воспроизведение из WebSocket имеет выпадения

В основном это работает. Единственная проблема заключается в том, что каждые несколько секунд происходят кратковременные выпадения, предположительно вызванные накладными расходами, связанными с созданием каждого последующего экземпляра AudioBufferSourceNode. Спецификация проекта WebAudio говорит, что AudioBuffer следует использовать для воспроизведения звуков, длительностью не более одной минуты, и чтобы более длинные звуки воспроизводились с использованием MediaElementSourceNode. Это не работает для меня, потому что мне нужно воспроизводить аудио из источника WebSocket, и я не знаю, как создать элемент мультимедиа (например, аудио-элемент HTML5) для работы с WebSocket.

Возможно, я пытаюсь сделать то, что WebAudio не может поддерживать, объединив экземпляры AudioBufferSourceNode и ожидая, что они будут играть один за другим без проблем. Но, похоже, должен быть способ воспроизвести данные WebSocket через WebAudio, и действительно, auroa.js (вместе с плагином aurora-websocket.js), похоже, это делает. Я закодировал клиента, используя aurora.js, но я столкнулся с другими проблемами, для которых я создал проблему auroa.js на Github. Тем временем я надеюсь, что могу сделать в своем клиенте то, что они, похоже, сделали, используя WebAudio для беспрепятственного воспроизведения данных из WebSocket.

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

var context = ... 
var gainNode = ... 

var playBuffer = function(buf) { 
    var source = context.createBufferSource(); 
    source.buffer = buf; 
    source.connect(gainNode); 
    source.start(); 
}; 

var socket = ... 
socket.binaryType = 'arraybuffer'; 
socket.addBinaryListener(function (data) { 
    context.decodeAudioData(data, playBuffer); 
}); 
socket.connect... 

Я также попробовал реализацию, в котором я отслеживать входящие буфера из WebSocket и воспроизводить их в порядке получения, через AudioBufferSourceNode, после того, как «закончились» событие, полученная от предыдущего AudioBufferSourceNode. Это имеет ту же проблему, что и выше.

ответ

1

Ваш поток действительно гарантированно получит полные аудиофайлы в каждом сетевом фрагменте? (decodeAudioData не работает с частичными фрагментами MP3.)

Похоже, что (из фрагмента кода выше) вы просто полагаетесь на сетевое время, чтобы запустить куски потока в нужное время? Это гарантированно не выстраивается правильно; вам нужно немного задержаться в потоке (обрабатывать несогласованную сеть) и тщательно планировать каждый фрагмент. (Бит выше, что делает меня съежиться является source.start() - без времени парам, которые будут держать Куски запланированных один за другим, а именно:.

var nextStartTime = 0; 

function addChunkToQueue(buffer) { 
    if (!nextStartTime) { 
     // we've not yet started the queue - just queue this up, 
     // leaving a "latency gap" so we're not desperately trying 
     // to keep up. Note if the network is slow, this is going 
     // to fail. Latency gap here is 1 second. 
     nextStartTime = audioContext.currentTime + 1; 
    } 
    var bsn = audioContext.createBufferSource(); 
    bsn.buffer = buffer; 
    bsn.connect(audioContext.destination); 
    bsn.start(nextStartTime); 

    // Ensure the next chunk will start at the right time 
    nextStartTime += buffer.duration; 
} 

Кроме того, в зависимости от того, насколько велика ваша чанки, Я бы подумал, не собирается ли сбор мусора в проблему. Вы должны проверить это в профилировщике.

Исправленный путь не будет работать хорошо, он зависит от обработки событий JS и только срабатывает ПОСЛЕ аудиосистема будет воспроизводиться, поэтому ВСЕГДА будет пробел.

И наконец - это не будет работать, если звуковой поток не работает h частота дискретизации аудиоустройства по умолчанию; всегда будут клики, потому что decodeAudioData будет пересчитывать скорость устройства, которая не будет иметь идеальной продолжительности. Он будет работы, но, скорее всего, будут артефакты, такие как клики на границах кусков. Вам нужна функция, которая еще не реализована или реализована - выбираемые частоты выборки AudioContext - чтобы исправить это.

+0

Спасибо. У меня было время начала обработки, пока вы показываете; Я вытащил как одну из вещей, которые я пробовал, чтобы заставить ее работать, и забыл вернуть ее. Итак, у меня все еще были исключения из-за правильного времени.Я переключился с ogg/vorbis на wav/lpcm data, ad все в порядке. Возможно, это была проблема с кодером vorbis, который написал мой коллега; но у меня не было выпадений при использовании aurora.js и vorbis.js (но vorbis.js ушел с ошибкой памяти через 13 минут 25 секунд). Несжатые данные подходят для нашего приложения. – MidnightJava

+0

Что касается частоты дискретизации, наш источник является выборкой на 32000, а AudioContext сообщает о частоте дискретизации 41100. Я не слышу никаких артефактов на границах буфера, но это не аудио высокой точности. Это доказательство концепции программного обеспечения радио с использованием RTL-устройства, и мы просто потоковое моно. – MidnightJava

+1

Ах. Большинство кодов с потерями заполняют данные, поэтому, возможно, вы получаете несогласованные длины. – cwilso