WebRTC实时音视频通话之语音通话设计与实践

一、背景

在移动互联网流量时代,很多业务场景都有音视频通信的需求,比如IM场景,除了文字交流还需要音视频通话进行实时交互。为了帮助58、赶集、安居客等业务线更好的为用户提供服务,节约沟通成本,提升效率,TEG基于WebRTC提供了一套完整的实时音视频通话解决方案——WRTC。

另外还有一种场景,比如在进行语音通话时,APP中的两个用户可能不是同时在线,导致一端无法向另一端发起实时通话。为了解决这个问题,WRTC还具备语音转IP电话的能力。业务方可以通过后端配置选择是否使用。本文主要以语音通话为切入点,详细介绍语音及语音转IP电话在WRTC中的设计与实践。

二、WebRTC简介

作为音视频开源核心项目之一,WebRTC整个框架的设计非常庞大,很多大型公司都在基于WebRTC进行音视频能力开发,包括阿里云、网易云、七牛云等。TEG也在2016年就开始提供基于WebRTC的实时音视频通话能力。同时WebRTC的架构设计灵活,功能强大,覆盖了大部分移动端多媒体技术。

比如APM(声音处理模块),被很多公司借鉴用于音频的AEC、NS、AGC。JitterBuffer用于视频抗抖动。Android端Camera和Camera2结合使用,用于视频采集,可扩展的软编码框架以及软硬编结合方式处理视频流等。可以说WebRTC的每个模块都值得我们深入研究,学习其中的设计思想和音视频处理技术。

目前网上关于WebRTC资料有很多,限于篇幅,本文也只做个简单介绍,具体细节,感兴趣的同学可以深入研究模块代码,就像Linux鼻祖Linus曾说的至理名言"Read the f*** source code"。

  • 音频,音频采集、处理模块
  • 视频,视频采集、编解码模块
  • ICE打洞中继服务器,STUN/TURN
  • 媒体流传输,RTP/RTCP

WRTC功能模块主要分为视频通话、语音通话、语音转IP电话。本文主要介绍语音和语音转IP电话部分。

三、音视频通话架构

音视频通话包括音频通话和视频通话。同时,为了丰富音视频电话在当前网络环境下的应用场景和通话能力,WRTC还需要提供IP电话的解决方案。业界比较流行的IP电话方案是用FreeSwitch作为电话网关后台,该方案支撑的架构如下图:

在上图这种架构下,客户端除了实现WRTC需要的信令协议通信之外,还需要额外增加同FreeSwitch服务之间的SIP协议通信。从SDK的角度来考虑,这对客户端SDK的包体积、接入复杂度、容错率以及版本灵活性等都带来了额外的挑战。所以我们最终决定将这部分实现放在服务端,架构如下图:

架构优化后,在没有增加客户端和服务端交互复杂度的前提下,由服务端对音频流进行转接,通过SIP协议对接到电话网关,实现与对端手机的通信。另外,服务端还可以进行语音录制,为后期业务方的语音监控、通话记录分析等需求增加了便利。

通话流程

首先介绍下WRTC的音视频通话流程,如下图所示,主叫通过Room/Signaling服务和被叫进行信息交互,IM服务器对于音视频通话来说并不是必须的,把它放在WRTC的流程当中是为了让被叫顺利接收主叫的通话请求。在一个完整的通话流程中,主叫首先尝试和被叫建立音视频通话的连接,假如连接超时或者主叫主动发起IP电话时,WRTC服务端会通过运营商拨打被叫电话,从而完成IP电话的流程。

客户端:

1、房间管理。房间是一个抽象概念,目的是在主被叫之间建立一个随时可查询可追溯的信息通道,比如说当主叫发起音视频通话请求时,被叫需要一个标识来确定需要和哪一方进行通话,这个标识就是用房间信息来储存的。音视频通话需要双方先加入房间,然后再使用PeerConnection建立连接进行通话。下面举几个房间管理的例子:

/**
 @brief 请求RoomInfo(后台需要进行身份验证,并分配roomId等)
 @param completeHandler 回调block
 @since v1.0.0
 */
+ (void)requestRoomInfo:(CompleteHandler)completeHandler;

/**
 @brief 加入房间
 @param roomid 房间的id
 @param params 参数字典
 @param completeHandler 回调返回
 @since v1.1.1
 */
+ (void)joinToRoom:(NSString *)roomId
        Parameters:(NSDictionary *)params
          Complete:(CompleteHandler)completeHandler;

 /**
 @brief 通知此时处于忙状态
 @param roomId 第三方呼叫发来的roomId
 @since v1.0.0
 */
