Android

业务流程

本节汇总了 在线娃娃机中一些常见的业务流程,帮助您更好地理解整个场景的实现过程。
在线娃娃机 TRTC 推流
在线娃娃机 RTMP 推流
下图展示了在线娃娃机 RTC Engine 推流的序列图,其中包含网络摄像头 RTC Engine 推流、用户拉流等流程。



下图展示了在线娃娃机 RTMP 推流的序列图,其中包含网络摄像头 RTMP 推流、用户拉流等流程。




接入准备

步骤1:开通服务

在线娃娃机场景通常需要依赖腾讯云 RTC Engine 付费 PaaS 服务构建。其中,RTC Engine 负责提供实时音视频互动能力。您可根据实际业务需求自由选择开通上述服务。
1. 登录 RTC Engine控制台 ,在应用页面单击创建应用,您可根据需要选择升级 RTC Engine 应用版本,例如旗舰版可解锁更多增值功能服务。

说明:
建议创建两个应用分别用于测试环境和生产环境,首次开通 RTC Engine 服务有免费 10000 分钟试用时长包。
RTC Engine 包月套餐(体验版、轻量版、标准版、专业版)可以解锁不同的增值功能服务,详情可见 包月套餐说明
2. 应用创建完毕之后,您可以在 应用 > 应用概览中看到该应用的基本信息,其中需要您保管好 SDKAppIDSDKSecretKey 便于后续使用,同时应避免密钥泄露造成流量盗刷。


步骤2:导入 SDK

RTC Engine SDK 已经发布到 mavenCentral 库,您可以通过配置 gradle 自动下载更新。
1. 在 dependencies 中添加合适版本 SDK 的依赖。
// RTC Engine 精简版 SDK, 包含 RTC和直播播放两项功能
dependencies {
implementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'
}
说明:
自动加载(aar)的方案需要确保您在 repositories 中添加了 mavenCentral 仓库。
2. 在 defaultConfig 中,指定 App 使用的 CPU 架构。
defaultConfig {
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}

步骤3:工程配置

1. 权限配置。
在 AndroidManifest.xml 中配置 App 权限,在线抓娃娃场景下 LiteAVSDK 需要以下权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus" />
注意:
请勿设置 android:hardwareAccelerated="false",关闭硬件加速之后,会导致对方的视频流无法渲染。
LiteAVSDK 没有内置权限申请逻辑,需要您自行声明相应的权限,部分权限(如存储、录音、相机等)还需要在运行时动态申请。
若 Android 项目 targetSdkVersion 为 31 或者目标设备涉及到 Android 12 及更高系统版本,官方要求需要在代码中动态申请 android.permission.BLUETOOTH_CONNECT 权限,以正常使用蓝牙功能,具体信息请参见 Android 官方说明
2. 混淆配置。
由于我们在 SDK 内部使用了 Java 的反射特性,需要您在 proguard-rules.pro 文件中将 SDK 相关类加入不混淆名单:
-keep class com.tencent.** { *; }

步骤4:鉴权与许可

UserSig 是腾讯云设计的一种安全保护签名,目的是为了阻止恶意攻击者盗用您的云服务使用权,RTC Engine 在进房时校验该鉴权凭证。
调试跑通阶段:可以通过 客户端示例代码控制台 两种方法计算生成 UserSig,仅用于调试测试。
正式运行阶段:推荐安全等级更高的服务端计算 UserSig 方案,防止客户端被逆向破解泄露密钥。
具体实现流程如下:
1. 您的 App 在调用 SDK 的初始化函数之前,首先要向您的服务器请求 UserSig。
2. 您的服务器根据 SDKAppID 和 UserID 计算 UserSig。
3. 服务器将计算好的 UserSig 返回给您的 App。
4. 您的 App 将获得的 UserSig 通过特定 API 传递给 SDK。
5. SDK 将 SDKAppID + UserID + UserSig 提交给腾讯云服务器进行校验。
6. 腾讯云校验 UserSig,确认合法性。
7. 校验通过后,会向 RTC Engine SDK 提供实时音视频服务。

注意:
调试跑通阶段的本地 UserSig 计算方式不推荐应用到线上环境,容易被逆向破解导致密钥泄露。
我们提供了多个语言版本(Java/GO/PHP/Nodejs/Python/C#/C++)的 UserSig 服务端计算源代码,详见 UserSig 计算源码

步骤5:初始化 SDK

// 创建 RTC Engine SDK 实例(单例模式)
TRTCCloud mTRTCCloud = TRTCCloud.sharedInstance(context);
// 设置事件监听器
mTRTCCloud.setListener(trtcSdkListener);

// 来自 SDK 的各类事件通知(比如:错误码,警告码,音视频状态参数等)
private TRTCCloudListener trtcSdkListener = new TRTCCloudListener() {
@Override
public void onError(int errCode, String errMsg, Bundle extraInfo) {
Log.d(TAG, errCode + errMsg);
}
@Override
public void onWarning(int warningCode, String warningMsg, Bundle extraInfo) {
Log.d(TAG, warningCode + warningMsg);
}
};

// 移除事件监听器
mTRTCCloud.setListener(null);
// 销毁 TRTC SDK 实例(单例模式)
TRTCCloud.destroySharedInstance();
说明:
建议监听 SDK 事件通知,对一些常见错误进行日志打印和处理,详请可参见 错误码表

步骤6:生成 RTMP 推流地址(RTMP 推流)

生成 RTMP 推流地址。
rtmp://intl-rtmp.rtc.qq.com/push/房间号?sdkappid=应用&userid=用户名&usersig=签名
主域名是 intl-rtmp.rtc.qq.com,备域名 rtmp.rtc-web.com,如果主域名解析有问题,可使用备域名。
RTMP appName 是 push。
地址中的房间号、应用、用户名、签名需要换成业务的。
为简化参数,只支持字符串房间号,不超过64个字符,字符只能是数字、字母、下划线。
注意:
RTC Engine 其他端如果要观看 RTMP 流,请使用字符串房间号进房
UserSig 的生成规则,请参见 UserSig 相关请注意签名要在有效期内)。
示例:
rtmp://intl-rtmp.rtc.qq.com/push/hello-string-room?sdkappid=140**66&userid=rtmp2&usersig=eJw1jdERBZ8qKGRj8Yp-wVbvmGMVZqS7w-mMDQL

接入过程

API 时序图





步骤1:娃娃机推流

RTC Engine 推流

1. 通过 客户端示例代码控制台 两种方法计算生成 UserSig。
2. 将 SdkAppid、UserId、UserSig、RoomId 等信息配置到 RTC Engine 网络摄像头或推流盒上开启推流。
注意:
RTC Engine 房间号分为数字类型 roomId 和字符串类型 strRoomId,两种类型的房间不互通,建议统一房间号类型。
RTC Engine 用户角色分为主播和听众,只有主播才有推流权限,进房时需指定用户角色,如未指定则默认为主播角色。
在线娃娃机场景下,进房模式建议选用 TRTC_APP_SCENE_VIDEOCALL,这样延迟更低。

RTMP 推流

1. 通过 RTMP 地址生成器 生成 RTMP 推流地址。



2. 将 RTMP 推流地址配置到 RTMP 网络摄像头或推流盒上开启推流。

步骤2:用户进房拉流

1. 用户进入 RTC Engine 房间。
public void enterRoomByAudience(String roomId, String userId) {
TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();
// 以字符串房间号为例
params.strRoomId = roomId;
params.userId = userId;
// 从业务后台获取到的 UserSig
params.userSig = getUserSig(userId);
// 替换成您的 SDKAppID
params.sdkAppId = SDKAppID;
mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);
}

// 进房结果事件回调
@Override
public void onEnterRoom(long result) {
if (result > 0) {
// result 代表加入房间所消耗的时间(毫秒)
Log.d(TAG, "Enter room succeed");
} else {
// result 代表进房失败的错误码
Log.d(TAG, "Enter room failed");
}
}
2. 用户订阅主播音视频流。
@Override
public void onUserAudioAvailable(String userId, boolean available) {
// 某远端用户发布/取消了自己的音频
// 在自动订阅模式下,您无需做任何操作,SDK 会自动播放远端用户音频
}

@Override
public void onUserVideoAvailable(String userId, boolean available) {
// 某远端用户发布/取消了主路视频画面
if (available) {
// 订阅远端用户的视频流,并绑定视频渲染控件
mTRTCCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, TXCloudVideoView view);
} else {
// 停止订阅远端用户的视频流,并释放渲染控件
mTRTCCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
}
}
3. 观众设置远端画面的渲染模式(可选项)。
TRTCCloudDef.TRTCRenderParams params = new TRTCCloudDef.TRTCRenderParams();
params.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_AUTO; // 画面镜像模式
params.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL; // 画面填充模式
params.rotation = TRTCCloudDef.TRTC_VIDEO_ROTATION_0; // 画面旋转角度
// 设置远端画面的渲染模式
mTRTCCloud.setRemoteRenderParams(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, params)

步骤3:用户退出房间

1. 用户退出房间。
public void exitRoom() {
mTRTCCloud.stopLocalAudio();
mTRTCCloud.stopLocalPreview();
mTRTCCloud.exitRoom();
}

