Некоторое время назад был разработан проект по разработке аудиокурсов. По сути, после импорта документов, изображений и других ресурсов страница становится макетом, похожим на PPT, а затем, выбрав изображение, можно вставить аудио. Существует два типа редактирования одной страницы. и глобальная модель редактирования. Есть два способа импортировать аудио: один — импорт из библиотеки ресурсов, а другой — упоминание записи.
Честно говоря, я никогда не сталкивался с Audio API HTML5 вначале, и нам пришлось оптимизировать его на основе кода, прежде чем взять на себя управление. Конечно, здесь также есть много ловушек. На этот раз я также расскажу о своих чувствах по поводу этих ловушек (инициализация и получение некоторых основных объектов будут опущены, поскольку это содержание не является предметом внимания на данный момент. Заинтересованные студенты могут поискать в MDN. документацию по себе):
Прежде чем начать запись, необходимо сначала узнать, поддерживает ли текущее устройство Audio API. Предыдущий метод navigator.getUserMedia был заменен на navigator.mediaDevices.getUserMedia. Обычно большинство современных браузеров теперь поддерживают использование navigator.mediaDevices.getUserMedia. Конечно, MDN также предоставляет информацию о совместимости.
const promisifiedOldGUM = function(constraints) { // Сначала получаем getUserMedia, если он присутствует const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // Некоторые браузеры просто не реализуют это обещание; с ошибкой // чтобы сохранить согласованность интерфейса if (!getUserMedia) { return Promise.reject( new Error('getUserMedia не реализована в этом браузере') ); // В противном случае оберните вызов старого navigator.getUserMedia с помощью Promise return new Promise(function(resolve, ignore) { getUserMedia.call (навигатор, ограничения, разрешение, отказ });}; // Старые браузеры могут вообще не реализовывать mediaDevices, поэтому сначала мы устанавливаем пустой объектif (navigator.mediaDevices === undefine) { navigator.mediaDevices = {};} // Некоторые браузеры частично реализуют mediaDevices. Мы не можем просто назначить объект// с помощью getUserMedia, поскольку это перезапишет существующие свойства.// Здесь мы не можем просто назначить объект // с помощью getUserMedia. просто добавит свойство getUserMedia, если оно отсутствует.if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = promisifiedOldGUM;}
Поскольку этот метод является асинхронным, мы можем предоставить удобные подсказки для несовместимых устройств.
navigator.mediaDevices.getUserMedia(constraints).then( function(mediaStream) { // Успех }, function(error) { // Ошибка const { name } = error; let errorMessage; switch (name) { // Пользователь отклоняет регистр ' NotAllowedError': case 'PermissionDeniedError': errorMessage = 'Пользователь запретил веб-странице вызывать записывающее устройство' перерыв // Записывающее устройство не подключено case 'NotFoundError': case; 'DevicesNotFoundError': errorMessage = 'Записывающее устройство не найдено'; // Другие случаи ошибок 'NotSupportedError': errorMessage = 'Функция записи не поддерживается';break; default: errorMessage = 'Ошибка вызова записи'; журнал (ошибка); вернуть errorMessage;
Если все пойдет хорошо, мы сможем перейти к следующему шагу.
(Метод получения контекста здесь опущен, потому что на этот раз он не в центре внимания)
Начать запись, приостановить записьЗдесь есть особый момент, то есть нужно добавить промежуточную переменную, чтобы идентифицировать, ведется ли в данный момент запись. Потому что в браузере Firefox мы обнаружили проблему. Процесс записи был нормальным, но когда мы нажали на паузу, мы обнаружили, что ее невозможно приостановить. В тот момент мы использовали метод отключения. Этот метод невозможен. Этот метод требует отключения всех соединений. Позже я обнаружил, что необходимо добавить промежуточную переменную this.isRecording, чтобы определить, происходит ли запись в данный момент. При нажатии кнопки «Пуск» установите для нее значение true, а при паузе — значение «false».
Когда мы начнем запись, в аудиопроцессе произойдет событие прослушивания записи. Если возвращается true, поток будет записан. Если возвращено false, он не будет записан. Поэтому оцените this.isRecording и, если он ложный, вернитесь напрямую.
// Некоторая инициализация const audioContext = new AudioContext(); const sourceNode = audioContext.createMediaStreamSource(mediaStream); const scriptNode = audioContext.createScriptProcessor( BUFFER_SIZE, INPUT_CHANNELS_NUM, OUPUT_CHANNELS_NUM);sourceNode.connect(this.scriptNode);scriptNode.connect(this.audioContext.destination); // Контролируем процесс записи scriptNode.onaudioprocess = event => { if (!this.isRecording) return; Регулярная запись this.buffers.push(event.inputBuffer.getChannelData(0)); Получить данные текущего канала и записать их в массив};
Конечно, здесь будет подводный камень, то есть его уже нельзя будет использовать. В комплекте идет метод получения текущей длительности записи, потому что на самом деле это не настоящая пауза, а поток не пишется. Значит нам еще нужно получить продолжительность текущей записи, которую нужно получить по формуле.
const getDuration = () => { return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096 — длина потока, sampleRate — частота дискретизации}
Таким образом, вы можете получить правильную продолжительность записи.
закончить записьЧтобы завершить запись, я сначала приостанавливаю ее, затем выполняю прослушивание или другие операции, если это необходимо, а затем устанавливаю длину массива потока хранения в 0.
Получить частотуgetVoiceSize = анализатор => { const dataArray = new Uint8Array(analyser. FrequencyBinCount); анализатор.getByteFrequencyData(dataArray); const data = dataArray.slice(100, 1000); const sum = data.reduce((a, b) => а + б); возвращаемая сумма;};
Подробную информацию можно найти по адресу https://developer.mozilla.org/zh-CN/docs/Web/API/AnalyserNode/ FrequencyBinCount.
другой
Большинство проблем, с которыми я столкнулся в этот раз, были проблемами совместимости, поэтому я столкнулся с множеством подводных камней, особенно на мобильной стороне. В начале была проблема, когда продолжительность записи была написана неправильно, из-за чего она напрямую зависала. Этот опыт также восполнил некоторые пробелы в HTML5 API. Конечно, самое главное — напомнить всем, что такого рода нативная документация по API получается просто и грубо путем непосредственного просмотра MDN!
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.