亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識(shí)庫(kù) > 詳解HTML5 錄音的踩坑之旅

詳解HTML5 錄音的踩坑之旅

熱門標(biāo)簽:電銷機(jī)器人電話用什么卡 當(dāng)涂高德地圖標(biāo)注 南寧點(diǎn)撥外呼系統(tǒng)哪家公司做的好 云南大理400電話申請(qǐng)官方 四川點(diǎn)撥外呼系統(tǒng) 黃島區(qū)地圖標(biāo)注 鎮(zhèn)江智能外呼系統(tǒng)有效果嗎 成都智能外呼系統(tǒng)平臺(tái) 江蘇智能電銷機(jī)器人哪家好

開篇閑扯

前一段時(shí)間的一個(gè)案子是開發(fā)一個(gè)有聲課件,大致就是通過導(dǎo)入文檔、圖片等資源后,頁面變?yōu)轭愃?PPT 的布局,然后選中一張圖片,可以插入音頻,有單頁編輯和全局編輯兩種模式。其中音頻的導(dǎo)入方式有兩種,一種是從資源庫(kù)中導(dǎo)入,還有一種就是要提到的錄音。

說實(shí)話,一開始都沒接觸過 HTML5 的 Audio API,而且要基于在我們接手前的代碼中進(jìn)行優(yōu)化。當(dāng)然其中也踩了不少坑,這次也會(huì)圍繞這幾個(gè)坑來說說感受(會(huì)省略一些基本對(duì)象的初始化和獲取,因?yàn)檫@些內(nèi)容不是這次的重點(diǎn),有興趣的同學(xué)可以自行查找 MDN 上的文檔):

  1. 調(diào)用 Audio API 的兼容性寫法
  2. 獲取錄音聲音的大小(應(yīng)該是頻率)
  3. 暫停錄音的兼容性寫法
  4. 獲取當(dāng)前錄音時(shí)間

錄音前的準(zhǔn)備

開始錄音前,要先獲取當(dāng)前設(shè)備是否支持 Audio API。早期的方法 navigator.getUserMedia 已經(jīng)被 navigator.mediaDevices.getUserMedia 所代替。正常來說現(xiàn)在大部分的現(xiàn)代瀏覽器都已經(jīng)支持 navigator.mediaDevices.getUserMedia 的用法了,當(dāng)然 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;
}

因?yàn)檫@個(gè)方法是異步的,所以我們可以對(duì)無法兼容的設(shè)備進(jìn)行友好的提示

navigator.mediaDevices.getUserMedia(constraints).then(
 function(mediaStream) {
 // 成功
 },
 function(error) {
 // 失敗
 const { name } = error;
 let errorMessage;
 switch (name) {
 // 用戶拒絕
 case 'NotAllowedError':
 case 'PermissionDeniedError':
 errorMessage = '用戶已禁止網(wǎng)頁調(diào)用錄音設(shè)備';
 break;
 // 沒接入錄音設(shè)備
 case 'NotFoundError':
 case 'DevicesNotFoundError':
 errorMessage = '錄音設(shè)備未找到';
 break;
 // 其它錯(cuò)誤
 case 'NotSupportedError':
 errorMessage = '不支持錄音功能';
 break;
 default:
 errorMessage = '錄音調(diào)用錯(cuò)誤';
 window.console.log(error);
 }
 return errorMessage;
 }
);

一切順利的話,我們就可以進(jìn)入下一步了。

(這里有對(duì)獲取上下文的方法進(jìn)行了省略,因?yàn)檫@不是這次的重點(diǎn))

開始錄音、暫停錄音

這里有個(gè)比較特別的點(diǎn),就是需要添加一個(gè)中間變量來標(biāo)識(shí)是否當(dāng)前是否在錄音。因?yàn)樵诨鸷鼮g覽器上,我們發(fā)現(xiàn)一個(gè)問題,錄音的流程都是正常的,但是點(diǎn)擊暫停時(shí)卻發(fā)現(xiàn)怎么也暫停不了,我們當(dāng)時(shí)是使用 disconnect 方法。這種方式是不行的,這種方法是需要斷開所有的連接才可以。后來發(fā)現(xiàn),應(yīng)該增加一個(gè)中間變量 this.isRecording 來判斷當(dāng)前是否正在錄音,當(dāng)點(diǎn)擊開始時(shí),將其設(shè)置為 true ,暫停時(shí)將其設(shè)置為 false 。

