1 对 1 语音聊天
1 对 1 语音聊天是一款双人实时通话产品(不具备视频通话功能),拥有实时通话、设置背景音乐等功能。能够为开发者提供高音质、低延迟、便捷接入、多平台互通的服务。可适用于私密聊、语音陪聊等社交场景。
Demo 体验
AliRTC 为 1 对 1 语音聊天提供 Android 和 iOS 的 Demo,通过钉钉扫码下载。
主要功能
主要功能 | 功能描述 |
实时语音通话 | 超低延时下,用户之间实现语音通话功能。 |
背景音乐 | 可以播放指定背景音乐。 |
伴奏混音 | 将本地或在线的音频和用户声音,同时发送并播放给另一名用户。 |
高音质 | 支持 48kHz 采样的高音质,支持左右声道。 |
3A 音频处理 | 行业领先的音频 3A(AGC、AEC、ANS),支持针对人声、乐器等场景定制化调优。 |
实现方法
创建房间 API 时序图(Android 端):
前提条件
源码下载
请单击 Demo 下载,下载源码。
实现流程
实现流程如下图所示:
集成服务端
前提条件
- 您已经完成注册阿里云账号,并完成实名认证,具体操作请参见阿里云账号注册流程。
- 您已经开通音视频通信服务,具体操作请参见开通服务。1 对 1 语音聊天无需购买套餐也可正常搭建。
- 首次开通 RTC 服务后,系统会自动帮您创建一个应用项目,可以直接使用自动创建好的应用项目进行使用。如果没有应用项目,需要您在阿里云音视频通信 RTC 控制台创建应用。
- 服务端环境需要 Java JDK 8 的版本,具体操作,请参见安装 JDK。
说明 Linux 环境推荐安装 Oracle JDK,不推荐使用 Open JDK 进行服务端集成。
操作步骤
说明 您在集成服务端时,如果遇到问题,请参见服务端运行常见问题。
- 获取应用 ID 和 AppKey。说明应用 ID 和 AppKey 需要对应,不同的应用 ID 有不同的 AppKey。在后续开发中会使用应用 ID 和 AppKey,建议记录到本地文档中,妥善保存。
- 登录 RTC 控制台。
- 在左侧导航栏单击应用管理,进入应用管理页面。
- 获取应用 ID 和查询 AppKey。
- 应用 ID:可在应用 ID / 名称列表下直接获取。
- AppKey:单击查询 AppKey 获取 AppKey。
- 如果您还未有应用,您可以单击创建应用创建。
- 获取 AccessKey。警告由于主账号 AccessKey 泄露会威胁您所有资源的安全,因此出于安全考虑,需要创建一个子账号(RAM 用户)并获取子账号的 AccessKey,用于 1 对 1 语音聊天 Demo 访问您的云资源。
- 登录 RAM 控制台。
- 在左侧导航栏选择人员管理 > 用户,进入用户页面。
- 单击创建用户,填写用户账号信息,选中编程访问创建用户。
- 单击确定。
- 重新返回用户页面。在用户登录名称 / 显示名称列表下,单击目标 RAM 子账户,进入管理页面。
- 单击权限管理,单击添加权限。
- 选择 AliyunRTCFullAccess(管理音视频通信(RTC)的权限),可输入 RTC 进行搜索。单击确定。
- 单击认证管理,在用户 AccessKey 区域单击创建 AccessKey。说明
- 首次创建时需填写手机验证码。
- 如果 AccessKey 泄露或丢失,则需要创建新的 AccessKey,最多可以创建 2 个 AccessKey。
- 获取 AccessKey ID 和 AccessKey Secret。创建 AccessKey 完成后,会弹出创建 AccessKey 对话框,可以获取 AccessKey ID 和 AccessKey Secret。
注意 AccessKey ID 和 AccessKey Secret 在后续开发中会使用,建议记录到本地文档妥善保存。AccessKey Secret 只在创建时显示,不提供查询。
- 下载 Demo 源码。说明
- 源码压缩文件内分为 Server 端、Android 端、iOS 端三个源文件。
- 若遇到 Github 代码库下载缓慢的问题,可通过安装加速插件等方式加速下载。
- 解压 Demo 源码压缩包。解压成功之后如下图所示:
- 选择 server/dist/rtc-api.zip 文件,解压到 dist 文件夹下。
- Mac 环境下请将终端定位至 dist 目录下,使用 unzip 命令解压。
unzip rtc-api.zip
- Windows 环境下请直接双击解压。
- 解压成功后如图所示。
说明 解压成功后,可以看到 BOOT-INF、META-INF 及 org 文件夹,这三个文件夹需要和 restart.sh 保持在同一个目录下。 - 修改配置文件。打开 BOOT-INF/classes/application.properties文件,修改配置。说明使用文本编辑器打开即可,若找不到打开方式,推荐安装 VSCode 等轻量级代码编辑器打开。
- 设置 RTC 应用 AppId 和 AppKey,可参见步骤获取 AppKey 和应用 ID。获取。rtc.1v1audio.appId = *
rtc.1v1audio.appKey = * - 设置 AK,需要添加 AliyunRTCFullAccess 权限,可参见步骤获取 AccessKey 获取。accessKeyID=*
accessKeySecret=*
- 运行服务,执行 restart.sh 文件。
- Mac 或 Linux 环境下请将终端定位至 dist 目录下,执行如下命令:sh restart.sh
后台执行可以使用如下命令以确保退出终端时程序能够继续运行。
nohup sh restart.sh >./run_log.log 2>&1 & - Windows 环境需要打开 CMD 终端定位到 server/dist 文件夹下,执行如下命令:java org.springframework.boot.loader.JarLauncher
若提示 8080 端口被占用,请尝试使用 netstat 命令查看占用 8080 端口的进程 pid 号,并使用 taskkill 关闭相关进程。
netstat -ano | findstr 8080
taskkill /pid 占用端口的进程 pid 号 /f
终端成功运行后可以看到服务端启动成功的日志信息。
- 访问指定 URL 地址。URL 地址:http://127.0.0.1:8080/1v1-audio/index.html。
如果您在浏览器上看到 Hello RTC! ,代表服务端已经启动。
主要功能说明
- 生成 joinChannel 所需鉴权信息访问地址:/app/token
客户端调用 RTC SDK 加入房间的 Token 信息就是从这个接口获得。具体生成方式,请参见 RTC 帮助文档生成 Token。
MessageDigest digest = MessageDigest.getInstance("SHA-256"); digest.update(appId.getBytes()); digest.update(appKey.getBytes()); digest.update(channelId.getBytes()); digest.update(userId.getBytes()); digest.update(nonce.getBytes()); digest.update(Long.toString(timestamp).getBytes()); String token = DatatypeConverter.printHexBinary(digest.digest()).toLowerCase(); return token;
- 查询频道实时在线用户列表访问地址:/app/descChannelUsers
AppServer 通过调用 rtcOpenApi 的 DescribeChannelUsers 接口查询频道的实时在线人数。
DefaultAcsClient client = initVodClient(); DescribeChannelUsersRequest request = new DescribeChannelUsersRequest(); request.setAppId(appId); request.setChannelId(channelId); DescribeChannelUsersResponse response = client.getAcsResponse(request);
- 查询房间开启时间访问地址:/app/descChannelStartTime
当客户端请求加入房间所需的 token 时,服务端查询当前房间人数,若房间人数为 0,保存当前时刻和房间 id。并把当前时刻作为此房间的创建时间。
DescribeChannelUsersResponse response = RtcOpenAPI.describeChannelUsers(appId, channelId); if (CollectionUtils.isEmpty(response.getUserList())) { ImmutablePair<String, String> appChannel = new ImmutablePair<>(appId, channelId); ScheduledFuture scheduledFuture = TASKS.getOrDefault(appChannel, new JSONObject()).getObject("scheduledFuture", ScheduledFuture.class); TASKS.put(appChannel, channelInfo); } JSONObject scheduledTask = ScheduledDeleteChannel.TASKS.get(ImmutablePair.of(app
集成iOS端
前提条件
开发前的环境要求如下表所示,详情请参见:使用限制。
类别 | 说明 |
iPhone 设备 | 支持 iPhone5 及以上。 |
系统版本 | 支持 iOS 8.0 及以上。 |
CPU 架构 | 支持真机架构 armv7+arm64,不支持模拟器 i386、x86 架构。 |
Xcode 版本 | 支持 Xcode9.0 及以上。下载 Xcode。 |
其他 | 不支持 Bitcode,不支持屏幕旋转。 |
您需要先集成服务端,具体操作,请参见集成服务端。
说明 您需要持有 Apple 开发证书或个人账号。
Demo 运行指引
说明
您在集成 iOS 端时,如果遇到问题,或者 Demo 体验过程中出现无法创建房间或通话等问题,请参见 iOS 端运行常见问题。
- 下载 Demo 并解压。说明
- Demo 源码中已经集成 AliRTC SDK(版本:1.17)。SDK 集成方式通过 CocoaPods 集成。
- 源码压缩文件内分为 Server 端、Android 端、iOS 端三个文件。
- 若遇到 GitHub 代码库下载缓慢的问题,可通过安装加速插件等方式加速下载。
- 修改配置文件。
- 打开解压后的 Demo 文件夹 AliRTC-UserCase-VoiceCallSolution_1To1-master,找到 iOS/demo/AlivcVoiceCallSolo/AlivcVoiceCallSolo/Utils/Http/AliBaseHttpClient.m文件。
- 修改文件中的
AppServer
变量,如:http://<服务器IP> :8080/1v1-audio
,部署到正式环境上建议绑定域名并使用:http://<域名>/1v1-audio
。示例假设本地 IP 为 192.0.2.1,那么BASE_URL="http://192.0.2.1:8080/1v1-audio"
。本地 IP 查询,请参见查询 IP 地址。注意
- 不要使用 127.0.0.1 的 IP。
- 手机和搭建服务器的电脑处在一个局域网中。
- 使用手机和电脑的浏览器验证。输入正确的 URL(
AppServer
变量)地址,即可在浏览器中打开并看到:Hello RTC!
。电脑端浏览器正确访问说明 IP 和端口号无误,手机端浏览器正确访问说明目前手机可以正常访问到服务器 IP。
- 导入 Demo 源码。打开 Xcode,单击 Open a project or file,双击打开 demo 目录下的 AlivcVoiceCallSoloClient.xcworkspace 文件。
- 选择运行 Target 为 AlivcVoiceCallSoloClient,将一台 IOS 真机设备使用数据线与电脑链接,在 Xcode 中选择相应的真机设备,真机在设置中打开开发者模式。(暂不支持模拟器运行)
- 修改 Bundle Identifier 和开发者证书。
注意 Bundle Identifier 改成为com.<公司名>.<项目名>
,避免由于 Bundle 已被注册从而运行失败。
General 选项卡中修改。
Sign & Capabilities 选项卡中修改。 - 在 Sign & Capabilities 选项卡,勾选 Automatically manage signing,在下方选择自己的 Team。
- 选择 Team。
- 若以前没添加过账号,单击 Add an Account 添加。
- 完成账号添加。
- 在 Team 里选择新创建的账号即可,并且在完成签名后确保下方没有报错提示。
- 单击 build and run 按钮编译。
- 进行 1 对 1 语音聊天。
- 将 2 台真机移动端设备(Android 或 iOS)装上 Demo App。
- 将 2 台设备都连接到同一局域网下,保证可以连接到 Server 端。
- 在第一台真机上输入任意房间号,创建房间并等待对方加入。
- 在第二台真机上输入相同房间号加入房间并进行通话。
Demo 源码解析
- 项目结构说明。说明Demo 是以 Cocoapods Lib 的方式集成到项目中的。
- RTC 把开发的业务代码封装到名称为 AlivcVoiceCallSolo 的库当中,这样 AlivcVoiceCallSolo 就可以像一个本地的第三方库一样。可以随便移植到其他项目中,只需在 Podfile 中指定 AlivcVoiceCallSolo 库的路径即可。如下所示:
pod 'AlivcVoiceCallSolo', :path => './AlivcVoiceCallSolo' ## pod 'AlivcVoiceCallSolo' 说明项目依赖AlivcVoiceCallSolo库 ## path => './AlivcVoiceCallSolo' 指明AlivcVoiceCallSolo库的位置(相对于Podfile)
- 名词解释如下:
- pod:表示工程依赖 AlivcVoiceCallSolo 库。
- path:表示 AlivcVoiceCallSolo 库的路径(相对 podfile 文件)。
- AlivcVoiceCallSolo 组件库目录说明,如下所示:
文件名 | 说明 |
AlivcVoiceCallSolo.podspec | 组件的描述文件。 |
AlivcVoiceCallSolo.bundle | 存放资源的 bundle。 |
AlivcVoiceCallChannelViewController | 首页。 |
AlivcVoiceCallChattingViewController | 聊天页。 |
AlivcDismissTransition | 转场动画。 |
AlivcPanInteractiveTransition | |
AlivcPresentTransition | |
AlivcVoiceCallSettingViewController | 设置页。 |
AlivcVideoCallUserAuthrization | 工具类。 |
NSBundle+AlivcVoiceCallSolo | |
UIViewController+Alert | |
AliBaseHttpClient | 网络请求。 |
AliRequestList |
- 功能实现。
- 创建并加入频道。
//实例化AliRtcEngine并设置代理。 _engine = [AliRtcEngine sharedInstance:self extras:@""]; //获取授权信息。 //AliRtcAuthInfo:各项参数均需要客户AppServer(客户的server端)通过OpenAPI来获取,然后AppServer下发至客户端,客户端将各项参数赋值后,即可joinChannel。 AuthInfo *authInfo = "从server端获取" [_engine joinChannel:authInfo name:name onResult:^(NSInteger errCode) { //加入频道回调处理 if (errCode == 0) { //加入房间成功 } else { //加入房间失败 } }];
- 离开频道。
//离开频道。 [self.engine leaveChannel]; //销毁SDK实例。 [AliRtcEngine destroy];
- 播放伴奏。
NSString *path = “文件的路径” NSString *url = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //预加载音效文件。 [self.engine preloadAudioEffectWithSoundId:soundId filePath:url]; //播放音效。 [self.engine playAudioEffectWithSoundId:soundId filePath:url cycles:1 publish:YES];
- 暂停伴奏。
[self.engine pauseAudioEffectWithSoundId:soundId];
- 停止伴奏。
[self.engine stopAudioEffectWithSoundId:soundId];
- 恢复播放伴奏。
[self.engine resumeAudioEffectWithSoundId:soundId];
- 静音模式。
[self.engine muteLocalMic:YES];
- 取消静音模式。
[self.engine muteLocalMic:NO];
- 开启扬声器。
[self.engine enableSpeakerphone:YES];
- 关闭扬声器。
[self.engine enableSpeakerphone:NO];
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。