+ (void)notifyBusy:(NSString *)roomId;

2、信令管理。WRTC采用的是Websocket作为信令服务器,进行媒体协商,发送SDP会话描述协议和Candidate候选信息等。这里主要涉及SDP会话描述协议(offer/answer)和Candidate信息交换。为了提升编码性能,WRTC视频编解码采用H264,音频编解码综合考虑性能和带宽,采用的是OPUS。Candidate交换的是打洞候选IP地址和端口号,用于p2p连接和中继。

下面是一对一音频通话,主叫方发送的SDP(offer)。

offer   
...  
a=mid:audio  
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level  
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time  
a=sendrecv  
a=rtcp-mux  
a=rtpmap:111 opus/48000/2  
a=rtcp-fb:111 transport-cc  
a=fmtp:111 minptime=10;useinbandfec=1  
a=rtpmap:103 ISAC/16000  
a=rtpmap:104 ISAC/32000  
a=rtpmap:9 G722/8000  
a=rtpmap:102 ILBC/8000  
a=rtpmap:0 PCMU/8000  
a=rtpmap:8 PCMA/8000  
a=rtpmap:106 CN/32000  
a=rtpmap:105 CN/16000  
a=rtpmap:13 CN/8000  
a=rtpmap:126 telephone-event/8000  
...  

主叫发送的sdp信息通过信令服务器发送到被叫,被叫收到该offer后,会根据该offer回一个answer信息。至此,主叫和被叫完成了媒体信息的协议协商。

3、状态管理。通过信令服务器进行双方通话状态的管理,状态包括busy、refuse、cancel等。状态管理一方面可以防止双通话,另一方面也能根据通话状态进行用户行为统计分析,然后进行迭代优化,为各个业务线提供更好、更稳定的音视频通话服务。

4、音频模块、视频模块、ICE打洞服务、媒体流传输等在上文做了简单介绍,其实这里的每一个模块,都值得我们去深入研究学习,比如我们也在尝试借鉴其中的音频处理模块用于直播服务。篇幅所限,本文不做过多描述。

服务端:

后台服务管理整个WRTC音视频通话的连接建立、信息交换、房间信息等。

  • 房间服务,对加入房间的主叫Caller和被叫Callee的行为进行管理,比如加入房间、退出房间等等(上文已经在客户端部分做过介绍,此处不再重复)。
  • 信令服务,控制双端用户的媒体协商、Candidate交换等。
  • ICE打洞服务,WRTC音视频通话方式分为p2p和中继两种方式。ICE包括STUN和TURN服务,用于打洞,STUN可以进行NAT类型检测,并获取NAT背后的外网IP地址和端口号。其中NAT类型主要分为Full Cone NAT、RestrictedCone NAT、Port Restricted Cone NAT、Symmetric NAT四种。对于前三种都可以建立p2p直连,对于Symmetric NAT(对称性NAT),因为每次连接端口都是变化的,所以通过STUN获取的端口号是无效的。此时WRTC会改走中继模式,来保证双端的正常通话。

考虑到一旦建立p2p连接,后续服务端不能控制干预媒体流,后端服务后续也计划进行系统升级,统一采用中继的方式进行音视频通话,来保证音视频通话的可靠性和可控性。

运营商(网关代理):

后端服务经过判断需要向被叫拨打IP电话时,协议转换服务会将接到的offer转换为SIP的带有协商信息的invite协议,发送给运营商,然后运营商会回复给100trying,表明正在处理SIP信令。

当被叫手机振铃时,运营商回复180或183协议给协议转换服务,并带有第一次协商的结果,协议转换服务将其转化为answer回复给客户端,完成第一次媒体通信即客户端听到彩铃。

当被叫手机接听时,运营商会发送200给协议转换服务,并带有第二次协商的结果,协议转换服务将其转化为answer回复给客户端,完成第二次媒体通信即被叫和主叫开始通话。

如下图所示:

IP电话二次拨号:

对于IP电话,WRTC也具备对分机二次拨号的能力。比如被叫方是座机,可以通过二次拨号和指定用户进行语音通话。

电话拨号,就必须要提到双音多频信号DTMF。DTMF是电话系统中电话机与交换机之间的一种用户信令,用于电话拨号。通过研究WebRTC底层代码,其实它是支持DTMF拨号能力的,只是没有对外部暴露。

