| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613 |
- //
- // BGTPublishController.m
- // BuguLive
- //
- // Created by xfg on 16/12/5.
- // Copyright © 2016年 xfg. All rights reserved.
- //
- #import "BGTPublishController.h"
- #import <Foundation/Foundation.h>
- #import <TXLiteAVSDK_Professional/TXLiveSDKTypeDef.h>
- #import <TXLiteAVSDK_Professional/TXLiveBase.h>
- //#import <TXLiteAVSDK_Professional/COSClient.h>
- #import <sys/types.h>
- #import <sys/sysctl.h>
- #import <UIKit/UIKit.h>
- #import <mach/mach.h>
- /////////////////// TiFaceSDK 添加 开始 ///////////////////
- #import "TiSDKInterface.h"
- //#import "TiUIView.h"
- #import "BeautySettingPanel.h"
- /////////////////// TiFaceSDK 添加 结束 ///////////////////
- //声网dev
- #import "AgoraPushUtils.h"
- #import "UIView+CustomAutoLayout.h"
- #import "BogoPkProgressModel.h"
- // 清晰度定义
- #define HD_LEVEL_720P 1 // 1280 * 720
- #define HD_LEVEL_540P 2 // 960 * 540
- #define HD_LEVEL_360P 3 // 640 * 360
- #define HD_LEVEL_360_PLUS 4 // 640 * 360 且开启码率自适应
- #define kRePublishTime 3 // 断开后重新尝试的次数
- #import "UserView.h"
- //语音连麦
- #import "VoiceLianmaiView.h"
- #import "VoiceLianmaiUserModel.h"
- @interface BGTPublishController ()<TXLivePushListener,TXLivePlayListener,TXVideoCustomProcessDelegate,TiUIManagerDelegate,BeautySettingPanelDelegate,UserViewDelegate,TRTCCloudDelegate>{
- BeautySettingPanel *_beautyPanel; // 美颜控件
- }
- /////////////// TiSDK 添加 开始 /////////////
- //@property(nonatomic, strong) TiSDKManager *tiSDKManager;
- //@property(nonatomic, strong) TiUIView *tiUIView;
- /////////////// TiSDK 添加 结束 /////////////
- @property (nonatomic,copy) NSString * txTaskId;
- @end
- @implementation BGTPublishController
- {
- //声网dev
- BOOL unpublishing;
- UIView *userListView;
- UserView *userView1;
- UserView *userView2;
- UserView *userView3;
- NSMutableArray <NSString *> *lianMaiuser;
- NSMutableArray <NSString *> *linkedUsers;//已经连接的用户
- NSString *PKRtmpURL;
-
- //是否已经混流了
- BOOL _isMix;
-
- }
- - (void)endLive
- {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startPushRtmpLiveMethod) object:nil];
- }
- - (void)dealloc
- {
- NSLog(@"%s",__func__);
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- // if (self.tiSDKManager) {
- // [self.tiSDKManager destroy];
- // self.tiSDKManager = nil;
- // }
- }
- - (void)clickUserView:(UserView *)view
- {
- }
- - (void)clickCloseBtn:(UserView *)view
- {
- // view.uid
- //是否断开连麦
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
- unpublishing = NO;
-
- ///////////// TiSDK 添加 开始 ////////////
- lianMaiuser = [NSMutableArray array];
- linkedUsers = [NSMutableArray array];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMainSwitchButtonClick:) name:@"onMainSwitchButtonClick" object:nil];
-
- //#error TiSDK Key, 与包名对应,请联系商务获取
- NSString* key = [GlobalVariables sharedInstance].appModel.bogo_beauty_key;
- if([BGUtils isBlankString:key])
- {
- //这里写上那个key
- key = @"517a990947274dd8b51e1525feb0fb79";
- // [[BGHUDHelper sharedInstance] tipMessage:ASLocalizedString(@"美颜key为空,请尝试重新打开app获取!")];
- }
- else
- {
- // NSString* key = [GlobalVariables sharedInstance].appModel.bogo_beauty_key;
- //
- // // NSString* key = @"";
- //
- //// [[TiSDKManager shareManager] destroy];
- //// [[TiUIManager shareManager] destroy]; // TiSDK开源UI窗口对象资源释放
- // [TiSDK init:key CallBack:^(InitStatus initStatus) {
- // [[NSNotificationCenter defaultCenter] postNotificationName:@"TiSDKInitStatusNotification" object:nil];
- // }];
- //
- // // [[TiUIManager shareManager] loadToSuperview:self.view];
- // [TiUIManager shareManager].showsDefaultUI = YES;
- // [[TiUIManager shareManager]loadToWindowDelegate:self];
- }
-
- [self initConfig];
- ///////////// TiSDK 添加 结束 /////////////
- //loading imageview
- float width = 34;
- float height = 34;
- float offsetX = (self.view.frame.size.width - width) / 2;
- float offsetY = (self.view.frame.size.height - height) / 2;
- NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:@"loading_image0.png"],[UIImage imageNamed:@"loading_image1.png"],[UIImage imageNamed:@"loading_image2.png"],[UIImage imageNamed:@"loading_image3.png"],[UIImage imageNamed:@"loading_image4.png"],[UIImage imageNamed:@"loading_image5.png"],[UIImage imageNamed:@"loading_image6.png"],[UIImage imageNamed:@"loading_image7.png"], nil];
- _loadingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX, offsetY, width, height)];
- _loadingImageView.animationImages = array;
- _loadingImageView.animationDuration = 1;
- _loadingImageView.hidden = YES;
- [self.view addSubview:_loadingImageView];
-
- }
- -(void)onMainSwitchButtonClick:(NSNotificationCenter *)sender{
-
- [[TiUIManager shareManager]showMainMenuView];
-
- _beautyPanel.hidden = NO;
- // [self.tiUIView onMainSwitchButtonClick:nil];
- }
- - (void)adjustPlayItemVoiceUserList:(NSArray <VoiceLianmaiUserModel * > *)userlist
- {
- NSLog(@"刷新语音连麦视图");
- NSLog(@"%@",userlist);
- userView1.hidden = YES;
- userView2.hidden = YES;
- userView3.hidden = YES;
-
- // NSMutableArray *needAddLianMaiUser = [NSMutableArray array];//需要连麦的列表
- // NSMutableArray *needDelLianMaiUser = [NSMutableArray array];//需要删除的列表
- //
- //
-
-
- for (int i=0; i<userlist.count; i++) {
- if(i == 0)
- {
- userView1.hidden = NO;
- userView1.userName.text = userlist[i].nick_name;
- userView1.uid = userlist[i].user_id;
-
- [self.trtcCloud startRemoteView:userView1.uid streamType:TRTCVideoStreamTypeBig view:userView1.videoView];
- }
- else if(i == 1)
- {
- userView2.hidden = NO;
- userView2.userName.text = userlist[i].nick_name;
- userView2.uid = userlist[i].user_id;
-
-
- TRTCRenderParams *params = [[TRTCRenderParams alloc] init];
- // 画面镜像模式
- params.mirrorType = TRTCVideoMirrorTypeDisable;
- // 画面填充模式
- params.fillMode = TRTCVideoFillMode_Fill;
- // 画面旋转角度
- params.rotation = TRTCVideoRotation_0;
- // 设置远端画面的渲染模式
- [self.trtcCloud setRemoteRenderParams:userView2.uid streamType:TRTCVideoStreamTypeBig params:params];
- [self.trtcCloud startRemoteView:userView1.uid streamType:TRTCVideoStreamTypeBig view:userView2.videoView];
-
- // AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
- // videoCanvas.uid = userlist[i].user_id.intValue;
- // videoCanvas.renderMode = AgoraVideoRenderModeHidden;
- // videoCanvas.view = userView2.videoView;
- // [self.agoraKit setupRemoteVideo:videoCanvas];
- }
- else if(i == 2)
- {
- userView3.hidden = NO;
- userView3.userName.text = userlist[i].nick_name;
- userView3.uid = userlist[i].user_id;
-
-
- TRTCRenderParams *params = [[TRTCRenderParams alloc] init];
- // 画面镜像模式
- params.mirrorType = TRTCVideoMirrorTypeDisable;
- // 画面填充模式
- params.fillMode = TRTCVideoFillMode_Fill;
- // 画面旋转角度
- params.rotation = TRTCVideoRotation_0;
- // 设置远端画面的渲染模式
- [self.trtcCloud setRemoteRenderParams:userView3.uid streamType:TRTCVideoStreamTypeBig params:params];
- [self.trtcCloud startRemoteView:userView1.uid streamType:TRTCVideoStreamTypeBig view:userView3.videoView];
-
- // AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
- // videoCanvas.uid = userlist[i].user_id.intValue;
- // videoCanvas.renderMode = AgoraVideoRenderModeHidden;
- // videoCanvas.view = userView3.videoView;
- // [self.agoraKit setupRemoteVideo:videoCanvas];
-
-
-
-
- }
-
-
-
- }
-
- if (userlist.count <= 0) {
- return;
- }
-
- NSArray *subView = userListView.subviews;
-
- // for (int i=0; i<subView.count; i++) {
- // UIView *itemView = subView[i];
- // [itemView mas_remakeConstraints:^(MASConstraintMaker *make) {
- //
- // }];
- // }
-
- NSMutableArray *realViewArr = [NSMutableArray array];
- for (int i=0; i<subView.count; i++) {
- UIView *itemView = subView[i];
- if(itemView.hidden == NO)
- {
- [realViewArr addObject:itemView];
- }
- }
- int userViewWidth = 120;
- int userViewHeight = userViewWidth * 1.6;
-
- [userListView mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.width.equalTo(@(userViewWidth));
- make.height.equalTo(@(userViewHeight * realViewArr.count));
- make.bottom.equalTo(self.view).offset(-80);
- make.right.equalTo(self.view).offset(-20);
- make.height.equalTo(@(realViewArr.count * userViewHeight));
- }];
-
-
- if(realViewArr.count > 1)
- {
- [realViewArr mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.height.equalTo(@(userViewHeight));
- make.width.equalTo(@(userViewWidth));
- }];
- [realViewArr mas_distributeViewsAlongAxis:MASAxisTypeVertical withFixedItemLength:userViewHeight leadSpacing:3 tailSpacing:3];
- }
- else if(realViewArr.count == 1)
- {
- [realViewArr[0] mas_remakeConstraints:^(MASConstraintMaker *make) {
- make.bottom.equalTo(userListView);
- make.height.equalTo(@(userViewHeight));
- make.width.equalTo(@(userViewWidth));
- }];
- }
-
- }
- - (void)adjustPlayItemAgora:(TLiveMickListModel *)mickListModel;
- {
- // [lianMaiuser removeObjectAtIndex:removeIndex];
- // [lianMaiuser removeAllObjects];
-
- __block BOOL isfind = NO;
-
- NSMutableArray *allUserIds = [NSMutableArray array];
- for (int i=0; i<mickListModel.list_lianmai.count; i++) {
-
- //如果之前有了就不处理他了
- TLiveMickModel *mickModel = mickListModel.list_lianmai[i];
- if(![lianMaiuser containsObject:mickModel.user_id])
- {
- [lianMaiuser addObject:mickModel.user_id];
- isfind = YES;
- }
-
- [allUserIds addObject:mickModel.user_id];
- }
- [lianMaiuser enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- if(![allUserIds containsObject:obj])
- {
- isfind = YES;
- [lianMaiuser removeObject:obj];
- }
- }];
-
-
- if(isfind)
- {
- [self reloduserListView];
- }
- }
- #pragma mark - 初始化
- - (void)initializeAgoraEngine {
-
- self.trtcCloud = [TRTCCloud sharedInstance];
- [self.trtcCloud addDelegate:self];
- }
- - (void)joinChannel {
-
- // 设置本地画面的预览模式:开启左右镜像,设置画面为填充模式
- TRTCRenderParams *param = [[TRTCRenderParams alloc] init];
- param.fillMode = TRTCVideoFillMode_Fill;
- param.mirrorType = TRTCVideoMirrorTypeDisable;
- [self.trtcCloud setLocalRenderParams:param];
- // 启动本地摄像头的预览(localCameraVideoView 是用于渲染本地渲染画面的控件)
- [self.trtcCloud startLocalPreview:YES view:_preViewContainer];
- // 通过 TXDeviceManager 开启自动对焦并将闪光灯打开
- TXDeviceManager *manager = [self.trtcCloud getDeviceManager];
- if ([manager isAutoFocusEnabled]) {
- [manager enableCameraAutoFocus:YES];
- }
- //开启闪光灯,手电筒
- // [manager enableCameraTorch:YES];
- // 开启麦克风采集,并设置当前场景为:音乐模式(高保真采集、低音质损失,推荐配合专业声卡使用)
- [self.trtcCloud startLocalAudio:TRTCAudioQualityMusic];
-
- TRTCParams *params = [[TRTCParams alloc] init];
- // 以字符串房间号为例
- params.roomId = self.roomIDStr.intValue;
- params.userId = [IMAPlatform sharedInstance].host.userId;
- // 从业务后台获取到的 UserSig
- params.userSig = [IMALoginParam loadFromLocal].userSig;
- // 替换成您的 SDKAppID
- params.sdkAppId = TXSDKAppID;
- // 根据需要指定用户角色
- params.role = TRTCRoleAnchor;
- // 根据需要指定场景
- [self.trtcCloud enterRoom:params appScene:TRTCAppSceneLIVE];
-
- TRTCVideoEncParam *videoEncParam = [[TRTCVideoEncParam alloc] init];
- videoEncParam.videoFps = 24;
- videoEncParam.resMode = TRTCVideoResolutionModePortrait;
- videoEncParam.videoResolution = TRTCVideoResolution_960_540;
- [self.trtcCloud setVideoEncoderParam:videoEncParam];
- }
- #pragma mark ******************* 腾讯代理方法 *******************
- - (void)onEnterRoom:(NSInteger)result {
- if (result > 0) {
- // result 代表加入房间所消耗的时间(毫秒)
- // [self toastTip:@"Enter room succeed!"];
- [self startRtmpStreaming:self.pushUrlStr];
- } else {
- // result 代表进房失败的错误码
- [self toastTip:@"Enter room failed!"];
- }
-
- AppDelegate.sharedAppDelegate.isEnterLiveVC = YES;
- }
- //远程静音视频或者音频
- - (void)onUserAudioAvailable:(NSString *)userId available:(BOOL)available {
- if (available) {
- // 发布音频
- } else {
- // 取消发布音频
- }
-
- NSArray *subView = userListView.subviews;
-
- for (int i=0; i<subView.count; i++) {
- UserView *itemView = subView[i];
- if(itemView.uid == userId)
- {
- if(available == NO)
- {
- NSLog(@"%@ 静音",userId);
- }
- }
- }
- }
- #pragma mark - //功能描述:某远端用户发布/取消了主路视频画面 取消或者开始连麦
- - (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
- if (available) {
- // 发布视频
- } else {
- // 取消发布视频
- }
-
- NSArray *subView = userListView.subviews;
-
- for (int i=0; i<subView.count; i++) {
- UserView *itemView = subView[i];
- if(itemView.uid == userId)
- {
- if(available == NO)
- {
- NSLog(@"%@ 关闭视频",userId);
- itemView.muteVideoView.hidden = NO;
- // itemView.videoView.hidden = YES;
- }
- else
- {
- NSLog(@"%@ 打开视频",userId);
- itemView.muteVideoView.hidden = YES;
- // itemView.videoView.hidden = NO;
- }
- }
- }
- }
- //功能描述:有用户加入当前房间
- // 远端用户加入频道时,会触发该回调
- - (void)onRemoteUserEnterRoom:(NSString *)userId {
- NSLog(@"用户加入房间 %@",userId);
-
- //如果正在pk混流pk
- #warning 暂时注释,后续确认是否需要
- // if(self.pkTranscodin)
- // {
- // [self startPKRtmpStreaming:PKRtmpURL];
- //
- // }
- // else
- {
- // [self.agoraKit updateRtmpTranscoding:self.transcoding];
- [self updatePublishMediaStream];
- }
- [self updateUser];
- // [lianMaiuser addObject:StringFromInt(uid)];
- // [self reloduserListView];
- // AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
- // videoCanvas.uid = uid;
- // videoCanvas.renderMode = AgoraVideoRenderModeHidden;
- // videoCanvas.view = userView1;
- // // 设置远端视图
- // [self.agoraKit setupRemoteVideo:videoCanvas];
- }
- - (void)updatePublishMediaStream {
- // 媒体流发布的目标地址
- TRTCPublishTarget* target = [[TRTCPublishTarget alloc] init];
- // 目标地址设定为旁路转推到 CDN
- target.mode = TRTCPublishMixStreamToCdn;
- TRTCPublishCdnUrl* cdnUrl = [[TRTCPublishCdnUrl alloc] init];
- // 拼接发布到直播服务商的推流地址(RTMP 格式)
- cdnUrl.rtmpUrl = self.pushUrlStr;
- // 腾讯云直播推流地址为 true,第三方为 false
- cdnUrl.isInternalLine = YES;
- NSMutableArray* cdnUrlList = [NSMutableArray array];
- // 可以添加多个 CDN 推流地址
- [cdnUrlList addObject:cdnUrl];
- target.cdnUrlList = cdnUrlList;
- [self.trtcCloud updatePublishMediaStream:self.txTaskId publishTarget:target encoderParam:nil mixingConfig:nil];
- }
- - (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason {
- // [self.agoraKit updateRtmpTranscoding:self.transcoding];
- [self updatePublishMediaStream];
-
- // NSLog(@"用户加入房间");
- // int removeIndex = 0;
- // BOOL isFind = NO;
- // for (int i = 0; i < lianMaiuser.count; i++) {
- // if(i == lianMaiuser[i].intValue)
- // {
- // removeIndex = i;
- // isFind = YES;
- // }
- // }
- // if(isFind)
- // {
- // [lianMaiuser removeObjectAtIndex:removeIndex];
- // [self reloduserListView];
- // }
- NSLog(@"用户离开");
- }
- //功能描述:请求跨房通话的结果回调
- - (void)onConnectOtherRoom:(NSString *)userId errCode:(TXLiteAVError)errCode errMsg:(NSString *)errMsg{
- NSLog(@"channelMediaRelayStateDidChange state %ld --error %@",(long)errCode,errMsg);
- }
- //我们可以让自己的类继承TRTCCloudDelegate,并重载 onError 函数,最后将 this 指针通过 TRTCCCloud 的 delegate 属性设置给 SDK,就可以在当前类中监听来自 SDK 的回调事件了。
- // 监听 SDK 的事件,并对“摄像头未被授权”等错误进行日志打印
- - (void)onError:(TXLiteAVError)errCode
- errMsg:(nullable NSString *)errMsg
- extInfo:(nullable NSDictionary *)extInfo {
- if (ERR_CAMERA_NOT_AUTHORIZED == errCode) {
- NSString *errorInfo = @"Current application is not authorized to use the camera:";
- errorInfo = [errorInfo stringByAppendingString:errMsg];
-
- NSLog(@"腾讯直播报错日志:%@",errorInfo);
-
- [self toastTip:errorInfo];
- }
- }
- // 如果切换角色失败,onSwitchRole 回调的错误码便不是 0
- // If switching operation failed, the error code of the 'onSwitchRole' is not zero
- - (void)onSwitchRole:(TXLiteAVError)errCode errMsg:(nullable NSString *)errMsg {
- if (errCode != 0) {
- NSLog(@"Switching operation failed... ");
- }
- }
- //开始发布媒体流的事件回调
- - (void)onStartPublishMediaStream:(NSString *)taskId code:(int)code message:(NSString *)message extraInfo:(nullable NSDictionary *)extraInfo {
- self.txTaskId = taskId;
- }
- // 离开房间事件回调
- - (void)onExitRoom:(NSInteger)reason {
- if (reason == 0) {
- NSLog(@"主动调用 exitRoom 退出房间");
- } else if (reason == 1) {
- NSLog(@"被服务器踢出当前房间");
- } else if (reason == 2) {
- NSLog(@"当前房间整个被解散");
- }
-
- if (self.leaveRoomBlockSuccess) {
- self.leaveRoomBlockSuccess();
- }
-
- AppDelegate.sharedAppDelegate.isEnterLiveVC = NO;
- }
- #pragma mark ******************* 腾讯代理方法 end *******************
- -(void)startPKRtmpStreaming:(NSString *)rtmp
- {
- // [self.agoraKit startRtmpStreamWithTranscoding:rtmp transcoding:self.pkTranscodin];
- // 功能描述:开始发布媒体流
-
- [self startRtmpStreaming:rtmp];
- }
- -(void)startRtmpStreaming:(NSString *)rtmp
- {
- // self.transcoding = [AgoraPushUtils getLiveHostTranscoding:[IMAPlatform sharedInstance].host.userId];
- // [self.agoraKit startRtmpStreamWithTranscoding:rtmp transcoding:self.transcoding];
-
- // 媒体流发布的目标地址
- TRTCPublishTarget* target = [[TRTCPublishTarget alloc] init];
- // 目标地址设定为旁路转推到 CDN
- target.mode = TRTCPublishBigStreamToCdn;
- TRTCPublishCdnUrl* cdnUrl = [[TRTCPublishCdnUrl alloc] init];
- // 拼接发布到直播服务商的推流地址(RTMP 格式)
- cdnUrl.rtmpUrl = rtmp;
- // 腾讯云直播推流地址为 true,第三方为 false
- cdnUrl.isInternalLine = YES;
- NSMutableArray* cdnUrlList = [NSMutableArray array];
- // 可以添加多个 CDN 推流地址
- [cdnUrlList addObject:cdnUrl];
- target.cdnUrlList = cdnUrlList;
- // 如果需要混流
- TRTCStreamMixingConfig *config = [[TRTCStreamMixingConfig alloc] init];
- // if (self.mixUserList.count) {
- NSMutableArray<TRTCUser *> *userList = [NSMutableArray array];
- NSMutableArray<TRTCVideoLayout *> *layoutList = [NSMutableArray array];
- // for (int i = 1; i < MIN(self.mixUserList.count, 16); i++) {
- // TRTCUser *user = [[TRTCUser alloc] init];
- // // 整型房间号为 intRoomId
- // user.roomId = self.roomId.intValue;
- // user.userId = self.mixUserList[i];
- // [userList addObject:user];
- //
- // TRTCVideoLayout *layout = [[TRTCVideoLayout alloc] init];
- // if ([self.mixUserList[i] isEqualToString:self.userId]) {
- // // 主播画面布局
- // layout.rect = CGRectMake(0, 0, 540, 960);
- // layout.zOrder = 0;
- // } else {
- // // 连麦观众画面布局
- // layout.rect = CGRectMake(400, 5 + i * 245, 135, 240);
- // layout.zOrder = 1;
- // }
- // layout.fixedVideoUser = user;
- // layout.fixedVideoStreamType = TRTCVideoStreamTypeBig;
- // [layoutList addObject:layout];
- // }
- // 指定转码流中的每一路输入音频的信息
- config.audioMixUserList = [userList copy];
- // 指定混合画面的中每一路视频画面的位置、大小、图层以及流类型等信息
- config.videoLayoutList = [layoutList copy];
- #warning 暂时注释,后续确认是否需要
- // 开始发布媒体流 不转码
- // [self.trtcCloud startPublishMediaStream:target encoderParam:nil mixingConfig:nil];
- // 开始发布媒体流 转码
- // [self.trtcCloud startPublishMediaStream:target encoderParam:encoderParam mixingConfig:nil];
- // 开始发布媒体流 转码+混流
- // [self.trtcCloud startPublishMediaStream:target encoderParam:encoderParam mixingConfig:config];
- }
- -(void)updateLianMaiCoin
- {
- //用户加入
- NSMutableDictionary *parmDict = [NSMutableDictionary dictionary];
- [parmDict setObject:@"live_multi_room" forKey:@"ctl"];
- [parmDict setObject:@"api_mic_list" forKey:@"act"];
- [parmDict setObject:[BogoNetwork shareInstance].token forKey:@"token"];
- [parmDict setObject:[BogoNetwork shareInstance].uid forKey:@"uid"];
- [parmDict setObject:self.roomIDStr forKey:@"video_id"];
- [[NetHttpsManager manager] POSTWithParameters:parmDict SuccessBlock:^(NSDictionary *responseJson)
- {
- FWWeakify(self)
- if ([responseJson toInt:@"status"] == 1)
- {
- NSMutableArray *model_arr = [NSMutableArray array];
-
- NSArray *arr = [responseJson valueForKey:@"list"];
- if ([arr isKindOfClass:[NSArray class]]) {
- for (NSDictionary *dic in arr) {
- VoiceLianmaiUserModel *model =[VoiceLianmaiUserModel mj_objectWithKeyValues: dic];
- if(model.user_id.intValue == [BogoNetwork shareInstance].uid.intValue)
- {
- continue;
- }
-
- if(model.user_id.intValue == userView1.uid.intValue)
- {
- userView1.numberLab.text = model.coin;
- }
-
- if(model.user_id.intValue == userView2.uid.intValue)
- {
- userView2.numberLab.text = model.coin;
- }
-
- if(model.user_id.intValue == userView2.uid.intValue)
- {
- userView3.numberLab.text = model.coin;
- }
- }
- }
-
-
-
- }
- } FailureBlock:^(NSError *error)
- {
- }];
- }
- -(void)updateUser
- {
- //用户加入
- NSMutableDictionary *parmDict = [NSMutableDictionary dictionary];
- [parmDict setObject:@"live_multi_room" forKey:@"ctl"];
- [parmDict setObject:@"api_mic_list" forKey:@"act"];
- [parmDict setObject:[BogoNetwork shareInstance].token forKey:@"token"];
- [parmDict setObject:[BogoNetwork shareInstance].uid forKey:@"uid"];
- [parmDict setObject:self.roomIDStr forKey:@"video_id"];
- [[NetHttpsManager manager] POSTWithParameters:parmDict SuccessBlock:^(NSDictionary *responseJson)
- {
- FWWeakify(self)
- if ([responseJson toInt:@"status"] == 1)
- {
- NSMutableArray *model_arr = [NSMutableArray array];
-
- NSArray *arr = [responseJson valueForKey:@"list"];
- if ([arr isKindOfClass:[NSArray class]]) {
- for (NSDictionary *dic in arr) {
- VoiceLianmaiUserModel *model =[VoiceLianmaiUserModel mj_objectWithKeyValues: dic];
- if(model.user_id.intValue == [BogoNetwork shareInstance].uid.intValue)
- {
- continue;
- }
- [model_arr addObject:model];
- }
- }
- [self adjustPlayItemVoiceUserList:model_arr];
-
- [self updateLianMaiCoin];
- }
- } FailureBlock:^(NSError *error)
- {
- }];
- }
- //===
- #pragma mark 初始化配置
- - (void)initConfig
- {
- [self.view setBackgroundColor:kBlackColor];
-
- [self initializeAgoraEngine];
-
-
- [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onPKViewChange:) name:@"onPKViewChange" object:nil];
- // 初始化视频父视图
- _preViewContainer = [[UIView alloc] initWithFrame:self.view.bounds];
- [self.view insertSubview:_preViewContainer atIndex:0];
- _preViewContainer.center = self.view.center;
- _preViewContainer.backgroundColor = kBlackColor;
-
- int userViewWidth = 120;
- int userViewHeight = userViewWidth * 1.6;
- userListView = [[UIView alloc] initWithFrame:CGRectMake(kScreenW - userViewWidth - 10, kScreenH - userViewHeight*3 - 60, 0, 0)];
-
- userListView.backgroundColor = kClearColor;
-
- // [self.view addSubview:userListView];
- [[GlobalVariables sharedInstance].tliveView addSubview:userListView];
-
-
- userView1 = [UserView getView];
- userView1.delegate = self;
- userView1.frame = CGRectMake(0, 0, userViewWidth, userViewHeight);
- // userView1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, userViewWidth, userViewHeight)];
- userView1.backgroundColor = kRedColor;
- [userListView addSubview:userView1];
-
- userView2 = [UserView getView];
- userView2.delegate = self;
- userView2.frame = CGRectMake(0, 0, userViewWidth, userViewHeight);
- userView2.backgroundColor = kYellowColor;
- [userListView addSubview:userView2];
-
- userView3 = [UserView getView];
- userView3.delegate = self;
- userView3.frame = CGRectMake(0, 0, userViewWidth, userViewHeight);
-
- userView1.hidden = YES;
- userView2.hidden = YES;
- userView3.hidden = YES;
-
- userView1.userInteractionEnabled = YES;
- userView2.userInteractionEnabled = YES;
- userView3.userInteractionEnabled = YES;
-
- //添加手势
- UITapGestureRecognizer * tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGestureRecognizer:)];
- [userView1 addGestureRecognizer:tapGesture1];
-
- //添加手势
- UITapGestureRecognizer * tapGesture2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGestureRecognizer:)];
- [userView2 addGestureRecognizer:tapGesture2];
-
- UITapGestureRecognizer * tapGesture3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGestureRecognizer:)];
- [userView3 addGestureRecognizer:tapGesture3];
-
- [self reloduserListView];
- // [userListView alignSubviewsVerticallyWithPadding:0 margin:0];
- // [userListView gridViews:userListView.subviews inColumn:1 size:CGSizeMake(userViewWidth, userViewHeight) margin:CGSizeMake(0, 0) inRect:CGRectMake(0, 0, userViewWidth, userViewHeight)];
-
- if (_delegate && [_delegate respondsToSelector:@selector(firstIFrame:)])
- {
- [_delegate firstIFrame:self];
- _rePublishTime = 0;
- }
-
-
-
- #if TARGET_IPHONE_SIMULATOR
- [self toastTip:ASLocalizedString(@"iOS模拟器不支持推流和播放,请使用真机体验")];
- #endif
-
- NSLog(ASLocalizedString(@"==========腾讯SDK版本号:%@"),[TXLiveBase getSDKVersionStr]);
- }
- - (void)handleTapGestureRecognizer:(UITapGestureRecognizer *)gestureRecognizer {
- UserView *view = (UserView*)gestureRecognizer.view;
- NSString *uid = view.uid;
- NSLog(@"点击 %@",uid);
- // if([uid isEqualToString:[IMAPlatform sharedInstance].host.userId])
- // {
- FDActionSheet *actionSheet = [[FDActionSheet alloc] initWithTitle:@"" message:@""];
- [actionSheet addAction:[FDAction actionWithTitle:ASLocalizedString(@"下麦") type:FDActionTypeDefault CallBack:^{
- NSMutableDictionary *mDict = [NSMutableDictionary dictionary];
- [mDict setObject:@"video" forKey:@"ctl"];
- [mDict setObject:@"stop_lianmai" forKey:@"act"];
- [mDict setObject:self.roomIDStr forKey:@"room_id"];
- [mDict setObject:uid forKey:@"to_user_id"];
-
- [[NetHttpsManager manager] POSTWithParameters:mDict SuccessBlock:^(NSDictionary *responseJson) {
-
- } FailureBlock:^(NSError *error) {
-
- }];
- }]];
-
-
- [actionSheet addAction:[FDAction actionWithTitle:ASLocalizedString(@"关闭麦克风") type:FDActionTypeDefault CallBack:^{
- // _lianmaiOpenSound = NO;
-
- NSMutableDictionary *mDict = [NSMutableDictionary dictionary];
- [mDict setObject:@"video" forKey:@"ctl"];
- [mDict setObject:@"setLinkUserMuteVoiceStatus" forKey:@"act"];
- [mDict setObject:self.roomIDStr forKey:@"video_id"];
- [mDict setObject:@"1" forKey:@"mute_status"];
-
-
- [[NetHttpsManager manager] POSTWithParameters:mDict SuccessBlock:^(NSDictionary *responseJson) {
- NSDictionary * userInfo = [NSDictionary dictionaryWithObject:uid forKey:@"uid"];
- [[NSNotificationCenter defaultCenter] postNotificationName:@"NOTIFY_onMuteUser" object:userInfo userInfo:userInfo];
-
- } FailureBlock:^(NSError *error) {
-
- }];
-
- //view.micbutton.selected NO
- // [self.agoraKit enableLocalAudio:view.micbutton.selected];
- // view.micbutton.selected = !view.micbutton.selected;
-
- }]];
-
-
- [actionSheet addAction:[FDAction actionWithTitle:ASLocalizedString(@"取消") type:FDActionTypeCancel CallBack:^{
-
- }]];
-
- [actionSheet show:[UIApplication sharedApplication].keyWindow];
-
- // }
- }
- -(void)stopLinkMicWithUid:(NSString *)uid
- {
-
- }
- -(void)reloduserListView
- {
- //不要动之前的混流逻辑
-
- //删除之前已有的
- for (NSString *item in linkedUsers) {
- #warning 暂时注释,后续确认是否需要 AgoraPushUtils
- // [self.transcoding removeUser:item.intValue];
- }
-
- //添加所有
- for (int i=0; i<lianMaiuser.count; i++) {
- #warning 暂时注释,后续确认是否需要 AgoraPushUtils
- // [AgoraPushUtils setLianMaiTranscodingUser:self.transcoding nowNum:i+1 uid:lianMaiuser[i]];
- }
-
- // [self.agoraKit updateRtmpTranscoding:self.pushUrlStr transcoding:self.transcoding];
- linkedUsers = lianMaiuser;
- //延迟两秒更新旁路流
- // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- // });
- }
- - (void)initRightVideoContainerView{
- if (!_rightVideoContrainerView) {
- _rightVideoContrainerView = [[UIView alloc]initWithFrame:CGRectMake(kScreenW / 2, kStatusBarHeight + 53 + 55, kScreenW / 2, kScreenW * 2 / 3)];
- _rightVideoContrainerView.backgroundColor = kClearColor;
- [self.view addSubview:_rightVideoContrainerView];
- }
- }
- - (void)initTXLivePlayerWithUrl:(NSString *)playUrl playType:(NSInteger)playType{
-
-
- if([GlobalVariables sharedInstance].openAgora)
- {
- return;
- }
-
- if (!_txLivePlayer) {
- _txLivePlayer = [[TXLivePlayer alloc] init];//初始化
- }
- if (!_txLivePlayConfig) {
- _txLivePlayConfig = [[TXLivePlayConfig alloc]init];
- _txLivePlayConfig.enableAEC = YES;
- }
- [_txLivePlayer setConfig:_txLivePlayConfig];
- _txLivePlayer.delegate = self; //如果您需要处理播放的事件
- [_txLivePlayer setupVideoWidget:CGRectMake(0, 0, 0, 0) containView:_rightVideoContrainerView insertIndex:0];
- //4-16 2.苹果连麦无法与安卓和苹果之间连麦,对方是没有影子。
- int result = [_txLivePlayer startLivePlay:[NSString stringWithFormat:@"%@%@",playUrl,@""] type:playType];
- if (result == -1)
- {
- [self toastTip:ASLocalizedString(@"非腾讯云链接,若要放开限制请联系腾讯云商务团队")];
- }
- if( result != 0)
- {
- NSLog(ASLocalizedString(@"播放器启动失败"));
- }
- }
- #pragma mark - Pk
- //该参数就是发送过来的通知,接到通知后执行的方法
- - (void)onPKViewChange:(NSNotification *)notify
- {
-
- NSLog(@"pk通知来了 = %@",notify);
-
- int isFull = [[notify.userInfo valueForKey:@"isFull"] intValue];
- NSString *playUrl = [notify.userInfo valueForKey:@"playUrl"];
-
- TX_Enum_PlayType _playType = PLAY_TYPE_LIVE_RTMP;
- if ([playUrl hasPrefix:@"rtmp:"])
- {
- _playType = PLAY_TYPE_LIVE_RTMP;
- }
- else if (([playUrl hasPrefix:@"https:"] || [playUrl hasPrefix:@"http:"]) && [playUrl rangeOfString:@".flv"].length > 0)
- {
- _playType = PLAY_TYPE_LIVE_FLV;
- }
-
- if(isFull == 1) {
- // self.pkTranscodin = nil;
- // [self.agoraKit stopChannelMediaRelay];
- //好像有问题,上面代码注释会崩溃
- [self.trtcCloud disconnectOtherRoom];
- //模拟动态修改
- _preViewContainer.frame = self.view.bounds;
- // [redBgView removeFromSuperview];
- // [blueBgView removeFromSuperview];
- [pkBgView removeFromSuperview];
- _txLivePlayer.delegate = nil;
- [_txLivePlayer stopPlay];
- [_txLivePlayer removeVideoWidget];
- _txLivePlayer = nil;
- [_rightVideoContrainerView removeFromSuperview];
- _rightVideoContrainerView = nil;
- float width = 34;
- float height = 34;
- float offsetX = (self.view.frame.size.width - width) / 2;
- float offsetY = (self.view.frame.size.height - height) / 2;
- _loadingImageView.frame = CGRectMake(offsetX, offsetY, width, height);
- [_txLivePublisher setVideoQuality:VIDEO_QUALITY_HIGH_DEFINITION adjustBitrate:YES adjustResolution:YES];
-
- _isMix = NO;
- [self stopLoadingAnimation];
- return;
- }
-
- if(isFull == 3) {
- // _preViewContainer.frame = CGRectMake(0, 0, kScreenW/2, kScreenH/);
-
- _preViewContainer.frame = CGRectMake(0, kStatusBarHeight + 53 + 55, kScreenW / 2, kScreenW * 2 / 3);
- [self addPkBgView];
- [self initRightVideoContainerView];
- [self initTXLivePlayerWithUrl:[self changeRTMPToFlv:playUrl] playType:_playType];
- _loadingImageView.centerX = _rightVideoContrainerView.centerX;
- _loadingImageView.centerY = _rightVideoContrainerView.centerY;
-
- [_txLivePublisher setVideoQuality:VIDEO_QUALITY_STANDARD_DEFINITION adjustBitrate:YES adjustResolution:YES];
-
-
- if([GlobalVariables sharedInstance].openAgora)
- {
-
- NSMutableDictionary *mDict = [NSMutableDictionary dictionary];
-
- [mDict setObject:@"pk_agora" forKey:@"ctl"];
-
- BogoPkProgressModel *model = [notify.userInfo valueForKey:@"model"];
- [mDict setObject:@"getPKRTCChannelToken" forKey:@"act"];
- [mDict setObject:[NSString stringWithFormat:@"%@",model.id] forKey:@"pk_id"];
- [[NetHttpsManager manager] POSTWithParameters:mDict SuccessBlock:^(NSDictionary *responseJson) {
- if ([responseJson toInt:@"status"] == 1 || [responseJson toInt:@"status"] == 2) {
-
- //imUserId 是主播自己的id
- NSInteger imUserId = [IMAPlatform sharedInstance].host.imUserId.integerValue;
- //src_token 是别人要加入我房间的源token
- NSString *src_token = responseJson[@"data"][@"agora_token_src"];
-
- //desc_token 是要加入对方房间的token
- NSString *desc_token = responseJson[@"data"][@"agora_token_desc"];
-
- #warning 暂时注释,后续确认是否需要
- /*
- //总体的config
- AgoraChannelMediaRelayConfiguration *config = [[AgoraChannelMediaRelayConfiguration alloc] init];
- config.sourceInfo = [[AgoraChannelMediaRelayInfo alloc] initWithToken:responseJson[@"data"][@"agora_token_src"]];
- config.sourceInfo.uid = 0;
- //声明一个sourceInfo ,用我的房间token
- config.sourceInfo = [[AgoraChannelMediaRelayInfo alloc] initWithToken:src_token];
-
- //文档说了必须设置成0
- // config.sourceInfo.uid = imUserId;
- */
-
-
- //tagget 是对方的roomid,也是频道号
- NSString *tagget = @"";
-
- //myromid 是我的房间号也是我的频道id
- NSString *myRoomId = @"";
-
- //toEmccUserid 对方主播的id
- NSString *toEmccUserid = @"";
- NSString *pushUrl;
-
-
- if(model.emcee_user_id1.intValue == imUserId) {
- tagget = model.room_id2;
- myRoomId = model.room_id1;
- toEmccUserid = model.emcee_user_id2;
- pushUrl = model.push_url1;
- } else {
- toEmccUserid = model.emcee_user_id1;
- tagget = model.room_id1;
- myRoomId = model.room_id2;
- pushUrl = model.push_url2;
- }
-
- //开始混流
- // int status = [self.agoraKit startChannelMediaRelay:config];
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- // 需要延迟执行的代码
- // [self channelMediaRelayWidthUid:imUserId andSrcToken:src_token andDestToken:desc_token andChannel:tagget];
- });
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- // 需要延迟执行的代码
-
- // AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];
- // videoCanvas.uid = toEmccUserid.intValue;
- // videoCanvas.renderMode = AgoraVideoRenderModeHidden;
- // videoCanvas.view = self->_rightVideoContrainerView;
- // // 设置远端视图
- // [self.agoraKit setupRemoteVideo:videoCanvas];
-
-
- // 功能描述:请求跨房通话
- NSMutableDictionary *jsonDict = [[NSMutableDictionary alloc] init];
- // 此处为数字房间号; 数字房间号为 roomId 对方房间ID,对方主播ID
- [jsonDict setObject:@(tagget.intValue) forKey:@"roomId"];
- [jsonDict setObject:toEmccUserid forKey:@"userId"];
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:NSJSONWritingPrettyPrinted error:nil];
- NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
- [self.trtcCloud connectOtherRoom:jsonString];
-
-
- TRTCRenderParams *params = [[TRTCRenderParams alloc] init];
- // 画面镜像模式
- params.mirrorType = TRTCVideoMirrorTypeDisable;
- // 画面填充模式
- params.fillMode = TRTCVideoFillMode_Fill;
- // 画面旋转角度
- params.rotation = TRTCVideoRotation_0;
- // 设置远端画面的渲染模式
- [self.trtcCloud setRemoteRenderParams:toEmccUserid streamType:TRTCVideoStreamTypeBig params:params];
- [self.trtcCloud startRemoteView:toEmccUserid streamType:TRTCVideoStreamTypeBig view:self->_rightVideoContrainerView];
- });
- // [self setPKTranscodingWithId:toEmccUserid];
- // NSLog(@"status %d",status);
- }
- } FailureBlock:^(NSError *error) {
- //do nothing;
- }];
-
- //跨频道推流
- }
-
- return;
- }
-
- if(isFull == 0)
- {
- _preViewContainer.frame = CGRectMake(0, kStatusBarHeight + 53 + 55, kScreenW / 2, kScreenW * 2 / 3);
- // _preViewContainer.frame = CGRectMake(kScreenW/2, 0, kScreenW/2, kScreenH/2);
- [self addPkBgView];
- [self initRightVideoContainerView];
- [self initTXLivePlayerWithUrl:[self changeRTMPToFlv:playUrl] playType:_playType];
- _loadingImageView.centerX = _rightVideoContrainerView.centerX;
- _loadingImageView.centerY = _rightVideoContrainerView.centerY;
- [_txLivePublisher setVideoQuality:VIDEO_QUALITY_STANDARD_DEFINITION adjustBitrate:YES adjustResolution:YES];
- return;
- }
- }
- -(void)channelMediaRelayWidthUid:(int)uid andSrcToken:(NSString *)srcToken andDestToken:(NSString *)destToken andChannel:(NSString *)channel;
- {
- //如果不是主播直接退出
-
- // AgoraChannelMediaRelayConfiguration *config = [[AgoraChannelMediaRelayConfiguration alloc] init];
- // AgoraChannelMediaRelayInfo *src = [config sourceInfo];
- //
- //// src.channelName = nil;
- // src.uid = 0;
- // src.token = srcToken;
- //
- //
- // AgoraChannelMediaRelayInfo *dst = [[AgoraChannelMediaRelayInfo alloc] init];
- // dst.channelName = channel;
- // dst.uid = uid;
- // dst.token = destToken;
- //
- // [config setDestinationInfo:dst forChannelName:dst.channelName];
-
- if(_isMix == NO)
- {
- _isMix = YES;
- // [self.agoraKit stopChannelMediaRelay];
- //功能描述:退出跨房通话
- [self.trtcCloud disconnectOtherRoom];
- // [self.agoraKit startChannelMediaRelay:config];
-
- // 功能描述:请求跨房通话
- NSMutableDictionary *jsonDict = [[NSMutableDictionary alloc] init];
- // 此处为字符房间号; 数字房间号为 roomId
- [jsonDict setObject:channel forKey:@"roomId"];
- [jsonDict setObject:@(uid) forKey:@"userId"];
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict options:NSJSONWritingPrettyPrinted error:nil];
- NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
- [self.trtcCloud connectOtherRoom:jsonString];
- }
-
- }
- - (void)addVSView{
- //红蓝双方
- if (!redBgView) {
- redBgView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, kScreenW / 2, kScreenH)];
- redBgView.backgroundColor = [UIColor colorWithHexString:@"#731a5a"];
- [self.view addSubview:redBgView];
- [self.view sendSubviewToBack:redBgView];
- }else{
- [self.view addSubview:redBgView];
- [self.view sendSubviewToBack:redBgView];
- }
- if (!blueBgView) {
- blueBgView = [[UIView alloc]initWithFrame:CGRectMake(kScreenW / 2, 0, kScreenW / 2, kScreenH)];
- blueBgView.backgroundColor = [UIColor colorWithHexString:@"#012e89"];
- [self.view addSubview:blueBgView];
- [self.view sendSubviewToBack:blueBgView];
- }else{
- [self.view addSubview:blueBgView];
- [self.view sendSubviewToBack:blueBgView];
- }
- }
- - (void)addPkBgView{
- if (!pkBgView) {
- pkBgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, kScreenW, kScreenH)];
- pkBgView.image = [UIImage imageNamed:@"pk_bg"];
- }
- [self.view addSubview:pkBgView];
- [self.view sendSubviewToBack:pkBgView];
- }
- - (void)viewWillDisappear:(BOOL)animated {
- [super viewWillDisappear:animated];
- if (!self.txLivePublisher.isPublishing) {
- [[NSNotificationCenter defaultCenter]removeObserver:self name:@"onPKViewChange" object:nil];
- [GlobalVariables sharedInstance].appModel.spear_live = @"0";
- // if (self.tiSDKManager) {
- // [self.tiSDKManager destroy];
- // self.tiSDKManager = nil;
- // if(_tiUIView.viewArr != nil)
- // for (UIView *sview in _tiUIView.viewArr) {
- // [sview removeFromSuperview];
- // }
- // }
- }
- }
- //6-19 修改-onPKViewChange
- -(void)viewWillAppear:(BOOL)animated{
- [super viewWillAppear:animated];
- // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onPKViewChange:) name:@"onPKViewChange" object:nil];
- }
- - (void)viewDidDisappear:(BOOL)animated{
- [super viewDidDisappear:animated];
-
- }
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
-
- #if !TARGET_IPHONE_SIMULATOR
- //是否有摄像头权限
- AVAuthorizationStatus statusVideo = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
- if (statusVideo == AVAuthorizationStatusDenied)
- {
- [FanweMessage alert:ASLocalizedString(@"获取摄像头权限失败,请前往隐私-相机设置里面打开应用权限")];
- return;
- }
- #endif
-
- }
- #pragma mark - ----------------------- 开始、停止推流 -----------------------
- #pragma mark 开始推流
- - (BOOL)startPushRtmpLiveMethod {
-
- _startTime = [[NSDate date]timeIntervalSince1970]*1000;
- _lastTime = _startTime;
-
- NSString* rtmpUrl = self.pushUrlStr;
-
- [self joinChannel];
-
- //是否有摄像头权限
- AVAuthorizationStatus statusVideo = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
- if (statusVideo == AVAuthorizationStatusDenied)
- {
- [FanweMessage alert:ASLocalizedString(@"获取摄像头权限失败,请前往隐私-相机设置里面打开应用权限")];
- return NO;
- }
-
- //是否有麦克风权限
- AVAuthorizationStatus statusAudio = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
- if (statusAudio == AVAuthorizationStatusDenied)
- {
- [FanweMessage alert:ASLocalizedString(@"获取麦克风权限失败,请前往隐私-麦克风设置里面打开应用权限")];
- return NO;
- }
-
- return YES;
- }
- #pragma mark 停止推流
- - (void)stopRtmp {
- if (_txLivePlayer != nil) {
- _txLivePlayer.delegate = nil;
- [_txLivePlayer stopPlay];
- [_txLivePlayer removeVideoWidget];
- }
- }
- #pragma mark - BeautySettingPanelDelegate
- - (void)onSetBeautyStyle:(NSUInteger)beautyStyle beautyLevel:(float)beautyLevel whitenessLevel:(float)whitenessLevel ruddinessLevel:(float)ruddinessLevel {
- [_txLivePublisher setBeautyStyle:beautyStyle beautyLevel:beautyLevel whitenessLevel:whitenessLevel ruddinessLevel:ruddinessLevel];
- }
- - (void)onSetMixLevel:(float)mixLevel {
- [_txLivePublisher setSpecialRatio:mixLevel / 10.0];
- }
- - (void)onSetEyeScaleLevel:(float)eyeScaleLevel {
- [_txLivePublisher setEyeScaleLevel:eyeScaleLevel];
- }
- - (void)onSetFaceScaleLevel:(float)faceScaleLevel {
- [_txLivePublisher setFaceScaleLevel:faceScaleLevel];
- }
- - (void)onSetFaceBeautyLevel:(float)beautyLevel {
- }
- - (void)onSetFaceVLevel:(float)vLevel {
- [_txLivePublisher setFaceVLevel:vLevel];
- }
- - (void)onSetChinLevel:(float)chinLevel {
- [_txLivePublisher setChinLevel:chinLevel];
- }
- - (void)onSetFaceShortLevel:(float)shortLevel {
- [_txLivePublisher setFaceShortLevel:shortLevel];
- }
- - (void)onSetNoseSlimLevel:(float)slimLevel {
- [_txLivePublisher setNoseSlimLevel:slimLevel];
- }
- - (void)onSetFilter:(UIImage*)filterImage {
- [_txLivePublisher setFilter:filterImage];
- }
- - (void)onSetGreenScreenFile:(NSURL *)file {
- [_txLivePublisher setGreenScreenFile:file];
- }
- - (void)onSelectMotionTmpl:(NSString *)tmplName inDir:(NSString *)tmplDir {
- [_txLivePublisher selectMotionTmpl:tmplName inDir:tmplDir];
- }
- #pragma mark ------------TXLivePlayListener----------
- -(void) onPlayEvent:(int)EvtID withParam:(NSDictionary*)param{
- switch (EvtID) {
- case PLAY_EVT_PLAY_BEGIN:
- [self stopLoadingAnimation];
- break;
- case PLAY_EVT_PLAY_LOADING:
- [self startLoadingAnimation];
- break;
- default:
- break;
- }
- }
- - (void)startLoadingAnimation
- {
- if (_loadingImageView != nil)
- {
- _loadingImageView.hidden = NO;
- [_loadingImageView startAnimating];
- }
- }
- - (void)stopLoadingAnimation
- {
- if (_loadingImageView != nil)
- {
- _loadingImageView.hidden = YES;
- [_loadingImageView stopAnimating];
- }
- }
- #pragma mark - ----------------------- 摄像头、闪光灯 -----------------------
- #pragma mark 开、关闪光灯
- - (void)clickTorch:(BOOL)isOpen
- {
- if (_txLivePublisher)
- {
- if (![_txLivePublisher toggleTorch:isOpen])
- {
- [self toastTip:ASLocalizedString(@"闪光灯启动失败")];
- }
- }
- }
- #pragma mark 前置后置摄像头切换
- - (void)clickCamera:(UIButton*)btn
- {
- [_txLivePublisher switchCamera];
- }
- #pragma mark - ----------------------- 定义清晰度 -----------------------
- - (void)changeHD:(UIButton*)btn
- {
- if ([btn.titleLabel.text isEqualToString:@"720p"] && NO == [self isSuitableMachine:7])
- {
- [FanweMessage alert:ASLocalizedString(@"直播推流")message:ASLocalizedString(@"iphone 6 及以上机型适合开启720p!")isHideTitle:NO destructiveAction:nil];
- return;
- }
-
- if ([btn.titleLabel.text isEqualToString:@"540p"] && NO == [self isSuitableMachine:5])
- {
- [FanweMessage alert:ASLocalizedString(@"直播推流")message:ASLocalizedString(@"iphone 5 及以上机型适合开启540p!")isHideTitle:NO destructiveAction:nil];
- return;
- }
-
- if (_txLivePublisher == nil) return;
-
- if ([btn.titleLabel.text isEqualToString:@"720p"])
- {
- TXLivePushConfig* _config = _txLivePublisher.config;
- _config.videoBitratePIN = 1500;
- _config.videoResolution = [self isSuitableMachine:7 ] ? VIDEO_RESOLUTION_TYPE_720_1280 : VIDEO_RESOLUTION_TYPE_540_960;
- _config.enableAutoBitrate = NO;
- [_txLivePublisher setConfig:_config];
- }
- else if ([btn.titleLabel.text isEqualToString:@"540p"])
- {
- TXLivePushConfig* _config = _txLivePublisher.config;
- _config.videoBitratePIN = 1000;
- _config.videoResolution = [self isSuitableMachine:5 ] ? VIDEO_RESOLUTION_TYPE_540_960 : VIDEO_RESOLUTION_TYPE_360_640;
- _config.enableAutoBitrate = NO;
- [_txLivePublisher setConfig:_config];
- }
- else if ([btn.titleLabel.text isEqualToString:@"360p"])
- {
- TXLivePushConfig* _config = _txLivePublisher.config;
- _config.videoBitratePIN = 700;
- _config.videoResolution = VIDEO_RESOLUTION_TYPE_360_640;
- _config.enableAutoBitrate = NO;
- [_txLivePublisher setConfig:_config];
-
- }
- else if ([btn.titleLabel.text isEqualToString:@"360+"])
- {
- TXLivePushConfig* _config = _txLivePublisher.config;
- _config.videoBitrateMin = 500;
- _config.videoBitrateMax = 1200;
- _config.enableAutoBitrate = YES;
- _config.videoResolution = VIDEO_RESOLUTION_TYPE_360_640;
- [_txLivePublisher setConfig:_config]; // 此模式下设置bitrate无效
- }
- }
- // iphone 6 及以上机型适合开启720p, 否则20帧的帧率可能无法达到, 这种"流畅不足,清晰有余"的效果并不好
- - (BOOL)isSuitableMachine:(int)targetPlatNum
- {
- int mib[2] = {CTL_HW, HW_MACHINE};
- size_t len = 0;
- char* machine;
-
- sysctl(mib, 2, NULL, &len, NULL, 0);
-
- machine = (char*)malloc(len);
- sysctl(mib, 2, machine, &len, NULL, 0);
-
- NSString* platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];
- free(machine);
- if ([platform length] > 6)
- {
- NSString * platNum = [NSString stringWithFormat:@"%C", [platform characterAtIndex: 6 ]];
- return ([platNum intValue] >= targetPlatNum);
- }
- else
- {
- return NO;
- }
- }
- #pragma mark - ----------------------- 自定义Toast -----------------------
- /**
- @method 获取指定宽度width的字符串在UITextView上的高度
- @param textView 待计算的UITextView
- @param Width 限制字符串显示区域的宽度
- @result float 返回的高度
- */
- - (float)heightForString:(UITextView *)textView andWidth:(float)width
- {
- CGSize sizeToFit = [textView sizeThatFits:CGSizeMake(width, MAXFLOAT)];
- return sizeToFit.height;
- }
- - (void)toastTip:(NSString*)toastInfo
- {
- NSLog(@"======publishtoastInfo:%@",toastInfo);
-
- CGRect frameRC = [[UIScreen mainScreen] bounds];
- frameRC.origin.y = frameRC.size.height - 110;
- frameRC.size.height -= 110;
- __block UITextView * toastView = [[UITextView alloc] init];
-
- toastView.editable = NO;
- toastView.selectable = NO;
-
- frameRC.size.height = [self heightForString:toastView andWidth:frameRC.size.width];
-
- toastView.frame = frameRC;
-
- toastView.text = toastInfo;
- toastView.backgroundColor = [UIColor whiteColor];
- toastView.alpha = 0.5;
-
- [self.view addSubview:toastView];
-
- dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
-
- dispatch_after(popTime, dispatch_get_main_queue(), ^(){
- [toastView removeFromSuperview];
- toastView = nil;
- });
- }
- #pragma mark ---------美颜增加-------------
- //隐藏美颜
- /*
- - (GLuint)onPreProcessTexture:(GLuint)texture width:(CGFloat)width height:(CGFloat)height{
- return [[TiSDKManager shareManager] renderTexture2D:texture Width:width Height:height Rotation:CLOCKWISE_0 Mirror:_txLivePublisher.config.frontCamera];
- // if (self.tiSDKManager && [self.tiSDKManager renderTexture2D:texture Width:width Height:height Rotation:CLOCKWISE_0 Mirror:NO]) {
- // /////////////////// TiFaceSDK 添加 开始 ///////////////////
- // return [self.tiSDKManager renderTexture2D:texture Width:width Height:height Rotation:CLOCKWISE_0 Mirror:NO];
- // /////////////////// TiFaceSDK 添加 结束 ///////////////////
- // }
- // return texture;
- }*/
- //#pragma mark ---------美颜增加-------------
- //- (GLuint)onPreProcessTexture:(GLuint)texture width:(CGFloat)width height:(CGFloat)height{
- // if (self.tiSDKManager && [self.tiSDKManager renderTexture2D:texture Width:width Height:height Rotation:CLOCKWISE_0 Mirror:NO]) {
- // /////////////////// TiFaceSDK 添加 开始 ///////////////////
- // return [self.tiSDKManager renderTexture2D:texture Width:width Height:height Rotation:CLOCKWISE_0 Mirror:NO];
- // /////////////////// TiFaceSDK 添加 结束 ///////////////////
- // }
- // return texture;
- //}
- //可以在这里释放创建的OpenGL资源
- - (void)onTextureDestoryed{
- // [self.tiSDKManager destroy];
- }
- - (NSString *)changeRTMPToFlv:(NSString *)originalString{
- NSMutableString *mStr = [NSMutableString stringWithString:originalString];
- // [mStr replaceCharactersInRange:NSMakeRange(0, 4) withString:@"http"];
- // [mStr appendString:@".flv"];
- return mStr;
- }
- //功能描述:音量大小的反馈回调
- //SDK 可以评估每一路音频的音量大小,并每隔一段时间抛出该事件回调,您可以根据音量大小在 UI 上做出相应的提示,比如 波形图 或 音量槽 。 要完成这个功能, 您需要先调用 enableAudioVolumeEvaluation 开启这个能力并设定事件抛出的时间间隔。 需要补充说明的是,无论当前房间中是否有人说话,SDK 都会按照您设定的时间间隔定时抛出此事件回调。
- - (void)onUserVoiceVolume:(NSArray<TRTCVolumeInfo *> *)userVolumes totalVolume:(NSInteger)totalVolume {
-
-
- //totalVolume
-
- NSLog(@"totalVolume");
- NSLog(@"%ld",totalVolume);
- /*bug:当a用户在麦上正在说话时,切换到无网状态,此时虽然还显示在麦上(im还没下线),
- 但观众席听不到声音,光圈还在闪烁
- 原因: 这时观众席speakers 里面找不到a,就不会进入for循环,就不会更新a的声音为0
- 解决: 1先找到 麦上的用户 2去判断有无声音
- */
-
-
- for (TRTCVolumeInfo *info in userVolumes) {
-
- // for (AgoraRtcAudioVolumeInfo *speaker in speakers) {
- NSString *uid = @"";
- if (info.userId.intValue == 0) {
- uid = [IMAPlatform sharedInstance].host.userId;
-
- }else{
- uid = [NSString stringWithFormat:@"%@",info.userId];
-
- }
-
- if([[userView1 uid] isEqualToString:uid])
- {
- userView1.totalVolume = info.volume;
- }
-
- if([[userView2 uid] isEqualToString:uid])
- {
- userView2.totalVolume = info.volume;
- }
-
- if([[userView3 uid] isEqualToString:uid])
- {
- userView3.totalVolume = info.volume;
- }
-
-
- //speaker.volume
-
-
- }
-
- if(userVolumes.count == 0)
- {
- userView1.totalVolume = 0;
- userView2.totalVolume = 0;
- userView3.totalVolume = 0;
- }
-
- // [self.uiController.micView setUsers:self.users];
- }
- @end
|