Maison  >  Article  >  interface Web  >  Explication détaillée des pièges rencontrés dans l'enregistrement HTML5

Explication détaillée des pièges rencontrés dans l'enregistrement HTML5

小云云
小云云original
2018-05-17 14:25:338718parcourir

Cet article présente principalement les pièges consistant à expliquer en détail l'enregistrement HTML5. L'éditeur pense que c'est assez bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur et jetons un œil. J'espère que cela pourra aider tout le monde.

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. Documents sur) :

  1. Méthode d'écriture de compatibilité pour appeler l'API Audio

  2. Obtenir la taille du son enregistré (doit être la fréquence )

  3. Méthode d'écriture de compatibilité pour suspendre l'enregistrement

  4. Obtention de la durée d'enregistrement actuelle

Préparation avant l'enregistrement

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 instructions de compatibilité

const promisifiedOldGUM = function(constraints) {
 // First get ahold of getUserMedia, if present
 const getUserMedia =
 navigator.getUserMedia ||
 navigator.webkitGetUserMedia ||
 navigator.mozGetUserMedia;
 
 // Some browsers just don't implement it - return a rejected promise with an error
 // to keep a consistent interface
 if (!getUserMedia) {
 return Promise.reject(
 new Error('getUserMedia is not implemented in this browser')
 );
 }
 
 // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
 return new Promise(function(resolve, reject) {
 getUserMedia.call(navigator, constraints, resolve, reject);
 });
};
 
// Older browsers might not implement mediaDevices at all, so we set an empty object first
if (navigator.mediaDevices === undefined) {
 navigator.mediaDevices = {};
}
 
// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
if (navigator.mediaDevices.getUserMedia === undefined) {
 navigator.mediaDevices.getUserMedia = promisifiedOldGUM;
}

car cette méthode est asynchrone, nous pouvons donc fournir des invites conviviales pour les appareils incompatibles

navigator.mediaDevices.getUserMedia(constraints).then(
 function(mediaStream) {
 // 成功
 },
 function(error) {
 // 失败
 const { name } = error;
 let errorMessage;
 switch (name) {
 // 用户拒绝
 case 'NotAllowedError':
 case 'PermissionDeniedError':
 errorMessage = '用户已禁止网页调用录音设备';
 break;
 // 没接入录音设备
 case 'NotFoundError':
 case 'DevicesNotFoundError':
 errorMessage = '录音设备未找到';
 break;
 // 其它错误
 case 'NotSupportedError':
 errorMessage = '不支持录音功能';
 break;
 default:
 errorMessage = '录音调用错误';
 window.console.log(error);
 }
 return errorMessage;
 }
);
Si tout se passe bien, nous pouvons passer à l'étape suivante.

(La méthode d'obtention du contexte est omise ici car ce n'est pas le focus cette fois)

Démarrer l'enregistrement, mettre l'enregistrement en pause

Ici Un spécial Le fait est qu’une variable intermédiaire doit être ajoutée pour identifier si l’enregistrement est en cours. 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, il a été 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, elle est définie sur true et lorsqu'elle est en pause, elle est définie 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. S'il est faux, renvoyez directement

// 一些初始化
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)); // 获取当前频道的数据,并写入数组
};
Bien sûr, il y aura un piège ici, c'est-à-dire qu'il ne peut plus être utilisé. obtenir la durée d'enregistrement actuelle, car ce n'est pas réellement une pause, mais le flux n'est pas écrit. Nous devons donc également obtenir la durée d'enregistrement actuelle, qui doit être obtenue grâce à une formule

const getDuration = () => {
    return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096为一个流的长度,sampleRate 为采样率
}
afin que nous puissions obtenir la durée d'enregistrement correcte.

Terminer l'enregistrement

La façon de terminer l'enregistrement est de le mettre d'abord en pause, puis d'effectuer d'abord une écoute ou d'autres opérations, puis de stocker la longueur du tableau du flux Régler sur 0.

Obtenir la fréquence

getVoiceSize = analyser => {
 const dataArray = new Uint8Array(analyser.frequencyBinCount);
 analyser.getByteFrequencyData(dataArray);
 const data = dataArray.slice(100, 1000);
 const sum = data.reduce((a, b) => a + b);
 return sum;
};
Autres

  1. HTTPS : sous Chrome, l'ensemble du site doit avoir HTTPS avant est autorisé à être utilisé

  2. WeChat : le navigateur intégré dans WeChat doit appeler JSSDK pour utiliser

  3. Conversion de format audio : il existe de nombreuses façons de formater l'audio, vous pouvez vérifier. La plupart des informations que nous avons reçues ont été essentiellement copiées les unes des autres. Bien sûr, il y a aussi le problème de la qualité audio, que je n'entrerai pas dans les détails ici.

Conclusion

La plupart des problèmes rencontrés cette fois-ci étaient des problèmes de compatibilité, j'ai donc marché sur beaucoup d'embûches, notamment C'est un problème sur du côté mobile, au début, il y avait un problème avec la mauvaise manière d'obtenir la durée d'enregistrement, ce qui provoquait un gel 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 !

Recommandations associées :

10 articles recommandés sur l'enregistrement

Fonction d'enregistrement développée par WeChat

Explication détaillée de l'exemple de code d'enregistrement et de compression de pages Web HTML5

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn