Как воспроизвести массив аудиобайтов (не файл!) с помощью JavaScript в браузере

#streaming #web #wav

#потоковая передача #веб #wav

Вопрос:

В основном по соображениям безопасности мне не разрешено хранить файл WAV на сервере, к которому будет доступен браузер. У меня есть массив байтов, содержащий аудиоданные (часть данных файла WAV, я полагаю) на сервере, и я хочу, чтобы они воспроизводились в браузере через JavaScript (или апплет, но предпочтительнее JS), я могу использовать JSON-PRC для отправки всего байта [], или я могу открыть сокет для его потоковой передачи, но в любом случае я не знаю, кому воспроизводить байт [] в браузере?

Ответ №1:

Следующий код будет воспроизводить синусоидальную волну при 0,5 и 2,0. Вызовите функцию play_buffersource() в вашей кнопке или в любом другом месте, где вы хотите.

Протестировано с использованием Chrome с включенным флагом веб-аудио. В вашем случае все, что вам нужно сделать, это просто перетасовать ваши аудиобайты в buf .

 <script type="text/javascript">
const kSampleRate = 44100; // Other sample rates might not work depending on the your browser's AudioContext
const kNumSamples = 16834;
const kFrequency  = 440;
const kPI_2       = Math.PI * 2;

function play_buffersource() {
    if (!window.AudioContext) {
        if (!window.webkitAudioContext) {
            alert("Your browser sucks because it does NOT support any AudioContext!");
            return;
        }
        window.AudioContext = window.webkitAudioContext;
    }

    var ctx = new AudioContext();

    var buffer = ctx.createBuffer(1, kNumSamples, kSampleRate);
    var buf    = buffer.getChannelData(0);
    for (i = 0; i < kNumSamples;   i) {
        buf[i] = Math.sin(kFrequency * kPI_2 * i / kSampleRate);
    }

    var node = ctx.createBufferSource(0);
    node.buffer = buffer;
    node.connect(ctx.destination);
    node.noteOn(ctx.currentTime   0.5);

    node = ctx.createBufferSource(0);
    node.buffer = buffer;
    node.connect(ctx.destination);
    node.noteOn(ctx.currentTime   2.0);
}
</script>
  

Ссылки:

Если вам нужно выполнить повторную выборку звука, вы можете использовать средство повторной выборки JavaScript:https://github.com/grantgalitz/XAudioJS

Если вам нужно декодировать данные base64, существует множество декодеров JavaScript base64:https://github.com/carlo/jquery-base64

Комментарии:

1. это не работает в Firefox! есть ли способ заставить это работать?

2. Функция NoteOn() была заменена на start() с момента написания этого ответа. Смотрите developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API /…

Ответ №2:

Я выполнил это с помощью следующего кода. Я передаю массив байтов, содержащий данные из wav-файла, в функцию playByteArray. Мое решение похоже на решение Питера Ли, но я не смог заставить его работать в моем случае (вывод был искажен), тогда как это решение хорошо работает для меня. Я проверил, что это работает в Firefox и Chrome.

 window.onload = init;
var context;    // Audio context
var buf;        // Audio buffer

function init() {
    if (!window.AudioContext) {
    if (!window.webkitAudioContext) {
        alert("Your browser does not support any AudioContext and cannot play back this audio.");
        return;
    }
        window.AudioContext = window.webkitAudioContext;
    }

    context = new AudioContext();
}

function playByteArray(byteArray) {

    var arrayBuffer = new ArrayBuffer(byteArray.length);
    var bufferView = new Uint8Array(arrayBuffer);
    for (i = 0; i < byteArray.length; i  ) {
      bufferView[i] = byteArray[i];
    }

    context.decodeAudioData(arrayBuffer, function(buffer) {
        buf = buffer;
        play();
    });
}

// Play the loaded file
function play() {
    // Create a source node from the buffer
    var source = context.createBufferSource();
    source.buffer = buf;
    // Connect to the final output node (the speakers)
    source.connect(context.destination);
    // Play immediately
    source.start(0);
}
  

Комментарии:

1. Что должен делать BufferView?

2. @patrickdamery это композиция над буфером, которая используется для изменения его содержимого (вот почему вы не видите его дальнейшего использования после завершения итерации)

Ответ №3:

Если у вас есть байты на сервере, я бы посоветовал вам создать на сервере какой-то обработчик, который будет передавать байты в ответ в виде файла wav. Этот «файл» будет находиться только в памяти на сервере, а не на диске. Тогда браузер может просто обрабатывать его как обычный wav-файл. Потребуется более подробная информация о стеке сервера, чтобы предоставить больше информации о том, как это можно сделать в вашей среде.

Ответ №4:

Я подозреваю, что вы можете достичь этого с помощью HTML5 Audio API достаточно легко:

https://developer.mozilla.org/en/Introducing_the_Audio_API_Extension

Эта библиотека тоже может пригодиться, хотя я не уверен, отражает ли она последние модели поведения браузера:

https://github.com/jussi-kalliokoski/audiolib.js

Комментарии:

1. Спасибо! Но, похоже, здесь используется плавающий сэмпл, мои исходные данные wav audio имеют моно 16 Кб Гц и базовую частоту 64 байта, нужно ли мне их конвертировать? Как?

2. В первой ссылке говорится, что эта функция теперь устарела, и замена developer.mozilla.org/en-US/docs /… не поддерживается Internet Explorer! Есть ли какое-либо решение, которое работает для всех браузеров?

3. @Pi Конечно, нет. Теперь это стандарт. Зачем IE внедрять стандарт? Не будь глупым!