// 离开房间事件回调
@Override
public void onExitRoom(int reason) {
if (reason == 0) {
Log.d(TAG, "主动调用 exitRoom 退出房间");
} else if (reason == 1) {
Log.d(TAG, "被服务器踢出当前房间");
} else if (reason == 2) {
Log.d(TAG, "当前房间整个被解散");
}
}
注意:
待 SDK 占用的所有资源释放完毕后,SDK 会抛出 onExitRoom 回调通知到您。
如果您要再次调用 enterRoom 或者切换到其他音视频 SDK,请等待 onExitRoom 回调之后再执行相关操作。否则可能会遇到例如摄像头、麦克风设备被强占等各种异常问题。
2. 解散房间。
服务端解散房间
RTC Engine 提供了服务端解散数字类型房间 API DismissRoom,以及解散字符串类型房间 API DismissRoomByStrRoomId,您可以通过调用服务端解散房间接口把房间内所有用户从房间移出,并解散房间。
客户端解散房间
客户端没有直接解散房间的 API,需要各个客户端调用 exitRoom 退出房间,当房间内的所有主播和观众完成退房后,根据 RTC Engine 房间生命周期规则,房间将会自动解散,详情请参见 RTC Engine 退出房间

异常处理

异常错误处理

RTC Engine SDK 遇到不可恢复的错误会在 onError 回调中抛出,详见 RTC Engine 错误码表
1. UserSig 相关。
UserSig 校验失败会导致进房失败,您可参考 UserSig 生成与校验 进行校验。
枚举
取值
描述
ERR_TRTC_INVALID_USER_SIG
-3320
进房参数 UserSig 不正确,请检查 TRTCParams.userSig 是否为空。
ERR_TRTC_USER_SIG_CHECK_FAILED
-100018
UserSig 校验失败,请检查参数 TRTCParams.userSig 是否填写正确或已经过期。
2. 进退房相关。
进房失败请先检查进房参数是否正确,且进退房接口必须成对调用,即便进房失败也需要调用退房接口。
枚举
取值
描述
ERR_TRTC_CONNECT_SERVER_TIMEOUT
-3308
请求进房超时,请检查是否断网或者是否开启 VPN,您也可以切换4G进行测试。
ERR_TRTC_INVALID_SDK_APPID
-3317
进房参数 sdkAppId 错误,请检查 TRTCParams.sdkAppId 是否为空
ERR_TRTC_INVALID_ROOM_ID
-3318
进房参数 roomId 错误,请检查 TRTCParams.roomIdTRTCParams.strRoomId 是否为空,注意 roomId 和 strRoomId 不可混用。
ERR_TRTC_INVALID_USER_ID
-3319
进房参数 userId 不正确,请检查 TRTCParams.userId 是否为空。
ERR_TRTC_ENTER_ROOM_REFUSED
-3340
进房请求被拒绝,请检查是否连续调用 enterRoom 进入相同 Id 的房间。
3. 设备相关。
可监听设备相关错误,在出现相关错误时 UI 提示用户。
枚举
取值
描述
ERR_CAMERA_START_FAIL
-1301
打开摄像头失败,例如在 Windows 或 Mac 设备,摄像头的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序。
ERR_MIC_START_FAIL
-1302
打开麦克风失败,例如在 Windows 或 Mac 设备,麦克风的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序。
ERR_CAMERA_NOT_AUTHORIZED
-1314
摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了。
ERR_MIC_NOT_AUTHORIZED
-1317
麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了。
ERR_CAMERA_OCCUPY
-1316
摄像头正在被占用中,可尝试打开其他摄像头。
ERR_MIC_OCCUPY
-1319
麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败。

观众拉流黑屏

在 RTMP 娃娃机推流的场景中,使用了 RTMP 推流进入 RTC Engine 房间的功能,并且推流操作成功。但是,在 RTC Engine 的房间内无法正常拉流。经过问题定位,发现是因为推流配置中包含了 B 帧,而 RTC Engine 的房间不支持包含 B 帧的场景,这导致无法拉取 RTMP 推流。推流配置参考如下:


观众拉流画面卡住/拉流出现第三方画面

在娃娃机场景中,当 RTC Engine 观众进入房间并拉流一段时间后,便会自动遇到拉流卡住问题,尤其在多次触发 peer-join 或 onUserVideoAvailable 回调后,观众拉流的画面会停留在最后一帧不动。遇到这种情况时,可以首先访问仪表盘查看详细的通话信息。如果仪表盘显示的特征表明主播多次进出房间,那么可以基本确认问题是由于互踢导致的,仪表盘特征如下。

解决方案:可以尝试关闭当前机器的推流来解决问题。如果问题仍未解决,那么请检查同一台机器上是否配置了两个相同的推流地址。