Android

业务流程

本节汇总了电商直播场景中一些常见的业务流程,帮助您更好地理解整个场景的实现流程。
主播开播及关播
主播跨房 PK 连麦
RTC 观众进房连麦
带货商品管理
下图展示了主播(房主)本地预览、创建房间、进房开播、退房关播的流程。



下图展示了主播 A 邀请主播 B 进行跨房 PK 连麦的流程。跨房 PK 过程中,两个房间内的观众都可以看到两个房主 PK 连麦直播的画面。



下图展示了 RTC 实时互动直播间观众进入房间、申请连麦、结束连麦、退出房间的流程。



下图展示了直播带货场景中主播编辑、上架商品,观众浏览、购买商品的流程。




接入准备

步骤一:开通服务

电商直播场景通常需要依赖 RTC Engine美颜 AR播放器 SDK 等付费 PaaS 服务构建。其中,RTC Engine 负责提供实时音视频互动能力,美颜 AR 负责提供美颜特效能力,播放器负责提供直播和点播播放能力。您可根据实际业务需求自由选择开通上述服务。
开通 RTC Engine 服务
开通美颜 AR 服务
开通播放器服务
1. 首先,您需要登录 RTC Engine 控制台 创建应用,您可根据需要选择升级 RTC Engine 应用版本,例如专业版可解锁更多增值功能服务。



说明:
建议创建两个应用分别用于测试环境和生产环境,一年内每个腾讯云账号(UIN)每月赠送10,000分钟免费时长。
RTC Engine 包月套餐分为体验版(默认)、轻量版、标准版、专业版,可解锁不同的增值功能服务,详情可见 版本功能与包月套餐说明
2. 应用创建完毕之后,您可以在应用管理-应用概览栏目看到该应用的基本信息,其中需要您保管好 SDKAppIDSDKSecretKey 便于后续使用,同时应避免密钥泄露造成流量盗刷。

1. 登录 美颜 AR 控制台 > 移动端 License,单击新建测试 License(测试版 License 免费测试有效期为14天,可续期1次,共28天)。选择移动,并根据实际需要填写 App Name、Package Name 和 Bundle ID。勾选您想试用的功能:所有美颜功能虚拟背景人脸识别手势识别礼物动画特效,然后单击确认

2. 激活后,您可以在当前页面查看您的信息,并参考上方集成指南进行集成。可在 集成指南 中查看 License Key 和 License URL 如何使用。

1. 登录 云点播控制台云直播控制台 > License 管理 > 移动端 License,单击新建测试 License



2. 根据实际需求填写 App NamePackage NameBundle ID,选择播放器高级版,单击创建



3. 测试版 License 成功创建后,页面会显示生成的 License 信息。在 SDK 初始化配置时需要传入 License Key 和 License URL 两个参数,请妥善保存以下信息。



注意:
同一应用的 License URL 和 Key 唯一,测试版 License 升级为正式版后 License URL 和 Key 不变。

步骤二:导入 SDK

