HTML5實時語音通話聊天,MP3壓縮傳輸3KB每秒

自從Recorder H5 GitHub開源庫優化後,對邊錄邊轉碼成小語音片斷文件實時上傳服務器這種操做支持很是良好,所以之前不太好支持的H5語音通話已經有了更好的突破空間。所以花了兩晚時間打造了一個H5語音通話聊天的demo。

歡迎在線把玩:https://xiangyuecn.github.io/Recorder/javascript

webrtc

1、把玩方法

  1. 準備局域網內兩臺設備(Peer A、Peer B)用最新版本瀏覽器(demo未適配低版本)分別打開demo頁面(也能夠是同一瀏覽器打開兩個標籤)
  2. 勾選頁面中的H5版語音通話聊天,在Peer A中點擊新建鏈接
  3. 把Peer A的本機信手動複製傳輸給Peer B,粘貼到遠程信息中,並點擊肯定鏈接
  4. 把Peer B自動生成的本機信息手動複製傳輸給Peer A,粘貼到遠程信息中,並點擊肯定鏈接
  5. 雙方P2P鏈接已創建,使用頁面上方的錄音功能,隨時開啓錄音,音頻數據會實時發送給對方
局域網H5版對講機😂

2、技術特性

(1)數據傳輸

github demo中考慮到減小對服務器的依賴,所以採用了WebRTC P2P傳輸功能,無需任何服務器支持便可實現局域網內的兩個設備之間互相鏈接,鏈接代碼也算簡單。有服務器支持可能就要逆天了,不過代碼也會更復雜。前端

若是正式使用,可能不太會考慮使用WebRTC,用WebSocket經過服務器進行轉發多是最佳的選擇。java

WebRTC局域網P2P鏈接要點(實際代碼其實差很少,只不過多作了點兼容):git

/******Peer A(本機)******/
var peerA=new RTCPeerConnection(null,null)

//開啓會話,等待遠程鏈接
peerA.createOffer().then(function(offer){
    peerA.setLocalDescription(offer);
    peerAOffer=offer;
});

var peerAICEList=[......] //經過peerA.onicecandidate監聽得到全部的ICE鏈接信息候選項,若是有多個網絡適配器,就會有多個候選

//建立鏈接通道對象,A端經過這個來進行數據發送
var peerAChannel=peerA.createDataChannel("RTC Test");



/******Peer B(遠程)******/
var peerB=new RTCPeerConnection(null,null)

//鏈接到Peer A
peerB.setRemoteDescription(peerAOffer);

//開啓應答會話,等待Peer A確認鏈接
peerB.createAnswer().then(function(answer){
    peerB.setLocalDescription(answer);
    peerBAnswer=answer;
});

//把Peer A的鏈接點都添加進去
peerB.addIceCandidate(......peerAICEList)

var peerBICEList=[......] //經過peerB.onicecandidate監聽得到全部的ICE鏈接信息候選項,若是有多個網絡適配器,就會有多個候選

var peerBChannel=... //經過peerB.ondatachannel獲得鏈接通道對象,B端經過這個來進行數據發送


/*******最終完成鏈接********/
//鏈接到Peer B
peerA.setRemoteDescription(peerBAnswer);

//把Peer B的鏈接點都添加進去
peerA.addIceCandidate(......peerBICEList)

/*
peerA peerB分別等待peerA/BChannel.onopen回調即完成P2P鏈接
,而後經過監聽peerA/BChannel.onmessage得到對方發送的信息
,經過peerA/BChannel.send(data) 發送數據。
*/

(2)音頻採集和編碼

因爲是在個人Recorder庫中新加的demo,所以音頻採集和編碼都是現成的,Recorder庫有好的兼容性和穩定性,所以節省了最大頭的工做量。github

編碼最佳使用MP3格式,由於此格式已優化了實時編碼性能,可作到邊錄邊轉碼,16kbps 16khz的狀況下可作到2kb每秒的文件大小,音質還能夠,實時傳輸時爲3kb每秒,15分鐘大概3M的流量。web

用wav格式也能夠,不過此格式編碼出來的數據量太大,16位 16khz接近50kb每秒的實時傳輸數據,15分鐘要37M多流量。其餘格式因爲暫未對實時編碼進行優化,使用中會致使明顯卡頓。瀏覽器

降噪、靜音檢測等高級功能是沒有的,畢竟是非專業人員😂 要求高點能夠,但不要超出範圍太多啦。服務器

(3)音頻實時接收和播放

接收到一個音頻片斷後,本應該是當即播放的,但因爲編碼、網絡傳輸致使的延遲,可能上個片斷還未播放完(甚至未開始播放),所以須要緩衝處理。微信

由於存在緩衝,就須要進行實時同步處理,若是緩衝內積壓了過多的音頻片斷,會致使語音播放滯後太多,所以須要適當進行對數據進行丟棄,實測發現網絡正常、設備性能靠譜的狀況下基本沒有丟棄的數據。網絡

而後就是播放了,本應是播完一個就播下一個,測試發現這是不靠譜的。由於結束一個片斷後再開始播放下一個發出聲音,這個過程會中斷比較長時間,明顯感受得出來中間存在短暫停頓。所以必須在片斷未播完時準備好下一個片斷的播放,而且提早開始播放,達到抹掉中間的停頓。

我寫了兩個播放方式:

  1. 實時解碼播放
  2. 雙Audio輪換播放

最開始用一個Audio停頓感太明顯,所以用兩個Audio輪換抹掉中間的停頓,但發現不一樣格式Auido播放差別巨大,播放wav很是流暢,但播放mp3仍是存在停頓(後面用解碼的發現是獲得的PCM時長變長了,致使事件觸發會出現偏差,爲何會變長?怪異)。

所以後面寫了一個解碼而後再播放,mp3此次終於能正常連續播放了,wav格式和雙Audio的播放差別不大。實時解碼裏面也用到了雙Audio中的技巧,其實也是用到了兩個BufferSource進行相似的輪換操做,以抹掉兩個片斷間的停頓。

不過最終播放效果仍是不夠好,音質變差了點,而且多了點噪音。若是有現成的播放代碼拿過來用就就行了。

3、應用場景

  1. 數據傳輸改爲WebSocket,作個仿微信語音通話H5版仍是能夠的(受限於Recorder瀏覽器支持)
  2. 局域網H5版對講機(前端玩具)
  3. ......沒有想到

完。

相關文章
相關標籤/搜索