(前面我们已经了解TRTC的基本架构和功能,现在我们就来接入实时视频通话功能,此功能和微信的一对一视频通话是一致的,需要两个角色,一个角色是主动呼叫、一个为呼叫接听,结合使用场景我们来接入此功能。
新工程准备
由于SDK已经有Swift的 此工程使用OC来编写。
新建工程
Xcode12新建工程不再默认是OC而是Swift(可见Swift才是苹果的亲儿子),切换成OC也很简单,只要在interface、lifeCycle、language中不选择【Swift】选项即可(先切换interface)。
使用Cocoapods导入TRTC 专业版,导入成功后可以在工程的Pods里面查看到
测试app的UI页面我们可以自定义,但是串联接听和拨打信令可以用腾讯提供的通话组件 - TRTCCalling,将Demo中的model文件夹导入我们的新工程中。
由于TRTCCalling同时依赖于TRTC和IM SDK,所以我们还需要通过pod导入“TXIMSDK_iOS”。
再导入自己常用的一些库和工具包等,根据自己的需求导入,编译通过即可进行下一步。
配置权限
因为在使用实时音视频的时候避免不了使用到麦克风和摄像头,所以我们要向系统申请使用权限,在info.plist文件中添加一下两个key和对应的描述:
key | 描述 |
---|---|
Privacy - Camera Usage Description | App需要使用摄像头权限,开启后才会有视频画面 |
Privacy - Microphone Usage Description | App需要使用麦克风权限,开启后才会有语音信息 |
权限添加之后我们就可以开心的尝试下功能了!
实时视频通话Coding
如果在新建工程之后对SceneDelegate有疑问请点击此处来详细了解。我门测试App不需要使用多窗口的功能,所以不会使用SceneDelegate。
初始化并登录组件
设置推送相关 imBusinessID和deviceToken在下图配置并查找,找到自己对应的App,点击进入配置推送。
配置推送,和极光推送配置基本上是一致的。
初始化推送信息,此功能为在App非活跃状态下也可接受信息
代码语言:javascript复制[TRTCCalling shareInstance].imBusinessID = your business ID;
[TRTCCalling shareInstance].deviceToken = deviceToken;
登录IM组件,其中GenerateTestUserSig类在SDK的demo中有使用,可自行拖入工程进行计算userSig。
代码语言:javascript复制// sdkAppID 为实时音视频创建的应用,分配的SDKAppID
// userSig 为当前登录用户的用户名 SDKAppID 秘钥生成的签名 (可通过GenerateTestUserSig类获取)
NSString *usersig = [GenerateTestUserSig genTestUserSig:@"123456"];
//登录组件
[[TRTCCalling shareInstance] login:1400433373 user:@"123456" userSig:usersig success:^{
NSLog(@"登录组建成功");
} failed:^(int code, NSString * _Nonnull des) {
NSLog(@"%d----%@",code,des);
}];
实现1V1通话
我们在新的Controller的页面新建一个按钮和输入框,来接收用户需要呼叫的对象和呼叫手势,当输入完需要呼叫对象后,点击呼叫按钮开始呼叫。
当开始呼叫时代码都做了些什么呢?
1. 实例化TRTCCloud,设置代理
代码语言:objective-c复制TRTCCloud *clould = [TRTCCloud sharedInstance];
clould.delgate = self;
2.组装入房参数,参数说明:
代码语言:javascript复制TRTCParams *param = [[TRTCParams alloc] init];
param.sdkAppId = self.mSDKAppID;
param.userId = self.mUserID;
param.userSig = self.mUserSig;
param.roomId = self.curRoomID;
参数名称 | 字段类型 | 补充说明 | 填写示例 |
---|---|---|---|
sdkAppId | 数字 | 应用 ID,您可以在 实时音视频控制台 中查看 SDKAppID。 | 1400000123 |
userId | 字符串 | 只允许包含大小写英文字母(a-z、A-Z)、数字(0-9)及下划线和连词符。 | test_user_001 |
userSig | 字符串 | 基于 userId 可以计算出 userSig,计算方法请参见 如何计算 UserSig 。 | eJyrVareCeYrSy1SslI... |
roomId | 数字 | 默认不支持字符串类型的房间号,字符串类型的房间号会影响进房速度。(调用 enterRoom() 即可加入 TRTCParams 参数中roomId代指的音视频房间。如果该房间不存在,SDK 会自动创建一个以字段roomId的值为房间号的新房间。) | 29834 |
sdkAppId查询地址、userSig计算方法
3.进入房间并设置通话类型
代码语言:javascript复制[[TRTCCloud sharedInstance] enterRoom:param appScene:TRTCAppSceneAudioCall];
//开启音频采集并发送出去
[[TRTCCloud sharedInstance] startLocalAudio];
//启用音量大小提示
[[TRTCCloud sharedInstance] enableAudioVolumeEvaluation:300];
4.需要实现TRTCCloud的代理方法
错误回调
代码语言:javascript复制/**
* 1.1 错误回调,表示 SDK 不可恢复的错误,一定要监听并分情况给用户适当的界面提示。
*
* @param errCode 错误码
* @param errMsg 错误信息
* @param extInfo 扩展信息字段,个别错误码可能会带额外的信息帮助定位问题
*出现错误后可以及时停止通话
*/
- (void)onError:(TXLiteAVError)errCode errMsg:(nullable NSString *)errMsg
extInfo:(nullable NSDictionary*)extInfo {
self.curLastModel.code = errCode;
if ([self canDelegateRespondMethod:@selector(onCallEnd)]) {
[self.delegate onCallEnd];
}
[self hangup];
}
进房成功后回调
代码语言:objective-c复制/**
* 调用 TRTCCloud 中的 enterRoom() 接口执行进房操作后,会收到来自 SDK 的 onEnterRoom(result) 回调:
*
* - 如果加入成功,result 会是一个正数(result > 0),代表加入房间的时间消耗,单位是毫秒(ms)。
* - 如果加入失败,result 会是一个负数(result < 0),代表进房失败的错误码。
* @param result result > 0 时为进房耗时(ms),result < 0 时为进房错误码。
*/
- (void)onEnterRoom:(NSInteger)result {
if (result < 0) {
self.curLastModel.code = result;
if ([self canDelegateRespondMethod:@selector(onCallEnd)]) {
[self.delegate onCallEnd];
}
[self hangup];
}
}
注:
如果进房失败,SDK 同时还会回调onError事件,并返回参数errCode(错误码)、errMsg(错误原因) 以及extraInfo(保留参数)
如果已在某一个房间中,则必须先调用
exitRoom()
退出当前房间,才能进入下一个房间。
5.设置麦克风静音开启、关闭,扬声器切换方法
代码语言:objective-c复制/**
* 静音/取消静音本地的音频
*
* 当静音本地音频后,房间里的其它成员会收到 onUserAudioAvailable(userId, NO) 回调通知。
* 当取消静音本地音频后,房间里的其它成员会收到 onUserAudioAvailable(userId, YES) 回调通知。
*
* 与 stopLocalAudio 不同之处在于,muteLocalAudio:YES 并不会停止发送音视频数据,而是继续发送码率极低的静音包。
* 由于 MP4 等视频文件格式,对于音频的连续性是要求很高的,使用 stopLocalAudio 会导致录制出的 MP4 不易播放。
* 因此在对录制质量要求很高的场景中,建议选择 muteLocalAudio,从而录制出兼容性更好的 MP4 文件。
*
* @param mute YES:静音;NO:取消静音
*/
- (void)muteLocalAudio:(BOOL)mute;
代码语言:javascript复制/**
* 扬声器切换
*
* 微信和手机 QQ 视频通话功能的免提模式就是基于音频路由实现的。
* 一般手机都有两个扬声器,一个是位于顶部的听筒扬声器,声音偏小;一个是位于底部的立体声扬声器,声音偏大。
* 设置音频路由的作用就是决定声音使用哪个扬声器播放。
*
* @param route 音频路由,即声音由哪里输出(扬声器、听筒),默认值:TRTCAudioModeSpeakerphone
*/
- (void)setAudioRoute:(TRTCAudioRoute)route;
typedef NS_ENUM(NSInteger, TRTCAudioRoute) {
TRTCAudioModeSpeakerphone = 0, ///< 扬声器
TRTCAudioModeEarpiece = 1, ///< 听筒
};
设置订阅模式:自动订阅(默认)和手动订阅。
自动订阅:
当房间中有其他用户在上行音频数据时,会收到 onUserAudioAvailable() 事件通知,SDK 会自动播放这些远端用户的声音。
代码语言:javascript复制- (void)onUserAudioAvailable:(NSString *)userID available:(BOOL)available {
}
屏蔽所有远端用户的音频
代码语言:javascript复制/**
* 静音/取消静音所有用户的声音
*
* @param mute YES:静音;NO:取消静音
*
* @note 静音时会停止接收所有用户的远端音频流并停止播放,取消静音时会自动拉取所有用户的远端音频流并进行播放。
*/
- (void)muteAllRemoteAudio:(BOOL)mute;
手动订阅:
切换手动订阅,需要在进房间之前调用才有效
代码语言:javascript复制/**
* 设置音视频数据接收模式,需要在进房前设置才能生效
*
* 为实现进房秒开的绝佳体验,SDK 默认进房后自动接收音视频。即在您进房成功的同时,您将立刻收到远端所有用户的音视频数据。
* 若您没有调用 startRemoteView,视频数据将自动超时取消。
* 若您主要用于语音聊天等没有自动接收视频数据需求的场景,您可以根据实际需求选择接收模式。
*
* @param autoRecvAudio YES:自动接收音频数据;NO:需要调用 muteRemoteAudio 进行请求或取消。默认值:YES
* @param autoRecvVideo YES:自动接收视频数据;NO:需要调用 startRemoteView/stopRemoteView 进行请求或取消。默认值:YES
*
* @note 需要在进房前设置才能生效。
**/
- (void)setDefaultStreamRecvMode:(BOOL)autoRecvAudio video:(BOOL)autoRecvVideo;
当有用户在房间中上行音频数据时还是会回调以下方法,
代码语言:javascript复制- (void)onUserAudioAvailable:(NSString *)userID available:(BOOL)available {
}
这时需要我们调用以下方法来订阅用户的音频,手动订阅之后SDK会自行解码并播放。
代码语言:javascript复制- (void)muteRemoteAudioWithUserID:(NSString *)userID isMuted:(BOOL)isMuted
NS_SWIFT_NAME(muteRemoteAudio(userID:isMuted:));
退出房间
代码语言:javascript复制//离开房间
//调用 exitRoom() 接口会执行退出房间的相关逻辑,例如释放音视频设备资源和编解码器资源等。 待资源释放完毕,SDK 会通过 TRTCCloudDelegate 中的 onExitRoom() 回调通知到您。
//如果您要再次调用 enterRoom() 或者切换到其他的音视频 SDK,请等待 onExitRoom() 回调到来之后再执行相关操作。 否则可能会遇到摄像头或麦克风(例如 iOS 里的 AudioSession)被占用等各种异常问题。
- (void) exitRoom;
1v1视频通话
视频通话是在音频通话上增加远端视频的显示、本地视频采集、推送、摄像头切换等
获取远端视频渲染
代码语言:objective-c复制/**
* 开始显示远端视频画面
*
* 在收到 SDK 的 onUserVideoAvailable(userid, YES) 通知时,可以获知该远程用户开启了视频,
* 此后调用 startRemoteView(userid) 接口加载该用户的远程画面,此时可以用 loading 动画优化加载过程中的等待体验。
* 待该用户的首帧画面开始显示时,您会收到 onFirstVideoFrame(userId) 事件回调。
*
* @param userId 对方的用户标识
* @param view 承载视频画面的控件
*/
- (void)startRemoteView:(NSString *)userId view:(TXView *)view;
此处有坑:
注意:userID尽量不要是纯数字,此方法内部有严格的类型限制(猜测),如果使用过短的纯数字userID并使用对象保存时,在测试时无法播放出该用户视频,其原因为NSString在保存短的纯数字字符串时会使用Tagged Pointer技术,在查看其类型并不是__NSCFConstantString。
代码语言:objective-c复制 NSLog(@"----%@----",[self.userID class]);
NSLog(@"----%@----",[@"123456" class]);
代码语言:javascript复制2020-10-13 10:19:08.144046 0800 TestTRTC[6153:47191] ----NSTaggedPointerString----
2020-10-13 10:19:08.144149 0800 TestTRTC[6153:47191] ----__NSCFConstantString----
停止远端视频及停止所有远端视频,可根据自己实际情况选择
代码语言:javascript复制/**
* 停止显示远端视频画面,同时不再拉取该远端用户的视频数据流
*
* 调用此接口后,SDK 会停止接收该用户的远程视频流,同时会清理相关的视频显示资源。
*
* @param userId 对方的用户标识
*/
- (void)stopRemoteView:(NSString *)userId;
/**
* 停止显示所有远端视频画面,同时不再拉取远端用户的视频数据流
*
* @note 如果有屏幕分享的画面在显示,则屏幕分享的画面也会一并被关闭。
*/
- (void)stopAllRemoteView;
也可以暂停、恢复远端视频流
代码语言:javascript复制/**
* 暂停/恢复接收指定的远端视频流(单用户)
*
* 该接口仅暂停/恢复接收指定的远端用户的视频流,但并不释放显示资源,所以如果暂停,视频画面会冻屏在 mute 前的最后一帧。
*
* @param userId 对方的用户标识
* @param mute 是否暂停接收
*/
- (void)muteRemoteVideoStream:(NSString*)userId mute:(BOOL)mute;
/**
* 暂停/恢复接收所有远端视频流
*
* 该接口仅暂停/恢复接收所有远端用户的视频流,但并不释放显示资源,所以如果暂停,视频画面会冻屏在 mute 前的最后一帧。
*
* @param mute 是否暂停接收
*/
- (void)muteAllRemoteVideoStreams:(BOOL)mute;
本地视频的采集与推送
代码语言:objective-c复制/**
* 开启本地视频的预览画面 (iOS 版本)
*
* 当开始渲染首帧摄像头画面时,您会收到 TRTCCloudDelegate 中的 onFirstVideoFrame(nil) 回调。
*
* @param frontCamera YES:前置摄像头;NO:后置摄像头。
* @param view 承载视频画面的控件
*/
- (void)startLocalPreview:(BOOL)frontCamera view:(TXView *)view;
停止本地视频视频采集
代码语言:objective-c复制/**
* 停止本地视频采集及预览
*/
- (void)stopLocalPreview;
暂停/恢复推送本地的视频数据
代码语言:objective-c复制/**
* 暂停/恢复推送本地的视频数据
*
* 当暂停推送本地视频后,房间里的其它成员将会收到 onUserVideoAvailable(userId, NO) 回调通知
* 当恢复推送本地视频后,房间里的其它成员将会收到 onUserVideoAvailable(userId, YES) 回调通知
*
* @param mute YES:暂停;NO:恢复
*/
- (void)muteLocalVideo:(BOOL)mute;
以上为1V1的视频语音通话常用的API,在下载的SDK内(非CocoaPods下载)Demo内部有已经封装好的TRTCCalling
可直接使用,如果功能不能满需求,可自行进行二次封装,自己写的Demo中即使用封装的TRTCCalling,后续会更新上来。如在接入中对API有不明白的可访问TRTC更加详细的API解释在这里。