Gravando som JS de um microfone ou comentários de voz

Gravando som JS de um microfone ou comentários de voz


Há pouco tempo, ao desenvolver um aplicativo da Web corporativo, o cliente desejava poder deixar comentários de voz. Anteriormente, não encontrei a criação de conteúdo de mídia e comecei a estudar esse tópico com interesse.

A rede forneceu informações básicas suficientes sobre o tópico de criação e processamento desse tipo de conteúdo, mas não encontrei um exemplo simples e totalmente funcional. Após a implementação da tarefa pelo cliente, decidi publicar o exemplo mais simplificado de gravar e salvar comentários de voz e escrever um artigo. Talvez este material seja útil para alguém e ajude no estudo.

Declaração do problema


Nós nos propusemos a tarefa de desenvolver um miniaplicativo em execução em um navegador que permita gravar um comentário de voz, enviar uma gravação para o servidor, o servidor salvará a gravação, se for bem-sucedido, retornará uma resposta com o nome do arquivo criado e exibirá o objeto na página para que a gravação possa ser ouvida.

Gravar som no navegador


A gravação de som foi decidida para ser implementada usando a API da web MediaStream Recording. Para gravação, usamos a interface MediaRecorder (). Mas primeiro, crie uma interface. Vamos index.html contendo apenas as tags mais básicas e, no corpo da tag, incluiremos um arquivo com nosso futuro voice.js do JavaScript:

<!DOCTYPE html> <head> <meta charset="UTF-8"> <title>Voice comments</title> </head> <body> <script src="voice.js"></script> </body> </html> 

Crie um arquivo voice.js, defina nele uma constante de URL que conterá um link para um script que recebe o som gravado. Em seguida, crie os botões Iniciar e Parar para iniciar e parar a gravação de som, bem como o bloco div no qual os registros salvos serão exibidos. Nesta nossa interface está pronta, você pode prosseguir diretamente para a gravação do som.

Como já mencionado para a gravação, usaremos a interface MediaRecorder () (para obter mais informações sobre a interface, consulte a documentação), para sua operação, é necessário determinar o fluxo de mídia a partir do qual capturaremos o som, inicialize apenas que precisamos apenas de uma faixa de áudio.

 navigator.mediaDevices.getUserMedia({ audio: true}) .then(stream => { const mediaRecorder = new MediaRecorder(stream)}); 

Agora temos a constante mediaRecorder, que contém uma instância da interface, e continuaremos a trabalhar com ela.

Para iniciar a gravação, precisamos chamar o método MediaRecorder.start (), para interromper a gravação, o método MediaRecorder.stop (). Nesse caso, MediaRecorder.stop () gera um evento disponível por dados, através do qual obtemos acesso à gravação de som digitalizada na forma de uma matriz binária.

E assim descreveremos os eventos acima, declararemos a matriz de voz [] e escreveremos os dados recebidos nela:

 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(); }); }); 

Agora vamos preparar os dados recebidos para o envio. Para fazer isso, pelo evento stop, crie uma instância BLOB, coloque os dados recebidos e especifique o tipo de dados MIME. No nosso caso, será áudio / wav.

 mediaRecorder.addEventListener("stop", function() { const voiceBlob = new Blob(voice, { type: 'audio/wav' }); 

Como resultado, temos a constante voiceBlob, que é o conteúdo do nosso futuro arquivo wav com a gravação de uma mensagem de voz.

Enviando um registro para o servidor


Para enviar um registro para o servidor, decidi usar o método fetch (). Como esse método é o mais moderno e fornece uma interface aprimorada para fazer solicitações ao servidor. Como parte de nossa tarefa, precisamos iniciar uma solicitação POST no corpo da qual enviar o conteúdo do nosso arquivo futuro para salvar no servidor (como o método fetch () funciona e quais recursos podem ser encontrados na documentação em detalhes). Crie um novo formulário com o campo de voz e coloque o conteúdo do nosso registro nele.

 let fd = new FormData(); fd.append('voice', voiceBlob); 

Criamos uma função assíncrona para enviar uma mensagem ao servidor para receber uma resposta e exibir um objeto de áudio para reproduzir um arquivo já salvo. Como argumento, a função assumirá a forma criada acima.

Iniciamos uma solicitação do servidor:

 let promise = await fetch(URL, { method: 'POST', body: form}); 

Se a resposta HTTP do servidor não contiver um código de erro (o código de resposta está no intervalo de 200-299), resta decodificar a resposta, criar um novo objeto de áudio na página, determinar suas propriedades e exibi-lo. Como a resposta é formada será discutida abaixo.

Salvando um arquivo no servidor


Vamos criar um script no servidor que receberá nossa solicitação POST com uma mensagem de voz. Como a gravação de som que enviamos já é essencialmente um arquivo no formulário, nós a receberemos no servidor de acordo:

 $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); 

Você pode encontrar muitos exemplos semelhantes de código PHP, processando arquivos recebidos na rede. Primeiro, inicialize as variáveis, $ uploadDir - o diretório em que o arquivo recebido será salvo, o tipo e o tipo de arquivo File, no nosso caso, serão iguais a wav e o nome completo do arquivo, incluindo o diretório. O nome do arquivo nesse caso é formado combinando o nome do arquivo "temporário" e o valor da cadeia de caracteres do horário atual criptografado usando o método md5. Se você salvar com êxito o arquivo com uma mensagem de voz no diretório especificado, formaremos uma resposta na forma de uma matriz contendo o campo de resultado igual a "OK" ou "ERRO", dependendo do resultado e o campo "dados" que, em caso de processamento bem-sucedido, contém um link para o arquivo salvo.

Por conveniência, transformamos o array em um objeto JSON e o enviamos como resposta.

O código de exemplo completo está disponível no GitHub .

PS O navegador permite gravar conteúdo de mídia apenas com uma conexão HTTPS segura.

Source: https://habr.com/ru/post/pt484196/


All Articles