HTML5 ‹audio› плохой выбор для потоковой передачи в прямом эфире?

Как обсуждалось в предыдущем вопросе, я создал прототип (используя веб-API MVC, NAudio и NAudio.Lame), который транслирует в реальном времени звук низкого качества после преобразования его в mp3. Исходный поток - PCM: 8K, 16-бит, моно, и я использую аудио-тег html5.

В обоих Chrome и IE11 есть задержка 15–34 секунды (высокая задержка), прежде чем звук будет слышен из браузера, что, как мне сказали, неприемлемо для наших конечные пользователи. В идеале задержка не должна превышать 5 секунд. Задержка возникает даже при использовании атрибута preload = "none" в моем аудио теге.

Если присмотреться к проблеме более внимательно, похоже, что оба браузера не начнут воспроизводить звук, пока они не получат ~ 32 КБ аудиоданных. Имея это в виду, я могу повлиять на задержку, изменив настройку битрейта MP3 Lame. Однако, если я уменьшу задержку (отправив больше данных в браузер для той же длины звука), я введу пропадание звука позже.

Примеры:

  • Если я использую кодировку Lame V0, задержка составляет почти 34 секунды, что требует почти 0,5 МБ исходного звука.
  • Если я использую кодировку Lame ABR_32, я могу уменьшить задержку до 10-15 секунд, но я буду испытывать паузы и пропадания во время сеанса прослушивания.

Вопросы:

  1. Есть идеи, как минимизировать задержку запуска (задержку)?
  2. Стоит ли мне продолжить изучение различных пресетов Lame в надежде выбрать «правильный»?
  3. Может быть, MP3 - не лучший формат для прямой потоковой передачи?
  4. Помогло бы переключение на Ogg / Vorbis (или Ogg / OPUS)?
  5. Нужно ли нам отказаться от тега аудио HTML5 и использовать Flash или Java-апплет?

Спасибо.


person Tony    schedule 18.12.2013    source источник


Ответы (1)


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

Однако вы можете реализовать решение с помощью webaudio API (это довольно просто), где вы сами управляете потоковой передачей.

Если вы можете разделить кусок вашего MP3 по фиксированному размеру (так, чтобы размер каждого фрагмента MP3 был известен заранее или, по крайней мере, во время приема), вы можете иметь прямую трансляцию в 20 строках кода. Размер блока будет вашей задержкой.

Ключ в том, чтобы использовать AudioContext :: decodeAudioData.

// Fix up prefixing
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var offset = 0;
var byteOffset = 0;
var minDecodeSize = 16384; // This is your chunk size

var request = new XMLHttpRequest();
request.onprogress = function(evt)
{
   if (request.response)
   {
       var size = request.response.length - byteOffset;
       if (size < minDecodeSize) return;
       // In Chrome, XHR stream mode gives text, not ArrayBuffer.
       // If in Firefox, you can get an ArrayBuffer as is
       var buf;
       if (request.response instanceof ArrayBuffer)
           buf = request.response;
       else
       { 
           ab = new ArrayBuffer(size);
           buf = new Uint8Array(ab);
           for (var i = 0; i < size; i++) 
               buf[i] = request.response.charCodeAt(i + byteOffset) & 0xff;
       }
       byteOffset = request.response.length;
       context.decodeAudioData(ab, function(buffer) {
           playSound(buffer);
       }, onError);
   }
};
request.open('GET', url, true);
request.responseType = expectedType; // 'stream' in chrome, 'moz-chunked-arraybuffer' in firefox, 'ms-stream' in IE
request.overrideMimeType('text/plain; charset=x-user-defined');
request.send(null);

function playSound(buffer) {
    var source = context.createBufferSource(); // creates a sound source
    source.buffer = buffer;                    // tell the source which sound to play
    source.connect(context.destination);       // connect the source to the context's destination (the speakers)
    source.start(offset);                           // play the source now
                                           // note: on older systems, may have to use deprecated noteOn(time);
    offset += buffer.duration;
}
person xryl669    schedule 03.12.2014