我们需要修改PeerConnection,增加insertDtmf功能。拨打分机号时需要传入本地AudioTrack ID,默认值为ARDAMSa0。分机号码ext_number取值范围0~15,对应event为0-9,*, #, A-D。拨号音duration SDK设置的为1000ms。

下面是insertDtmf部分代码:

bool PeerConnection::insertDtmf(const std::string& audio_track_id,const int ext_number,const int duration){
   //判断是否支持发送DTMF信号
   bool canInsertDtmf = session_->CanInsertDtmf(audio_track_id);
   if (canInsertDtmf) {
     //WebRTCSession对象发送DTMF
     isInsert = session_->InsertDtmf(audio_track_id,ext_number,duration);
   }
   return isInsert;
}

下面具体说说音视频开发WebRTC方面需要学习哪些内容,以及推荐的资源:

关于选取资源,我的建议是:资源不在多,而贵在精。不要总是屯一大堆资源而却一直放在那里吃灰

四、总结

本文主要介绍了WRTC的实现方案、流程以及IP电话的原理。其中涉及到的细节还有很多,这里就不再赘述。目前WRTC已经能提供了稳定的音视频通话输出能力,后续我们将继续在WRTC方案的基础之上,结合TEG的短视频SDK,从采集端、通话端进行持续优化,采集端丰富音视频处理细节,通话端增加多人通话,最终形成一对一以及多对多的音频、视频、IP电话混合对话的能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/631117.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

月薪3万,沉迷“薅羊毛”

在网购江湖中,蟹老板是一位拥有十年经验的资深“羊毛党”。 他不仅是位精明的数学家,更是一位高效的“生产线”工人,专注于各大网购平台的优惠机制。每逢618大促,他总能凭借超凡的洞察力和手速,轻松斩获丰厚的“羊毛”…

C语言 | Leetcode C语言题解之第91题解码方法

题目&#xff1a; 题解&#xff1a; int numDecodings(char* s) {int n strlen(s);// a f[i-2], b f[i-1], c f[i]int a 0, b 1, c;for (int i 1; i < n; i) {c 0;if (s[i - 1] ! 0) {c b;}if (i > 1 && s[i - 2] ! 0 && ((s[i - 2] - 0) * 10…

Ubuntu22 下配置 Qt5 环境

1. Qt 简介 Qt5 中的新功能&#xff0c;可以看到各个版本的情况Whats New in Qt 5 | Qt 5.15 Qt 源文件网址Index of /archive/qt 2. 安装 Qt Creator cd 到安装包所在目录&#xff0c;进行软件安装。赋予可执行权限&#xff0c;加上 sudo 权限进入安装&#xff0c;这样会安…

Python专题:十六、异常处理(2)

异常的预判和防护 import randomnum random.randint(1, 100) # 获得一个随机数 is_done False # 是否猜中的标记 count 0 # 玩家猜了几次while not is_done:guess int(input(请输入一个[1, 100]的整数&#xff1a;))if guess num:is_done Trueelif guess > num:pr…

公司邮箱是什么?公司邮箱和个人邮箱有什么不同?

公司邮箱是企业用来收发邮件的专业版电子邮箱&#xff0c;不同于个人邮箱的简单功能和有限的存储空间&#xff0c;公司邮箱的功能更加丰富&#xff0c;能够满足企业的日常办公和协作需求。本文将为您详细讲解公司邮箱和个人邮箱的区别&#xff0c;以供您选择更适合自己的邮箱类…

哈希表法快速求解最长连续序列 | 力扣128题详细解析

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

分布式锁:场景和使用方法(通俗讲解)

这里写目录标题 通俗讲解分布式锁&#xff1a;场景和使用方法前言引入业务场景业务场景一出现业务场景二出现&#xff1a;业务场景三出现&#xff1a; 分布式锁的使用场景分布式锁的几种特性分布式锁的几种实现方式一、基于 Mysql 实现分布式锁二、基于单Redis节点的分布式锁三…

Python 机器学习 基础 之 监督学习 [决策树集成] 算法 的简单说明

Python 机器学习 基础 之 监督学习 [决策树集成] 算法 的简单说明 目录 Python 机器学习 基础 之 监督学习 [决策树集成] 算法 的简单说明 一、简单介绍 二、监督学习 算法 说明前的 数据集 说明 三、监督学习 之 决策树集成 1、随机森林 2、梯度提升回归树&#xff08;梯…

HNU-算法设计与分析-作业6

