DecodeAudioData: примеры (JAVASCRIPT)

Полное руководство по decodeAudioData с примерами на JavaScript
Раздел: Web Audio API, Декодирование
decodeAudioData(audioData (ArrayBuffer), successCallback (function), errorCallback (function)): Promise

Функция decodeAudioData

Метод decodeAudioData() является частью Web Audio API и применяется для асинхронного декодирования аудиоданных, содержащихся в массиве байтов (ArrayBuffer).

Функция используется, когда необходимо преобразовать загруженный или сгенерированный аудиофайл (например, в форматах MP3, WAV, OGG) в аудиобуфер (AudioBuffer), который затем может быть воспроизведен или обработан через AudioContext.

Синтаксис:

audioContext.decodeAudioData(arrayBuffer, successCallback, errorCallback);

Параметры:

  • arrayBuffer - ArrayBuffer, содержащий сжатые аудиоданные.
  • successCallback - функция, вызываемая при успешном декодировании. Принимает единственный аргумент - декодированный AudioBuffer.
  • errorCallback (необязательный) - функция, вызываемая при ошибке декодирования.

Возвращаемое значение: В современных браузерах метод возвращает Promise, который разрешается с AudioBuffer. Старый подход с колбэками также поддерживается для обратной совместимости.

Базовые примеры использования

Пример 1: Использование с Promise (современный подход)

async function loadAudio(url) {
    const response = await fetch(url);
    const arrayBuffer = await response.arrayBuffer();
    const audioContext = new AudioContext();
    
    try {
        const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
        console.log('Аудио декодировано:', audioBuffer);
        return audioBuffer;
    } catch (err) {
        console.error('Ошибка декодирования:', err);
    }
}
// Результат: AudioBuffer { duration: 30.5, sampleRate: 44100, ... }

Пример 2: Использование с колбэками (устаревший подход)

function loadAudioOldWay(url) {
    fetch(url)
        .then(response => response.arrayBuffer())
        .then(arrayBuffer => {
            const audioContext = new AudioContext();
            audioContext.decodeAudioData(
                arrayBuffer,
                function(decodedData) {
                    console.log('Успех:', decodedData);
                },
                function(error) {
                    console.error('Ошибка:', error);
                }
            );
        });
}

Похожие функции в JavaScript

AudioContext.createBuffer() - создает пустой AudioBuffer вручную. Полезен для генерации аудиосигналов программно, а не для декодирования из файлов.

Обработка через MediaElementAudioSourceNode - позволяет использовать аудио из HTMLMediaElement (тег <audio>) без явного декодирования. Подходит для простого воспроизведения, но не дает доступа к сырым аудиоданным для анализа или обработки.

Рекомендации: decodeAudioData применяют, когда нужен полный доступ к аудиоданным для сложной обработки, визуализации или редактирования. Для простого воспроизведения достаточно тега <audio>.

Альтернативы в других языках программирования

Python (библиотека pydub):

from pydub import AudioSegment

# Загрузка и декодирование аудио
audio = AudioSegment.from_mp3('file.mp3')
print(f'Длительность: {len(audio)}ms')
Длительность: 30000ms

PHP (библиотека audiowaveform) - часто используется для генерации волновых форм, требует установки дополнительных пакетов.

C/C++ (библиотека libsndfile) - низкоуровневая работа с аудиофайлами. Основное отличие - синхронное выполнение и прямой доступ к файловой системе.

Типичные ошибки

Ошибка 1: Передача некорректного ArrayBuffer

const audioContext = new AudioContext();
const invalidBuffer = new ArrayBuffer(0); // Пустой буфер
audioContext.decodeAudioData(invalidBuffer)
    .then(buffer => console.log(buffer))
    .catch(err => console.error(err));
DOMException: Unable to decode audio data

Ошибка 2: Использование после закрытия AudioContext

const audioContext = new AudioContext();
audioContext.close(); // Контекст закрыт

fetch('audio.mp3')
    .then(r => r.arrayBuffer())
    .then(buffer => {
        // Вызовет ошибку
        return audioContext.decodeAudioData(buffer);
    });
InvalidStateError: AudioContext is not running

Изменения в последних версиях

Основное изменение произошло в спецификации Web Audio API: метод decodeAudioData теперь возвращает Promise, а использование колбэков считается устаревшим, но поддерживается для совместимости.

В старых версиях браузеров (например, Safari 14 и ранее) необходимо использовать полифиллы или проверять поддержку Promise-based API.

Пример проверки:

const audioContext = new AudioContext();
const isPromiseBased = audioContext.decodeAudioData.length === 1;
console.log('Promise-based API:', isPromiseBased);

Расширенные примеры

Пример 1: Декодирование с последующим анализом аудио

Пример javascript
async function analyzeAudio(url) {
    const buffer = await loadAudio(url);
    const audioContext = new AudioContext();
    const decoded = await audioContext.decodeAudioData(buffer);
    
    // Анализ данных первого канала
    const channelData = decoded.getChannelData(0);
    let maxAmplitude = 0;
    for (let i = 0; i < channelData.length; i++) {
        maxAmplitude = Math.max(maxAmplitude, Math.abs(channelData[i]));
    }
    console.log('Максимальная амплитуда:', maxAmplitude);
    return decoded;
}

Пример 2: Пакетное декодирование нескольких файлов

Пример javascript
async function decodeMultipleFiles(urls) {
    const audioContext = new AudioContext();
    const promises = urls.map(async url => {
        const response = await fetch(url);
        const buffer = await response.arrayBuffer();
        return audioContext.decodeAudioData(buffer);
    });
    
    const results = await Promise.allSettled(promises);
    const successful = results.filter(r => r.status === 'fulfilled');
    console.log(`Успешно декодировано: ${successful.length} файлов`);
    return successful.map(r => r.value);
}

Пример 3: Декодирование из Blob

Пример javascript
async function decodeFromBlob(blob) {
    const arrayBuffer = await blob.arrayBuffer();
    const audioContext = new AudioContext();
    return audioContext.decodeAudioData(arrayBuffer);
}

// Использование с записи с микрофона
navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {
        const recorder = new MediaRecorder(stream);
        const chunks = [];
        recorder.ondataavailable = e => chunks.push(e.data);
        recorder.onstop = async () => {
            const blob = new Blob(chunks);
            const audioBuffer = await decodeFromBlob(blob);
            console.log('Декодированная запись:', audioBuffer);
        };
        recorder.start();
        setTimeout(() => recorder.stop(), 3000);
    });

JS decodeAudioData function comments

En
DecodeAudioData Decodes audio file data asynchronously