項目需求 Web端播放實時音頻流,折騰了兩天后問題得以解決。記錄下開發調試過程,方便后來者。
首次想到是利用Audio標簽,Audio標簽可以直接播放MP3格式,服務端將實時音頻流編碼成MP3格式
通過Http方式傳給Web端即可,前端代碼如下所示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script> </script> </head> <body> <audio controls="controls" autoplay="autoplay"> <source src="http://127.0.0.1:12345/cgmedia/28181/getaudio?id=34020000001310000001@192.168.1.108:5060&format=mp3&transporttype=udp&transportport=22000" type="audio/mpeg"> </audio> </body> </html>
通過Audio標簽 實現音頻流播放 代碼比較簡單,但有緩沖過大問題,粗略測試了下延時 20-30s左右,這顯然
不滿足實時播放實時播放需求。開始調試時懷疑是后台服務端傳輸過來的流有問題,於是將流保存成MP3文件進行
測試 ,結果正常未出現緩沖一段時間后開始播放。分析Audio標簽發出的Http報文,發現Http請求Head中有Range字段,
嘗試做了相應Response,結果未發生變化。猜想Audio標簽可能只適合於MP3文件(一次性將Audio數據加載完成再處
理)。如這個猜測不對,歡迎指正(本人主要從事后台媒體服務開發,前端經驗很少)。
Audio標簽的方式不行,想到利用Web Audio API是實現,基本的思路是:通過WebSocket 接收服務端推送過來的音
頻流(MP3格式)調用decodeAudioData進行解碼,最后將解碼數據推送到AudioContext最后一個Node,代碼如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function WebSocketTest()
{
var wsUrl = "ws://127.0.0.1:12345/cgmedia/28181/getaudio?id=34020000001310000001@192.168.1.108:5060&format=mp3&transporttype=udp&transportport=22000";
ws = new WebSocket(wsUrl);
ws.binaryType = 'arraybuffer'; //arraybuffer
ws.onmessage = function(msg) {
var data = msg.data;
var datalen = msg.data.size;
var audioContext = new AudioContext({
sampleRate:8000,
});
reader.onload = function(evt)
{
if(evt.target.readyState == FileReader.DONE)
{
audioContext.decodeAudioData(data, function(buffer) {
console.log("decode success");
var bufferSource = audioContext.createBufferSource();
bufferSource.connect(audioContext.destination);
bufferSource.buffer = buffer;
bufferSource.start(0);
}, function(e) {
console.log("decode failed" + e);
});
}
}
reader.readAsArrayBuffer(new Blob([data]));
};
ws.onopen = function(evt) {
if(self.verbose) {
console.log("Connection open......");
}
};
ws.onclose = function(evt) {
if(self.verbose) {
console.log("Connection closed......");
}
};
}
</head>
<body>
<button onclick="WebSocketTest()">發送請求</button>
</body>
</html>
采用Audio Web API方式播放實時流會出現卡頓現象,以上方法一次性解碼的數據可以連續播放,每次解碼后要重新
創建BufferSource,顯而易見這種播放模式播放實時流效率很低,查閱了Audio Web API 文檔 播放網絡流似乎要利用
基於AudioWorkletProcessor的自定義節點,文檔也給了一個簡單的例子,那個例子不符合我們的使用場景。沒有
更多的時間研究Audio Web API,這種方案只好作罷,單看Audio Web API接口有些無語, 這有可能跟Web端處理能力有關。
可行的方法
條條大路通羅馬,畢竟項目不是科研,可以實現需求就行。一種可行的方法是服務端輸出Rtmp音頻流 通過video.js播放
實際應該是用了flash。項目開始已經想到了這個方案可行只是覺得有些繞(需要將音頻流封裝后推送到rtmp server)。
另外一個可行的方案就是利用H5 MSE實現,這個方案也有開源的庫可以用,例如flv.js 這需要 服務端將音頻打包成flv格式
推送給Web前端,Web端接收到音頻數據后調用flv.js進行播放。video.js 及flv.js github都有下載 代碼就不貼出來了。
如需交流可加QQ群766718184,1038388075 或者QQ3501870
視頻下載地址:http://www.chungen90.com/?news_33/
Demo下載地址: http://www.chungen90.com/?news_34