RTC Engine SDK、美颜 AR SDK、播放器 SDK 均已经发布到 mavenCentral 库,您可以通过配置 gradle 自动下载更新。
1. 在 dependencies 中添加合适版本 SDK 的依赖。
dependencies {
// 全功能版 SDK, 包含 RTC Engine、直播、短视频、播放器等多项功能
implementation 'com.tencent.liteav:LiteAVSDK_Professional:latest.release'
// 美颜 AR SDK 例如: S1-07套餐如下
implementation 'com.tencent.mediacloud:TencentEffect_S1-07:latest.release'
}
说明:
除了推荐的自动加载方式,您还可以选择下载 SDK 并手动导入,详见 手动集成 RTC Engine SDK手动集成美颜 AR SDK
电商直播场景的实现通常需要依赖 RTC Engine、播放器等多项能力的组合,为避免单独集成的符号冲突问题,推荐您集成全功能版 SDK
2. 在 defaultConfig 中,指定 App 使用的 CPU 架构。
defaultConfig {
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
说明:
LiteAVSDK 全功能版支持 armeabi-v7a/arm64-v8a/x86/x86_64 架构,美颜 AR SDK 仅支持 armeabi-v7a/arm64-v8a 架构。
3. 单击 Sync Now,自动下载 SDK 并集成到工程里。如果您的美颜 AR套餐包含动效和滤镜功能,那么您需要在 SDK 下载页面 下载对应的套餐包,将包内免费的滤镜素材(./assets/lut)和贴纸动效(./MotionRes)解压并放置在您工程下的如下目录:
动效:../assets/MotionRes
滤镜:../assets/lut

步骤三:工程配置

1. 权限配置。在 AndroidManifest.xml 中配置 App 权限,电商直播场景下 RTC Engine 及美颜 AR SDK 需要以下权限:
<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",关闭硬件加速之后,会导致对方的视频流无法渲染。
RTC Engine SDK 没有内置权限申请逻辑,需要您自行声明相应的权限,部分权限(如存储、录音、相机等)还需要在运行时动态申请。
若 Android 项目 targetSdkVersion 为 31 或者目标设备涉及到 Android 12 及更高系统版本,官方要求需要在代码中动态申请 android.permission.BLUETOOTH_CONNECT 权限,以正常使用蓝牙功能,具体信息请参见 蓝牙权限
2. 混淆配置。由于我们在 SDK 内部使用了 Java 的反射特性,需要您在 proguard-rules.pro 文件中将 SDK 相关类加入不混淆名单。
-keep class com.tencent.** { *; }
-keep class org.light.** { *;}
-keep class org.libpag.** { *;}
-keep class org.extra.** { *;}
-keep class com.gyailib.**{ *;}
-keep class androidx.exifinterface.** { *;}

步骤四:鉴权与许可

RTC Engine 鉴权凭证
美颜 AR 鉴权许可
播放器鉴权许可
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/Node.js/Python/C#/C++)的 UserSig 服务端计算源代码,详见 服务端计算 UserSig.
使用美颜 AR 之前,需要向腾讯云校验许可凭证。设置 License 需要用到 License Key 和 License URL,示例代码如下。
import com.tencent.xmagic.telicense.TELicenseCheck;

// 如果仅仅是为了触发下载或更新 License,而不关心鉴权结果,则第4个参数传入 null
TELicenseCheck.getInstance().setTELicense(context, URL, KEY, new TELicenseCheck.TELicenseCheckListener() {
@Override
public void onLicenseCheckFinish(int errorCode, String msg) {
// 注意:此回调不一定在调用线程
if (errorCode == TELicenseCheck.ERROR_OK) {
// 鉴权成功
} else {
// 鉴权失败
}

}
});
注意:
建议在相关业务模块的初始化代码中触发鉴权许可,避免在使用前才临时去下载 License,同时鉴权时应具有网络权限。
实际应用的包名必须和创建 License 时绑定的 Package Name 完全匹配,否则会导致 License 校验失败,详情可参见 鉴权错误码
直播播放、点播播放功能需要配置播放器 License 授权后方可播放成功,否则将播放失败(黑屏),全局仅需设置一次即可。若您暂未获取 License,可 免费申请测试版 License 以正常播放,正式版 License 需 购买。申请 License 成功后,您将获得两个字符串:License URL License Key
在您的 App 调用 SDK 相关功能之前,需进行如下配置(建议在 Application 类配置):
public class MApplication extends Application {
public void onCreate() {
super.onCreate();
String licenceURL = ""; // 获取到的 licence url
String licenceKey = ""; // 获取到的 licence key
TXLiveBase.getInstance().setLicence(appContext, licenceURL, licenceKey);
TXLiveBase.setListener(new TXLiveBaseListener() {
@Override
public void onLicenceLoaded(int result, String reason) {
Log.i(TAG, "onLicenceLoaded: result:" + result + ", reason:" + reason);
if (result != 0) {
// 如果 result 不为 0,表示设置失败,需要进行重试
TXLiveBase.getInstance().setLicence(appContext, licenceURL, licenceKey);
}
}
});
}
}
License 设置成功后(需稍等一段时间,具体时间长短依据网络情况而定),您可以通过调用如下方法查看 License 信息:
TXLiveBase.getInstance().getLicenceInfo();
注意:
实际应用的包名必须和创建 License 时绑定的 Package Name 完全匹配,否则会导致 License 校验失败。
License 是强线上检验逻辑,应用首次启动后调用 TXLiveBase#setLicence 时,需确保网络可用。 在App首次启动时,可能还没有授权联网权限,则需要等授予联网权限后,再次调用 TXLiveBase#setLicence 。
监听 TXLiveBase#setLicence 加载结果:onLicenceLoaded 接口,如果失败要根据实际情况做对应重试及引导,如果多次失败后,可以限频,并业务辅以产品弹窗等引导,让用户检查网络情况。
TXLiveBase#setLicence 可以多次调用,建议在进入 App 主界面时调用 TXLiveBase#setLicence, 确保加载成功。
对于多进程的 App, 确保每个使用播放器的进程启动时,都调用了 TXLiveBase#setLicence。例如: Android 端使用独立进程播放视频的 App, 后台播放时进程被系统 kill 掉重启时,也要调用 TXLiveBase#setLicence。

步骤五:初始化 SDK

初始化 RTC Engine SDK
初始化美颜 AR SDK
初始化播放器 SDK
// 创建 RTC Engine SDK 实例(单例模式)
TRTCCloud mTRTCCloud = TRTCCloud.sharedInstance(context);
// 设置事件监听器
mTRTCCloud.addListener(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.removeListener(trtcSdkListener);
// 销毁 RTC Engine SDK 实例(单例模式)
TRTCCloud.destroySharedInstance();
说明:
建议监听 SDK 事件通知,对一些常见错误进行日志打印和处理,详情可参见 错误码表
import com.tencent.xmagic.XmagicApi;

// 初始化美颜 AR SDK
XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());

// 开发调试时,可以把日志级别设置为DEBUG,发布包请设置为 WARN,否则会影响性能
mXmagicApi.setXmagicLogLevel(Log.WARN);

// 释放美颜 AR SDK,此方法需要在 GL 线程中调用
mXmagicApi.onDestroy();
说明:
初始化美颜 AR SDK 之前,还需进行资源拷贝等准备工作,详细步骤可参考 美颜 AR SDK 使用流程
点播播放场景 SDK 初始化。
// 设置 SDK 接入环境(若您服务全球用户,配置 SDK 接入环境为全球接入环境)
TXLiveBase.setGlobalEnv("GDPR");

// 创建 Player 对象
TXVodPlayer mVodPlayer = new TXVodPlayer(mContext);

// 添加用于视频渲染的 View 控件
TXCloudVideoView mPlayerView = findViewById(R.id.video_view);
// 关联 Player 对象与 View 控件
mVodPlayer.setPlayerView(mPlayerView);

// 播放器参数配置
TXVodPlayConfig config = new TXVodPlayConfig();
config.setEnableAccurateSeek(true); // 设置是否精确 seek,默认 true
config.setMaxCacheItems(5); // 设置缓存文件个数为 5
config.setProgressInterval(200); // 设置进度回调间隔,单位毫秒
config.setMaxBufferSize(50); // 最大预加载大小,单位 MB
mVodPlayer.setConfig(config); // 把 config 传给 mVodPlayer

// 播放器事件监听
mVodPlayer.setVodListener(new ITXVodPlayListener() {
@Override
public void onPlayEvent(TXVodPlayer player, int event, Bundle param) {
// 事件通知
}

@Override
public void onNetStatus(TXVodPlayer player, Bundle bundle) {
// 状态反馈
}
});
直播播放场景 SDK 初始化。
// 需要提前添加用于视频渲染的 TXCloudVideoView
TXCloudVideoView mRenderView = findViewById(R.id.video_view);
// 创建 Player 对象
V2TXLivePlayer mLivePlayer = new V2TXLivePlayerImpl(mContext);
// 关联 Player 对象与视频渲染 view
mLivePlayer.setRenderView(mRenderView);

// 播放器事件监听
mLivePlayer.setObserver(new V2TXLivePlayerObserver() {
@Override
public void onVideoLoading(V2TXLivePlayer player, Bundle extraInfo) {
// 视频加载事件
}
@Override
public void onVideoPlaying(V2TXLivePlayer player, boolean firstPlay, Bundle extraInfo) {
// 视频播放事件
}
});

接入过程

API 时序图





步骤一:主播进房推流

RTC Engine SDK 用于承载视频画面的控件只支持传入 TXCloudVideoView 类型,因此您需要先在布局文件中定义视图渲染控件。
<com.tencent.rtmp.ui.TXCloudVideoView
android:id="@+id/live_cloud_view_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
注意:
如果您需要指定使用 TextureViewSurfaceView 作为视图渲染控件,请参照 高级功能-视图渲染控件
1. 主播进房前开启本地视频预览及音频采集。
// 获取用于展示主播本地画面预览的视频渲染控件
TXCloudVideoView mTxcvvAnchorPreviewView = findViewById(R.id.live_cloud_view_main);

// 设置视频编码参数,决定远端用户看到的画面质量
TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();
encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_960_540;
encParam.videoFps = 15;
encParam.videoBitrate = 1300;
encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
mTRTCCloud.setVideoEncoderParam(encParam);

// boolean mIsFrontCamera 可指定使用前置/后置摄像头进行视频采集
mTRTCCloud.startLocalPreview(mIsFrontCamera, mTxcvvAnchorPreviewView);

// 这里可指定声音音质,从低到高分别为 SPEECH/DEFAULT/MUSIC
mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
注意:
您可根据业务需求自行设置视频编码参数 TRTCVideoEncParam,各档位最佳分辨率和码率搭配详见 分辨率码率参照表
enterRoom 之前调用以上接口,SDK 只会开启摄像头预览和音频采集,并一直等到您调用 enterRoom 之后才开始推流。
enterRoom 之后调用以上接口,SDK 会开启摄像头预览和音频采集,并自动开始推流。
2. 主播设置本地画面的渲染参数,以及编码器输出画面模式(可选项)。
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.setLocalRenderParams(params);

// 设置编码器输出的画面镜像模式
mTRTCCloud.setVideoEncoderMirror(boolean mirror);
// 设置视频编码器输出的画面方向
mTRTCCloud.setVideoEncoderRotation(int rotation);
注意:
设置本地画面渲染参数仅影响本地画面的渲染效果。
设置编码器输出模式会影响房间中其他用户所观看到(以及云端录制文件)的画面效果。
3. 主播正式开始直播,进房推流。
public void enterRoomByAnchor(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;
// 指定主播角色
params.role = TRTCCloudDef.TRTCRoleAnchor;
// 以互动直播场景进房
mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_LIVE);
}

