电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

JS實現audio音頻剪裁剪切復制播放與上傳(步驟詳解)

瀏覽:120日期:2024-04-28 13:37:25

JS實現audio音頻剪裁剪切復制播放與上傳(步驟詳解)

背景是這樣的,用戶上傳音頻文件,可能只需要幾十秒就夠了,但是常規的音樂都要3~5分鐘,80%的流量都是不需要的,要是就這么傳上去,其實是流量的浪費,如果可以在前端就進行剪裁,也就是只取前面一段時間的音頻,豈不是可以給公司省很多流量費用,前端的業務價值就體現了。

關鍵如何實現呢?

下面,就以“截取用戶上傳音頻前3秒內容”的需求示意下如何借助Web Audio API實現音頻的部分復制與播放功能。

一、不嗶嗶,直接正題

實現步驟如下。

1. File對象轉ArrayBuffer

在Web網頁中,用戶選擇的文件是個file對象,我們可以將這個文件對象轉換成Blob、ArrayBuffer或者Base64。

在音頻處理這里,都是使用ArrayBuffer這個數據類型。

代碼如下所示,假設file類型的文件選擇框的id是 ’file’ 。

file.onchange = function (event) { var file = event.target.files[0]; // 開始識別 var reader = new FileReader(); reader.onload = function (event) { var arrBuffer = event.target.result; // arrBuffer就是包含音頻數據的ArrayBuffer對象 }); reader.readAsArrayBuffer(file);};

使用的是 readAsArrayBuffer() 方法,無論是MP3格式、OGG格式還是WAV格式,都可以轉換成ArrayBuffer類型。

2. ArrayBuffer轉AudioBuffer

這里的ArrayBuffer相對于把音頻文件數組化了,大家可以理解為把音頻文件分解成一段一段的,塞進了一個一個有地址的小屋子里,在計算機領域稱為“緩沖區”,就是單詞Buffer的意思。

所謂音頻的剪裁,其實就是希望可以復制音頻前面一段時間的內容。

但是問題來了,ArrayBuffer里面的數據并沒有分類,統一分解了,想要準確提取某一截音頻數據,提取不出來。

所以,才需要轉換成AudioBuffer,純粹的音頻數據,方便提取。

AudioBuffer是一個僅僅包含音頻數據的數據對象,是Web Audio API中的一個概念。

既然說到了Web Audio API,那我們就順便……順便……,想了想,還是不展開,因為太龐雜了,這Web Audio API至少比Web Animation API復雜了10倍,API之多,體量之大,世間罕見,想要完全吃透了,沒有三年五載,啃不下來。

如果大家不是想要立志成為音視頻處理專家,僅僅是臨時解決一點小毛小病的問題,則不必深入,否則腦坑疼,使用MDN文檔中的一些案例東拼西湊,基本的效果也能弄出來。

扯遠了,回到這里。

AudioBuffer大家可以理解為音樂數據,那為什么叫AudioBuffer,不叫AudioData呢?

因為Buffer是個專有名詞,直譯為緩沖區,大家可以理解為高速公路,AudioBuffer處理數據更快,而且還有很多延伸的API,就像是高速公路上的服務區,有吃有喝還有加油的地方。

AudioData一看名字就是鄉下土鱉,雖然接地氣,但是,處理好幾兆的數據的時候,就有些帶不動了,就好像騎小電驢,在公速公路和鄉道縣道沒多大區別,但是如果是開跑車,嘖嘖,鄉下路就帶不動了。

如何才能轉換成AudioBuffer呢?

使用AudioContext對象的 decodeAudioData() 方法,代碼如下:

var audioCtx = new AudioContext();audioCtx.decodeAudioData(arrBuffer, function(audioBuffer) { // audioBuffer就是AudioBuffer});

3. 復制AudioBuffer前3秒數據

AudioBuffer對象是一個音頻專用Buffer對象,包含很多音頻信息,包括:

durationnumberOfChannelssampleRate

等。

包括一些音頻聲道數據處理方法,例如:

getChannelData()copyFromChannel()copyToChannel()

文檔見這里: https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer

所以,實現的原理很簡單,創建一個空的AudioBuffer,復制現有的通道數據前3秒的數據,然后復制的內容寫入到這個空的AudioBuffer,于是我們就得到了一個剪裁后的音頻Buffer數據了。

代碼如下:

// 聲道數量和采樣率var channels = audioBuffer.numberOfChannels;var rate = audioBuffer.sampleRate;// 截取前3秒var startOffset = 0;var endOffset = rate * 3;// 3秒對應的幀數var frameCount = endOffset - startOffset;// 創建同樣采用率、同樣聲道數量,長度是前3秒的空的AudioBuffervar newAudioBuffer = new AudioContext().createBuffer(channels, endOffset - startOffset, rate);// 創建臨時的Array存放復制的buffer數據var anotherArray = new Float32Array(frameCount);// 聲道的數據的復制和寫入var offset = 0;for (var channel = 0; channel < channels; channel++) { audioBuffer.copyFromChannel(anotherArray, channel, startOffset); newAudioBuffer.copyToChannel(anotherArray, channel, offset);}// newAudioBuffer就是全新的復制的3秒長度的AudioBuffer對象

上面JavaScript代碼中的變量 newAudioBuffer 就是全新的復制的3秒長度的AudioBuffer對象。

4. 使用newAudioBuffer做點什么?

其實應該是有了AudioBuffer對象后我們可以做點什么。

能做很多事情。

1) 如果希望直接播放

我們可以直接把AudioBuffer的數據作為音頻數據進行播放

// 創建AudioBufferSourceNode對象var source = audioCtx.createBufferSource();// 設置AudioBufferSourceNode對象的buffer為復制的3秒AudioBuffer對象source.buffer = newAudioBuffer;// 這一句是必須的,表示結束,沒有這一句沒法播放,沒有聲音// 這里直接結束,實際上可以對結束做一些特效處理source.connect(audioCtx.destination);// 資源開始播放source.start();

2) 如果希望在<audio>元素中播放

這個還挺麻煩的。

從 <audio> 的src屬性獲取音頻資源,再進行處理是簡單的,網上的案例也很多。

但是,想要處理后的AudioBuffer再變成src讓 <audio> 元素播放,嘿嘿,就沒那么容易了。

我 (張鑫旭) 找了一圈,沒有看到Web Audio API中有專門的“逆轉錄”方法。

唯一可行的路數就是根據AudioBuffer數據,重新構建原始的音頻數據。研究了一番,轉成WAV格式相對容易,想要轉換成MP3格式比較麻煩,這里有個項目: https://github.com/higuma/mp3-lame-encoder-js 不過自己沒驗證過,不過看代碼量,還挺驚人的。

因此,我們的目標還是轉到WAV音頻文件生成上吧,下面這段方法是從網上找的AudioBuffer轉WAV文件的方法,以Blob數據格式返回。

// Convert AudioBuffer to a Blob using WAVE representationfunction bufferToWave(abuffer, len) { var numOfChan = abuffer.numberOfChannels, length = len * numOfChan * 2 + 44, buffer = new ArrayBuffer(length), view = new DataView(buffer), channels = [], i, sample, offset = 0, pos = 0; // write WAVE header // 'RIFF' setUint32(0x46464952); // file length - 8 setUint32(length - 8); // 'WAVE' setUint32(0x45564157); // 'fmt ' chunk setUint32(0x20746d66); // length = 16 setUint32(16); // PCM (uncompressed) setUint16(1); setUint16(numOfChan); setUint32(abuffer.sampleRate); // avg. bytes/sec setUint32(abuffer.sampleRate * 2 * numOfChan); // block-align setUint16(numOfChan * 2); // 16-bit (hardcoded in this demo) setUint16(16); // 'data' - chunk setUint32(0x61746164); // chunk length setUint32(length - pos - 4); // write interleaved data for(i = 0; i < abuffer.numberOfChannels; i++) channels.push(abuffer.getChannelData(i)); while(pos < length) { // interleave channels for(i = 0; i < numOfChan; i++) { // clamp sample = Math.max(-1, Math.min(1, channels[i][offset])); // scale to 16-bit signed int sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767)|0; // write 16-bit sample view.setInt16(pos, sample, true); pos += 2; } // next source sample offset++ } // create Blob return new Blob([buffer], {type: 'audio/wav'}); function setUint16(data) { view.setUint16(pos, data, true); pos += 2; } function setUint32(data) { view.setUint32(pos, data, true); pos += 4; }}

WAV格式的兼容性還是很6的,如下圖所示:

JS實現audio音頻剪裁剪切復制播放與上傳(步驟詳解)

凡事支持Web Audio API的瀏覽器都支持WAV格式,所以,技術上完全可行。

下面這段JS可以得到剪裁后的WAV音頻的Blob數據格式:

var blob = bufferToWave(newAudioBuffer, frameCount);

有了Blob數據,接下來事情就簡單了。

我們可以直接把Blob數據轉換成URL,可以使用 URL.createObjectURL() 生成一個Blob鏈接。

假設頁面上有如下HTML代碼:

<audio controls=''></audio>

則如下設置,就可以點擊上面的 <audio> 元素進行播放了。

audio.src = URL.createObjectURL(blob);

如果要轉換成Base64地址,可以這么處理:

var reader2 = new FileReader();reader2.onload = function(event){ audio.src = event.target.result;};reader2.readAsDataURL(blob);

3) 如果希望上傳剪裁的音頻