當(dāng)我們開始錄音時(shí),會(huì)有一個(gè)錄音監(jiān)聽的事件 onaudioprocess ,如果返回 true 則會(huì)將流寫入,如果返回 false 則不會(huì)將其寫入。因此判斷 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);
// 監(jiān)聽錄音的過程
scriptNode.onaudioprocess = event => {
 if (!this.isRecording) return; // 判斷是否正則錄音
 this.buffers.push(event.inputBuffer.getChannelData(0)); // 獲取當(dāng)前頻道的數(shù)據(jù),并寫入數(shù)組
};

當(dāng)然這里也會(huì)有個(gè)坑,就是無法再使用,自帶獲取當(dāng)前錄音時(shí)長(zhǎng)的方法了,因?yàn)閷?shí)際上并不是真正的暫停,而是沒有將流寫入罷了。于是我們還需要獲取一下當(dāng)前錄音的時(shí)長(zhǎng),需要通過一個(gè)公式進(jìn)行獲取

const getDuration = () => {
    return (4096 * this.buffers.length) / this.audioContext.sampleRate // 4096為一個(gè)流的長(zhǎng)度,sampleRate 為采樣率
}

這樣就能夠獲取正確的錄音時(shí)長(zhǎng)了。

結(jié)束錄音

結(jié)束錄音的方式,我采用的是先暫停,之后需要試聽或者其它的操作先執(zhí)行,然后再將存儲(chǔ)流的數(shù)組長(zhǎng)度置為 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;
};

具體可以參考 https://developer.mozilla.org/zh-CN/docs/Web/API/AnalyserNode/frequencyBinCount

其它

  1. HTTPS:在 chrome 下需要全站有 HTTPS 才允許使用
  2. 微信:在微信內(nèi)置的瀏覽器需要調(diào)用 JSSDK 才能使用
  3. 音頻格式轉(zhuǎn)換:音頻格式的方式也有很多了,能查到的大部分資料,大家基本上是互相 copy,當(dāng)然還有一個(gè)音頻質(zhì)量的問題,這里就不贅述了。

結(jié)語

這次遇到的大部分問題都是兼容性的問題,因此在上面踩了不少坑,尤其是移動(dòng)端的問題,一開始還有出現(xiàn)因?yàn)楂@取錄音時(shí)長(zhǎng)寫法錯(cuò)誤的問題,導(dǎo)致直接卡死的情況。這次的經(jīng)歷也彌補(bǔ)了 HTML5 API 上的一些空白,當(dāng)然最重要的還是要提醒一下大家,這種原生的 API 文檔還是直接查看 MDN 來的簡(jiǎn)單粗暴!

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