// 进房结果事件回调
@Override
public void onEnterRoom(long result) {
if (result > 0) {
// result 代表加入房间所消耗的时间(毫秒)
Log.d(TAG, "Enter room succeed");
} else {
// result 代表进房失败的错误码
Log.d(TAG, "Enter room failed");
}
}
注意:
RTC Engine 房间号分为数字类型 roomId 和字符串类型 strRoomId,两种类型的房间不互通,建议统一房间号类型。
RTC Engine 用户角色分为主播和听众,只有主播才有推流权限,进房时需指定用户角色,如未指定则默认为主播角色。
电商直播场景下,进房模式建议选用 TRTC_APP_SCENE_LIVE

步骤二:观众进房拉流

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;
// 指定观众角色
params.role = TRTCCloudDef.TRTCRoleAudience;
// 以互动直播场景进房
mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_LIVE);
}

// 进房结果事件回调
@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)

步骤三:观众连麦互动

1. 观众切换为主播角色。
// 切换为主播角色
mTRTCCloud.switchRole(TRTCCloudDef.TRTCRoleAnchor);

// 切换角色事件回调
@Override
public void onSwitchRole(int errCode, String errMsg) {
if (errCode == TXLiteAVCode.ERR_NULL) {
// 切换角色成功
}
}
2. 观众开始本地音视频采集和推流。
// 获取用于展示连麦观众本地画面预览的视频渲染控件
TXCloudVideoView mTxcvvAudiencePreviewView = findViewById(R.id.live_cloud_view_sub);