有了Blob數據,上傳還不是灑灑水的事情。

可以使用FormData進行傳輸,例如:

var formData = new FormData();formData.append(’audio’, blob);// 請求走起var xhr = new XMLHttpRequest();xhr.open(’POST’, this.cgiGetImg, true);// 請求成功xhr.onload = function () {};// 發送數據xhr.send(formData);

有demo可以進行效果體驗的,您可以狠狠地點擊這里: 用戶上傳的MP3音頻剪裁并播放demo

使用截圖示意如下:

JS實現audio音頻剪裁剪切復制播放與上傳(步驟詳解)

本文地址: https://www.zhangxinxu.com/wordpress/?p=9505

到此這篇關于JS實現audio音頻剪裁剪切復制播放與上傳的文章就介紹到這了,更多相關js audio音頻剪裁內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 铝箔袋,铝箔袋厂家,东莞铝箔袋,防静电铝箔袋,防静电屏蔽袋,防静电真空袋,真空袋-东莞铭晋让您的产品与众不同 | 除尘器布袋骨架,除尘器滤袋,除尘器骨架,电磁脉冲阀膜片,卸灰阀,螺旋输送机-泊头市天润环保机械设备有限公司 | 广州云仓代发-昊哥云仓专业电商仓储托管外包代发货服务 | 氧氮氢联合测定仪-联测仪-氧氮氢元素分析仪-江苏品彦光电 | 蜗轮丝杆升降机-螺旋升降机-丝杠升降机厂家-润驰传动 | 船老大板材_浙江船老大全屋定制_船老大官网 | 流程管理|流程管理软件|企业流程管理|微宏科技-AlphaFlow_流程管理系统软件服务商 | 塑料撕碎机_编织袋撕碎机_废纸撕碎机_生活垃圾撕碎机_废铁破碎机_河南鑫世昌机械制造有限公司 | 中国产业发展研究网 - 提供行业研究报告 可行性研究报告 投资咨询 市场调研服务 | 定硫仪,量热仪,工业分析仪,马弗炉,煤炭化验设备厂家,煤质化验仪器,焦炭化验设备鹤壁大德煤质工业分析仪,氟氯测定仪 | 医学模型生产厂家-显微手术模拟训练器-仿真手术模拟训练系统-北京医教科技 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 一氧化氮泄露报警器,二甲苯浓度超标报警器-郑州汇瑞埔电子技术有限公司 | 章丘丰源机械有限公司 - 三叶罗茨风机,罗茨鼓风机,罗茨风机 | 四川成都干燥设备_回转筒干燥机_脉冲除尘器_输送设备_热风炉_成都川工星科机电设备有限公司 | 昆山PCB加工_SMT贴片_PCB抄板_线路板焊接加工-昆山腾宸电子科技有限公司 | 三防漆–水性三防漆–水性浸渍漆–贝塔三防漆厂家 | 烽火安全网_加密软件、神盾软件官网| 江苏远邦专注皮带秤,高精度皮带秤,电子皮带秤研发生产 | 带锯机|木工带锯机圆木推台锯|跑车带锯机|河北茂业机械制造有限公司| | 北京发电车出租-发电机租赁公司-柴油发电机厂家 - 北京明旺盛安机电设备有限公司 | 天津拓展_天津团建_天津趣味运动会_天津活动策划公司-天津华天拓展培训中心 | 青岛代理记账_青岛李沧代理记账公司_青岛崂山代理记账一个月多少钱_青岛德辉财税事务所官网 | 超声波清洗机_大型超声波清洗机_工业超声波清洗设备-洁盟清洗设备 | 筛分机|振动筛分机|气流筛分机|筛分机厂家-新乡市大汉振动机械有限公司 | OLChemim试剂-ABsciex耗材-广州市自力色谱科仪有限公司 | PCB设计,PCB抄板,电路板打样,PCBA加工-深圳市宏力捷电子有限公司 | 无菌水质袋-NASCO食品无菌袋-Whirl-Pak无菌采样袋-深圳市慧普德贸易有限公司 | 防水套管-柔性防水套管-刚性防水套管-上海执品管件有限公司 | 防爆电机生产厂家,YBK3电动机,YBX3系列防爆电机,YBX4节防爆电机--河南省南洋防爆电机有限公司 | 整车VOC采样环境舱-甲醛VOC预处理舱-多舱法VOC检测环境仓-上海科绿特科技仪器有限公司 | 心得体会网_心得体会格式范文模板 | 磁棒电感生产厂家-电感器厂家-电感定制-贴片功率电感供应商-棒形电感生产厂家-苏州谷景电子有限公司 | 牛皮纸|牛卡纸|进口牛皮纸|食品级牛皮纸|牛皮纸厂家-伽立实业 | SRRC认证_电磁兼容_EMC测试整改_FCC认证_SDOC认证-深圳市环测威检测技术有限公司 | 污水处理设备维修_污水处理工程改造_机械格栅_过滤设备_气浮设备_刮吸泥机_污泥浓缩罐_污水处理设备_污水处理工程-北京龙泉新禹科技有限公司 | 丝杆升降机-不锈钢丝杆升降机-非标定制丝杆升降机厂家-山东鑫光减速机有限公司 | 河北码上网络科技|邯郸小程序开发|邯郸微信开发|邯郸网站建设 | 吹塑加工_大型吹塑加工_滚塑代加工-莱力奇吹塑加工有限公司 | 电动球阀_不锈钢电动球阀_电动三通球阀_电动调节球阀_上海湖泉阀门有限公司 | 七维官网-水性工业漆_轨道交通涂料_钢结构漆 |