HTML5实时语音通话聊天MP3压缩传输3KB每秒


Posted in HTML / CSS onAugust 28, 2019

自从Recorder H5 GitHub开源库优化后,对边录边转码成小语音片段文件实时上传服务器这种操作支持非常良好,因此以前不太好支持的H5语音通话已经有了更好的突破空间。因此花了两晚时间打造了一个H5语音通话聊天的demo。

欢迎在线把玩:  https://xiangyuecn.github.io/Recorder/ 

HTML5实时语音通话聊天MP3压缩传输3KB每秒

一、把玩方法

  • 准备局域网内两台设备(Peer A、Peer B)用最新版本浏览器(demo未适配低版本)分别打开demo页面 (也可以是同一浏览器打开两个标签)
  • 勾选页面中的H5版语音通话聊天,在Peer A中点击新建连接
  • 把Peer A的本机信手动复制传输给Peer B,粘贴到远程信息中,并点击确定连接
  • 把Peer B自动生成的本机信息手动复制传输给Peer A,粘贴到远程信息中,并点击确定连接 双方P2P连接已建立,使用页面上方的录音功能,随时开启录音,音频数据会实时发送给对方

局域网H5版对讲机:joy:

二、技术特性

(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 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库有好的兼容性和稳定性,因此节省了最大头的工作量。

编码最佳使用MP3格式,因为此格式已优化了实时编码性能,可做到边录边转码,16kbps 16khz的情况下可做到2kb每秒的文件大小,音质还可以,实时传输时为3kb每秒,15分钟大概3M的流量。

用wav格式也可以,不过此格式编码出来的数据量太大,16位 16khz接近50kb每秒的实时传输数据,15分钟要37M多流量。其他格式由于暂未对实时编码进行优化,使用中会导致明显卡顿。

降噪、静音检测等高级功能是没有的,毕竟是非专业人员:joy: 要求高点可以,但不要超出范围太多啦。

(3)音频实时接收和播放

接收到一个音频片段后,本应该是立即播放的,但由于编码、网络传输导致的延迟,可能上个片段还未播放完(甚至未开始播放),因此需要缓冲处理。

因为存在缓冲,就需要进行实时同步处理,如果缓冲内积压了过多的音频片段,会导致语音播放滞后太多,因此需要适当进行对数据进行丢弃,实测发现网络正常、设备性能靠谱的情况下基本没有丢弃的数据。

然后就是播放了,本应是播完一个就播下一个,测试发现这是不靠谱的。因为结束一个片段后再开始播放下一个发出声音,这个过程会中断比较长时间,明显感觉得出来中间存在短暂停顿。因此必须在片段未播完时准备好下一个片段的播放,并且提前开始播放,达到抹掉中间的停顿。

我写了两个播放方式:

  1. 实时解码播放
  2. 双Audio轮换播放

最开始用一个Audio停顿感太明显,因此用两个Audio轮换抹掉中间的停顿,但发现不同格式Auido播放差异巨大,播放wav非常流畅,但播放mp3还是存在停顿(后面用解码的发现是得到的PCM时长变长了,导致事件触发会出现误差,为什么会变长?怪异)。

因此后面写了一个解码然后再播放,mp3这次终于能正常连续播放了,wav格式和双Audio的播放差异不大。实时解码里面也用到了双Audio中的技巧,其实也是用到了两个BufferSource进行类似的轮换操作,以抹掉两个片段间的停顿。

不过最终播放效果还是不够好,音质变差了点,并且多了点噪音。如果有现成的播放代码拿过来用就就好了。

三、应用场景

  • 数据传输改成WebSocket,做个仿微信语音通话H5版还是可以的(受限于Recorder浏览器支持)
  • 局域网H5版对讲机(前端玩具)
  • ......没有想到 完。

总结

以上所述是小编给大家介绍的HTML5实时语音通话聊天MP3压缩传输3KB每秒,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

HTML / CSS 相关文章推荐
详解CSS的border边框属性及其在CSS3中的新特性
May 10 HTML / CSS
Css3+Js制作漂亮时钟(附源码)
Apr 24 HTML / CSS
CSS3 实用技巧:实现黑白图像效果示例代码
Jul 11 HTML / CSS
纯CSS3实现鼠标悬停提示气泡效果
Feb 28 HTML / CSS
CSS3实现的炫酷菜单代码分享
Mar 12 HTML / CSS
详解CSS3中使用gradient实现渐变效果的方法
Aug 18 HTML / CSS
CSS3实现多重边框的方法总结
May 31 HTML / CSS
CSS3条纹背景制作的实战攻略
May 31 HTML / CSS
纯CSS3实现移动端展开和收起效果的示例代码
Apr 26 HTML / CSS
html5各种页面切换效果和模态对话框用法总结
Dec 15 HTML / CSS
HTML5+CSS3实现机器猫
Oct 17 HTML / CSS
使用HTML5加载音频和视频的实现代码
Nov 30 HTML / CSS
详解基于 Canvas 手撸一个六边形能力图
Sep 02 #HTML / CSS
html+css实现自定义图片上传按钮功能
Sep 04 #HTML / CSS
Html5 Canvas 实现一个“刮刮乐”游戏
Sep 05 #HTML / CSS
canvas实现圆绘制的示例代码
Sep 11 #HTML / CSS
前端canvas水印快速制作(附完整代码)
Sep 19 #HTML / CSS
HTML5 Canvas 破碎重组的视频特效的示例代码
Sep 24 #HTML / CSS
HTML5实现的震撼3D焦点图动画的示例代码
Sep 26 #HTML / CSS
You might like
php chr() ord()中文截取乱码问题解决方法
2008/09/08 PHP
php判断正常访问和外部访问的示例
2014/02/10 PHP
详解PHP匿名函数与注意事项
2016/03/29 PHP
PHP 结合 Boostrap 结合 js 实现学生列表删除编辑及搜索功能
2019/05/21 PHP
简单的JS多重继承示例
2008/03/13 Javascript
JavaScript XML实现两级级联下拉列表
2008/11/10 Javascript
使用js对select动态添加和删除OPTION示例代码
2013/08/12 Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
2016/02/23 Javascript
jQuery的Each比JS原生for循环性能慢很多的原因
2016/07/05 Javascript
微信开发 JS-SDK 6.0.2 经常遇到问题总结
2016/12/08 Javascript
JS实现的类似微信聊天效果示例
2019/01/29 Javascript
Vue开发Html5微信公众号的步骤
2019/04/11 Javascript
解决layui 三级联动下拉框更新时回显的问题
2019/09/03 Javascript
react MPA 多页配置详解
2019/10/18 Javascript
vue 路由meta 设置导航隐藏与显示功能的示例代码
2020/09/04 Javascript
vue点击按钮实现简单页面的切换
2020/09/08 Javascript
[07:55]2014DOTA2 TI正赛第三日 VG上演推进荣耀DKEG告别
2014/07/21 DOTA
[41:41]TFT vs Secret Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
[01:01:42]Secret vs Optic Supermajor 胜者组 BO3 第二场 6.4
2018/06/05 DOTA
Python中的with...as用法介绍
2015/05/28 Python
Python多进程池 multiprocessing Pool用法示例
2018/09/07 Python
python获取txt文件词向量过程详解
2019/07/05 Python
python 实现IP子网计算
2021/02/18 Python
中国医药集团国药在线:国药网
2017/02/06 全球购物
美国礼品卡商城: Gift Card Mall
2017/08/25 全球购物
房屋改造计划书
2014/01/10 职场文书
村官学习十八大感想
2014/01/15 职场文书
卖车协议书范本4篇
2014/10/01 职场文书
交通安全教育主题班会
2015/08/12 职场文书
2015年六年级班主任工作总结
2015/10/15 职场文书
小学生大队委竞选稿
2015/11/20 职场文书
你离财务总监还有多远?速览CFO的岗位职责
2019/11/18 职场文书
祝福语集锦:给满月宝宝的祝福语
2019/11/20 职场文书
Oracle中update和select 关联操作
2022/01/18 Oracle
详解MongoDB排序时内存大小限制与创建索引的注意事项
2022/05/06 MongoDB
使用opencv-python如何打开USB或者笔记本前置摄像头
2022/06/21 Python