// 设置视频编码参数,决定远端用户看到的画面质量
TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();
encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_480_270;
encParam.videoFps = 15;
encParam.videoBitrate = 550;
encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
mTRTCCloud.setVideoEncoderParam(encParam);

// boolean mIsFrontCamera 可指定使用前置/后置摄像头进行视频采集
mTRTCCloud.startLocalPreview(mIsFrontCamera, mTxcvvAudiencePreviewView);

// 这里可指定声音音质,从低到高分别为 SPEECH/DEFAULT/MUSIC
mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
注意:
您可根据业务需求自行设置视频编码参数 TRTCVideoEncParam,各档位最佳分辨率和码率搭配详见 分辨率码率参照表
3. 观众下麦停止推流。
// 切换为观众角色
mTRTCCloud.switchRole(TRTCCloudDef.TRTCRoleAudience);

// 切换角色事件回调
@Override
public void onSwitchRole(int errCode, String errMsg) {
if (errCode == TXLiteAVCode.ERR_NULL) {
// 停止摄像头采集推流
mTRTCCloud.stopLocalPreview();
// 停止麦克风采集推流
mTRTCCloud.stopLocalAudio();
}
}

步骤四:退出与解散房间

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 退出房间
注意:
当一次直播结束之后,建议您调用服务端解散房间 API 确保房间被解散,防止因部分用户未如期退房导致房间存续,从而产生非期望的费用。