標(biāo)簽:十堰 咸寧 佳木斯 酒泉 南京 淮安 廣西 西寧

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解HTML5 錄音的踩坑之旅》,本文關(guān)鍵詞  詳解,HTML5,錄音,的,踩坑,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《詳解HTML5 錄音的踩坑之旅》相關(guān)的同類信息!
  • 本頁收集關(guān)于詳解HTML5 錄音的踩坑之旅的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    精品国产香蕉在线播出| 精品国产一区二区三区久久久蜜臀| 成人a大片高清在线观看| 日本伦理黄色大片在线观看网站| 日日夜夜婷婷| 青青久热| 亚洲精品影院一区二区| 亚久久伊人精品青青草原2020| 日本乱中文字幕系列| 日本免费看视频| 日韩免费在线观看视频| 国产激情视频在线观看| 日日日夜夜操| 国产91精品一区| 国产国语在线播放视频| 成人影视在线播放| 成人高清视频在线观看| 欧美a级成人淫片免费看| 精品视频在线看| 中文字幕一区二区三区 精品| 四虎影视久久久| 欧美大片a一级毛片视频| 成人免费网站久久久| 久草免费在线视频| 色综合久久久久综合体桃花网| 中文字幕Aⅴ资源网| 午夜精品国产自在现线拍| 久久99中文字幕久久| 国产精品123| 免费一级片网站| 九九精品影院| 欧美大片一区| 日本在线不卡免费视频一区| 国产一区二区福利久久| 成人a大片高清在线观看| 麻豆网站在线看| 色综合久久手机在线| 九九久久99| 国产不卡在线观看| 亚洲精品中文字幕久久久久久| 国产视频一区在线| 韩国三级视频网站| 欧美大片一区| 欧美a免费| 国产伦久视频免费观看 视频| 九九久久国产精品大片| 精品在线观看一区| 成人高清视频在线观看| 国产亚洲精品aaa大片| 国产高清在线精品一区二区| 国产一区二区精品久久91| 日本免费区| 九九精品久久久久久久久| 日本免费区| 九九精品在线播放| 国产麻豆精品高清在线播放| 日本特黄特黄aaaaa大片| 久久99中文字幕| 国产麻豆精品hdvideoss| 黄色短视屏| 在线观看导航| 国产网站麻豆精品视频| 国产伦久视频免费观看 视频| 成人a级高清视频在线观看| 国产一区二区精品| 黄色免费三级| 高清一级片| 国产成人女人在线视频观看| 成人免费网站视频ww| 黄视频网站免费观看| 九九精品在线| 黄视频网站在线观看| 欧美另类videosbestsex | 99久久精品国产高清一区二区| 成人免费网站视频ww| 亚洲精品久久久中文字| 国产极品精频在线观看| 91麻豆精品国产高清在线| 国产高清在线精品一区二区| 高清一级淫片a级中文字幕| 国产成+人+综合+亚洲不卡| 一级毛片看真人在线视频| 四虎影视库| 久久99中文字幕| 精品国产香蕉伊思人在线又爽又黄| 国产视频一区在线| 欧美a级片免费看| 天天做日日爱| 日本特黄一级| 欧美国产日韩在线| 999精品在线| 久久精品道一区二区三区| 免费国产一级特黄aa大片在线| 欧美国产日韩久久久| 日韩男人天堂| 91麻豆精品国产自产在线观看一区| 久久精品道一区二区三区| 精品国产三级a∨在线观看| 久久久久久久男人的天堂| 亚欧成人乱码一区二区| 国产精品免费久久| 一级女人毛片人一女人| 久久久久久久男人的天堂| 国产一级强片在线观看| 久久久成人影院| 四虎久久影院| 免费一级片在线观看| 日本特黄特色aaa大片免费| 成人高清护士在线播放| 亚洲第一页色| 欧美激情一区二区三区在线 | 亚洲天堂在线播放| 亚洲 国产精品 日韩| 日韩男人天堂| 亚洲 激情| 成人免费观看视频| 可以在线看黄的网站| 午夜在线影院| 超级乱淫黄漫画免费| 欧美另类videosbestsex久久| 日韩av东京社区男人的天堂| 日日爽天天| 久久国产精品永久免费网站| 亚洲第一页色| 国产一区二区精品久久| 久久精品欧美一区二区| 久久久成人网| 精品久久久久久免费影院| 成人免费福利片在线观看| 国产91丝袜在线播放0| 免费国产一级特黄aa大片在线| 久久久久久久免费视频| 久久精品免视看国产成人2021| 欧美一区二区三区在线观看| 久久精品免视看国产成人2021| 欧美激情一区二区三区在线| 久久国产影院| 91麻豆爱豆果冻天美星空| 亚洲精品久久久中文字| 国产精品免费久久| 四虎影视久久| 日日夜夜婷婷| 国产不卡高清在线观看视频| 99热精品一区| 国产不卡在线观看| 黄视频网站免费看| 精品久久久久久免费影院| 亚洲爆爽| 日本在线www| 可以免费在线看黄的网站| 在线观看成人网| 国产成人精品综合| 韩国三级视频在线观看| 色综合久久天天综合绕观看| 99热精品在线| 在线观看成人网 | 高清一级片| 国产91精品露脸国语对白| 午夜激情视频在线观看| 国产极品精频在线观看| 青青青草视频在线观看| 国产不卡在线看| 在线观看成人网 | 午夜激情视频在线观看 | 欧美日本二区| 欧美电影免费| 国产精品自拍在线观看| 九九精品在线| 日韩男人天堂| 韩国毛片免费大片| 欧美爱色| 二级片在线观看| 精品国产亚一区二区三区| 色综合久久天天综合| a级黄色毛片免费播放视频| 精品久久久久久中文字幕2017| 精品久久久久久中文| 亚洲女人国产香蕉久久精品| 亚洲第一页色| 韩国三级一区| 美女免费精品视频在线观看| 国产高清视频免费| 人人干人人草| 99久久网站| 日本在线不卡视频| 青青青草影院| 国产成人啪精品| 成人免费观看视频| 欧美国产日韩精品| 日韩中文字幕在线播放| 日韩免费在线观看视频| 91麻豆国产级在线| 国产一级强片在线观看| 欧美大片a一级毛片视频| 香蕉视频久久| 久久99欧美| 国产一区二区精品久久| 人人干人人草| 99色播| 深夜做爰性大片中文|