DecodeAudioData: примеры (JAVASCRIPT)
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: Декодирование с последующим анализом аудио
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: Пакетное декодирование нескольких файлов
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
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);
});