高级功能

商品信息弹窗

商品信息弹窗功能可以通过 Chat 自定义消息 实现,也可以通过 SEI 信息 实现,下面将分别介绍这两种实现方式。

自定义消息

自定义消息需要依赖腾讯云 Chat 的能力,您需提前开通服务并导入 Chat SDK,详细指引请参考 语聊房接入指引-接入准备
1. 发送自定义消息。
方式一:主播在客户端发送商品弹窗相关的群组自定义消息。
// 构造商品弹窗消息体
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("cmd", "item_popup_msg");
JSONObject msgJsonObject = new JSONObject();
msgJsonObject.put("itemNumber", 1); // 商品编号
msgJsonObject.put("itemPrice", 199.0); // 商品价格
msgJsonObject.put("itemTitle", "xxx"); // 商品标题
msgJsonObject.put("itemUrl", "xxx"); // 商品图片地址
jsonObject.put("msg", msgJsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
String data = jsonObject.toString();

// 发送群自定义消息(商品弹窗消息建议设置为高优先级)
V2TIMManager.getInstance().sendGroupCustomMessage(data.getBytes(), mRoomId,
V2TIMMessage.V2TIM_PRIORITY_HIGH, new V2TIMValueCallback<V2TIMMessage>() {
@Override
public void onError(int i, String s) {
// 发送商品弹窗消息失败
}

@Override
public void onSuccess(V2TIMMessage v2TIMMessage) {
// 发送商品弹窗消息成功
// 本地渲染商品弹窗效果
}
});
方式二:后台运营在服务端发送商品弹窗相关的群组自定义消息。
请求 URL 示例:
https://xxxxxx/v4/group_open_http_svc/send_group_msg?sdkappid=88888888&identifier=admin&usersig=xxx&random=99999999&contenttype=json
请求包体示例:
{
"GroupId": "@TGS#12DEVUDHQ",
"Random": 2784275388,
"MsgPriority": "High", // 消息的优先级,商品弹窗消息建议设置为高优先级
"MsgBody": [
{
"MsgType": "TIMCustomElem",
"MsgContent": {
// itemNumber: 商品编号; itemPrice: 商品价格; itemTitel: 商品标题; itemUrl: 商品图片地址
"Data": "{\"cmd\": \"item_popup_msg\", \"msg\": {\"itemNumber\": 1, \"itemPrice\": 199.0, \"itemTitle\": \"xxx\", \"itemUrl\": \"xxx\"}}"
}
}
]
}
2. 接收自定义消息。
房间内其他用户客户端收到群自定义消息回调,然后进行消息解析和商品弹窗效果渲染。
// 收到群自定义消息
V2TIMManager.getInstance().addSimpleMsgListener(new V2TIMSimpleMsgListener() {
@Override
public void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {
String customStr = new String(customData);
if (!customStr.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(customStr);
String command = jsonObject.getString("cmd");
JSONObject messageJsonObject = jsonObject.getJSONObject("msg");
if (command.equals("item_popup_msg")) {
int itemNumber = messageJsonObject.getInt("itemNumber"); // 商品编号
double itemPrice = messageJsonObject.getDouble("itemPrice"); // 商品价格
String itemTitle = messageJsonObject.getString("itemTitle"); // 商品标题
String itemUrl = messageJsonObject.getString("itemUrl"); // 商品图片地址
// 根据商品编号、商品价格、商品标题、商品图片地址渲染商品弹窗效果
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});

SEI 信息

SEI 信息会插入到主播视频流中进行传输,能够实现商品信息弹窗和主播直播画面的精准同步。
1. 发送 SEI 信息。
主播在 RTC Engine 客户端发送商品弹窗相关的 SEI 消息。
// 构造商品弹窗消息体
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("cmd", "item_popup_msg");
JSONObject msgJsonObject = new JSONObject();
msgJsonObject.put("itemNumber", 1); // 商品编号
msgJsonObject.put("itemPrice", 199.0); // 商品价格
msgJsonObject.put("itemTitle", "xxx"); // 商品标题
msgJsonObject.put("itemUrl", "xxx"); // 商品图片地址
jsonObject.put("msg", msgJsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
String data = jsonObject.toString();

// 发送 SEI 信息
mTRTCCloud.sendSEIMsg(data.getBytes(), 1);
2. 接收 SEI 信息。
观众在 RTC Engine 客户端接收 SEI 消息,然后进行消息解析和商品弹窗效果渲染。
mTRTCCloud.setListener(new TRTCCloudListener() {
@Override
public void onRecvSEIMsg(String userId, byte[] data) {
String dataStr = new String(data);
if (!dataStr.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(dataStr);
String command = jsonObject.getString("cmd");
JSONObject messageJsonObject = jsonObject.getJSONObject("msg");
if (command.equals("item_popup_msg")) {
int itemNumber = messageJsonObject.getInt("itemNumber"); // 商品编号
double itemPrice = messageJsonObject.getDouble("itemPrice"); // 商品价格
String itemTitle = messageJsonObject.getString("itemTitle"); // 商品标题
String itemUrl = messageJsonObject.getString("itemUrl"); // 商品图片地址
// 根据商品编号、商品价格、商品标题、商品图片地址渲染商品弹窗效果
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});

商品讲解回放

通过播放提前录制好的商品讲解视频,实现商品讲解回放功能。
首先需要进行 播放器初始化,然后开始播放录制视频。TXVodPlayer 支持两种播放模式,您可以根据需要自行选择:
通过 URL 方式
通过 FileId 方式
// 播放 URL 视频资源
String url = "http://1252463788.vod2.myqcloud.com/xxxxx/v.f20.mp4";
mVodPlayer.startVodPlay(url);

// 播放本地视频资源
String localFile = "/sdcard/video.mp4";
mVodPlayer.startVodPlay(localFile);
// 推荐使用下面的新接口
// psign 即播放器签名,签名介绍和生成方式参见链接:https://cloud.tencent.com/document/product/266/42436
TXPlayInfoParams playInfoParam = new TXPlayInfoParams(1252463788, // 腾讯云账户的appId
"4564972819220421305", // 视频的fileId
"psignxxxxxxx"); // 播放器签名
mVodPlayer.startVodPlay(playInfoParam);

// 旧接口,不推荐使用
TXPlayerAuthBuilder authBuilder = new TXPlayerAuthBuilder();
authBuilder.setAppId(1252463788);
authBuilder.setFileId("4564972819220421305");
mVodPlayer.startVodPlay(authBuilder);
播放控制:调整进度、暂停播放、恢复播放、结束播放。
// 调整进度(秒)
mVodPlayer.seek(time);

// 暂停播放
mVodPlayer.pause();

// 恢复播放
mVodPlayer.resume();

// 结束播放(清除最后一帧画面)
mVodPlayer.stopPlay(true);
注意:
结束播放时记得销毁 View 控件,尤其是在下次 startVodPlay 之前,否则会产生大量的内存泄漏以及闪屏问题。
同时,在退出播放界面时,记得一定要调用渲染 View 的 onDestroy() 函数,否则可能会产生内存泄漏和“Receiver not registered”警告。
@Override
public void onDestroy() {
super.onDestroy();
mVodPlayer.stopPlay(true); // true 代表清除最后一帧画面
mPlayerView.onDestroy();
}

跨房 PK 连麦

1. 任意一方发起跨房 PK 连麦。
public void connectOtherRoom(String roomId, String userId) {
try {
JSONObject jsonObj = new JSONObject();
// 数字房间号为 roomId
jsonObj.put("strRoomId", roomId);
jsonObj.put("userId", userId);
mTRTCCloud.ConnectOtherRoom(jsonObj.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}

// 请求跨房连麦的结果回调
@Override
public void onConnectOtherRoom(String userId, int errCode, String errMsg) {
// 要跨房通话的另一个房间中的主播的用户 ID
// 错误码,ERR_NULL 代表请求成功
// 错误信息
}
注意:
跨房 PK 连麦的本地用户和对端用户必须都为主播角色,且必须都有音频/视频上行。
可通过多次调用 ConnectOtherRoom() 来实现与多个房间主播跨房连麦,目前限制一个房间最多可以和其他三个房间的主播跨房连麦,一个房间中最多10个主播可与其他房间的主播跨房连麦。
2. 两个房间中的所有用户都会收到来自另一个房间中的 PK 主播的音视频流可用回调。
@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. 任意一方退出跨房 PK 连麦。
// 退出跨房连麦
mTRTCCloud.DisconnectOtherRoom();

// 退出跨房连麦的结果回调
@Override
public void onDisConnectOtherRoom(int errCode, String errMsg) {
super.onDisConnectOtherRoom(errCode, errMsg);
}
注意:
调用 DisconnectOtherRoom() 后,即退出与所有其他房间主播的跨房 PK 连麦。
跨房 PK 连麦的发起端和接收端任意一端均可调用 DisconnectOtherRoom() 退出跨房 PK 连麦。

第三方美颜接入

RTC Engine 支持接入第三方美颜产品,下面以美颜 AR为例,展示第三方美颜接入流程。
1. 集成美颜 AR SDK、申请授权 License,详情请参照 接入准备 步骤实现。
2. 资源拷贝(如有)。如果您的资源文件是内置在 assets 目录的,那么使用前需要 copy 到 App 的私有目录。
XmagicResParser.setResPath(new File(getFilesDir(), "xmagic").getAbsolutePath());
//loading

//copy资源文件到私有目录,只需要做一次
XmagicResParser.copyRes(getApplicationContext());
如果您的资源文件是从 网络动态下载 的,下载成功后,需要设置资源文件路径。
XmagicResParser.setResPath(下载的资源文件本地路径);
3. 设置第三方美颜的视频数据回调,将美颜 AR SDK 处理每帧数据结果传入 RTC Engine SDK 内部做渲染处理。
mTRTCCloud.setLocalVideoProcessListener(TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D, TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE, new TRTCCloudListener.TRTCVideoFrameListener() {
@Override
public void onGLContextCreated() {
// SDK 内部 OpenGL 环境已经创建,此时可进行第三方美颜的初始化工作
if (mXmagicApi == null) {
XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());
} else {
mXmagicApi.onResume();
}
}

@Override
public int onProcessVideoFrame(TRTCCloudDef.TRTCVideoFrame srcFrame, TRTCCloudDef.TRTCVideoFrame dstFrame) {
// 用于对接第三方美颜组件的视频处理回调
if (mXmagicApi != null) {
dstFrame.texture.textureId = mXmagicApi.process(srcFrame.texture.textureId, srcFrame.width, srcFrame.height);
}
return 0;
}

@Override
public void onGLContextDestory() {
// SDK 内部 OpenGL 环境被销毁,此时可进行第三方美颜的资源销毁工作
mXmagicApi.onDestroy();
}
});
注意:
步骤1、步骤2根据不同的第三方美颜产品实现方式有所不同,而步骤3是 RTC Engine 集成第三方美颜的通用且重要步骤

双路编码模式

开启双路编码模式后,当前用户的编码器会同时输出【高清大画面】和【低清小画面】两路视频流(但只有一路音频流)。这样,房间中的其他用户就可以根据自身的网络情况或屏幕大小选择订阅【高清大画面】或是【低清小画面】。
1. 开启大小画面双路编码模式。
public void enableDualStreamMode(boolean enable) {
// 小流的视频编码参数(可自定义)
TRTCCloudDef.TRTCVideoEncParam smallVideoEncParam = new TRTCCloudDef.TRTCVideoEncParam();
smallVideoEncParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_480_270;
smallVideoEncParam.videoFps = 15;
smallVideoEncParam.videoBitrate = 550;
smallVideoEncParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
mTRTCCloud.enableEncSmallVideoStream(enable, smallVideoEncParam);
}
注意:
双路编码开启后,会消耗更多的 CPU 和 网络带宽,所以 Mac、Windows 或者高性能 Pad 可以考虑开启,不建议手机端开启。
2. 选择拉取远端用户视频流类型。
// 订阅远端用户视频流时可选视频流类型
mTRTCCloud.startRemoteView(userId, streamType, videoView);

// 亦可随时切换指定远端用户的大小画面
mTRTCCloud.setRemoteVideoStreamType(userId, streamType);
注意:
双路编码开启后,可通过指定 streamType 视频流类型为 TRTC_VIDEO_STREAM_TYPE_SMALL 来拉取低清小画面观看。

视图渲染控件

RTC Engine 中有很多需要操控视频画面的接口,这些接口都需要您指定视频渲染控件。在 Android 平台中,使用 TXCloudVideoView 作为视频渲染控件,支持 SurfaceViewTextureView 两种渲染方案。下面介绍指定渲染控件类型,以及更新视频渲染控件的方法。
1. 如果您希望强制使用某一种方案,或者将本地视频渲染控件转换为 TXCloudVideoView,您可以按照如下方法进行编码。
// 强制使用 TextureView
TextureView textureView = findViewById(R.id.texture_view);
TXCloudVideoView cloudVideoView = new TXCloudVideoView(context);
cloudVideoView.addVideoView(textureView);

// 强制使用 SurfaceView
SurfaceView surfaceView = findViewById(R.id.surface_view);
TXCloudVideoView cloudVideoView = new TXCloudVideoView(surfaceView);
2. 如果您业务涉及到切换显示区域的交互场景,可以使用 RTC Engine SDK 更新本地预览画面、更新远端用户视频渲染控件功能实现。
// 更新本地预览画面渲染控件
mTRTCCloud.updateLocalView(videoView);

// 更新远端用户视频渲染控件
mTRTCCloud.updateRemoteView(userId, streamType, videoView);
注意:
传参 videoView 为目标视频渲染控件,streamType 仅支持 TRTC_VIDEO_STREAM_TYPE_BIGTRTC_VIDEO_STREAM_TYPE_SUB

异常处理

异常错误处理

RTC Engine SDK 遇到不可恢复的错误会在 onError 回调中抛出,详见 错误码表
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
麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败。

远端镜像模式无效问题

RTC Engine 设置画面镜像分为本地预览镜像 setLocalRenderParams 和视频编码镜像 setVideoEncoderMirror,两者分别影响本地预览画面镜像效果,以及视频编码输出画面的镜像效果(远端观众及云端录制的镜像模式)。如果希望本地预览的镜像效果同时在远端观众侧生效,请按照如下方法进行编码。
// 设置本地画面的渲染参数
TRTCCloudDef.TRTCRenderParams params = new TRTCCloudDef.TRTCRenderParams();
params.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_ENABLE; // 画面镜像模式
params.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL; // 画面填充模式
params.rotation = TRTCCloudDef.TRTC_VIDEO_ROTATION_0; // 画面旋转角度
mTRTCCloud.setLocalRenderParams(params);

// 设置编码器输出的画面镜像模式
mTRTCCloud.setVideoEncoderMirror(true);

摄像头缩放/对焦/切换问题

电商直播场景下,主播可能会对摄像头有自定义调整的需求,RTC Engine SDK 设备管理类下也有解决此类需求的相关接口。
1. 查询、设置摄像头的缩放倍数。
// 获取摄像头的最大缩放倍数(仅适用于移动端)
float zoomRatio = mTRTCCloud.getDeviceManager().getCameraZoomMaxRatio();
// 设置摄像头的缩放倍数(仅适用于移动端)
// 取值范围1-5,取值为1表示最远视角(正常镜头),取值为5表示最近视角(放大镜头);最大值推荐为5,若超过5,视频数据会变得模糊不清
mTRTCCloud.getDeviceManager().setCameraZoomRatio(zoomRatio);
2. 设置摄像头的对焦功能及位置。
// 开启或关闭摄像头的自动对焦功能(仅适用于移动端)
mTRTCCloud.getDeviceManager().enableCameraAutoFocus(false);
// 设置摄像头的对焦位置(仅适用于移动端)
// 使用该接口的前提是先通过 enableCameraAutoFocus 关闭自动对焦功能
mTRTCCloud.getDeviceManager().setCameraFocusPosition(int x, int y);
3. 判断、切换前置或后置摄像头。
// 判断当前是否为前置摄像头(仅适用于移动端)
boolean isFrontCamera = mTRTCCloud.getDeviceManager().isFrontCamera();
// 切换前置或后置摄像头(仅适用于移动端)
// 传入true: 切换为前置;传入false: 切换为后置
mTRTCCloud.getDeviceManager().switchCamera(!isFrontCamera);