第六次作业【分支限界法】 文章目录 第六次作业【分支限界法】<1> 算法实现题6-2 最小权顶点覆盖问题<2> 算法实现题6-6 n后问题<3> 算法实现题6-7 布线问题 <1> 算法实现题6-2 最小权顶点覆盖问题 ▲问题重述 问题描述&#xff1a; 给定一个赋权无向…

从融媒到智媒,小程序框架可助力传媒企业在AI实践下的服务变现

过去5年&#xff0c;媒体行业一直都在进行着信息化建设向融媒体平台建设的转变。一些融媒体的建设演变总结如下&#xff1a; 新闻终端的端侧内容矩阵建设&#xff0c;如App新闻端&#xff0c;社交平台上的官方媒体等 新闻本地生活双旗舰客户端&#xff0c;兼顾主流媒体核心宣传…

Android 10.0 Launcher3定制folder文件夹2x2布局之三foldericon的2x2的布局后拖拽只能停放在右边的问题修复

1.前言 在10.0的系统rom产品定制化开发中,在对Launcher3的folder文件夹功能定制中,要求folder文件夹跨行显示,就是 2x2布局显示,默认的都是占1格的,现在要求占4格显示,系统默认是不支持显示4格的,所以接下来需要分析相关的 功能,然后来实现这个功能 2.Launcher3定制fo…

HNU-算法设计与分析-作业2

第二次作业【分治算法】 文章目录 第二次作业【分治算法】<1>算法实现题 2-2 马的Hamilton周游路线问题<2> 算法实现题 2-3 半数集问题<3>算法实现题 2-6 排列的字典序问题<4> 算法实现题 2-7 集合划分问题 <1>算法实现题 2-2 马的Hamilton周游路…

某东-绑卡

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章未…

代码随想录--链表--反转链表

题目 题意&#xff1a;反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 思路 如果再定义一个新的链表&#xff0c;实现链表元素的反转&#xff0c;其实这是对内存空间的浪费。 其实只需要改变链表的next指针的…

柯桥外语成人教育之生活口语培训“January and May”才不是“一月和五月”!真正的意思差远了!

“January and May”正确翻译是&#xff1f; 一月跟五月这八杆子打不到的月份能有什么关系&#xff1f;为什么要放在一起说&#xff1f;其实&#xff0c;它们不仅有关系而且还很亲密。 这个俚语起源于英国作家乔叟所著的《坎特伯雷故事集》中“商人的故事”&#xff1a; Januar…

【重生之我在学Android】WorkManager (章一)

相关文章 【重生之我在学Android原生】ContentProvider(Java) 【重生之我在学Android原生】Media3 【重生之我在学Android】WorkManager &#xff08;章一&#xff09; 前言 官方文档 官方推荐 - 前台服务、后台服务都可以使用WorkManger来实现 案例 语言&#xff1a;JA…

Leetcode---1.两数之和 (详解加哈希表解释和使用)

文章目录 题目 [两数之和](https://leetcode.cn/problems/two-sum/)方法一&#xff1a;暴力枚举代码方法二&#xff1a;哈希表代码 哈希表哈希表的基本概念哈希函数&#xff08;Hash Function&#xff09;&#xff1a;冲突&#xff08;Collision&#xff09;&#xff1a;链地址…

Linux查看进程命令ps和top

Linux 是一种自由和开放源代码的操作系统&#xff0c;它的使用在全球范围内非常广泛。在 Linux 中&#xff0c;进程是操作系统中最重要的组成部分之一&#xff0c;它代表了正在运行的程序。了解如何查看正在运行的进程是非常重要的&#xff0c;因为它可以帮助你了解系统的运行状…

Qwen学习笔记4:Qwen 7B模型调用天气API实现天气的实时查询

前言 在学习Qwen模型的函数调用功能后&#xff0c;进一步尝试利用本地的Qwen模型访问OpenWeather API来获取实时的天气情况。 参考代码来源于视频教程&#xff1a; 简单粗暴&#xff0c;轻松配置Qwen模型查询实时数据功能_哔哩哔哩_bilibili 说明 该代码运行前&#xff0c…

基于51单片机的AD/DA转换的串口通信proteus仿真(附源码)

文章目录 一、前言二、PCF85911.介绍2.原理图3.引脚介绍 三、仿真图1.未仿真时2.仿真时 四、仿真程序main.cIIC.c 五、总结 一、前言 AT89C52是一款经典的8051系列单片机&#xff0c;它通常不包含内置的模数转换器&#xff08;ADC&#xff09;或数字模拟转换器&#xff08;DAC…