Il y a quelque temps, un projet consistait à développer un didacticiel audio. Fondamentalement, après avoir importé des documents, des images et d'autres ressources, la page devient une mise en page de type PPT, puis la sélection d'une image peut insérer de l'audio. Il existe deux types d'édition sur une seule page. et modèle d'édition global. Il existe deux manières d'importer de l'audio : l'une consiste à importer à partir de la bibliothèque de ressources et l'autre à mentionner l'enregistrement.
Pour être honnête, je n'ai jamais été exposé à l'API Audio de HTML5 au début, et nous devons l'optimiser en fonction du code avant de prendre le relais. Bien sûr, il y a aussi de nombreux pièges impliqués. Cette fois, je parlerai également de mes sentiments autour de ces pièges (l'initialisation et l'acquisition de certains objets de base seront omises car ces contenus ne sont pas au centre de cette fois. Les étudiants intéressés peuvent effectuer une recherche dans MDN. par eux-mêmes.
Avant de commencer l'enregistrement, vous devez d'abord vérifier si l'appareil actuel prend en charge l'API audio. La méthode précédente navigator.getUserMedia a été remplacée par navigator.mediaDevices.getUserMedia. Normalement, la plupart des navigateurs modernes prennent désormais en charge l'utilisation de navigator.mediaDevices.getUserMedia. Bien entendu, MDN fournit également des informations de compatibilité.
const promisifiedOldGUM = function(constraints) { // Obtenez d'abord getUserMedia, s'il est présent const getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // Certains navigateurs ne l'implémentent tout simplement pas - renvoient une promesse rejetée; avec une erreur // pour garder une interface cohérente if (!getUserMedia) { return Promise.reject( new Error('getUserMedia n'est pas implémenté dans ce navigateur') ); } // Sinon, enveloppez l'appel à l'ancien navigator.getUserMedia avec une promesse return new Promise(function(resolve, rejet) { getUserMedia.call (navigateur, contraintes, résolution, rejet); });}; // Les navigateurs plus anciens peuvent ne pas implémenter mediaDevices du tout, nous définissons donc d'abord un objet vide si (navigator.mediaDevices === undefined) { navigator.mediaDevices = {};} // Certains navigateurs implémentent partiellement mediaDevices Nous ne pouvons pas simplement attribuer un objet// avec getUserMedia car cela écraserait les propriétés existantes.// Ici, nous. ajoutera simplement la propriété getUserMedia si elle est manquante.if (navigator.mediaDevices.getUserMedia === non défini) { navigator.mediaDevices.getUserMedia = promisifiedOldGUM;}
Cette méthode étant asynchrone, nous pouvons fournir des invites conviviales pour les appareils incompatibles.
navigator.mediaDevices.getUserMedia(constraints).then( function(mediaStream) { // Succès }, function(error) { // Échec const { name } = error; let errorMessage; switch (name) { // L'utilisateur rejette le cas ' NotAllowedError': case 'PermissionDeniedError': errorMessage = 'L'utilisateur a interdit à la page Web d'appeler l'appareil d'enregistrement'; break; 'DevicesNotFoundError': errorMessage = 'Périphérique d'enregistrement introuvable'; break; // Autres cas d'erreur 'NotSupportedError': errorMessage = 'La fonction d'enregistrement n'est pas prise en charge'; default: errorMessage = 'Erreur d'appel d'enregistrement'; log (erreur); } return message d'erreur });
Si tout se passe bien, nous pourrons passer à l'étape suivante.
(La méthode d'obtention du contexte est omise ici, car elle n'est pas au centre de l'attention cette fois)
Démarrer l'enregistrement, mettre en pause l'enregistrementIl y a ici un point particulier, c'est-à-dire qu'une variable intermédiaire doit être ajoutée pour identifier si un enregistrement est en cours d'exécution. Parce que sur le navigateur Firefox, nous avons trouvé un problème. Le processus d'enregistrement était normal, mais lorsque nous avons cliqué pour mettre en pause, nous avons constaté qu'il ne pouvait pas être mis en pause. Nous avons utilisé la méthode de déconnexion à ce moment-là. Cette méthode n'est pas possible. Cette méthode nécessite de déconnecter toutes les connexions. Plus tard, j'ai découvert qu'une variable intermédiaire this.isRecording devait être ajoutée pour déterminer si l'enregistrement était en cours. Lorsque vous cliquez sur Démarrer, définissez-la sur true et en cas de pause, définissez-la sur false.
Lorsque nous commencerons l'enregistrement, il y aura un événement d'écoute d'enregistrement sur le processus audio. Si true est renvoyé, le flux sera écrit. Si false est renvoyé, il ne sera pas écrit. Par conséquent, jugez this.isRecording, et s'il est faux, revenez directement
// Une certaine initialisation 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); // Surveiller le processus d'enregistrement scriptNode.onaudioprocess = event => { if (!this.isRecording) return; Enregistrement régulier this.buffers.push(event.inputBuffer.getChannelData(0)); Récupère les données du canal actuel et les écrit dans le tableau};
Bien sûr, il y aura un piège ici, c'est-à-dire qu'il ne peut plus être utilisé avec une méthode pour obtenir la durée d'enregistrement actuelle, car il ne s'agit pas réellement d'une véritable pause, mais le flux n'est pas écrit. Nous devons donc également connaître la durée de l’enregistrement en cours, qui doit être obtenue via une formule.
const getDuration = () => { return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096 est la longueur d'un flux, sampleRate est la fréquence d'échantillonnage}
De cette façon, vous pouvez obtenir la durée d'enregistrement correcte.
terminer l'enregistrementPour terminer l'enregistrement, je le mets d'abord en pause, puis j'effectue une écoute ou d'autres opérations si nécessaire, puis je règle la longueur du tableau du flux de stockage sur 0.
Obtenir la fréquencegetVoiceSize = analyseur => { const dataArray = new Uint8Array (analyser. FrequencyBinCount); analyseur.getByteFrequencyData (dataArray); const data = dataArray.slice (100, 1000); a + b); retourner la somme ;} ;
Pour plus de détails, veuillez vous référer à https://developer.mozilla.org/zh-CN/docs/Web/API/AnalyserNode/ FrequencyBinCount
autre
La plupart des problèmes que j'ai rencontrés cette fois étaient des problèmes de compatibilité, j'ai donc rencontré de nombreux pièges, notamment du côté mobile, il y avait un problème où la durée d'enregistrement était mal écrite, ce qui provoquait son blocage direct. Cette expérience a également comblé certaines lacunes de l'API HTML5. Bien entendu, le plus important est de rappeler à tous que ce type de documentation API native s'obtient simplement et grossièrement en visualisant directement MDN !
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.