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 permission; 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 by passing the track list into ConnectOptions.Builder.
You subscribe to remote tracks via callbacks from RemoteParticipant.Listener.
You render video using a VideoSink or VideoView.
Tencent RTC Engine Architecture
Tencent RTC Engine uses an API-driven architecture:
You capture and publish by calling startLocalPreview() and startLocalAudio() on the TRTCCloud singleton.
You subscribe to remote streams via TRTCCloudListener callbacks and startRemoteView().
You render video with TXCloudVideoView.
You don’t need to manually create or manage track objects.
Tencent RTC Engine APIs are more concise and simplify object management compared to Twilio Video.
Migration Preparation
Step 1. Activate the Service
To use Tencent RTC Engine services, you need to create an application and obtain credentials. Follow these steps to create a Tencent RTC Engine application in the console:
2. Click Create Application.
3. In the popup, enter your application name, select RTC Engine, then click Create.
After the application is created, view the following credentials under Basic Information:
SDKAppID: Automatically generated application ID that uniquely identifies your Tencent RTC app.
SDKSecretKey: Key used to generate the UserSig, which ensures secure access to Tencent RTC services.
Note:
Authentication Comparison: Twilio Video uses Access Token for authentication, whereas Tencent RTC uses UserSig. Both are time-limited credentials generated on the server side, but the generation methods differ. See UserSig Authentication Documentation. Step 2. Import the SDK
Original Twilio Podfile (Reference)
source 'https://github.com/CocoaPods/Specs'
platform :ios, '12.2'
target 'TARGET_NAME' do
pod 'TwilioVideo', '~> 5'
end
Tencent RTC Engine SDK (New Dependency)
CocoaPods (Recommended)
1. If CocoaPods is not installed, install it:
sudo gem install cocoapods
2. In your project root directory, initialize a Podfile:
3. Add the TRTC SDK dependency to your Podfile:
platform :ios, '9.0'
target 'YourApp' do
pod 'TXLiteAVSDK_TRTC', :podspec => 'https://liteav.sdk.qcloud.com/pod/liteavsdkspec/TXLiteAVSDK_TRTC.podspec'
end
4. Install the SDK:
5. After pod install finishes, a new .xcworkspace file will be generated. Open the .xcworkspace file to continue development.
Step 3. Project Configuration
1. Open your .xcworkspace project file, click your project name in Xcode’s Project Navigator, and select the correct TARGETS.
2. In Build Settings, search for User Script Sandboxing and set its value to No to allow user scripts broader access.
3. In Info.plist, add Privacy-Microphone Usage Description and Privacy-Camera Usage Description. Fill in appropriate prompts for microphone and camera permissions.
4. Under Signing & Capabilities, add Background Modes and check Audio, AirPlay and Picture in Picture to enable background audio, AirPlay, and Picture in Picture features.
Migration Instructions
Step 4. Initializing SDK Instance and Setting Event Listener
Twilio Video
import TwilioVideo
class TwilioVideoManager {
var room: Room?
var localVideoTrack: LocalVideoTrack?
var localAudioTrack: LocalAudioTrack?
init() {
}
}
Tencent RTC
import TXLiteAVSDK_TRTC
class TRTCManager: NSObject {
let trtcCloud = TRTCCloud.sharedInstance()
override init() {
super.init()
trtcCloud.delegate = self
}
}
#import <TXLiteAVSDK_TRTC/TRTCCloud.h>
@interface TRTCManager : NSObject <TRTCCloudDelegate>
@property (nonatomic, strong) TRTCCloud *trtcCloud;
@end
@implementation TRTCManager
- (instancetype)init {
self = [super init];
if (self) {
_trtcCloud = [TRTCCloud sharedInstance];
_trtcCloud.delegate = self;
}
return self;
}
@end
Step 5. Entering a Room
Twilio Video
@IBAction func connectToRoom(sender: AnyObject) {
let connectOptions = ConnectOptions(token: accessToken) { (builder) in
builder.roomName = "my-room"
}
room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
}
Tencent RTC
func enterRoom(sdkAppId: UInt32, roomId: UInt32, userId: String, userSig: String) {
let params = TRTCParams()
params.sdkAppId = sdkAppId
params.roomId = roomId
params.userId = userId
params.userSig = userSig
params.role = .anchor
trtcCloud.enterRoom(params, appScene: .LIVE)
}
- (void)enterRoomWithSdkAppId:(UInt32)sdkAppId
roomId:(UInt32)roomId
userId:(NSString *)userId
userSig:(NSString *)userSig {
TRTCParams *params = [[TRTCParams alloc] init];
params.sdkAppId = sdkAppId;
params.roomId = roomId;
params.userId = userId;
params.userSig = userSig;
params.role = TRTCRoleAnchor;
[self.trtcCloud enterRoom:params appScene:TRTCAppSceneLIVE];
}
Step 6. Implementing Event Callback Methods
Twilio Video
extension TwilioVideoManager: RoomDelegate {
func roomDidConnect(room: Room) {
print("Connected to room: \\(room.name)")
}
func roomDidDisconnect(room: Room, error: Error?) {
print("Room connection disconnected")
}
func roomDidFailToConnect(room: Room, error: Error) {
print("Connection failed: \\(error.localizedDescription)")
}
func participantDidConnect(room: Room, participant: RemoteParticipant) {
print("Participant joined: \\(participant.identity)")
}
func participantDidDisconnect(room: Room, participant: RemoteParticipant) {
print("Participant left: \\(participant.identity)")
}
}
Tencent RTC
extension TRTCManager: TRTCCloudDelegate {
func onEnterRoom(_ result: Int) {
if result > 0 {
print("Entered room successfully, time: \\(result)ms")
} else {
print("Failed to enter room, error code: \\(result)")
}
}
func onExitRoom(_ reason: Int) {
print("Exited room, reason: \\(reason)")
}
func onError(_ errCode: TXLiteAVError, errMsg: String?, extInfo: [AnyHashable: Any]?) {
print("Error: \\(errCode.rawValue) - \\(errMsg ?? "")")
}
func onRemoteUserEnterRoom(_ userId: String) {
print("Remote user entered: \\(userId)")
}
func onRemoteUserLeaveRoom(_ userId: String, reason: Int) {
print("Remote user left: \\(userId), reason: \\(reason)")
}
func onUserVideoAvailable(_ userId: String, available: Bool) {
print("User \\(userId) video available: \\(available)")
}
func onUserAudioAvailable(_ userId: String, available: Bool) {
print("User \\(userId) audio available: \\(available)")
}
}
#pragma mark - TRTCCloudDelegate
- (void)onEnterRoom:(NSInteger)result {
if (result > 0) {
NSLog(@"Entered room successfully, time: %ldms", (long)result);
} else {
NSLog(@"Failed to enter room, error code: %ld", (long)result);
}
}
- (void)onExitRoom:(NSInteger)reason {
NSLog(@"Exited room, reason: %ld", (long)reason);
}
- (void)onError:(TXLiteAVError)errCode errMsg:(NSString *)errMsg extInfo:(NSDictionary *)extInfo {
NSLog(@"Error: %d - %@", errCode, errMsg);
}
- (void)onRemoteUserEnterRoom:(NSString *)userId {
NSLog(@"Remote user entered: %@", userId);
}
- (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason {
NSLog(@"Remote user left: %@, reason: %ld", userId, (long)reason);
}
- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
NSLog(@"User %@ video available: %@", userId, available ? @"YES" : @"NO");
}
- (void)onUserAudioAvailable:(NSString *)userId available:(BOOL)available {
NSLog(@"User %@ audio available: %@", userId, available ? @"YES" : @"NO");
}
Step 7. Capturing and Publishing Local Streams
Twilio Video
func startPreview() {
camera = CameraSource(delegate: self)
localVideoTrack = LocalVideoTrack(source: camera!, enabled: true, name: "camera")
localVideoTrack?.addRenderer(previewView)
if let frontCamera = CameraSource.captureDevice(position: .front) {
camera?.startCapture(device: frontCamera)
}
}
func stopLocalVideo() {
localVideoTrack?.isEnabled = false
}
func startLocalAudio() {
localAudioTrack = LocalAudioTrack()
}
func stopLocalAudio() {
localAudioTrack?.isEnabled = false
}
func muteAudio(_ mute: Bool) {
localAudioTrack?.isEnabled = !mute
}
Tencent RTC
func startLocalVideo(view: UIView, frontCamera: Bool = true) {
let renderParams = TRTCRenderParams()
renderParams.fillMode = .fill
renderParams.mirrorType = .auto
trtcCloud.setLocalRenderParams(renderParams)
trtcCloud.startLocalPreview(frontCamera, view: view)
}
func stopLocalVideo() {
trtcCloud.stopLocalPreview()
}
func muteLocalVideo(_ mute: Bool) {
trtcCloud.muteLocalVideo(.big, mute: mute)
}
func switchCamera(_ frontCamera: Bool) {
trtcCloud.getDeviceManager().switchCamera(frontCamera)
}
func startLocalAudio(quality: TRTCAudioQuality = .default) {
trtcCloud.startLocalAudio(quality)
}
func stopLocalAudio() {
trtcCloud.stopLocalAudio()
}
func muteLocalAudio(_ mute: Bool) {
trtcCloud.muteLocalAudio(mute)
}
#pragma mark - Local Video
- (void)startLocalVideoWithView:(UIView *)view frontCamera:(BOOL)frontCamera {
TRTCRenderParams *renderParams = [[TRTCRenderParams alloc] init];
renderParams.fillMode = TRTCVideoFillMode_Fill;
renderParams.mirrorType = TRTCVideoMirrorTypeAuto;
[self.trtcCloud setLocalRenderParams:renderParams];
[self.trtcCloud startLocalPreview:frontCamera view:view];
}
- (void)stopLocalVideo {
[self.trtcCloud stopLocalPreview];
}
- (void)muteLocalVideo:(BOOL)mute {
[self.trtcCloud muteLocalVideo:TRTCVideoStreamTypeBig mute:mute];
}
- (void)switchCamera:(BOOL)frontCamera {
[[self.trtcCloud getDeviceManager] switchCamera:frontCamera];
}
#pragma mark - Local Audio
- (void)startLocalAudioWithQuality:(TRTCAudioQuality)quality {
[self.trtcCloud startLocalAudio:quality];
}
- (void)stopLocalAudio {
[self.trtcCloud stopLocalAudio];
}
- (void)muteLocalAudio:(BOOL)mute {
[self.trtcCloud muteLocalAudio:mute];
}
Step 8. Subscribing to and Playing Remote Streams
Twilio Video
extension TwilioVideoManager: RemoteParticipantDelegate {
func didSubscribeToVideoTrack(videoTrack: RemoteVideoTrack,
publication: RemoteVideoTrackPublication,
participant: RemoteParticipant) {
videoTrack.addRenderer(remoteVideoView)
}
func didUnsubscribeFromVideoTrack(videoTrack: RemoteVideoTrack,
publication: RemoteVideoTrackPublication,
participant: RemoteParticipant) {
videoTrack.removeRenderer(remoteVideoView)
}
}
Tencent RTC
extension TRTCManager: TRTCCloudDelegate {
func onUserVideoAvailable(_ userId: String, available: Bool) {
if available {
trtcCloud.startRemoteView(userId, streamType: .big, view: remoteVideoView)
} else {
trtcCloud.stopRemoteView(userId, streamType: .big)
}
}
func onUserAudioAvailable(_ userId: String, available: Bool) {
if available {
trtcCloud.muteRemoteAudio(userId, mute: false)
}
}
}
func muteRemoteAudio(userId: String, mute: Bool) {
trtcCloud.muteRemoteAudio(userId, mute: mute)
}
func muteAllRemoteAudio(_ mute: Bool) {
trtcCloud.muteAllRemoteAudio(mute)
#pragma mark - TRTCCloudDelegate
- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
if (available) {
[self.trtcCloud startRemoteView:userId streamType:TRTCVideoStreamTypeBig view:self.remoteVideoView];
} else {
[self.trtcCloud stopRemoteView:userId streamType:TRTCVideoStreamTypeBig];
}
}
- (void)onUserAudioAvailable:(NSString *)userId available:(BOOL)available {
if (available) {
[self.trtcCloud muteRemoteAudio:userId mute:NO];
}
}
- (void)muteRemoteAudio:(NSString *)userId mute:(BOOL)mute {
[self.trtcCloud muteRemoteAudio:userId mute:mute];
}
- (void)muteAllRemoteAudio:(BOOL)mute {
[self.trtcCloud muteAllRemoteAudio:mute];
}
Step 9. Leaving the Room
Twilio Video
func disconnect() {
localVideoTrack?.isEnabled = false
localAudioTrack?.isEnabled = false
room?.disconnect()
}
extension TwilioVideoManager: RoomDelegate {
func roomDidDisconnect(room: Room, error: Error?) {
localVideoTrack = nil
localAudioTrack = nil
self.room = nil
if let error = error {
print("Disconnected, error: \\(error.localizedDescription)")
}
}
}
Tencent RTC
func exitRoom() {
trtcCloud.stopLocalPreview()
trtcCloud.stopLocalAudio()
trtcCloud.exitRoom()
}
extension TRTCManager: TRTCCloudDelegate {
func onExitRoom(_ reason: Int) {
switch reason {
case 0:
print("Exited room normally")
case 1:
print("Kicked by server")
case 2:
print("Room dismissed")
default:
break
}
}
}
class TRTCManager: NSObject {
deinit {
TRTCCloud.destroySharedInstance()
}
}
- (void)exitRoom {
[self.trtcCloud stopLocalPreview];
[self.trtcCloud stopLocalAudio];
[self.trtcCloud exitRoom];
}
#pragma mark - TRTCCloudDelegate
- (void)onExitRoom:(NSInteger)reason {
switch (reason) {
case 0:
NSLog(@"Exited room normally");
break;
case 1:
NSLog(@"Kicked by server");
break;
case 2:
NSLog(@"Room dismissed");
break;
default:
break;
}
}
- (void)dealloc {
[TRTCCloud destroySharedInstance];
}
Advanced Features
Screen Sharing
Twilio Video
screenCapturer = ReplayKitVideoSource(isScreencast: true)
let screenTrack = LocalVideoTrack(source: screenCapturer)
RPScreenRecorder.shared().startCapture { sampleBuffer, bufferType, error in
}
Tencent RTC
let encParam = TRTCVideoEncParam()
encParam.videoResolution = ._1280_720
encParam.videoFps = 10
encParam.videoBitrate = 1600
trtcCloud.startScreenCapture(byReplaykit: .sub,
encParam: encParam,
appGroup: "group.your.app.identifier")
trtcCloud.stopScreenCapture()
TRTCVideoEncParam *encParam = [[TRTCVideoEncParam alloc] init];
encParam.videoResolution = TRTCVideoResolution_1280_720;
encParam.videoFps = 10;
encParam.videoBitrate = 1600;
- (void)startScreenCapture {
TRTCVideoEncParam *videoEncConfig = [[TRTCVideoEncParam alloc] init];
videoEncConfig.videoResolution = TRTCVideoResolution_1280_720;
videoEncConfig.videoFps = 10;
videoEncConfig.videoBitrate = 2000;
[[TRTCCloud sharedInstance] startScreenCaptureByReplaykit:videoEncConfig
appGroup:APPGROUP];
}
- (void)stopScreenCapture {
[[TRTCCloud sharedInstance] stopScreenCapture];
}
Audio/Video Encoding Configuration
Twilio Video
let connectOptions = ConnectOptions(token: token) { builder in
builder.preferredVideoCodecs = [Vp8Codec(), H264Codec()]
builder.encodingParameters = EncodingParameters(
audioBitrate: 64,
videoBitrate: 1500
)
}
Tencent RTC
let videoEncParam = TRTCVideoEncParam()
videoEncParam.videoResolution = ._960_540
videoEncParam.videoFps = 15
videoEncParam.videoBitrate = 1200
videoEncParam.resMode = .portrait
trtcCloud.setVideoEncoderParam(videoEncParam)
trtcCloud.startLocalAudio(.music)
TRTCVideoEncParam *videoEncParam = [[TRTCVideoEncParam alloc] init];
videoEncParam.videoResolution = TRTCVideoResolution_960_540;
videoEncParam.videoFps = 15;
videoEncParam.videoBitrate = 1200;
videoEncParam.resMode = TRTCVideoResolutionModePortrait;
[self.trtcCloud setVideoEncoderParam:videoEncParam];
[self.trtcCloud startLocalAudio:TRTCAudioQualityMusic];
Device Management
Twilio Video
if let camera = camera {
let newDevice = CameraSource.captureDevice(position: .back)
camera.selectCaptureDevice(newDevice!) { _, _, error in
}
}
localAudioTrack?.isEnabled = false
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
} catch { }
Tencent RTC
let deviceManager = trtcCloud.getDeviceManager()
deviceManager.switchCamera(true)
let isFront = deviceManager.isFrontCamera()
deviceManager.setCameraZoomRatio(2.0)
deviceManager.setCameraFocusPosition(CGPoint(x: 100, y: 100))
deviceManager.enableCameraTorch(true)
deviceManager.enableCameraAutoFocus(true)
trtcCloud.muteLocalAudio(true)
trtcCloud.setAudioRoute(.speakerphone)
trtcCloud.setAudioRoute(.earpiece)
TXDeviceManager *deviceManager = [self.trtcCloud getDeviceManager];
[deviceManager switchCamera:YES];
BOOL isFront = [deviceManager isFrontCamera];
[deviceManager setCameraZoomRatio:2.0];
[deviceManager setCameraFocusPosition:CGPointMake(100, 100)];
[deviceManager enableCameraTorch:YES];
[deviceManager enableCameraAutoFocus:YES];
[self.trtcCloud muteLocalAudio:YES];
[self.trtcCloud setAudioRoute:TRTCAudioModeSpeakerphone];
[self.trtcCloud setAudioRoute:TRTCAudioModeEarpiece];
Network Quality Monitoring
Twilio Video
extension TwilioVideoManager: RoomDelegate {
func networkQualityLevelDidChange(participant: Participant,
networkQualityLevel: NetworkQualityLevel) {
print("Participant \\(participant.identity) network quality: \\(networkQualityLevel.rawValue)")
}
}
let connectOptions = ConnectOptions(token: token) { builder in
builder.networkQualityEnabled = true
builder.networkQualityConfiguration = NetworkQualityConfiguration(
localVerbosity: .minimal,
remoteVerbosity: .minimal
)
}
Tencent RTC
extension TRTCManager: TRTCCloudDelegate {
func onNetworkQuality(_ localQuality: TRTCQualityInfo,
remoteQuality: [TRTCQualityInfo]) {
print("Local network quality: \\(localQuality.quality.rawValue)")
}
func onStatistics(_ statistics: TRTCStatistics) {
print("RTT: \\(statistics.rtt)ms")
}
}
- (void)onNetworkQuality:(TRTCQualityInfo *)localQuality remoteQuality:(NSArray<TRTCQualityInfo *> *)remoteQuality {
switch(localQuality.quality) {
case TRTCQuality_Unknown:
NSLog(@"SDK has not yet detected the current network quality.");
break;
case TRTCQuality_Excellent:
NSLog(@"The network is excellent.");
break;
case TRTCQuality_Good:
NSLog(@"The network is good.");
break;
case TRTCQuality_Poor:
NSLog(@"Network quality barely meets requirements.");
break;
case TRTCQuality_Bad:
NSLog(@"Network is poor; expect significant lag and delays.");
break;
case TRTCQuality_VeryBad:
NSLog(@"Network is very poor; communication quality can't be guaranteed.");
break;
case TRTCQuality_Down:
NSLog(@"Network does not meet minimum requirements.");
break;
default:
break;
}
for (TRTCQualityInfo *info in remoteQuality) {
NSLog(@"remote user: %@, quality = %@", info.userId, @(info.quality));
}
}
Custom Video Capture
Twilio Video
class CustomVideoSource: NSObject, VideoSource {
weak var sink: VideoSink?
func sendFrame(_ pixelBuffer: CVPixelBuffer, timestamp: CMTime) {
let frame = VideoFrame(timestamp: timestamp,
buffer: pixelBuffer.videoFrameBuffer())
sink?.onVideoFrame(frame)
}
}
let customSource = CustomVideoSource()
let videoTrack = LocalVideoTrack(source: customSource, enabled: true, name: "custom")
Tencent RTC
trtcCloud.enableCustomVideoCapture(.big, enable: true)
func sendCustomVideoFrame(_ pixelBuffer: CVPixelBuffer) {
let videoFrame = TRTCVideoFrame()
videoFrame.pixelFormat = ._NV12
videoFrame.bufferType = .pixelBuffer
videoFrame.pixelBuffer = pixelBuffer
trtcCloud.sendCustomVideoData(.big, frame: videoFrame)
}
func sendCustomVideoTexture(_ textureId: GLuint, width: Int, height: Int) {
let videoFrame = TRTCVideoFrame()
videoFrame.pixelFormat = ._Texture_2D
videoFrame.bufferType = .texture
videoFrame.textureId = textureId
videoFrame.width = UInt32(width)
videoFrame.height = UInt32(height)
trtcCloud.sendCustomVideoData(.big, frame: videoFrame)
}
trtcCloud.enableCustomVideoCapture(.big, enable: false)
[self.trtcCloud enableCustomVideoCapture:TRTCVideoStreamTypeBig enable:YES];
- (void)sendCustomVideoFrame:(CVPixelBufferRef)pixelBuffer timestamp:(uint64_t)timestamp {
TRTCVideoFrame *videoFrame = [[TRTCVideoFrame alloc] init];
videoFrame.pixelFormat = TRTCVideoPixelFormat_NV12;
videoFrame.bufferType = TRTCVideoBufferType_PixelBuffer;
videoFrame.pixelBuffer = pixelBuffer;
videoFrame.timestamp = timestamp;
[self.trtcCloud sendCustomVideoData:TRTCVideoStreamTypeBig frame:videoFrame];
}
[self.trtcCloud enableCustomVideoCapture:TRTCVideoStreamTypeBig enable:NO];
Data Channel / Custom Messages
Twilio Video
let localDataTrack = LocalDataTrack(options: dataTrackOptions)
localDataTrack?.send("Hello, World!")
extension ViewController: RemoteDataTrackDelegate {
func remoteDataTrackDidReceiveString(remoteDataTrack: RemoteDataTrack,
message: String) {
print("Received message: \\(message)")
}
}
Tencent RTC
trtcCloud.sendCustomCmdMsg(1,
data: "Hello, World!".data(using: .utf8)!,
reliable: true,
ordered: true)
trtcCloud.sendSEIMsg("Timestamp: 12345".data(using: .utf8)!,
repeatCount: 1)
extension TRTCManager: TRTCCloudDelegate {
func onRecvCustomCmdMsgUserId(_ userId: String,
cmdID: Int,
seq: UInt32,
message: Data) {
let text = String(data: message, encoding: .utf8) ?? ""
print("Received message from \\(userId) [cmdID=\\(cmdID)]: \\(text)")
}
func onMissCustomCmdMsgUserId(_ userId: String,
cmdID: Int,
errCode: Int,
missed: Int) {
print("Lost \\(missed) messages from \\(userId)")
}
func onRecvSEIMsg(_ userId: String, message: Data) {
let text = String(data: message, encoding: .utf8) ?? ""
print("Received SEI message: \\(text)")
}
}
- (void)sendHello {
NSInteger cmdID = 0x1;
NSData *data = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding];
[trtcCloud sendCustomCmdMsg:cmdID data:data reliable:YES ordered:YES];
}
[self.trtcCloud sendSEIMsg:[@"Timestamp: 12345" dataUsingEncoding:NSUTF8StringEncoding]
repeatCount:1];
#pragma mark - TRTCCloudDelegate
- (void)onRecvCustomCmdMsgUserId:(NSString *)userId
cmdID:(NSInteger)cmdID
seq:(UInt32)seq
message:(NSData *)message {
NSString *text = [[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding];
NSLog(@"Received message from %@ [cmdID=%ld]: %@", userId, (long)cmdID, text);
}
- (void)onMissCustomCmdMsgUserId:(NSString *)userId
cmdID:(NSInteger)cmdID
errCode:(NSInteger)errCode
missed:(NSInteger)missed {
NSLog(@"Lost %ld messages from %@", (long)missed, userId);
}
- (void)onRecvSEIMsg:(NSString *)userId message:(NSData *)message {
NSString *text = [[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding];
NSLog(@"Received SEI message: %@", text);
}
FAQs
Q1: What is the difference between Twilio Video's Access Token and TRTC's UserSig?
Both are time-sensitive credentials used for client authentication, but their generation methods differ:
Twilio Access Token: Generated using Account SID, API Key SID, and API Key Secret on the server side with Twilio SDK helper libraries.
TRTC UserSig: Generated with SDKAppID and SDKSecretKey on the server side using HMAC SHA256.
Q2: How does Twilio's Room Name (string) map to TRTC's Room ID?
TRTC supports two types of room identifiers:
Numeric Room ID (roomId): Integer between 1 and 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 with strRoomId.
Note:
You cannot mix roomId and strRoomId in the same TRTC application; they are not interoperable.
Q3: Why doesn’t TRTC require manual subscription for remote audio?
In Twilio Video, remote audio must be handled via the RemoteParticipant.Listener.onAudioTrackSubscribed callback. In TRTC, remote audio plays automatically after a user enters the room, with no extra action required. If you want to control audio playback for a specific remote user, use muteRemoteAudio(userId, true/false).
Q4: How do Twilio's P2P Room and Group Room map to TRTC's scenarios?
|
Peer-to-Peer Room | TRTCAppSceneVideoCall | 1v1 Video Call |
Peer-to-Peer Room (Audio Only) | TRTCAppSceneAudioCall | 1v1 Audio Call |
Group Room | TRTCAppSceneLIVE | Interactive Live Streaming, Multi-party Conference |
Group Room (Audio Only) | TRTCAppSceneVoiceChatRoom | Voice Chat Room |
Q5: How does TRTC handle reconnection?
TRTC SDK features built-in automatic reconnection. When the network connection is lost, the SDK automatically attempts to reconnect. You can monitor reconnection status with these callbacks:
onConnectionLost(): Connection to server lost
onTryToReconnect(): Attempting to reconnect
onConnectionRecovery(): Connection restored
These correspond to Twilio’s onReconnecting and onReconnected callbacks.
For a complete list of functions and descriptions, see the API Reference. If you encounter issues during integration or use, refer to Other Issues.