xml地图|网站地图|网站标签 [设为首页] [加入收藏]

您的位置:亚洲必赢 > 计算机尝试 > 录音的踩坑之旅,踩坑之旅

录音的踩坑之旅,踩坑之旅

发布时间:2019-04-21 14:08编辑:计算机尝试浏览(145)

    HTML5 录音的踩坑之旅

    2017/12/25 · HTML5 · 录音

    原稿出处: 翁旺   

    详解HTML伍 录音的踩坑之旅,详解html伍坑之旅

    开始比赛闲扯

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

    说实话,1开头都没接触过 HTML5 的 奥迪(Audi)o API,而且要基于在大家接手前的代码中举行优化。当然当中也踩了多数坑,本次也会围绕这多少个坑来讲说感触(会轻巧一些主旨目标的开始化和获取,因为那些内容不是此次的机要,有意思味的同室能够自行检索 MDN 上的文书档案):

    1. 调用 奥迪o API 的包容性写法
    2. 获得录音声音的轻重缓急(应该是成效)
    3. 停顿录音的包容性写法
    4. 录音的踩坑之旅,踩坑之旅。获得当前录音时间

    录音前的盘算

    初步录音前,要先获得当前配备是还是不是匡助 奥迪(Audi)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;
     }
    );
    

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

    (那里有对得到上下文的章程开展了简约,因为那不是此次的机要)

    始发录音、暂停录音

    这里有个相比尤其的点,便是索要加上一当中档变量来标志是或不是当前是否在录音。因为在火狐浏览器上,大家开掘3个主题素材,录音的流程都以符合规律的,但是点击暂停时却开采怎么也暂停不了,我们立马是接纳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)); // 获取当前频道的数据,并写入数组
    };
    

    自然那里也会有个坑,便是无力回天再利用,自带获取当前录音时长的点子了,因为实际并不是实在的中止,而是未有将流写入罢了。于是我们还索要得到一下脚下录音的时间长度,须要通过3个公式进行获取

    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,当然还有贰个旋律品质的标题,那里就不赘述了。

    结语

    本次蒙受的大部难题都以包容性的主题材料,因而在上边踩了累累坑,特别是运动端的难点,一起首还有出现因为获取录音时间长度写法错误的主题素材,导致直接卡死的状态。本次的经验也弥补了 HTML伍 API 上的局地空手,当然最重视的依旧要唤醒一下豪门,那种原生的 API 文档依然平素查看 MDN 来的简短冷酷!

    以上就是本文的全体内容,希望对我们的就学抱有帮助,也愿意大家多多帮忙帮客之家。

    录音的踩坑之旅,详解html5坑之旅 开篇闲扯 前壹段时间的2个案件是支付三个有声课件,大概就是经过导入文书档案、图片等财富后,...

    > db.user.update({"parentuser":"wyt1314"},{$set:{"parentuser":"1234"}},false,true)

    近年写东西用到了MediaRecorder.一切就绪,运行出现那个荒唐~程序一贯崩溃

    开篇闲扯

    前1段时间的三个案件是开荒2个有声课件,大概正是经过导入文书档案、图片等能源后,页面变为类似 PPT 的布局,然后选中一张图纸,能够插入音频,有单页编辑和全局编辑二种格局。个中音频的导入格局有二种,1种是从资源库中程导弹入,还有一种正是要涉及的录音。
    说实话,1初步都没接触过 HTML5 的 奥迪o API,而且要基于在我们接手前的代码中实行优化。当然当中也踩了许多坑,本次也会围绕那多少个坑来说说感触(会简单一些骨干目标的起头化和得到,因为那些剧情不是此次的首要,有意思味的同班能够自行检索 MDN 上的文书档案):

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

     

    db.user.update({"level":0},{$set:{"level":NumberInt(一)}},false,true)//更新某些字段

    图片 1Paste_Image.png

    录音前的准备

    发端录音前,要先取妥贴前设备是还是不是帮忙 奥迪(Audi)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;
    }
    );

    壹切顺遂的话,我们就能够进去下一步了。
    (那里有对得到上下文的点子开始展览了简约,因为那不是此番的主要性)

    db.user.update({},{$set:{gwb:NumberInt(0)}},{multi:一})//加多有个别地方

    谬误指向自家的那1行:

    起来录音、暂停录音

    此地有个相比尤其的点,就是急需加上一其中间变量来标识是或不是当前是或不是在录音。因为在火狐浏览器上,大家开采二个主题素材,录音的流程都以健康的,然而点击暂停时却发掘怎么也暂停不了,我们当便是选拔 disconnect 方法。那种艺术是不行的,那种方式是内需断开全部的连年才足以。后来开采,应该扩大二个个中变量 this.isRecording 来决断当前是否正在录音,当点击开头时,将其设置为true,暂停时将其安装为false
    当大家起始录音时,会有3个录音监听的事件 onaudioprocess ,如若回到 true 则会将流写入,假诺回到 false 则不会将其写入。由此确定this.isRecording,如果为 false 则直接 return

    JavaScript

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

    本来那里也会有个坑,就是无能为力再采用,自带获取当前录音时间长度的办法了,因为实在并不是确实的暂停,而是未有将流写入罢了。于是大家还须要获得一下脚下录音的时间长度,必要通过2个公式进行获取

    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 为采样率
    }

    那般就可知拿走科学的录音时间长度了。

    db.user.update({},{$unset:{'refree_number':''}},false, true)//删除有个别字段

    图片 2Paste_Image.png

    终结录音

    停止录音的方式,笔者利用的是先暂停,之后需求试听或然别的的操作先推行,然后再将存款和储蓄流的数CEO度置为 0。

    cnpm install forever -g

    别的的也不报错,也不说错误原因是吗,结果笔者重头看半天代码,权限检查了有个别遍都没察觉哪儿错了。末了依旧海底捞针找到了:

    获得频率

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

    现实能够参见

    db.getCollection('user').find({teamId:{$exists:false}})//查询数据库没有有个别字段

    本来给mediaRecorder设置积存路线,定期间各异设置差别文件名,是这么的:

    其它

    • HTTPS:在 chrome 下要求全站有 HTTPS 才允许行使
    • 微信:在微信内置的浏览器供给调用 JSSDK 本事利用
    • 音频格式调换:音频格式的方式也有过多了,能查到的大多数素材,大家差不离是彼此copy,当然还有三个节奏品质的标题,那里就不赘述了。

    db.user.update({integral:{$exists:false}},{$set:{integral:NumberInt(0)}},{multi:一})//更新数据库的尚未某些字段的增加上去

    // 5设置保存路径mediaRecorder.setOutputFile ( Environment.getExternalStorageDirectory ().getAbsolutePath () SystemClock.currentThreadTimeMillis()  ".amr");
    

    结语

    这一次蒙受的大大多主题素材都是包容性的主题材料,由此在上头踩了诸多坑,特别是运动端的难题,一齐首还有出现因为获取录音时间长度写法错误的主题素材,导致一向卡死的境况。此次的经验也弥补了 HTML伍 API 上的有的空手,当然最要害的照旧要提示一下豪门,那种原生的 API 文档依然直接查看 MDN 来的简便阴毒!

    1 赞 3 收藏 评论

    图片 3

    db.getCollection('sheng_xiao').aggregate([

    笔者和代码肆目相对了半天开采,。。。尼玛路线写错了,少了个斜杠,应该是:

                        {$group : {"_id" : {uid:"$uid",palaceid:"$palaceid"}, num_tutorial : {$sum : 1}}},

    // 5设置保存路径mediaRecorder.setOutputFile ( Environment.getExternalStorageDirectory ().getAbsolutePath () "/" SystemClock.currentThreadTimeMillis ()   ".amr");
    

                        { $sort: { num_tutorial: -1 } }])//查询某多少个字段同样的值

    愿后人小白们能以笔者为戒,不要再那种指鹿为马上浪费了多量日子~~~~

    db.runCommand({"convertToCapped":"access_record","size":四千00})//定长字段

    db.auth("futureCity","futureCity$20一柒.")//登入数据库

    db.getCollection('user').aggregate([

                        {$group : {"_id" : {user_name:"$user_name",mobile:"$mobile"}, num_tutorial : {$sum : 1}}},

    本文由亚洲必赢发布于计算机尝试,转载请注明出处:录音的踩坑之旅,踩坑之旅

    关键词: HTML5 JS总结 MediaRecorde

上一篇:Chrome开发者工具不完全指南

下一篇:没有了