Um projeto há algum tempo era desenvolver um material didático de áudio. Basicamente, após a importação de documentos, imagens e outros recursos, a página se torna um layout tipo PPT e, ao selecionar uma imagem, pode-se inserir áudio. e modelo de edição global. Existem duas maneiras de importar áudio, uma é importar da biblioteca de recursos e a outra é mencionar a gravação.
Para ser honesto, nunca fui exposto à API de áudio do HTML5 no início e precisamos otimizá-la com base no código antes de assumirmos o controle. Claro, também há muitas armadilhas envolvidas. Desta vez também falarei sobre meus sentimentos em relação a essas armadilhas (a inicialização e aquisição de alguns objetos básicos serão omitidas porque esses conteúdos não são o foco desta vez. Os alunos interessados podem pesquisar no MDN. por si próprios.
Antes de iniciar a gravação, você deve primeiro verificar se o dispositivo atual suporta API de áudio. O método anterior navigator.getUserMedia foi substituído por navigator.mediaDevices.getUserMedia. Normalmente, a maioria dos navegadores modernos agora suporta o uso de navigator.mediaDevices.getUserMedia. É claro que o MDN também fornece informações de compatibilidade.
const promisifiedOldGUM = function(constraints) { // Primeiro obtenha getUserMedia, se presente const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; com um erro // para manter uma interface consistente if (!getUserMedia) { return Promise.reject( new Error('getUserMedia não está implementado neste navegador') } // Caso contrário, envolva a chamada para o antigo navigator.getUserMedia com uma Promise return new Promise(function(resolve, rejeitar) { getUserMedia.call (navigator, restrições, resolução, rejeitar });} // Navegadores mais antigos podem não implementar mediaDevices, então definimos um objeto vazio primeiro se (navigator.mediaDevices === indefinido) { navigator.mediaDevices = {};} // Alguns navegadores implementam parcialmente mediaDevices Não podemos simplesmente atribuir um objeto// com getUserMedia, pois isso substituiria as propriedades existentes.// Aqui, nós apenas adicionará a propriedade getUserMedia se estiver faltando.if (navigator.mediaDevices.getUserMedia === indefinido) { navigator.mediaDevices.getUserMedia = promisifiedOldGUM;}
Como esse método é assíncrono, podemos fornecer avisos amigáveis para dispositivos incompatíveis.
navigator.mediaDevices.getUserMedia(constraints).then( function(mediaStream) { // Success }, function(error) { // Falha const { name } = error; let errorMessage; switch (name) { // Usuário rejeita case ' NotAllowedError': case 'PermissionDeniedError': errorMessage = 'O usuário proibiu a página web de chamar o dispositivo de gravação'; // O dispositivo de gravação não está conectado case 'NotFoundError': case break; 'DevicesNotFoundError': errorMessage = 'Dispositivo de gravação não encontrado'; break; // Outros casos de erro 'NotSupportedError': errorMessage = 'A função de gravação não é suportada'; log (erro); } return mensagem de erro });
Se tudo correr bem, podemos passar para a próxima etapa.
(O método de obtenção do contexto é omitido aqui, pois não é o foco desta vez)
Comece a gravar, pause a gravaçãoHá um ponto especial aqui, ou seja, é necessário adicionar uma variável intermediária para identificar se a gravação está sendo realizada no momento. Porque no navegador Firefox encontramos um problema. O processo de gravação estava normal, mas quando clicamos para pausar, descobrimos que não era possível pausá-lo. Este método não é possível. Este método requer a desconexão de todas as conexões. Mais tarde, descobri que uma variável intermediária this.isRecording deveria ser adicionada para determinar se a gravação está ocorrendo no momento. Quando clicar em iniciar, defina-o como verdadeiro e, quando pausado, defina-o como falso.
Quando começarmos a gravar, haverá um evento de escuta de gravação no processo de áudio. Se verdadeiro for retornado, o fluxo será gravado. Se falso for retornado, ele não será gravado. Portanto, julgue this.isRecording e, se for falso, retorne diretamente
// Alguma inicialização const audioContext = new AudioContext(); const sourceNode = audioContext.createMediaStreamSource(mediaStream); OUPUT_CHANNELS_NUM);sourceNode.connect(this.scriptNode);scriptNode.connect(this.audioContext.destination); // Monitore o processo de gravação scriptNode.onaudioprocess = event => { if (!this.isRecording) return; Gravação regular this.buffers.push(event.inputBuffer.getChannelData(0)); Obtenha os dados do canal atual e escreva-os no array};
Claro, haverá uma armadilha aqui, ou seja, não pode mais ser usado. Ele vem com um método para obter a duração da gravação atual, porque na verdade não é uma pausa real, mas o fluxo não está gravado. Portanto também precisamos obter a duração da gravação atual, que precisa ser obtida através de uma fórmula.
const getDuration = () => { return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096 é o comprimento de um stream, sampleRate é a taxa de amostragem}
Desta forma, você pode obter a duração correta da gravação.
terminar a gravaçãoPara encerrar a gravação, eu a pauso primeiro, depois executo a escuta ou outras operações, se necessário, e então defino o comprimento da matriz do fluxo de armazenamento como 0.
Obtenha frequênciagetVoiceSize = analisador => { const dataArray = new Uint8Array(analyser.frequencyBinCount); a + b); soma de retorno;};
Para obter detalhes, consulte https://developer.mozilla.org/zh-CN/docs/Web/API/AnalyserNode/frequencyBinCount
outro
A maioria dos problemas que encontrei desta vez foram problemas de compatibilidade, então encontrei muitas armadilhas, especialmente no lado móvel. No início, houve um problema em que a duração da gravação foi gravada incorretamente, fazendo com que ela congelasse diretamente. Essa experiência também compensou algumas lacunas na API HTML5. Claro, o mais importante é lembrar a todos que esse tipo de documentação de API nativa é obtida de forma simples e grosseira pela visualização direta do MDN!
O texto acima é todo o conteúdo deste artigo. Espero que seja útil para o estudo de todos. Também espero que todos apoiem a Rede VeVb Wulin.