This document helps you move a Web app from the Twilio Video SDK to the Tencent RTC Engine SDK. It covers key architecture differences, step-by-step migration instructions, practical feature examples, and advanced feature comparisons to help you migrate smoothly.
Core concepts and architecture differences
Concept Comparison
This section maps key concepts between Tencent RTC Engine and Twilio Video. For Tencent RTC terminology, see Basic Concepts. |
Room | Room | Room | Session space connecting RTC participants. Tencent RTC uses roomId (numeric) or strRoomId (string); Twilio uses roomName (string). |
User | User | Participant | User participating in audio/video calls. |
Anchor | Anchor | — | User type with streaming permissions; can send and receive audio/video streams to/from the server. |
Audience | Audience | — | User type that only receives audio/video streams. |
Application Identifier | SDKAppID | Account SID | Unique application identifier. |
Authentication Credential | UserSig | Access Token | Client authentication credential. |
User Identifier | userId | Identity | Unique user identifier. |
Core Entry Class | TRTCCloud | Video (class) | SDK core entry class. |
Technical Architecture Differences
Twilio Video Architecture
Twilio Video uses a Track-based architecture:
You explicitly create LocalAudioTrack and LocalVideoTrack.
You publish tracks when connecting to a room (for example, via ConnectOptions.Builder / the connect options).
You subscribe to remote tracks through RemoteParticipant.Listener callbacks.
You render video by attaching tracks to a VideoSink or VideoView.
Tencent RTC Engine Architecture
Tencent RTC Engine follows an API-driven architecture:
You use the TRTCCloud singleton and call APIs like startLocalPreview() and startLocalAudio() to capture and publish.
You subscribe to remote media via TRTCCloudListener callbacks and play it with startRemoteView().
You render video using TXCloudVideoView.
You typically don’t need to create or manage track objects yourself.
This API design streamlines development and reduces object management complexity.
Migration Preparation
Step 1. Activate the Service
To access Tencent RTC Engine services, you need to create an application and obtain credentials. Follow these steps in the Tencent RTC Console:
2. Click Create Application.
3. In the popup, enter your application name, select RTC Engine, and click Create.
4. Once your application is created, locate the following credentials under Basic Information:
SDKAppID: Automatically generated application ID that uniquely identifies your Tencent RTC application.
SDKSecretKey: Used to generate secure UserSig signatures for authenticated access to Tencent RTC services.
Note:
Authentication Comparison: Twilio Video uses Access Token for authentication, while Tencent RTC uses UserSig. Both are time-sensitive credentials generated on your server, but the generation methods differ. See UserSig Authentication Documentation. Step 2. Import the SDK
Twilio Video SDK (Original Dependency)
dependencies {
implementation 'com.twilio:video-android:7.10.2'
}
Tencent RTC Engine SDK (New Dependency)
Add the TRTC SDK dependency to the dependencies section of app/build.gradle.
dependencies {
implementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'
}
Step 3. Project Configuration
Specify CPU Architecture
Specify supported CPU architectures in the defaultConfig section of app/build.gradle for devices using armeabi-v7a/arm64-v8a.
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
}
}
Configure Permissions
Add required permissions for TRTC SDK in AndroidManifest.xml.
<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.CAMERA" />
<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-feature android:name="android.hardware.camera.autofocus" />
Note:
Do not set android:hardwareAccelerated="false". Disabling hardware acceleration will prevent video streams from rendering.
Configure Proguard Rules
Add TRTC SDK classes and members to the keep list in proguard-rules.pro.
-keep class com.tencent.** { *; }
Migration Guide
Step 4. Initialize the SDK Instance
Twilio Video
Video.setLogLevel(LogLevel.DEBUG);
Tencent RTC Engine
TRTCCloud mCloud = TRTCCloud.sharedInstance(getApplicationContext());
val mCloud = TRTCCloud.sharedInstance(applicationContext)
Step 5. Set Event Listeners
Twilio Video
Room.Listener roomListener = new Room.Listener() {
@Override
public void onConnected(Room room) {
Log.i("Twilio", "Connected to " + room.getName());
}
@Override
public void onConnectFailure(Room room, TwilioException twilioException) {
Log.e("Twilio", "Connect failure: " + twilioException.getMessage());
}
@Override
public void onDisconnected(Room room, TwilioException twilioException) {
Log.i("Twilio", "Disconnected from " + room.getName());
}
@Override
public void onParticipantConnected(Room room, RemoteParticipant remoteParticipant) {
Log.i("Twilio", "Participant connected: " + remoteParticipant.getIdentity());
}
@Override
public void onParticipantDisconnected(Room room, RemoteParticipant remoteParticipant) {
Log.i("Twilio", "Participant disconnected: " + remoteParticipant.getIdentity());
}
@Override
public void onReconnecting(Room room, TwilioException twilioException) {
Log.i("Twilio", "Reconnecting...");
}
@Override
public void onReconnected(Room room) {
Log.i("Twilio", "Reconnected");
}
};
Tencent RTC Engine
TRTCCloudListener trtcListener = new TRTCCloudListener() {
@Override
public void onEnterRoom(long result) {
if (result > 0) {
Log.i("TRTC", "Room entry successful, took " + result + "ms");
} else {
Log.e("TRTC", "Room entry failed, error code " + result);
}
}
@Override
public void onExitRoom(int reason) {
Log.i("TRTC", "Exited room, reason: " + reason);
}
@Override
public void onRemoteUserEnterRoom(String userId) {
Log.i("TRTC", "Remote user entered room: " + userId);
}
@Override
public void onRemoteUserLeaveRoom(String userId, int reason) {
Log.i("TRTC", "Remote user left room: " + userId);
}
@Override
public void onError(int errCode, String errMsg, Bundle extraInfo) {
Log.e("TRTC", "Error: " + errCode + " - " + errMsg);
}
@Override
public void onConnectionLost() {
Log.w("TRTC", "Disconnected from server");
}
@Override
public void onTryToReconnect() {
Log.i("TRTC", "Attempting to reconnect...");
}
@Override
public void onConnectionRecovery() {
Log.i("TRTC", "Connection recovered");
}
};
mCloud.addListener(trtcListener);
val trtcListener = object : TRTCCloudListener() {
override fun onEnterRoom(result: Long) {
if (result > 0) {
Log.i("TRTC", "Room entry successful, took ${result}ms")
} else {
Log.e("TRTC", "Room entry failed, error code $result")
}
}
override fun onExitRoom(reason: Int) {
Log.i("TRTC", "Exited room, reason: $reason")
}
override fun onRemoteUserEnterRoom(userId: String?) {
Log.i("TRTC", "Remote user entered room: $userId")
}
override fun onRemoteUserLeaveRoom(userId: String?, reason: Int) {
Log.i("TRTC", "Remote user left room: $userId")
}
override fun onError(errCode: Int, errMsg: String?, extraInfo: Bundle?) {
Log.e("TRTC", "Error: $errCode - $errMsg")
}
override fun onConnectionLost() {
Log.w("TRTC", "Disconnected from server")
}
override fun onTryToReconnect() {
Log.i("TRTC", "Attempting to reconnect...")
}
override fun onConnectionRecovery() {
Log.i("TRTC", "Connection recovered")
}
}
mCloud.addListener(trtcListener)
Callback Event Mapping Table:
|
onConnected | onEnterRoom (result > 0) | Successfully connected to/entered room. |
onConnectFailure | onEnterRoom (result < 0) or onError | Connection failed. |
onDisconnected | onExitRoom | Disconnected/left the room. |
onParticipantConnected | onRemoteUserEnterRoom | Remote user entered. |
onParticipantDisconnected | onRemoteUserLeaveRoom | Remote user left. |
onReconnecting | onConnectionLost + onTryToReconnect | Reconnecting. |
onReconnected | onConnectionRecovery | Reconnection successful. |
Step 6. Entering/Connecting to Room
Twilio Video
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.roomName("my-room")
.build();
Room room = Video.connect(context, connectOptions, roomListener);
Tencent RTC Engine
TRTCCloudDef.TRTCParams trtcParams = new TRTCCloudDef.TRTCParams();
trtcParams.sdkAppId = 2000000000;
trtcParams.userId = "user_id";
trtcParams.userSig = "user_sig";
trtcParams.role = TRTCCloudDef.TRTCRoleAudience;
trtcParams.strRoomId = "my-room";
mCloud.enterRoom(trtcParams, TRTCCloudDef.TRTC_APP_SCENE_LIVE);
val trtcParams = TRTCCloudDef.TRTCParams().apply {
sdkAppId = 2000000000
userId = "user_id"
userSig = "user_sig"
role = TRTCCloudDef.TRTCRoleAudience
strRoomId = "my-room"
}
mCloud.enterRoom(trtcParams, TRTCCloudDef.TRTC_APP_SCENE_LIVE)
Note:
Twilio Peer-to-Peer Room corresponds to TRTC TRTC_APP_SCENE_VIDEOCALL (video call) or TRTC_APP_SCENE_AUDIOCALL (audio call)
Twilio Group Room corresponds to TRTC TRTC_APP_SCENE_LIVE (Interactive Live Streaming) or TRTC_APP_SCENE_VOICE_CHATROOM (Voice Chat Room)
Step 7. Capture and Publish Local Audio/Video Streams
Twilio Video
CameraCapturer cameraCapturer = new CameraCapturer(context,
CameraCapturer.CameraSource.FRONT_CAMERA);
LocalVideoTrack localVideoTrack = LocalVideoTrack.create(context, true, cameraCapturer);
VideoView localVideoView = findViewById(R.id.local_video_view);
localVideoTrack.addSink(localVideoView);
LocalAudioTrack localAudioTrack = LocalAudioTrack.create(context, true);
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.roomName("my-room")
.audioTracks(Collections.singletonList(localAudioTrack))
.videoTracks(Collections.singletonList(localVideoTrack))
.build();
Room room = Video.connect(context, connectOptions, roomListener);
room.getLocalParticipant().publishTrack(localVideoTrack);
room.getLocalParticipant().publishTrack(localAudioTrack);
Tencent RTC Engine
TXCloudVideoView localVideoView = findViewById(R.id.local_video_view);
TRTCCloudDef.TRTCRenderParams renderParams = new TRTCCloudDef.TRTCRenderParams();
renderParams.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL;
renderParams.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_AUTO;
mCloud.setLocalRenderParams(renderParams);
mCloud.startLocalPreview(true, localVideoView);
mCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
val localVideoView: TXCloudVideoView = findViewById(R.id.local_video_view)
val renderParams = TRTCCloudDef.TRTCRenderParams().apply {
fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL
mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_AUTO
}
mCloud.setLocalRenderParams(renderParams)
mCloud.startLocalPreview(true, localVideoView)
mCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT)
Note:
Twilio Video requests permissions when creating local tracks. Tencent RTC Engine requires permissions for startLocalPreview and startLocalAudio. On Android, request CAMERA and RECORD_AUDIO permissions at runtime before calling these APIs.
Step 8. Subscribe to and Play Remote Audio/Video Streams
Twilio Video
remoteParticipant.setListener(new RemoteParticipant.Listener() {
@Override
public void onVideoTrackSubscribed(RemoteParticipant remoteParticipant,
RemoteVideoTrackPublication remoteVideoTrackPublication,
RemoteVideoTrack remoteVideoTrack) {
VideoView remoteVideoView = findViewById(R.id.remote_video_view);
remoteVideoTrack.addSink(remoteVideoView);
}
@Override
public void onVideoTrackUnsubscribed(RemoteParticipant remoteParticipant,
RemoteVideoTrackPublication remoteVideoTrackPublication,
RemoteVideoTrack remoteVideoTrack) {
remoteVideoTrack.removeSink(remoteVideoView);
}
@Override
public void onAudioTrackSubscribed(RemoteParticipant remoteParticipant,
RemoteAudioTrackPublication remoteAudioTrackPublication,
RemoteAudioTrack remoteAudioTrack) {
}
});
Tencent RTC Engine
@Override
public void onUserVideoAvailable(String userId, boolean available) {
if (available) {
TXCloudVideoView remoteVideoView = findViewById(R.id.remote_video_view);
mCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG,
remoteVideoView);
} else {
mCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
}
}
@Override
public void onUserAudioAvailable(String userId, boolean available) {
}
override fun onUserVideoAvailable(userId: String?, available: Boolean) {
if (available) {
val remoteVideoView: TXCloudVideoView = findViewById(R.id.remote_video_view)
mCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG,
remoteVideoView)
} else {
mCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG)
}
}
override fun onUserAudioAvailable(userId: String?, available: Boolean) {
}
Step 9. Mute/Unmute Local Audio/Video
Twilio Video
localAudioTrack.enable(false);
localAudioTrack.enable(true);
localVideoTrack.enable(false);
localVideoTrack.enable(true);
Tencent RTC Engine
mCloud.muteLocalAudio(true);
mCloud.muteLocalAudio(false);
mCloud.muteLocalVideo(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, true);
mCloud.muteLocalVideo(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, false);
mCloud.stopLocalPreview();
mCloud.muteLocalAudio(true)
mCloud.muteLocalAudio(false)
mCloud.muteLocalVideo(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, true)
mCloud.muteLocalVideo(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, false)
mCloud.stopLocalPreview()
Step 10. Mute/Unmute Remote Audio/Video
Twilio Video
remoteAudioTrackPublication.getRemoteAudioTrack().setPlaybackEnabled(false);
remoteVideoTrack.removeSink(remoteVideoView);
Tencent RTC Engine
mCloud.muteRemoteAudio("remote_user_id", true);
mCloud.muteRemoteAudio("remote_user_id", false);
mCloud.muteAllRemoteAudio(true);
mCloud.muteAllRemoteAudio(false);
mCloud.muteRemoteVideoStream("remote_user_id",
TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, true);
mCloud.muteRemoteVideoStream("remote_user_id",
TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, false);
mCloud.muteAllRemoteVideoStreams(true);
mCloud.muteAllRemoteVideoStreams(false);
mCloud.muteRemoteAudio("remote_user_id", true)
mCloud.muteRemoteAudio("remote_user_id", false)
mCloud.muteAllRemoteAudio(true)
mCloud.muteAllRemoteAudio(false)
mCloud.muteRemoteVideoStream("remote_user_id",
TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, true)
mCloud.muteRemoteVideoStream("remote_user_id",
TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, false)
mCloud.muteAllRemoteVideoStreams(true)
mCloud.muteAllRemoteVideoStreams(false)
Step 11. Exit Room
Twilio Video
room.disconnect();
if (localAudioTrack != null) {
localAudioTrack.release();
localAudioTrack = null;
}
if (localVideoTrack != null) {
localVideoTrack.release();
localVideoTrack = null;
}
Tencent RTC Engine
mCloud.stopLocalAudio();
mCloud.stopLocalPreview();
mCloud.exitRoom();
TRTCCloud.destroySharedInstance();
mCloud.stopLocalAudio()
mCloud.stopLocalPreview()
mCloud.exitRoom()
TRTCCloud.destroySharedInstance()
Advanced Features
Screen Sharing
Twilio Video
ScreenCapturer screenCapturer = new ScreenCapturer(context, resultCode, data,
new ScreenCapturer.Listener() {
@Override
public void onScreenCaptureError(String errorDescription) {
Log.e("Twilio", "Screen capture error: " + errorDescription);
}
@Override
public void onFirstFrameAvailable() {
Log.i("Twilio", "First frame available");
}
});
LocalVideoTrack screenTrack = LocalVideoTrack.create(context, true, screenCapturer);
room.getLocalParticipant().publishTrack(screenTrack);
Tencent RTC Engine
TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();
encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_1280_720;
encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
encParam.videoFps = 10;
encParam.videoBitrate = 1200;
encParam.enableAdjustRes = false;
TRTCCloudDef.TRTCScreenShareParams screenShareParams =
new TRTCCloudDef.TRTCScreenShareParams();
mCloud.startScreenCapture(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB, encParam,
screenShareParams);
mCloud.stopScreenCapture();
val encParam = TRTCCloudDef.TRTCVideoEncParam().apply {
videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_1280_720
videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT
videoFps = 10
videoBitrate = 1200
enableAdjustRes = false
}
val screenShareParams = TRTCCloudDef.TRTCScreenShareParams()
mCloud.startScreenCapture(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB, encParam,
screenShareParams)
mCloud.stopScreenCapture()
Audio/Video Encoding Configuration
Twilio Video
EncodingParameters encodingParameters = new EncodingParameters(
16,
800
);
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.roomName("my-room")
.encodingParameters(encodingParameters)
.preferVideoCodecs(Collections.singletonList(new H264Codec()))
.preferAudioCodecs(Collections.singletonList(new OpusCodec()))
.build();
Tencent RTC Engine
TRTCCloudDef.TRTCVideoEncParam videoEncParam = new TRTCCloudDef.TRTCVideoEncParam();
videoEncParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_640_360;
videoEncParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;
videoEncParam.videoFps = 15;
videoEncParam.videoBitrate = 800;
videoEncParam.minVideoBitrate = 200;
mCloud.setVideoEncoderParam(videoEncParam);
TRTCCloudDef.TRTCNetworkQosParam qosParam = new TRTCCloudDef.TRTCNetworkQosParam();
qosParam.preference = TRTCCloudDef.TRTC_VIDEO_QOS_PREFERENCE_SMOOTH;
mCloud.setNetworkQosParam(qosParam);
val videoEncParam = TRTCCloudDef.TRTCVideoEncParam().apply {
videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_640_360
videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT
videoFps = 15
videoBitrate = 800
minVideoBitrate = 200
}
mCloud.setVideoEncoderParam(videoEncParam)
val qosParam = TRTCCloudDef.TRTCNetworkQosParam().apply {
preference = TRTCCloudDef.TRTC_VIDEO_QOS_PREFERENCE_SMOOTH
}
mCloud.setNetworkQosParam(qosParam)
Device Management
Twilio Video
CameraCapturer cameraCapturer = (CameraCapturer) localVideoTrack.getVideoCapturer();
cameraCapturer.switchCamera();
Tencent RTC Engine
TXDeviceManager deviceManager = mCloud.getDeviceManager();
deviceManager.switchCamera(true);
boolean isFront = deviceManager.isFrontCamera();
deviceManager.setCameraZoomRatio(2.0f);
deviceManager.enableCameraTorch(true);
deviceManager.enableCameraAutoFocus(true);
deviceManager.setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteSpeakerphone);
deviceManager.setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteEarpiece);
val deviceManager = mCloud.deviceManager
deviceManager.switchCamera(true)
val isFront = deviceManager.isFrontCamera
deviceManager.setCameraZoomRatio(2.0f)
deviceManager.enableCameraTorch(true)
deviceManager.enableCameraAutoFocus(true)
deviceManager.setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteSpeakerphone)
deviceManager.setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteEarpiece)
Network Quality Monitoring
Twilio Video
ConnectOptions connectOptions = new ConnectOptions.Builder(accessToken)
.roomName("my-room")
.enableNetworkQuality(true)
.build();
NetworkQualityLevel level = localParticipant.getNetworkQualityLevel();
Tencent RTC Engine
@Override
public void onNetworkQuality(TRTCCloudDef.TRTCQuality localQuality,
ArrayList<TRTCCloudDef.TRTCQuality> remoteQuality) {
Log.i("TRTC", "Local network quality: " + localQuality.quality);
for (TRTCCloudDef.TRTCQuality quality : remoteQuality) {
Log.i("TRTC", "User " + quality.userId + " network quality: " + quality.quality);
}
}
@Override
public void onStatistics(TRTCStatistics statistics) {
Log.i("TRTC", "Upstream packet loss: " + statistics.upLoss + "%");
Log.i("TRTC", "Downstream packet loss: " + statistics.downLoss + "%");
Log.i("TRTC", "RTT: " + statistics.rtt + "ms");
}
override fun onNetworkQuality(
localQuality: TRTCCloudDef.TRTCQuality?,
remoteQuality: ArrayList<TRTCCloudDef.TRTCQuality>?
) {
Log.i("TRTC", "Local network quality: ${localQuality?.quality}")
remoteQuality?.forEach { quality ->
Log.i("TRTC", "User ${quality.userId} network quality: ${quality.quality}")
}
}
override fun onStatistics(statistics: TRTCStatistics?) {
Log.i("TRTC", "Upstream packet loss: ${statistics?.upLoss}%")
Log.i("TRTC", "Downstream packet loss: ${statistics?.downLoss}%")
Log.i("TRTC", "RTT: ${statistics?.rtt}ms")
}
Custom Video Capture
Twilio Video
public class CustomCapturer implements VideoCapturer {
@Override
public void initialize(SurfaceTextureHelper surfaceTextureHelper,
Context context, CapturerObserver observer) {
}
@Override
public void startCapture(int width, int height, int framerate) {
}
@Override
public void stopCapture() {
}
@Override
public boolean isScreencast() {
return false;
}
}
LocalVideoTrack customTrack = LocalVideoTrack.create(context, true, customCapturer);
Tencent RTC Engine
mCloud.enableCustomVideoCapture(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, true);
TRTCCloudDef.TRTCVideoFrame frame = new TRTCCloudDef.TRTCVideoFrame();
frame.pixelFormat = TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D;
frame.bufferType = TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE;
frame.texture = new TRTCCloudDef.TRTCTexture();
frame.texture.textureId = textureId;
frame.texture.eglContext14 = eglContext;
frame.width = width;
frame.height = height;
frame.timestamp = timestamp;
mCloud.sendCustomVideoData(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, frame);
mCloud.enableCustomVideoCapture(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, true)
val frame = TRTCCloudDef.TRTCVideoFrame().apply {
pixelFormat = TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D
bufferType = TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE
texture = TRTCCloudDef.TRTCTexture().apply {
textureId = textureId
eglContext14 = eglContext
}
width = width
height = height
timestamp = timestamp
}
mCloud.sendCustomVideoData(TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, frame)
Data Channel/Custom Messages
Twilio Video
LocalDataTrack localDataTrack = LocalDataTrack.create(context);
room.getLocalParticipant().publishTrack(localDataTrack);
localDataTrack.send("Hello, World!");
localDataTrack.send(ByteBuffer.wrap(new byte[]{0x01, 0x02}));
remoteDataTrack.setListener(new RemoteDataTrack.Listener() {
@Override
public void onMessage(RemoteDataTrack remoteDataTrack, String message) {
Log.i("Twilio", "Received: " + message);
}
@Override
public void onMessage(RemoteDataTrack remoteDataTrack, ByteBuffer message) {
Log.i("Twilio", "Received binary data");
}
});
Tencent RTC Engine
boolean success = mCloud.sendCustomCmdMsg(1, "Hello, World!".getBytes(), true, true);
mCloud.sendSEIMsg("Hello via SEI".getBytes(), 1);
@Override
public void onRecvCustomCmdMsg(String userId, int cmdID, int seq, byte[] message) {
String msg = new String(message);
Log.i("TRTC", "Received message from " + userId + ": " + msg);
}
@Override
public void onRecvSEIMsg(String userId, byte[] data) {
String msg = new String(data);
Log.i("TRTC", "Received SEI message from " + userId + ": " + msg);
}
val success = mCloud.sendCustomCmdMsg(1, "Hello, World!".toByteArray(), true, true)
mCloud.sendSEIMsg("Hello via SEI".toByteArray(), 1)
override fun onRecvCustomCmdMsg(userId: String?, cmdID: Int, seq: Int, message: ByteArray?) {
val msg = message?.let { String(it) }
Log.i("TRTC", "Received message from $userId: $msg")
}
override fun onRecvSEIMsg(userId: String?, data: ByteArray?) {
val msg = data?.let { String(it) }
Log.i("TRTC", "Received SEI message from $userId: $msg")
}
FAQs
Q1: What is the difference between Twilio Video's Access Token and TRTC's UserSig?
Both are time-sensitive credentials for client authentication, but the generation methods differ:
Twilio Access Token: Generated on your server using Account SID, API Key SID, and API Key Secret with Twilio's SDK helper libraries.
TRTC UserSig: Generated on your server using SDKAppID and SDKSecretKey via HMAC SHA256.
Q2: How does Twilio's Room Name (string) map to TRTC's Room ID?
TRTC supports two room identifier types:
Numeric Room ID (roomId): Integer range 1 ~ 4294967294 (recommended).
String Room ID (strRoomId): Up to 64 bytes, supports letters, numbers, and select special characters.
If your Twilio project uses string room names, map them directly to strRoomId.
Note:
Do not mix roomId and strRoomId within the same TRTC application; they are not interoperable.
Q3: Why does TRTC not require manual subscription for remote audio?
Twilio Video requires manual handling of remote audio via RemoteParticipant.Listener.onAudioTrackSubscribed. In TRTC, remote audio is automatically played when a user enters the room. To control remote audio playback for a specific user, use muteRemoteAudio(userId, true/false).
Q4: Which TRTC scenarios correspond to Twilio's P2P Room and Group Room?
|
Peer-to-Peer Room | TRTC_APP_SCENE_VIDEOCALL | 1v1 Video Call |
Peer-to-Peer Room (audio only) | TRTC_APP_SCENE_AUDIOCALL | 1v1 Audio Call |
Group Room | TRTC_APP_SCENE_LIVE | Interactive live streaming, video conference |
Group Room (audio only) | TRTC_APP_SCENE_VOICE_CHATROOM | Voice chatroom |
Q5: How does TRTC handle reconnection?
TRTC SDK includes automatic reconnect logic—no manual intervention required. If the network disconnects, the SDK automatically attempts to reconnect. Monitor reconnect status with these callbacks:
onConnectionLost(): Disconnected from server
onTryToReconnect(): Attempting to reconnect
onConnectionRecovery(): Connection recovered
These callbacks correspond to Twilio's onReconnecting and onReconnected.
More Information
You can find the complete function list and descriptions in the API Reference. For additional integration or usage issues, see Other Issues.