Записывайте JS-аудио с микрофона или голосовые комментарии.
Не так давно при разработке корпоративного веб-приложения заказчик захотел иметь возможность оставлять голосовые комментарии.
Я никогда раньше не сталкивался с созданием медиаконтента и с интересом начал изучать эту тему.
В сети есть много справочной информации по теме создания и обработки такого рода контента, но простого, полностью работающего примера мне не удалось найти.
После того, как заказчик выполнил задачу, я решил опубликовать максимально упрощенный пример записи и сохранения голосового комментария и написать статью.
Возможно, кому-то этот материал окажется полезным и поможет в изучении.
Постановка задачи
Поставим перед собой задачу разработать мини-приложение, работающее в браузере, которое позволит записать голосовой комментарий, отправить запись на сервер, сервер сохранит запись, в случае успеха вернет ответ с именем созданного.файл и отобразить объект на странице, чтобы запись можно было прослушать.
Запись звука в браузере
Запись звука было решено реализовать с помощью веб-API MediaStream Recording. Для записи мы будем использовать интерфейс MediaRecorder().Но сначала давайте создадим интерфейс.
Пусть у нас будет index.html, содержащий только самые основные теги, а в тело тега мы включим файл с нашим будущим JavaScript voice.js:
Создадим файл voice.js, определим в нем URL-константу, которая будет содержать ссылку на скрипт, получающий записанный звук.<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>Voice comments</title> </head> <body> <script src="voice.js"></script> </body> </html>
Далее мы создадим кнопки «Старт» и «Стоп» для запуска и остановки записи звука, а также блок div, в котором будут отображаться сохраненные записи.
На этом наш интерфейс готов, можно переходить непосредственно к записи звука.
Как уже говорилось, для записи мы будем использовать интерфейс MediaRecorder() (подробнее об интерфейсе можно прочитать в документации).
Чтобы это работало, нам нужно определить медиапоток, из которого мы будем брать звук.
Мы его инициализируем только потому, что нам нужна только звуковая дорожка.
navigator.mediaDevices.getUserMedia({ audio: true})
.
then(stream => {
const mediaRecorder = new MediaRecorder(stream)});
Теперь у нас есть константа mediaRecorder, содержащая экземпляр интерфейса, и мы продолжим с ней работать.
Для начала записи нам нужно вызвать метод MediaRecorder.start(), для остановки записи — метод MediaRecorder.stop().
В этом случае MediaRecorder.stop() генерирует событие dataavailable, посредством которого мы получим доступ к оцифрованной звукозаписи в виде двоичного массива.
И так опишем вышеописанные события, объявим массив voice[] и запишем в него полученные данные: navigator.mediaDevices.getUserMedia({ audio: true})
.
then(stream => { const mediaRecorder = new MediaRecorder(stream); let voice = []; document.querySelector('#start').
addEventListener('click', function(){ mediaRecorder.start(); }); mediaRecorder.addEventListener("dataavailable",function(event) { voice.push(event.data); }); document.querySelector('#stop').
addEventListener('click', function(){
mediaRecorder.stop();
});
});
Теперь подготовим полученные данные к отправке.
Для этого по событию остановки мы создадим экземпляр BLOB, поместим в него полученные данные и укажем тип данных MIME. В нашем случае это будет audio/wav. mediaRecorder.addEventListener("stop", function() {
const voiceBlob = new Blob(voice, {
type: 'audio/wav'
});
В результате у нас есть константа voiceBlob, которая содержит содержимое нашего будущего wav-файла с записью голосового сообщения.
Отправка записи на сервер
Чтобы отправить запись на сервер, я решил использовать метод fetch().Так как этот метод является самым современным и обеспечивает улучшенный интерфейс выполнения запросов к серверу.
В рамках нашей задачи нам необходимо инициировать POST-запрос, в теле которого мы отправим содержимое нашего будущего файла для сохранения на сервере (как работает метод fetch() и какие возможности есть у метода fetch()).
Подробности можно найти в документации).
Давайте создадим новую форму с голосовым полем и поместим в нее содержимое нашей записи.
let fd = new FormData();
fd.append('voice', voiceBlob);
Создадим асинхронную функцию для отправки сообщения на сервер, получения ответа и отображения аудиообъекта для воспроизведения уже сохраненного файла.
Функция примет форму, созданную выше, в качестве аргумента.
Инициируем запрос к серверу: let promise = await fetch(URL, {
method: 'POST',
body: form});
Если HTTP-ответ от сервера не содержит кода ошибки (код ответа в диапазоне 200-299), то нам остается только декодировать ответ, создать на странице новый аудиообъект, определить его свойства и отобразить это.
О том, как формируется ответ, пойдет речь ниже.
Сохранение файла на сервере
Давайте создадим на сервере скрипт, который будет принимать наш POST-запрос голосовым сообщением.
Так как отправленная нами звукозапись по сути уже является файлом в виде, то на сервер мы получим ее соответственно: $uploadDir = 'voice/';
$typeFile = explode('/', $_FILES['voice']['type']);
$uploadFile = $uploadDir .
basename(md5($_FILES['voice']['tmp_name'].
time()).
'.
'.
$typeFile[1]); if (move_uploaded_file($_FILES['voice']['tmp_name'], $uploadFile)) { $response = ['result'=>'OK', 'data'=>'.
/'.
$uploadFile];
} else {
$response = ['result'=>'ERROR', 'data'=>''];
}
echo json_encode($response);
В Интернете можно найти множество подобных примеров PHP-кода для обработки полученных файлов.
Сначала инициализируем переменные $uploadDir — каталог, в котором будет сохранен полученный файл, тип файла &typeFile в нашем случае будет равен wav и полное имя файла, включая каталог.
Имя файла в этом случае формируется путем объединения «временного» имени файла и строкового значения текущего времени, зашифрованного методом md5. Если файл с голосовым сообщением успешно сохранен в указанной директории, формируем ответ в виде массива, содержащего поле результата, равное «ОК» или «ОШИБКА» в зависимости от результата и поля «данные», которое, в случае успешной обработки содержит ссылку на сохраненный файл.
Для удобства преобразуем массив в объект JSON и отправляем его в ответ. Полный код примера опубликован по адресу GitHub .
P.S. Браузер позволяет записывать медиаконтент только при наличии защищенного HTTPS-соединения.
Теги: #JavaScript #php #запись звука #голосовые сообщения
-
Неевклидова Геометрия
19 Oct, 24 -
Ампер, Андре Мари
19 Oct, 24 -
Ищем Пневмонию На Рентгене С Помощью Fast.ai
19 Oct, 24 -
Президент Предлагает...
19 Oct, 24 -
C#: Этюды, Часть 1
19 Oct, 24 -
Детали, Которые Имеют Значение
19 Oct, 24 -
Дайте Нам Немного Сплетен! Прямо Сейчас!
19 Oct, 24