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 代码库下载缓慢的问题,可通过安装加速插件等方式加速下载。
-
- 选择 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=*
- 设置 RTC 应用 AppId 和 AppKey,可参见步骤 获取 AppKey 和应用 ID。
-
- 运行服务,执行 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
集成Android端
开发前的环境要求如下表所示,详情请参见:
使用限制类别 | 说明 |
系统版本 | 支持 Android 4.1 及以上。 |
API 版本 | 不低于 16。 |
CPU 架构 | 支持真机架构 armeabi、armeabi-v7a、arm64-v8a (不支持模拟器 x86 架构)。 |
Android Studio 版本支持 | 支持 Android Studio3.0 及以上。下载 Android Studio |
您需要先集成服务端,具体操作,请参见
Demo 运行指引
说明 您在集成 Android 端时,如果遇到问题,或者 Demo 体验过程中出现无法创建房间或通话等问题,请参见
Android 端运行常见问题-
- Demo 源码中已经集成 AliRTC SDK(版本:1.17)。SDK 集成方式通过 Maven 集成。
- 源码压缩文件内分为 Server 端、Android 端、iOS 端三个文件。
- 若遇到 GitHub 代码库下载缓慢的问题,可通过安装加速插件等方式加速下载。
- 在 Android Studio 打开 Android 端工程。打开 Android Studio,单击 Open an existing Android Studio project 并选择 AliRTC-UserCase-VoiceCallSolution_1To1-master 目录下的 android 文件夹。
- 修改配置文件。
-
- 打开 Android Studio,在 Demo 中找到 android/AlivcVoiceCall/AlivcVoiceCall_demo/src/main/java/com/aliyun/rtc/voicecall/constant/Constant.java 文件。
- 修改文件中的
变量,如:BASE_URL
,部署到正式环境上建议绑定域名并使用:http://<服务器IP> :端口:8080/1v1-audio
。示例假设本地 IP 为 192.0.2.1,那么http://<域名>/1v1-audio
。本地 IP 查询,请参见 查询 IP 地址 注意BASE_URL="http://192.0.2.1:8080/1v1-audio"
-
-
- 不要使用 127.0.0.1 的 IP。
- 手机和搭建服务器的电脑处在一个局域网中。
-
-
- 使用手机端和电脑端浏览器验证。输入正确的 URL(
变量)地址,即可在浏览器中打开并看到:BASE_URL
。电脑端浏览器正确访问说明 IP 和端口号无误,手机端浏览器正确访问说明目前手机可以正常访问到服务器 IP。Hello RTC!
- 使用手机端和电脑端浏览器验证。输入正确的 URL(
- 选择一台已连接的真机设备。(暂不支持模拟器运行)将一台 Android 真机设备(需在系统设置中开启开发者模式和 USB 调试功能)使用数据线与电脑连接,在手机端同意调试后在 Android Studio 中选择接入的真机设备。
- 单击 build and run 按钮编译,Android 真机会安装并启动 1 对 1 语音聊天 App。
- 进行 1 对 1 语音聊天。
-
- 将 2 台真机移动端设备(Android 或 iOS)装上 Demo App。
- 将 2 台设备都连接到同一局域网下,保证可以连接到 Server 端。
- 在第一台真机上输入任意房间号,创建房间并等待对方加入。
- 在第二台真机上输入相同房间号加入房间并进行通话。
Demo 源码解析
- 项目结构说明。项目业务代码都封装在 AlivcVoiceCall 库里面,可以通过引用本地库的形式引用到项目中使用。项目名解释,如下所示:
-
- AlivcVoiceCall:功能实现库。
- AliyunVideoCommon:公共库。
- app:Demo 启动入口。
- thirdparty-lib:第三方库的引用。 UI 中存放 App 页面,constant 中存放常量数据,view 中存放自定义 view,network 中存放网络请求。
- 功能实现流程。
-
-
创建并加入房间。
注意 AliRtcEngieEventListener 回调在子线程中,如果您想操作 UI 界面需要切换到主线程。
-
//创建AliRtcEngin实例。
mEngine = AliRtcEngine.getInstance(getApplicationContext());
//设置AliRtcAuthInfo用户信息,通过Server Api获取到用户信息和RTC服务器的Token信息,拿到信息后
//设置给AliRtcAuthInfo就可以调用joinChannel加入频道进行通话。
AliRtcAuthInfo userInfo = “从server端获取”;
//调用joinChannel后在AliRtcEngieEventListener.onJoinChannelResult(int i)接受回调信息。
if (i != 0) {
//加入房间失败。
} else {
//加入房间成功。
}
-
- 用户推流。当用户加入房间成功时可以调用推流方法来发布自己的音频信息让对方订阅, 也可以在加入房间之前调用
来实现主动推流和订阅。mEngine.setAutoPublish(true, true);
- 用户推流。当用户加入房间成功时可以调用推流方法来发布自己的音频信息让对方订阅, 也可以在加入房间之前调用
//true表示允许发布音频流,false表示不允许。
mEngine.configLocalAudioPublish(true);
mEngine.publish();
-
- 播放伴奏。startAudioAccompany 方法只能播放一首歌,不支持多首同时播放 playAudioEffect 可以播放之前预加载的音效。两个方法可以同时调用,可以一边推送播放背景音效,一个本地试听。
//播放当前音效并推送。loopCycles=-1时代表循环播放。
mEngine.startAudioAccompany(mSelectedBgmData.first.getPath(), false, false, -1);
int i = mEngine.playAudioEffect(currBgm, file.getPath(), -1, false);
-
- 暂停伴奏。
mEngine.pauseAudioAccompany();
mEngine.pauseAudioEffect(soundId);
-
- 停止伴奏。
mEngine.pauseAudioAccompany();
mEngine.stopAudioEffect(currBgm);
-
- 恢复播放伴奏。
mEngine.resumeAudioAccompany();
mEngine.resumeAudioEffect(currBgm);
-
- 静音模式(停止发布本地音频流)。
mEngine.muteLocalMic(false);
-
- 取消静音模式(发布本地音频流)。
mEngine.muteLocalMic(true);
-
- 扬声器模式。
mEngine.enableSpeakerphone(true);
-
- 取消扬声器模式。
mEngine.enableSpeakerphone(false);
-
- 离开房间。
mEngine.leaveChannel();
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。