sudo gem install cocoapods
pod init
platform :ios, '8.0'target 'App' do# TRTC Lite Edition# The installation package has the minimum incremental size. It only supports two features of Tencent Real-Time Communication (TRTC) and TXLivePlayer for live streaming playback.pod 'TXLiteAVSDK_TRTC', :podspec => 'https://liteav.sdk.qcloud.com/pod/liteavsdkspec/TXLiteAVSDK_TRTC.podspec'# Add the IM SDKpod 'TXIMSDK_Plus_iOS'# pod 'TXIMSDK_Plus_iOS_XCFramework'# pod 'TXIMSDK_Plus_Swift_iOS_XCFramework'# If you need to add the Quic plugin, please uncomment the next line.# Note: This plugin must be used with the Objective-C edition or XCFramework edition of the IM SDK, and the plugin version number must match the IM SDK version number.# pod 'TXIMSDK_Plus_QuicPlugin'end
pod install
pod update
pod setuppod repo updaterm ~/Library/Caches/CocoaPods/search_index.json
Privacy - Microphone Usage Description. Also enter a prompt specifying the purpose of microphone use.
// Obtain the SDKAppID from the Instant Messaging (IM) console.// Add a V2TIMSDKListener event listener. self is the implementation class of id <V2TIMSDKListener>. This step can be skipped if you do not need to listen for events from the IM SDK.[[V2TIMManager sharedInstance] addIMSDKListener:self];// Initialize the IM SDK. After calling this API, you can immediately call the log-in API.[[V2TIMManager sharedInstance] initSDK:sdkAppID config:config];// After the SDK is initialized, it will trigger various events, such as connection status and expiration of log-in credentials.- (void)onConnecting {NSLog(@"The IM SDK is connecting to Tencent Cloud CVM.");}- (void)onConnectSuccess {NSLog(@"The IM SDK has successfully connected to Tencent Cloud CVM.");}// Remove event listener.// self is the implementation class of id <V2TIMSDKListener>.[[V2TIMManager sharedInstance] removeIMSDKListener:self];// Deinitialize the SDK.[[V2TIMManager sharedInstance] unInitSDK];
// Create TRTC SDK instance (Single Instance Pattern)._trtcCloud = [TRTCCloud sharedInstance];// Set event listeners._trtcCloud.delegate = self;// Notifications from various SDK events (e.g., error codes, warning codes, audio and video status parameters, etc.).- (void)onError:(TXLiteAVError)errCode errMsg:(nullable NSString *)errMsg extInfo:(nullable NSDictionary *)extInfo {NSLog(@"%d: %@", errCode, errMsg);}- (void)onWarning:(TXLiteAVWarning)warningCode warningMsg:(nullable NSString *)warningMsg extInfo:(nullable NSDictionary *)extInfo {NSLog(@"%d: %@", warningCode, warningMsg);}// Remove event listener._trtcCloud.delegate = nil;// Terminate TRTC SDK instance (Singleton Pattern).[TRTCCloud destroySharedIntance];
// Log in: userID can be defined by the user and userSig can be generated as per Step 1.[[V2TIMManager sharedInstance] login:userID userSig:userSig succ:^{NSLog(@"success");} fail:^(int code, NSString *desc) {// The following error codes mean an expired UserSig, and you need to generate a new one for log-in again.// 1. ERR_USER_SIG_EXPIRED(6206).// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001).// Note: Do not call the log-in API in case of other error codes. Otherwise, the IM SDK may enter an infinite loop of log-in.NSLog(@"failure, code:%d, desc:%@", code, desc);}];
// Log out.[[V2TIMManager sharedInstance] logout:^{NSLog(@"success");} fail:^(int code, NSString *desc) {NSLog(@"failure, code:%d, desc:%@", code, desc);}];
// Create a group.[[V2TIMManager sharedInstance] createGroup:GroupType_AVChatRoom groupID:groupID groupName:groupName succ:^(NSString *groupID) {// Group created successfully.} fail:^(int code, NSString *desc) {// Group creation failed.}];// Listen for group creation notifications.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupCreated:(NSString *)groupID {// Group creation callback. groupID is the ID of the newly created group.}
GroupType_AVChatRoom
.// Join a group.[[V2TIMManager sharedInstance] joinGroup:groupID msg:message succ:^{// Successfully joined the group.} fail:^(int code, NSString *desc) {// Failed to join the group.}];// Listen for the event of joining a group.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray<V2TIMGroupMemberInfo *>*)memberList {// Someone joined the group.}
- (void)enterRoomWithRoomId:(NSString *)roomId userID:(NSString *)userId {TRTCParams *params = [[TRTCParams alloc] init];// Using a string as the room ID for example, it is recommended to keep it consistent with the IM group ID.params.strRoomId = roomId;params.userId = userId;// UserSig obtained from the business backend.params.userSig = getUserSig(userId);// Replace with your SDKAppID.params.sdkAppId = SDKAppID;// For entering a room in voice chat interaction scenarios, specify the user's role.params.role = TRTCRoleAudience;// Use room entry in voice chat interaction scenarios as an example.[self.trtcCloud enterRoom:params appScene:TRTCAppSceneVoiceChatRoom];}// Event callback for the result of entering the room.- (void)onEnterRoom:(NSInteger)result {if (result > 0) {// result indicates the time taken (in milliseconds) to join the room.[self toastTip:@"Enter room succeed!"];} else {// result indicates the error code when you fail to enter the room.[self toastTip:@"Enter room failed!"];}}
roomId
and string type strRoomId
. The rooms of these two types are not interconnected. It is recommended to unify the room ID type.TRTCAppSceneVoiceChatRoom
. [[V2TIMManager sharedInstance] quitGroup:groupID succ:^{// Exiting the group successful.} fail:^(int code, NSString *desc) {// Exiting the group failed.}];[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onMemberLeave:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member {// Group member leave callback.}
dismissGroup
.- (void)exitTrtcRoom {self.trtcCloud = [TRTCCloud sharedInstance];[self.trtcCloud stopLocalAudio];[self.trtcCloud exitRoom];}// Listen for the onExitRoom callback to get the reason for exiting the room.- (void)onExitRoom:(NSInteger)reason {if (reason == 0) {// Actively call exitRoom to exit the room.NSLog(@"Exit current room by calling the 'exitRoom' api of sdk ...");} else if (reason == 1) {// Removed from the current room by the server.NSLog(@"Kicked out of the current room by server through the restful api...");} else if (reason == 2) {// The current room is dissolved.NSLog(@"Current room is dissolved by server through the restful api...");}}
onExitRoom
callback notification to inform you.enterRoom
again or switch to another audio/video SDK, wait for the onExitRoom
callback before proceeding. Otherwise, you may encounter exceptions such as the camera or microphone being forcefully occupied.[[V2TIMManager sharedInstance] dismissGroup:groupID succ:^{// Dissolving group successful.} fail:^(int code, NSString *desc) {// Dissolving the group failed.}];[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupDismissed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser {// Group dissolved callback.}
DismissRoom
(differentiating between numeric room ID and string room ID). You can call this API to remove all users from the room and dissolve the room.exitRoom
API of each client, all the anchors and audiences in the room can be completed of room exit. After room exit, according to TRTC room lifecycle rules, the room will automatically be dissolved. For details, see Exit Room.#import "JSONModel.h"typedef NS_ENUM(NSUInteger, SeatInfoStatus) {SeatInfoStatusUnused = 0,SeatInfoStatusUsed = 1,SeatInfoStatusLocked = 2,};NS_ASSUME_NONNULL_BEGIN@interface SeatInfoModel : JSONModel/// Seat status, corresponding to three statuses.@property (nonatomic, assign) SeatInfoStatus status;/// Whether the seat is muted.@property (nonatomic, assign) BOOL mute;/// When the seat is occupied, store the user information.@property (nonatomic, copy) NSString *userId;@endNS_ASSUME_NONNULL_END
// Audience sends a request to speak. userId is the Anchor ID, and data can pass in a JSON identifying the signaling.- (void)sendInvitationWithUserId:(NSString *)userId data:(NSString *)data {[[V2TIMManager sharedInstance] invite:userId data:data onlineUserOnly:YES offlinePushInfo:nil timeout:0 succ:^{NSLog(@"sendInvitation success");} fail:^(int code, NSString *desc) {NSLog(@"sendInvitation error %d", code);}];}// Anchor receives the request to speak. inviteID is the request ID, and inviter is the requester ID.[[V2TIMManager sharedInstance] addSignalingListener:self];- (void)onReceiveNewInvitation:(NSString *)inviteID inviter:(NSString *)inviter groupID:(NSString *)groupID inviteeList:(NSArray<NSString *> *)inviteeList data:(NSString * __nullable)data {NSLog(@"received invitation: %@ from %@", inviteID, inviter);}
// Agree to the request to speak.- (void)acceptInvitationWithInviteID:(NSString *)inviteID data:(NSString *)data {[[V2TIMManager sharedInstance] accept:inviteID data:data succ:^{NSLog(@"acceptInvitation success");} fail:^(int code, NSString *desc) {NSLog(@"acceptInvitation error %d", code);}];}// Reject the request to speak.- (void)rejectInvitationWithInviteID:(NSString *)inviteID data:(NSString *)data {[[V2TIMManager sharedInstance] reject:inviteID data:data succ:^{NSLog(@"rejectInvitation success");} fail:^(int code, NSString *desc) {NSLog(@"rejectInvitation error %d", code);}];}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// Callback for agreeing to the request to speak.- (void)onInviteeAccepted:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString * __nullable)data {NSLog(@"received accept invitation: %@ from %@", inviteID, invitee);NSInteger seatIndex = [self findSeatIndex:inviteID];[self takeSeatWithIndex:seatIndex];}// Audience begins to speak.- (void)takeSeatWithIndex:(NSInteger)seatIndex {// Create a seat information instance. Store the modified seat information.SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUsed;seatInfo.mute = localInfo.mute;seatInfo.userId = self.userId;// Serialize the seat information object into JSON format.NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Successfully modified group attributes. Switch TRTC role and start streaming.[self.trtcCloud switchRole:TRTCRoleAnchor];[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to become a speaker.}];}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// Anchor calls this API to modify the seat information saved in group attributes.- (void)pickSeatWithUserId:(NSString *)userId seatIndex:(NSInteger)seatIndex {// Create a seat information instance. Store the modified seat information.SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUsed;seatInfo.mute = localInfo.mute;seatInfo.userId = self.userId;// Serialize the seat information object into JSON format.NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Successfully modified group attributes and it triggers onGroupAttributeChanged callback.} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to become a speaker.}];}// Audience receives group attribute change callback. Audience starts streaming after successfully matching own information.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// Last locally saved full list of seats.NSArray *oldSeatArray = self.seatInfoArray;// The most recent full list of seats parsed from groupAttributeMap.NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// Iterate through the full list of seats. Compare old and new seat information.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.status != newInfo.status && newInfo.status == SeatInfoStatusUsed) {if ([newInfo.userId isEqualToString:self.userId]) {// Match own information successfully. Switch TRTC role and start streaming.[self.trtcCloud switchRole:TRTCRoleAnchor];[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];} else {// Update local seat list. Render local seat view.}}}}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;- (void)leaveSeatWithIndex:(NSInteger)seatIndex {// Create a seat information instance. Store the modified seat information.SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUnused;seatInfo.mute = localInfo.mute;seatInfo.userId = @"";// Serialize the seat information object into JSON format.NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Successfully modified group attributes. Switch TRTC role and stop streaming.[self.trtcCloud switchRole:TRTCRoleAudience];[self.trtcCloud stopLocalAudio];} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to become a listener.}];}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// Anchor calls this API to modify the seat information saved in group attributes.- (void)kickSeatWithIndex:(NSInteger)seatIndex {// Create a seat information instance. Store the modified seat information.SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = SeatInfoStatusUnused;seatInfo.mute = localInfo.mute;seatInfo.userId = @"";// Serialize the seat information object into JSON format.NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Successfully modified group attributes and it triggers onGroupAttributeChanged callback.} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to remove the speaker.}];}// Mic-connecting audience receives group attribute change callback. It stops streaming after successfully matching own information.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// Last locally saved full list of seats.NSArray *oldSeatArray = self.seatInfoArray;// The most recent full list of seats parsed from groupAttributeMap.NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// Iterate through the full list of seats. Compare old and new seat information.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.status != newInfo.status && newInfo.status == SeatInfoStatusUnused) {if ([newInfo.userId isEqualToString:self.userId]) {// Match own information successfully. Switch TRTC role and stop streaming.[self.trtcCloud switchRole:TRTCRoleAudience];[self.trtcCloud stopLocalAudio];} else {// Update local seat list. Render local seat view.}}}}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// Anchor calls this API to modify the seat information saved in group attributes.- (void)muteSeatWithIndex:(NSInteger)seatIndex mute:(BOOL)mute {// Create a seat information instance. Store the modified seat information.SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = localInfo.status;seatInfo.mute = mute;seatInfo.userId = localInfo.userId;// Serialize the seat information object into JSON format.NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Successfully modified group attributes and it triggers onGroupAttributeChanged callback.} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to mute the seat.}];}// The mic-connecting audience receives the group attribute change callback. The audience pauses/resumes streaming after successfully matching own information.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// Last locally saved full list of seats.NSArray *oldSeatArray = self.seatInfoArray;// The most recent full list of seats parsed from groupAttributeMap.NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// Iterate through the full list of seats. Compare old and new seat information.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.mute != newInfo.mute) {if ([newInfo.userId isEqualToString:self.userId]) {// Match own information successfully. Pause/resume local streaming.[self.trtcCloud muteLocalAudio:newInfo.mute];} else {// Update local seat list. Render local seat view.}}}}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// Anchor calls this API to modify the seat information saved in group attributes.- (void)lockSeatWithIndex:(NSInteger)seatIndex isLock:(BOOL)isLock {// Create a seat information instance. Store the modified seat information.SeatInfoModel *localInfo = self.seatInfoArray[seatIndex];SeatInfoModel *seatInfo = [[SeatInfoModel alloc] init];seatInfo.status = isLock? SeatInfoStatusLocked : SeatInfoStatusUnused;seatInfo.mute = localInfo.mute;seatInfo.userId = @"";// Serialize the seat information object into JSON format.NSString *jsonStr = seatInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", seatIndex]: jsonStr };// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Successfully modified group attributes and it triggers onGroupAttributeChanged callback.} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to lock the seat.}];}// The audience receives the group attribute change callback. Update the corresponding seat view.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary<NSString *,NSString *> *)attributes {// Last locally saved full list of seats.NSArray *oldSeatArray = self.seatInfoArray;// The most recent full list of seats parsed from groupAttributeMap.NSArray *newSeatArray = [self getSeatListFromAttr:attributes seatSize:self.seatSize];// Iterate through the full list of seats. Compare old and new seat information.for (int i = 0; i < self.seatSize; i++) {SeatInfoModel *oldInfo = oldSeatArray[i];SeatInfoModel *newInfo = newSeatArray[i];if (oldInfo.status == SeatInfoStatusLocked && newInfo.status == SeatInfoStatusUnused) {// Unlock a seat.} else if (oldInfo.status != newInfo.status && newInfo.status == SeatInfoStatusLocked) {// Lock a seat.}}}
// Locally saved full list of seats.@property (nonatomic, copy) NSArray<SeatInfoModel *> *seatInfoArray;// On-mic anchor calls this API to modify the seat information saved in group attributes.- (void)moveSeatToIndex:(NSInteger)dstIndex {// Obtain the source seat ID by userId.__block NSInteger srcIndex = -1;[self.seatInfoArray enumerateObjectsUsingBlock:^(SeatInfoModel * _Nonnull seatInfo, NSUInteger idx, BOOL * _Nonnull stop) {if ([seatInfo.userId isEqualToString:self.userId]) {srcIndex = idx;*stop = YES;}}];if (srcIndex < 0 || dstIndex < 0 || dstIndex >= self.seatInfoArray.count) {return;}// Obtain the corresponding seat information by its ID.SeatInfoModel *srcSeatInfo = self.seatInfoArray[srcIndex];SeatInfoModel *dstSeatInfo = self.seatInfoArray[dstIndex];// Create a seat information instance to store the modified source seat data.SeatInfoModel *srcChangeInfo = [[SeatInfoModel alloc] init];srcChangeInfo.status = SeatInfoStatusUnused;srcChangeInfo.mute = srcSeatInfo.mute;srcChangeInfo.userId = @"";// Create a seat information instance to store the modified target seat data.SeatInfoModel *dstChangeInfo = [[SeatInfoModel alloc] init];dstChangeInfo.status = SeatInfoStatusUsed;dstChangeInfo.mute = dstSeatInfo.mute;dstChangeInfo.userId = self.userId;// Serialize the seat information object into JSON format.NSString *srcJsonStr = srcChangeInfo.toJSONString;NSString *dstJsonStr = dstChangeInfo.toJSONString;NSDictionary *dict = @{ [NSString stringWithFormat:@"seat%ld", srcIndex]: srcJsonStr,[NSString stringWithFormat:@"seat%ld", dstIndex]: dstJsonStr};// Set group attributes. If the group attribute already exists, its value is updated. Otherwise, the attribute is added.[[V2TIMManager sharedInstance] setGroupAttributes:self.groupId attributes:dict succ:^{// Modify group attributes successfully. Move the seat successfully.} fail:^(int code, NSString *desc) {// Failed to modify group attributes. Failed to move the seat.}];}
muteRemoteAudio(userId, mute)
to subscribe to and play remote users' audio streams is required.// Automatic subscription mode (default).[self.trtcCloud setDefaultStreamRecvMode:YES video:YES];// Manual subscription mode (custom).[self.trtcCloud setDefaultStreamRecvMode:NO video:NO];
setDefaultStreamRecvMode
before entering the room enterRoom
to ensure to take effect.// Enable local audio capture and publishing.[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];// Stop local audio capture and publishing.[self.trtcCloud stopLocalAudio];
startLocalAudio
requests mic permissions, and stopLocalAudio
releases them.// Pause publishing local audio streams (mute).[self.trtcCloud muteLocalAudio:YES];// Resume publishing local audio streams (unmute).[self.trtcCloud muteLocalAudio:NO];// Pause the subscription and playback of a specific remote user's audio streams.[self.trtcCloud muteRemoteAudio:userId mute:YES];// Resume the subscription and playback of a specific remote user's audio streams.[self.trtcCloud muteRemoteAudio:userId mute:NO];// Pause the subscription and playback of all remote users' audio streams.[self.trtcCloud muteAllRemoteAudio:YES];// Resume the subscription and playback of all remote users' audio streams.[self.trtcCloud muteAllRemoteAudio:NO];
muteLocalAudio
only requires a pause or release of the data stream at the software level, thus it is more efficient and smoother. And it is better suited for scenarios that require frequent muting and unmuting.// Set audio quality during local audio capture and publishing.[self.trtcCloud startLocalAudio:TRTCAudioQualityDefault];// Dynamically set audio quality during audio streaming.[self.trtcCloud setAudioQuality:TRTCAudioQualityDefault];
// Set volume type.[self.trtcCloud setSystemVolumeType:TRTCSystemVolumeTypeAuto];
// Set audio routing.[self.trtcCloud setAudioRoute:TRTCAudioModeSpeakerphone];
// Send public screen bullet screen messages.[[V2TIMManager sharedInstance] sendGroupTextMessage:text to:groupID priority:V2TIM_PRIORITY_NORMAL succ:^{// Successfully sent bullet screen messages.} fail:^(int code, NSString *desc) {// Failed to send bullet screen messages.}];// Receive public screen bullet screen messages.[[V2TIMManager sharedInstance] addSimpleMsgListener:self];- (void)onRecvGroupTextMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info text:(NSString *)text {NSLog(@"%@: %@", info.nickName, text);}
// Enable volume level callback. It is recommended to be enabled immediately after successful room entry.// interval: Callback interval (ms). enable_vad: Whether to enable voice detection.[self.trtcCloud enableAudioVolumeEvaluation:interval enable_vad:enable_vad];self.trtcCloud.delegate = self;- (void)onUserVoiceVolume:(NSArray<TRTCVolumeInfo *> *)userVolumes totalVolume:(NSInteger)totalVolume {// userVolumes is used to hold the volume levels of all speaking users, including both local users and remote streaming users.// totalVolume is used to report the maximum volume value among remote streaming users....// Adjust the corresponding visual representation of sound waves on the UI based on volume levels....}
userVolumes
is an array. For each element in the array, when userId is empty, it means the volume captured by the local mic; when userId is not empty, it means the volume of remote users.// Obtain the management class for configuring background music, short sound effects, and voice special effects.self.audioEffectManager = [self.trtcCloud getAudioEffectManager];TXAudioMusicParam *param = [[TXAudioMusicParam alloc] init];param.ID = musicID;param.path = musicPath;// Whether to publish the music to remote (otherwise play locally only).param.publish = YES;// Whether the playback is from a short sound effect file.param.isShortFile = NO;// Start background music playback.__weak typeof(self) weakSelf = self;[self.audioEffectManager startPlayMusic:param onStart:^(NSInteger errCode) {__strong typeof(weakSelf) strongSelf = weakSelf;// Playback start callback.// -4001: Path opening failed.// -4002: Decoding failed.// -4003: Invalid URL address.// -4004: Playback not stopped.if (errCode < 0) {// Before replaying after playback failure, you must first stop the current music.[strongSelf.audioEffectManager stopPlayMusic:musicID];}} onProgress:^(NSInteger progressMs, NSInteger durationMs) {// Playback progress callback.// progressMs: Current playback duration (milliseconds).// durationMs: Total duration of the current music (milliseconds).} onComplete:^(NSInteger errCode) {// Playback end callback.// Playback failure due to weak network during playback will also throw this callback. In this case, errCode < 0.// Pausing or stopping playback midway will not trigger the onComplete callback.}];// Stop background music playback.[self.audioEffectManager stopPlayMusic:musicID];// Pause background music playback.[self.audioEffectManager pausePlayMusic:musicID];// Resume background music playback.[self.audioEffectManager resumePlayMusic:musicID];
musicPath
. MP3/AAC/M4A/WAV formats are supported.// Set the local playback volume of a piece of background music.[self.audioEffectManager setMusicPlayoutVolume:musicID volume:volume];// Set the remote playback volume of a specific background music.[self.audioEffectManager setMusicPublishVolume:musicID volume:volume];// Set the local and remote volume of all background music.[self.audioEffectManager setAllMusicVolume:volume];// Set the volume of voice capture.[self.audioEffectManager setVoiceVolume:volume];
setVoiceVolume(0)
to replace muteLocalAudio(true)
.AudioMusicParam
's loopCount
parameter to set the number of loop playbacks.- (void)startPlayMusicWithId:(int32_t)musicId path:(NSString *)path loopCount:(NSInteger)loopCount {TXAudioMusicParam *param = [[TXAudioMusicParam alloc] init];param.ID = musicId;param.path = path;param.publish = YES;// Whether the playback is from a short sound effect file.param.isShortFile = YES;// Set the number of loop playbacks. Negative number means an infinite loop.param.loopCount = loopCount < 0 ? NSIntegerMax : loopCount;[self.audioEffectManager startPlayMusic:param onStart:nil onProgress:nil onComplete:nil];}
onComplete
callback after each loop playback. It will only be triggered after all the set loop counts have been played.onComplete
. It is usually used for list loop or single track loop.- (void)repeatPlayMusicWithParam:(TXAudioMusicParam *)param {__weak typeof(self) weakSelf = self;[self.audioEffectManager startPlayMusic:param onStart:nil onProgress:nil onComplete:^(NSInteger errCode) {__strong typeof(weakSelf) strongSelf = weakSelf;// Here you can re-call the playback API to achieve loop playback of the music.if (errCode >= 0) {[strongSelf repeatPlayMusicWithParam:param];}}];}
- (void)startPublishMediaToCDN:(NSString *)streamName {NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0];// Expiration time of the streaming URL. By default, it is one day.NSTimeInterval time = [date timeIntervalSince1970] + (24 * 60 * 60);// LIVE_URL_KEY authentication key. Obtain from the streaming URL configuration page in the console.NSString *secretParam = [self getSafeUrl:LIVE_URL_KEY streamName:streamName time:time];// The target URLs for media stream publication.TRTCPublishTarget *target = [[TRTCPublishTarget alloc] init];// Publish to CDN after mixing.target.mode = TRTCPublishMixStreamToCdn;TRTCPublishCdnUrl* cdnUrl = [[TRTCPublishCdnUrl alloc] init];// Streaming URL must include parameters. Otherwise, streaming fails.cdnUrl.rtmpUrl = [NSString stringWithFormat:@"rtmp://%@/live/%@?%@", PUSH_DOMAIN, streamName, secretParam];// True means Tencent CSS push URLs, and false means third-party services.cdnUrl.isInternalLine = YES;NSMutableArray* cdnUrlList = [NSMutableArray new];// Multiple CDN push URLs can be added.[cdnUrlList addObject:cdnUrl];target.cdnUrlList = cdnUrlList;TRTCStreamEncoderParam* encoderParam = [[TRTCStreamEncoderParam alloc] init];// Set the encoding parameters of the transcoded audio stream (can be customized).encoderParam.audioEncodedSampleRate = 48000;encoderParam.audioEncodedChannelNum = 1;encoderParam.audioEncodedKbps = 50;encoderParam.audioEncodedCodecType = 0;// Set the encoding parameters of the transcoded video stream (must be filled in if mixing black frames, and can be ignored for pure audio mix stream).encoderParam.videoEncodedWidth = 64;encoderParam.videoEncodedHeight = 64;encoderParam.videoEncodedFPS = 15;encoderParam.videoEncodedGOP = 3;encoderParam.videoEncodedKbps = 30;// Configuration parameters for media stream transcoding.TRTCStreamMixingConfig *config = [[TRTCStreamMixingConfig alloc] init];// By default, leave this field empty. It indicates that all audio in the room will be mixed.config.audioMixUserList = nil;// Must have TRTCVideoLayout parameters if mixing black frames (can be ignored for pure audio mix stream).TRTCVideoLayout *layout = [[TRTCVideoLayout alloc] init];config.videoLayoutList = @[layout];// Start mixing and relaying mixed streams.[self.trtcCloud startPublishMediaStream:target encoderParam:encoderParam mixingConfig:config];}
- (void)startPublishMediaToRoom:(NSString *)roomId userID:(NSString *)userId {// The target URLs for media stream publication.TRTCPublishTarget *target = [[TRTCPublishTarget alloc] init];// After mixing, the stream is relayed back to the room.target.mode = TRTCPublishMixStreamToRoom;target.mixStreamIdentity.strRoomId = roomId;// Mixed stream robot's userid, must not duplicate with other users' userid in the room.target.mixStreamIdentity.userId = [NSString stringWithFormat:@"%@%@", userId, MIX_ROBOT];TRTCStreamEncoderParam* encoderParam = [[TRTCStreamEncoderParam alloc] init];// Set the encoding parameters of the transcoded audio stream (can be customized).encoderParam.audioEncodedSampleRate = 48000;encoderParam.audioEncodedChannelNum = 2;encoderParam.audioEncodedKbps = 64;encoderParam.audioEncodedCodecType = 2;// Set the encoding parameters of the transcoded video stream (can be ignored for pure audio mix stream).encoderParam.videoEncodedWidth = 64;encoderParam.videoEncodedHeight = 64;encoderParam.videoEncodedFPS = 15;encoderParam.videoEncodedGOP = 3;encoderParam.videoEncodedKbps = 30;// Set audio mixing parameters.TRTCStreamMixingConfig *config = [[TRTCStreamMixingConfig alloc] init];// By default, leave this field empty. It indicates that all audio in the room will be mixed.config.audioMixUserList = nil;// Configure video mixing template (can be ignored for pure audio mix stream).TRTCVideoLayout *layout = [[TRTCVideoLayout alloc] init];config.videoLayoutList = @[layout];// Start mixing and relaying mixed streams.[self.trtcCloud startPublishMediaStream:target encoderParam:encoderParam mixingConfig:config];}
#pragma mark - TRTCCloudDelegate- (void)onStartPublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(NSDictionary *)extraInfo {// taskId: When the request is successful, TRTC backend will provide the taskId of this task in the callback. You can later use this taskId with updatePublishMediaStream and stopPublishMediaStream to update and stop.// code: Callback result. 0 means success and other values mean failure.}- (void)onUpdatePublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(NSDictionary *)extraInfo {// When you call the publish media stream API (updatePublishMediaStream), the taskId you provide will be returned to you through this callback. It is used to identify which update request the callback belongs to.// code: Callback result. 0 means success and other values mean failure.}- (void)onStopPublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(NSDictionary *)extraInfo {// When you call the stop publishing media stream API (stopPublishMediaStream), the taskId you provide will be returned to you through this callback. It is used to identify which stop request the callback belongs to.// code: Callback result. 0 means success and other values mean failure.}
startPublishMediaStream
.// taskId: Task ID returned by the onStartPublishMediaStream callback.// target: For example, add or remove the published CDN URLs.// params: It is recommended to maintain consistency in the encoding output parameters for the media stream to avoid interruptions during playback.// config: Update the list of users involved in mix stream transcoding, such as cross-room competition.[self.trtcCloud updatePublishMediaStream:taskId publishTarget:target encoderParam:trtcStreamEncoderParam mixingConfig:trtcStreamMixingConfig];
startPublishMediaStream
.// taskId: Task ID returned by the onStartPublishMediaStream callback.[self.trtcCloud stopPublishMediaStream:taskId];
startPublishMediaStream
. If you have only initiated one media stream or want to stop all media streams initiated by you, this method is recommended.onNetworkQuality
to real-time monitor the network quality of both local and remote users. This callback is thrown every 2 seconds.#pragma mark - TRTCCloudDelegate- (void)onNetworkQuality:(TRTCQualityInfo *)localQuality remoteQuality:(NSArray<TRTCQualityInfo *> *)remoteQuality {// localQuality userId is empty. It represents the local user's network quality evaluation result.// remoteQuality represents the remote user's network quality evaluation result. The result is affected by both remote and local factors.switch(localQuality.quality) {case TRTCQuality_Unknown:NSLog(@"Undefined.");break;case TRTCQuality_Excellent:NSLog(@"The current network is excellent.");break;case TRTCQuality_Good:NSLog(@"The current network is good.");break;case TRTCQuality_Poor:NSLog(@"The current network is moderate.");break;case TRTCQuality_Bad:NSLog(@"The current network is poor.");break;case TRTCQuality_Vbad:NSLog(@"The current network is very poor.");break;case TRTCQuality_Down:NSLog(@"The current network does not meet the minimum requirements of TRTC.");break;default:break;}}
TRTCParams *params = [[TRTCParams alloc] init];params.sdkAppId = SDKAppID;params.roomId = self.roomId;params.userId = self.userId;// UserSig obtained from the business backend.params.userSig = [self getUserSig];// PrivateMapKey obtained from the backend.params.privateMapKey = [self getPrivateMapKey];params.role = TRTCRoleAudience;[self.trtcCloud enterRoom:params appScene:TRTCAppSceneVoiceChatRoom];
// Pass in the latest PrivateMapKey obtained from the backend into the role switching API.[self.trtcCloud switchRole:TRTCRoleAnchor privateMapKey:[self getPrivateMapKey]];
onError
callback. For details, see Error Code Table.Enumeration | Value | Description |
ERR_TRTC_INVALID_USER_SIG | -3320 | Room entry parameter userSig is incorrect. Check if TRTCParams.userSig is empty. |
ERR_TRTC_USER_SIG_CHECK_FAILED | -100018 | UserSig verification failed. Check if the parameter TRTCParams.userSig is filled in correctly or has expired. |
Enumeration | Value | Description |
ERR_TRTC_CONNECT_SERVER_TIMEOUT | -3308 | Room entry request timed out. Check if your internet connection is lost or if a VPN is enabled. You may also attempt to switch to 4G for testing. |
ERR_TRTC_INVALID_SDK_APPID | -3317 | Room entry parameter sdkAppId is incorrect. Check if TRTCParams.sdkAppId is empty. |
ERR_TRTC_INVALID_ROOM_ID | -3318 | Room entry parameter roomId is incorrect. Check if TRTCParams.roomId or TRTCParams.strRoomId is empty. Note that roomId and strRoomId cannot be used interchangeably. |
ERR_TRTC_INVALID_USER_ID | -3319 | Room entry parameter userId is incorrect. Check if TRTCParams.userId is empty. |
ERR_TRTC_ENTER_ROOM_REFUSED | -3340 | Room entry request is denied. Check if enterRoom is called consecutively to enter rooms with the same ID. |
Enumeration | Value | Description |
ERR_MIC_START_FAIL | -1302 | Failed to open the mic. For example, if there is an exception for the mic's configuration program (driver) on a Windows or macOS device, you should try disabling then re-enabling the device, restarting the machine, or updating the configuration program. |
ERR_SPEAKER_START_FAIL | -1321 | Failed to open the speaker. For example, if there is an exception for the speaker's configuration program (driver) on a Windows or macOS device, you should try disabling then re-enabling the device, restarting the machine, or updating the configuration program. |
ERR_MIC_OCCUPY | -1319 | The mic is occupied. This occurs when, for example, the user is currently having a call on the mobile device. |
onConnectionLost
callback, display a network disconnection icon on the local seat UI to notify the user. Simultaneously, initiate a local timer. If the onConnectionRecovery
callback is not received after exceeding the set time threshold, it means the network remains disconnected. Then, locally initiate leaving the seatmic and room exit process. Pop up a window to inform the user that they have exited the room and the page will be closed. If the disconnection exceeds 90 seconds (default), a timeout room-exit will be triggered, and the TRTC server will remove the user from the room. If the user has an anchor role, other users in the room will receive the onRemoteUserLeaveRoom
callback.#pragma mark - TRTCCloudDelegate- (void)onConnectionLost {// The connection between the SDK and the cloud has been disconnected.}- (void)onTryToReconnect {// The SDK is attempting to reconnect to the cloud.}- (void)onConnectionRecovery {// The connection between the SDK and the cloud has been restored.}
// Anchor subscribes to the connection status of mic-connecting audiences.[[V2TIMManager sharedInstance] subscribeUserStatus:userList succ:^{// Subscription of user status succeeded.} fail:^(int code, NSString *desc) {// Subscription of user status failed.}];// Anchor unsubscribes from the connection status of audiences leaving the seat.[[V2TIMManager sharedInstance] unsubscribeUserStatus:userList succ:^{// Unsubscription of user status succeeded.} fail:^(int code, NSString *desc) {// Failed to unsubscription of user status.}];// User status change notification and processing.[[V2TIMManager sharedInstance] addIMSDKListener:self];- (void)onUserStatusChanged:(NSArray<V2TIMUserStatus *> *)userStatusList {for (V2TIMUserStatus *userStatus in userStatusList) {NSString *userId = userStatus.userID;V2TIMUserStatusType status = userStatus.statusType;if (status == V2TIM_USER_STATUS_OFFLINE) {// Remove an offline-status user.[self kickSeatWithIndex:[self getSeatIndexWithUserId:userId]];}}}
subscribeUserStatus
.https://trtc.tencentcloudapi.com/?Action=RemoveUser&SdkAppId=1400000001&RoomId=1234&UserIds.0=test1&UserIds.1=test2&<Common request parameters>
onExitRoom()
callback on the client, with the reason
value being 1. At this moment, you can handle leaving the seat and exiting the IM group in this callback.// Exit TRTC room event callback.- (void)onExitRoom:(NSInteger)reason {if (reason == 0) {// Actively call exitRoom to exit the room.NSLog(@"Exit current room by calling the 'exitRoom' api of sdk ...");} else {// reason 1: Removed from the current room by the server.// reason 2: The current room is dissolved.NSLog(@"Kicked out of the current room by server or current room is dissolved ...");// Leave the seat.[self leaveSeatWithIndex:seatIndex];// Exit IM group.[[V2TIMManager sharedInstance] quitGroup:groupID succ:^{// Exiting the group successful.} fail:^(int code, NSString *desc) {// Exiting the group failed.}];}}
https://xxxxxx/v4/group_open_http_svc/destroy_group?sdkappid=88888888&identifier=admin&usersig=xxx&random=99999999&contenttype=json
onGroupDismissed()
callback on clients. At this point, you can handle operations such as exiting the TRTC room in this callback.// Group dissolved callback.[[V2TIMManager sharedInstance] addGroupListener:self];- (void)onGroupDismissed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser {// Exit TRTC room.[self.trtcCloud stopLocalAudio];[self.trtcCloud exitRoom];}
exitRoom()
, the TRTC room will be automatically dissolved. Of course, you can also mandatorily dissolve the TRTC room by calling the server API DismissRoom (for integer room IDs) or DismissRoomByStrRoomId (for string room IDs).V2TIMMessageListGetOption *option = [[V2TIMMessageListGetOption alloc] init];option.getType = V2TIM_GET_CLOUD_OLDER_MSG; // Pull earlier existing messages from the cloud.option.getTimeBegin = 1640966400; // Starting from midnight January 1, 2022.option.getTimePeriod = 1 * 24 * 60 * 60; // Pull messages from a 24-hour period.option.count = INT_MAX; // Return all messages within the time range.option.groupID = #your group id#; // Pull messages for the group chat.[V2TIMManager.sharedInstance getHistoryMessageList:option succ:^(NSArray<V2TIMMessage *> *msgs) {NSLog(@"success");} fail:^(int code, NSString *desc) {NSLog(@"failure, code:%d, desc:%@", code, desc);}];
onUserAudioAvailable(userId, true)
callback.- (void)onUserAudioAvailable:(NSString *)userId available:(BOOL)available {if (available) {// Unmute the corresponding anchors.}}
[[V2TIMManager sharedInstance] getGroupAttributes:groupID keys:nil succ:^(NSMutableDictionary<NSString *,NSString *> *groupAttributeList) {// Successfully obtained group attributes. It is assumed that the key used to store the mute status of the anchors is muteStatus.NSString *muteStatus = groupAttributeList[@"muteStatus"];// Parse muteStatus, and obtain the mute status of each on-mic anchor.} fail:^(int code, NSString *desc) {// Failed to obtain the group attributes.}];
Was this page helpful?