Node.js Live Streaming: избегайте буферизации

Я написал небольшой сервер nodeJS, который выводит системное аудио, захваченное ffmpeg в Windows (используя DirectShow), в браузер в виде потокового файла MP3. Звук должен быть максимально живым, с минимальной буферизацией / без буферизации, и эффект "пропуска" в аудио вполне приемлем.

При воспроизведении звука в Chrome с использованием звукового тега HTML5 происходит задержка около 8-10 секунд при подключении к локальной сети с низкой задержкой. Я подозревал, что это буфер на стороне клиента, и использовал Flash MP3-плеер на стороне клиента, что снизило задержку до 2-3 секунд.

Теперь, похоже, буферизация происходит на стороне сервера. В документации для NodeJS response.write упоминается, что данные записываются в буферы ядра. Как мне вообще избежать какой-либо буферизации или, по крайней мере, обойти ее, чтобы клиент всегда получал самые последние аудиоданные? Стратегии для обработки "утечек" событий, чтобы всегда выдвигать живые данные?

В объекте запроса я использовал setNoDelay (true), чтобы избежать использования алгоритма Нейгла. Ниже приведен фрагмент того, как данные записываются, когда порожденный процесс ffmpeg генерирует данные.

var clients = []; //List of client connections currently being served
ffmpeg.stdout.on('data', function(data) {
    for(var i = 0; i < clients.length; i++){
        clients[i].res.write(data);
    }
});

1 ответ

Есть несколько мест, где происходит задержка / буферизация:

  1. Запись DirectShow (~100 мс или около того)
  2. Буфер кодирования FFMPEG MPEG (1-10 секунд, в зависимости от конфигурации)
  3. Сетевые записи и передача (около 0 в вашей настройке)
  4. Буферизация на стороне клиента (зависит от клиента, как вы видели - большинство клиентов буферизуют ~2 секунды для декодирования)

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

Сделав это, вы обнаружите, что ваша задержка составляет секунду или две. По крайней мере, это то, что я получаю с подобной настройкой.

Другие вопросы по тегам