欢迎在线把玩:https://xiangyuecn.github.io/Recorder/
一、把玩方法准备局域网内两台设备(Peer A、Peer B)用最新版本浏览器(demo未适配低版本)分别打开demo页面(也可以是同一浏览器打开两个标签)勾选页面中的H5版语音通话谈天,在Peer A中点击新建连接把Peer A的本机信手动复制传输给Peer B,粘贴到远程信息中,并点击确定连接把Peer B自动天生的本机信息手动复制传输给Peer A,粘贴到远程信息中,并点击确定连接双方P2P连接已建立,利用页面上方的录音功能,随时开启录音,音频数据会实时发送给对方局域网H5版对讲机
二、技能特性
(1)数据传输
github demo中考虑到减少对做事器的依赖,因此采取了WebRTC P2P传输功能,无需任何做事器支持即可实现局域网内的两个设备之间相互连接,连接代码也算大略。有做事器支持可能就要逆天了,不过代码也会更繁芜。
如果正式利用,可能不太会考虑利用WebRTC,用WebSocket通过做事器进行转发可能是最佳的选择。
WebRTC局域网P2P连接要点(实际代码实在差不多,只不过多做了点兼容):
/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 ApeerB.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 BpeerA.setRemoteDescription(peerBAnswer);//把Peer B的连接点都添加进去peerA.addIceCandidate(......peerBICEList)/peerA peerB分别等待peerA/BChannel.onopen回调即完成P2P连接,然后通过监听peerA/BChannel.onmessage得到对方发送的信息,通过peerA/BChannel.send(data) 发送数据。/
(2)音频采集和编码
由于是在我的Recorder库中新加的demo,因此音频采集和编码都是现成的,Recorder库有好的兼容性和稳定性,因此节省了最大头的事情量。
编码最佳利用MP3格式,由于此格式已优化了实时编码性能,可做到边录边转码,16kbps 16khz的情形下可做到2kb每秒的文件大小,音质还可以,实时传输时为3kb每秒,15分钟大概3M的流量。
用wav格式也可以,不过此格式编码出来的数据量太大,16位 16khz靠近50kb每秒的实时传输数据,15分钟要37M多流量。其他格式由于暂未对实时编码进行优化,利用中会导致明显卡顿。
降噪、静音检测等高等功能是没有的,毕竟是非专业职员 哀求高点可以,但不要超出范围太多啦。
(3)音频实时吸收和播放
吸收到一个音频片段后,本该当是立即播放的,但由于编码、网络传输导致的延迟,可能上个片段还未播放完(乃至未开始播放),因此须要缓冲处理。
由于存在缓冲,就须要进行实时同步处理,如果缓冲内积压了过多的音频片段,会导致语音播放滞后太多,因此须要适当进行对数据进行丢弃,实测创造网络正常、设备性能靠谱的情形下基本没有丢弃的数据。
然后便是播放了,本应是播完一个就播下一个,测试创造这是不靠谱的。由于结束一个片段后再开始播放下一个发生发火声音,这个过程会中断比较永劫光,明显觉得得出来中间存在短停息留。因此必须在片段未播完时准备好下一个片段的播放,并且提前开始播放,达到抹掉中间的停顿。
我写了两个播放办法:
实时解码播放双Audio轮换播放最开始用一个Audio停顿感太明显,因此用两个Audio轮换抹掉中间的停顿,但创造不同格式Auido播放差异巨大,播放wav非常流畅,但播放mp3还是存在停顿(后面用解码的创造是得到的PCM时长变长了,导致事宜触发会涌现偏差,为什么会变长?怪异)。
因此后面写了一个解码然后再播放,mp3这次终于能正常连续播放了,wav格式和双Audio的播放差异不大。实时解码里面也用到了双Audio中的技巧,实在也是用到了两个BufferSource进行类似的轮换操作,以抹掉两个片段间的停顿。
不过终极播放效果还是不足好,音质变差了点,并且多了点噪音。如果有现成的播放代码拿过来用就就好了。
三、运用处景数据传输改成WebSocket,做个仿微信语音通话H5版还是可以的(受限于Recorder浏览器支持)局域网H5版对讲机(前端玩具)......没有想到完。