美高梅网投网站-美高梅手机网投-美高梅官方网站
做最好的网站

您的位置:美高梅网投网址 > Web前端 > 美高梅网投网站开始录音前,一种是从资源库中

美高梅网投网站开始录音前,一种是从资源库中

发布时间:2019-09-23 05:53编辑:Web前端浏览(161)

    HTML5 录音的踩坑之旅

    2017/12/25 · HTML5 · 录音

    原稿出处: 翁旺   

    详解HTML5 录音的踩坑之旅,详解html5坑之旅

    开张营业闲扯

    前一段时间的二个案子是开荒三个有声课件,大约正是经过导入文书档案、图片等能源后,页面变为类似 PPT 的布局,然后选中一张图片,能够插入音频,有单页编辑和大局编辑二种格局。当中音频的导入形式有三种,一种是从财富库中程导弹入,还也许有一种正是要提到的录音。

    说实话,一早先都没接触过 HTML5 的 奥迪o API,何况要依附在大家接手前的代码中展开优化。当然个中也踩了无数坑,这一次也会围绕那多少个坑来讲说感触(会轻巧一些中坚指标的伊始化和获得,因为这几个内容不是这次的十分重要,风乐趣的同校能够自动物检疫索 MDN 上的文书档案):

    1. 调用 奥迪o API 的兼容性写法
    2. 赢得录音声音的轻重(应该是效用)
    3. 暂停录音的包容性写法
    4. 得到当前录音时间

    录音前的预备

    千帆竞发录音前,要先得到当前道具是还是不是协理 奥迪o API。开始时代的不二秘籍navigator.getUserMedia 已经被 navigator.mediaDevices.getUserMedia 所代替。常常来讲现在好些个的今世浏览器都已经帮衬navigator.mediaDevices.getUserMedia 的用法了,当然 MDN 上也交给了兼容性的写法

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

    因为那些措施是异步的,所以我们能够对无法合作的设施开展温馨的提醒

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

    一切顺遂的话,我们就能够进去下一步了。

    (这里有对获得上下文的办法举办了简易,因为那不是此番的至关重大)

    始发录音、暂停录音

    这里有个相比非常的点,就是索要加上叁个中间变量来标志是还是不是当前是不是在录音。因为在火狐浏览器上,大家发掘多个主题材料,录音的流程都以例行的,可是点击暂停时却开采怎么也中断不了,大家立即是运用 disconnect 方法。这种办法是至极的,这种措施是亟需断开全体的连年才足以。后来意识,应该增添一个在那之中变量 this.isRecording 来判别当前是或不是正在录音,当点击最初时,将其设置为 true ,暂停时将其安装为 false 。

    当大家初叶录音时,会有叁个录音监听的事件 onaudioprocess ,尽管回到 true 则会将流写入,假使回去 false 则不会将其写入。因而肯定 this.isRecording ,尽管为 false 则一向 return

    // 一些初始化
    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)); // 获取当前频道的数据,并写入数组
    };
    

    当然这里也许有个坑,正是敬敏不谢再选取,自带获取当前录音时长的章程了,因为其实并不是实在的制动踏板,而是未有将流写入罢了。于是大家还亟需获得一下当下录音的时间长度,必要经过八个公式进行获取

    const getDuration = () => {
        return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096为一个流的长度,sampleRate 为采样率
    }
    

    那样就能够获取科学的录音时间长度了。

    得了录音

    终止录音的措施,作者使用的是先暂停,之后必要试听恐怕其余的操作先执行,然后再将存款和储蓄流的数老板度置为 0。

    获取频率

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

    切切实实可以参谋

    其它

    1. HTTPS:在 chrome 下必要全站有 HTTPS 才允许行使
    2. 微信:在微信内置的浏览器须求调用 JSSDK 技能采纳
    3. 音频格式转变:音频格式的方法也可能有为数相当多了,能查到的好些个材质,大家基本上是相互copy,当然还恐怕有八个旋律质量的主题材料,这里就不赘述了。

    结语

    美高梅手机网投,本次碰着的绝大大多主题素材都以包容性的标题,由此在上头踩了多数坑,尤其是活动端的难题,一最初还会有出现因为获取录音时间长度写法错误的主题素材,导致直接卡死的情况。这一次的经验也弥补了 HTML5 API 上的局地白手,当然最珍视的仍然要唤醒一下大家,这种原生的 API 文书档案还是一向查看 MDN 来的粗略暴虐!

    以上正是本文的全部内容,希望对我们的读书抱有援助,也意在大家多多援助帮客之家。

    美高梅网投网站, 录音的踩坑之旅,详解html5坑之旅 开篇闲扯 前一段时间的三个案子是付出三个有声课件,差不离便是通过导入文书档案、图片等财富后,...

    开张营业闲扯

    前一段时间的多少个案件是付出一个有声课件,大约正是经过导入文书档案、图片等能源后,页面变为类似 PPT 的布局,然后选中一张图纸,能够插入音频,有单页编辑和大局编辑二种情势。个中音频的导入格局有二种,一种是从能源库中程导弹入,还会有一种正是要涉及的录音。
    说实话,一起先都没接触过 HTML5 的 奥迪o API,何况要依照在大家接手前的代码中开展优化。当然在那之中也踩了成都百货上千坑,此番也会围绕那多少个坑来讲说感触(会轻易一些宗旨指标的起先化和获取,因为这么些内容不是此番的严重性,风野趣的校友可以自行检索 MDN 上的文书档案):

    • 调用 奥迪(Audi)o API 的兼容性写法
    • 收获录音声音的高低(应该是效能)
    • 停顿录音的包容性写法
    • 获取当前录音时间

     

    录音前的希图

    开头录音前,要先取安妥前配备是不是扶助 奥迪o API。初期的章程 navigator.getUserMedia 已经被 navigator.mediaDevices.getUserMedia 所代替。平常的话今后抢先八分之四的今世浏览器都曾经支撑navigator.mediaDevices.getUserMedia 的用法了,当然MDN上也交给了包容性的写法

    JavaScript

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    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;
    }

    因为那些方法是异步的,所以大家得以对不恐怕配合的器具实行温馨的提醒

    JavaScript

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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;
    }
    );

    一切顺遂的话,大家就足以进去下一步了。
    (这里有对获得上下文的情势进行了简便,因为那不是此次的要紧)

    发端录音、暂停录音

    这里有个相比极度的点,正是索要丰裕二个中等变量来标记是不是当前是还是不是在录音。因为在火狐浏览器上,我们发掘三个难题,录音的流程都以例行的,然则点击暂停时却发掘怎么也浅尝辄止不了,我们立马是采用 disconnect美高梅官方网站, 方法。这种方法是丰硕的,这种办法是索要断开全体的连日本领够。后来发觉,应该增添贰个个中变量 this.isRecording 来判定当前是否正在录音,当点击开端时,将其设置为true,暂停时将其安装为false
    当我们开端录音时,会有四个录音监听的事件 onaudioprocess ,如若回到 true 则会将流写入,假若回到 false 则不会将其写入。由此确定this.isRecording,如果为 false 则直接 return

    JavaScript

    // 一些初步化 const audioContext = new 奥迪oContext(); const sourceNode = audioContext.createMediaStreamSource(mediaStream); const scriptNode = audioContext.createScriptProcessor( BUFFECR-V_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)); // 获取当前频道的数据,并写入数组 };

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 一些初始化
    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)); // 获取当前频道的数据,并写入数组
    };

    理之当然这里也有个坑,正是无计可施再利用,自带获取当前录音时间长度的不二诀要了,因为实际实际不是真的的间歇,而是未有将流写入罢了。于是大家还索要获得一下脚下录音的时间长度,供给通过二个公式进行获取

    JavaScript

    const getDuration = () => { return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096为二个流的长度,sampleRate 为采集样品率 }

    1
    2
    3
    const getDuration = () => {
        return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096为一个流的长度,sampleRate 为采样率
    }

    如此就可以得到科学的录音时间长度了。

    终结录音

    得了录音的点子,笔者动用的是先暂停,之后供给试听也许另外的操作先实施,然后再将存款和储蓄流的数CEO度置为 0。

    获得频率

    JavaScript

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

    1
    2
    3
    4
    5
    6
    7
    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;
    };

    具体能够参考

    其它

    • HTTPS:在 chrome 下供给全站有 HTTPS 才允许行使
    • 微信:在微信内置的浏览器供给调用 JSSDK 技术动用
    • 音频格式调换:音频格式的艺术也许有为数非常的多了,能查到的许多材质,大家大概是互相copy,当然还会有一个节奏品质的难点,这里就不赘述了。

    结语

    本次碰着的绝大好些个主题素材都以包容性的标题,因而在上头踩了很多坑,特别是活动端的难点,一伊始还应该有出现因为获取录音时间长度写法错误的主题材料,导致一向卡死的情况。此次的经验也弥补了 HTML5 API 上的一对单手,当然最关键的依旧要提示一下豪门,这种原生的 API 文书档案如故直接查看 MDN 来的轻松残忍!

    1 赞 3 收藏 评论

    美高梅网投网站 1

    本文由美高梅网投网址发布于Web前端,转载请注明出处:美高梅网投网站开始录音前,一种是从资源库中

    关键词: