123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- //
- // TXRTCService.m
- // TeacherDaya
- //
- // Created by 王智 on 2023/4/14.
- // Copyright © 2023 DayaMusic. All rights reserved.
- //
- #import "TXRTCService.h"
- #import "ClassroomService.h"
- #import "UserInfoManager.h"
- #import "TXIMLinsenter.h"
- //#import "MBProgressHUD+KSShow.h"
- @interface TXRTCService ()<TRTCCloudDelegate>
- @property (nonatomic, strong) NSString *userSig;
- @property (nonatomic, strong) NSString *sdkAppId;
- @property (nonatomic, strong) NSString *rtcAppKey;
- @property (nonatomic, strong) NSString *rtcUserSig;
- @property (nonatomic, strong) NSString *roomID;
- @property (nonatomic, copy) KSRTCCallback success;
- @property (nonatomic, copy) KSRTCCallback error;
- @property (nonatomic, strong) TRTCCloud *engine;
- @end
- @implementation TXRTCService
- + (instancetype)shareInstance {
- static TXRTCService *service = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- service = [[self alloc] init];
- [service defaultAudioSetting];
- });
- return service;
- }
- - (void)defaultAudioSetting {
- self.ANS = 0;
- self.AEC = 100;
- self.AGC = 0;
- }
- - (void)configWithRoomConfig:(TxRTCRoomConfig *)roomConfig successCallback:(void(^)(void))callback {
- self.userSig = roomConfig.userSig;
- self.sdkAppId = roomConfig.appKey;
- self.rtcAppKey = roomConfig.rtcAppKey;
- self.rtcUserSig = roomConfig.rtcUserSig;
- callback();
- }
- - (void)setting3AParmWithANS:(NSInteger)ANS AEC:(NSInteger)AEC AGC:(NSInteger)AGC {
- self.ANS = ANS;
- self.AEC = AEC;
- self.AGC = AGC;
- }
- #pragma mark - 发布/订阅音视频流
- - (void)joinRTCRoom:(NSString *)roomId success:(KSRTCCallback)success failer:(KSRTCCallback)error {
- if (success) {
- self.success = success;
- }
- if (error) {
- self.error = error;
- }
- [self.engine enterRoom:[self getTRTCRoomConfig:roomId] appScene:TRTCAppSceneVideoCall];
- self.engine.delegate = self;
- [self configDefaultHardwareStatus];
- }
- - (void)configDefaultHardwareStatus {
- [self configVideoAndAudioSetting];
- BOOL micOn = [ClassroomService sharedService].currentRoom.currentMember.microphoneEnable;
- [self setMicrophoneDisable:!micOn];
- BOOL cameraOn = [ClassroomService sharedService].currentRoom.currentMember.cameraEnable;
- [self setCameraDisable:!cameraOn];
-
- // 开启音量检测
- TRTCAudioVolumeEvaluateParams *parms = [[TRTCAudioVolumeEvaluateParams alloc] init];
- parms.interval = 300;
- [[TRTCCloud sharedInstance] enableAudioVolumeEvaluation:YES withParams:parms];
- }
- - (void)leaveRoom:(KSRTCCallback)callback {
- if (callback) {
- self.success = callback;
- }
- [self.engine exitRoom];
- _engine = nil;
- [TRTCCloud destroySharedIntance];
- if (callback) {
- callback(1);
- }
- }
- - (void)publishStream {
- NSString *currentUserID = [ClassroomService sharedService].currentRoom.currentMemberId;
- NSString *streamId = [NSString stringWithFormat:@"%@_%@", self.roomID, currentUserID];
- [self.engine startPublishing:streamId type:TRTCVideoStreamTypeBig];
- }
- - (void)configVideoAndAudioSetting {
- [self.engine startLocalAudio:TRTCAudioQualityMusic];
- TRTCVideoEncParam *videoEncParams = [[TRTCVideoEncParam alloc] init];
- videoEncParams.videoFps = 15.0f;
- videoEncParams.resMode = TRTCVideoResolutionModeLandscape;
- videoEncParams.videoResolution = TRTCVideoResolution_640_480;
- [self.engine setVideoEncoderParam:videoEncParams];
- [self.engine setGSensorMode:TRTCGSensorMode_UIFixLayout];
- // [self.engine setVideoMuteImage:[self generalCloseImage] fps:5];
- [self config3AWithANS:self.ANS AEC:self.AEC AGC:self.AGC];
- }
- - (UIImage *)generalCloseImage {
- UIView *backView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
- backView.backgroundColor = HexRGB(0xE9EDF3);
-
- UIView *layerView = [[UIView alloc] initWithFrame:CGRectMake((300 - 84)/2.0f, (300 - 84)/2.0f, 84, 84)];
- layerView.backgroundColor = HexRGB(0xffffff);
- layerView.layer.cornerRadius = 42;
- [backView addSubview:layerView];
-
- NSString *imageName = UserDefaultObjectForKey(AvatarUrlKey);
- UIImageView *avatar = [[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 80, 80)];
- if ([NSString isEmptyString:imageName]) {
- imageName = USERDEFAULT_LOGO;
- [avatar setImage:[UIImage imageNamed:imageName]];
- }
- else {
- [avatar sd_setImageWithURL:[NSURL URLWithString:[imageName getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
- }
- [layerView addSubview:avatar];
- avatar.layer.cornerRadius = 40;
- avatar.clipsToBounds = YES;
- avatar.contentMode = UIViewContentModeScaleAspectFill;
- //高清方法
- //第一个参数表示区域大小 第二个参数表示是否是非透明的。如果需要显示半透明效果,需要传NO,否则传YES。第三个参数就是屏幕密度了
- CGSize size = CGSizeMake(backView.layer.bounds.size.width, backView.layer.bounds.size.height);
- UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
- [backView.layer renderInContext:UIGraphicsGetCurrentContext()];
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- return image;
- }
- - (void)renderLocalUserInView:(UIView *)displayView isCameraEnable:(BOOL)cameraEnable {
- if (cameraEnable) {
- [self.engine setLocalRenderParams:[self getRenderParms:YES]];
- [self.engine startLocalPreview:[self isFrontCamera] view:displayView];
- }
- else {
- [self stopLocalPreview];
- }
- }
- - (void)stopLocalPreview {
- [self.engine stopLocalPreview];
- }
- - (void)renderRemoteUser:(NSString *)userId inView:(UIView *)displayView {
- [self cancleRenderUserVideo:userId];
- [self.engine setRemoteRenderParams:userId streamType:TRTCVideoStreamTypeBig params:[self getRenderParms:NO]];
- [self.engine startRemoteView:userId streamType:TRTCVideoStreamTypeBig view:displayView];
- }
- - (void)cancleRenderUserVideo:(NSString *)userId {
- NSString *currentUserID = [ClassroomService sharedService].currentRoom.currentMemberId;
- if (![userId isEqualToString:currentUserID]) {
- [self.engine stopRemoteView:userId streamType:TRTCVideoStreamTypeBig];
- }
- else {
-
- }
- }
- - (TRTCParams *)getTRTCRoomConfig:(NSString *)roomId {
- TRTCParams *params = [[TRTCParams alloc] init];
- params.sdkAppId = [self.sdkAppId intValue];
- params.userSig = self.rtcUserSig;
- params.strRoomId = roomId;
- params.userId = UserDefault(IM_USERID);
- return params;
- }
- // 配置3A参数
- - (void)config3AWithANS:(NSInteger)ANS AEC:(NSInteger)AEC AGC:(NSInteger)AGC {
- // [MBProgressHUD ksShowMessage:[NSString stringWithFormat:@"ANS : %zd, AEC: %zd, AGC:%zd", ANS, AEC, AGC]];
- [self configANSParm:ANS];
- [self configAECParm:AEC];
- [self configAGCParm:AGC];
- }
- // 背景音抑制
- - (void)configANSParm:(NSInteger)number {
- NSMutableDictionary *dic = [NSMutableDictionary dictionary];
- [dic setValue:@"enableAudioANS" forKey:@"api"];
- NSMutableDictionary *subDic = [NSMutableDictionary dictionary];
- if (number > 0) {
- [subDic setValue:@(1) forKey:@"enable"];
- [subDic setValue:@(number) forKey:@"level"];
- }
- else {
- [subDic setValue:@(0) forKey:@"enable"];
- [subDic setValue:@(0) forKey:@"level"];
- }
- [dic setValue:subDic forKey:@"params"];
- NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:kNilOptions error:nil];
- NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- [self.engine callExperimentalAPI:jsonString];
- }
- // 回声消除
- - (void)configAECParm:(NSInteger)number {
- NSMutableDictionary *dic = [NSMutableDictionary dictionary];
- [dic setValue:@"enableAudioAEC" forKey:@"api"];
- NSMutableDictionary *subDic = [NSMutableDictionary dictionary];
- if (number > 0) {
- [subDic setValue:@(1) forKey:@"enable"];
- [subDic setValue:@(number) forKey:@"level"];
- }
- else {
- [subDic setValue:@(0) forKey:@"enable"];
- [subDic setValue:@(0) forKey:@"level"];
- }
- [dic setValue:subDic forKey:@"params"];
- NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:kNilOptions error:nil];
- NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- [self.engine callExperimentalAPI:jsonString];
- }
- // 自动增益
- - (void)configAGCParm:(NSInteger)number {
- NSMutableDictionary *dic = [NSMutableDictionary dictionary];
- [dic setValue:@"enableAudioAGC" forKey:@"api"];
- NSMutableDictionary *subDic = [NSMutableDictionary dictionary];
- if (number > 0) {
- [subDic setValue:@(1) forKey:@"enable"];
- [subDic setValue:@(number) forKey:@"level"];
- }
- else {
- [subDic setValue:@(0) forKey:@"enable"];
- [subDic setValue:@(0) forKey:@"level"];
- }
- [dic setValue:subDic forKey:@"params"];
- NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:kNilOptions error:nil];
- NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- [self.engine callExperimentalAPI:jsonString];
- }
- #pragma mark --- TRTCCloudDelegate
- - (void)onEnterRoom:(NSInteger)result {
- if (result > 0) {
- if (self.success) {
- self.success(result);
- }
- }
- else {
- if (self.error) {
- [self.engine exitRoom];
- _engine = nil;
- [TRTCCloud destroySharedIntance];
- self.error(result);
- }
- }
- }
- - (void)onExitRoom:(NSInteger)reason {
- if (self.success) {
- self.success(reason);
- }
- }
- - (void)onError:(TXLiteAVError)errCode errMsg:(NSString *)errMsg extInfo:(NSDictionary *)extInfo {
- NSLog(@"tx rtc error --- code %d message : %@", errCode, errMsg);
- if (self.error) {
- self.error(errCode);
- }
- }
- #pragma mark ---- 用户进出房间
- - (void)onRemoteUserEnterRoom:(NSString *)userId {
-
- }
- - (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason {
-
- }
- - (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
-
- }
- - (void)onUserAudioAvailable:(NSString *)userId available:(BOOL)available {
-
- }
- // 网络质量
- - (void)onNetworkQuality:(TRTCQualityInfo *)localQuality remoteQuality:(NSArray<TRTCQualityInfo *> *)remoteQuality {
- if (self.delegate && [self.delegate respondsToSelector:@selector(didReportNetworkQuality:remoteQuality:)]) {
- [self.delegate didReportNetworkQuality:localQuality.quality remoteQuality:remoteQuality];
- }
- }
- // 音量
- - (void)onUserVoiceVolume:(NSArray<TRTCVolumeInfo *> *)userVolumes totalVolume:(NSInteger)totalVolume {
- if (self.delegate && [self.delegate respondsToSelector:@selector(didReportUserVolume:)]) {
- [self.delegate didReportUserVolume:userVolumes];
- }
- }
- #pragma mark ---- 不播放音频流
- - (void)unPlayRemoteStudentAudioStreamExcept:(NSString *)studentId {
-
- NSMutableArray *memberList = [[ClassroomService sharedService].currentRoom.memberList mutableCopy];
- for (RoomMember *member in memberList) {
- if (member.role == RoleStudent) {
- if ([member.userId isEqualToString:studentId]) {
- [self.engine setRemoteAudioVolume:member.userId volume:100];
- }
- else {
- [self.engine setRemoteAudioVolume:member.userId volume:0];
- }
- }
- }
- }
- - (void)playAllRemoteStudentAudioStream {
- NSMutableArray *memberList = [[ClassroomService sharedService].currentRoom.memberList mutableCopy];
- for (RoomMember *member in memberList) {
- if (member.role == RoleStudent) {
- [self.engine setRemoteAudioVolume:member.userId volume:100];
- }
- }
- }
- - (void)unPlayRemoteStudentWithId:(NSString *)studentId {
- if (![NSString isEmptyString:studentId]) {
- [[TRTCCloud sharedInstance] setRemoteAudioVolume:studentId volume:0];
- }
- }
- #pragma mark - 顶部工具栏接口
- /**
- 关闭/打开麦克风
-
- @param disable YES 关闭,NO 打开
- */
- - (void)setMicrophoneDisable:(BOOL)disable {
- if (disable) {
- [self.engine setAudioCaptureVolume:0];
-
- }
- else {
- [self.engine setAudioCaptureVolume:100];
- }
- }
- /**
- 采集运行中关闭或打开摄像头
-
- @param disable YES 关闭,否则打开
- */
- - (void)setCameraDisable:(BOOL)disable {
- [self.engine muteLocalVideo:TRTCVideoStreamTypeBig mute:disable];
- }
- /**
- 切换前后摄像头
- */
- - (void)switchCamera {
- TXDeviceManager *deviceManager = [self.engine getDeviceManager];
- BOOL isFrontCamera = [deviceManager isFrontCamera];
- [deviceManager switchCamera:!isFrontCamera];
- }
- - (BOOL)isFrontCamera {
- TXDeviceManager *deviceManager = [self.engine getDeviceManager];
- BOOL isFrontCamera = [deviceManager isFrontCamera];
- return isFrontCamera;
- }
- /**
- 切换使用外放/听筒
- */
- - (void)useSpeaker:(BOOL)useSpeaker {
- TXDeviceManager *deviceManager = [self.engine getDeviceManager];
- TXAudioRoute route = useSpeaker ? TXAudioRouteSpeakerphone :TXAudioRouteEarpiece;
- [deviceManager setAudioRoute:route];
- }
- - (TRTCRenderParams *)getRenderParms:(BOOL)isLocal {
- TRTCRenderParams *parms = [[TRTCRenderParams alloc] init];
- parms.fillMode = TRTCVideoFillMode_Fill;
- parms.mirrorType = TRTCVideoMirrorTypeAuto;
- return parms;
- }
- - (TRTCCloud *)engine {
- if (!_engine) {
- _engine = [TRTCCloud sharedInstance];
- }
- return _engine;
- }
- @end
|