| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623 |
- //
- // 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;
-
- }
- - (TRTCCloud *)trtcCloud {
- return [TRTCCloud sharedInstance];
- }
- - (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 addDelegate:self];
- }
- - (void)joinChannel {
-
- // 设置本地画面的预览模式:开启左右镜像,设置画面为填充模式
- TRTCRenderParams *param = [[TRTCRenderParams alloc] init];
- param.fillMode = TRTCVideoFillMode_Fill;
- param.mirrorType = TRTCVideoMirrorTypeAuto;
- [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 代表进房失败的错误码
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- NSString *string = [NSString stringWithFormat:@"Enter room failed (%ld)", result];
- [self toastTip:string];
- });
-
- }
- NSLog(@"onEnterRoom result: %ld", (long)result);
- 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 {
- NSLog(@"onError code: %d message: %@", errCode, errMsg);
- 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 = TRTCVideoMirrorTypeAuto;
- // 画面填充模式
- 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);
-
- [QMUITips showWithText: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
|