互动连麦

互动功能即用户端与讲师端进行1对1或者1对多的在线视频连麦功能。VHCInteractive库提供此功能。

####注意:使用此类请先在plist文件中添加对于摄像头和麦克风的权限描述。

<!-- 相机 --> 
<key>NSCameraUsageDescription</key> 
<string>需要您的同意,APP才能访问相机</string> 
<!-- 麦克风 --> 
<key>NSMicrophoneUsageDescription</key> 
<string>需要您的同意,APP才能访问麦克风</string> 

1.VHCInteractiveRoom

简介

VHCInteractiveRoom类是微吼课堂互动直播间实体类,此类定义了进入互动、离开互动、推流等Api,实现用户在线互动功能。此类管理互动直播间的生命周期、上麦推流、互动消息等。

1.初始化

/**
 @brief 构造方法
 @warning cameraView 推流用的cameraView,即VHRenderView的实例对象,需用户自己手动创建。初始化时即绑定推流所用的cameraView,推流时只需调用- (void)startPublish方法即可。
 */
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithPushCameraView:(nonnull VHRenderView *)cameraView;

初始化时,需要传入推流使用的cameraView,即自己的摄像头实例,是VHRenderView类的实例。

2.进入直播间

/**
 @brief 进入互动直播间
 @discussion 结果会在- (void)roomdidEnteredWithRoomMetaDataerror:中回调,如果进入成功,可以开始推流上麦。
 */
- (void)enterLiveRoom;

互动前进入互动直播间,进入失败则不能互动,进入结果会有回调

3.上麦推流

/**
 @brief 推流上麦
 @discussion 调用此方法会有两个回调,先回调推流是否成功:- (void)room:didPublishWithCameraView:error:,然后回调上麦是否成功- (void)room:microUpWithError:
 */
- (BOOL)startPublish;

4.停止推流

/**
 @brief 停止推流
 @discussion 下麦的时候需要停止推流。
 */
- (void)stopPulish;

5.离开直播间

/**
 @brief 离开互动直播间,即下麦
 @discussion 停止推流后离开互动直播间需调用此方法。
 */
- (void)leaveLiveRoom;

6.操作自己的设备

/**
 @brief 设置麦克风开关
 @warning 推流后设置才可生效
 @return VHCError 设置失败 错误码:VHCErrorType_NoAuthority无权操作; VHCErrorType_NotEnterClass:未进入课堂或已掉线;VHCErrorType_InVaild:设置无效,未推流前设置都是无效的。
 */
- (VHCError *)closeMicphone:(BOOL)isClose;
/**
 @brief 设置摄像头开关
 @warning 推流后设置才可生效
 @return VHCError 设置失败 错误码:VHCErrorType_NoAuthority无权操作; VHCErrorType_NotEnterClass:未进入课堂或已掉线;VHCErrorType_InVaild:设置无效,未推流前设置都是无效的。
 */
- (VHCError *)closeVideo:(BOOL)isClose;

其中VHCInteractiveRoomDelegate是互动房间代理,此代理定义了进入互动房间结构回调、推流结果回调、上麦结果回调等与互动房间有关的回调方法。在回调中可以处理您关于互动的相关操作。

####VHCInteractiveRoomDelegate

///----------------------------
/// @name 互动直播间生命周期相关回调
///----------------------------

/**
 @brief 进入互动直播间结果回调
 @param data   互动直播间数据
 @param error  错误
 @discussion   当error为nil时候,表示已进入互动直播间;error不为空时,表示进入失败,失败原因描述:error.errorDescription。成功进入互动直播间成功就可以开始推流上麦了。
 */
- (void)room:(VHCInteractiveRoom *)room didEnteredWithRoomMetaData:(NSDictionary *)data error:(VHCError *)error;

/**
 @brief 推流结果回调
 @param cameraView 推流的cameraView
 @param error      推流错误,当error不为空时表示推流失败
 @discussion 推流成功之后,会收到上麦结果的回调。
 */
- (void)room:(VHCInteractiveRoom *)room didPublishWithCameraView:(VHRenderView *)cameraView error:(VHCError *)error;

/**
 @brief 停止推流回调
 @param cameraView 推流的cameraView
 @discussion 自己调用- unpublish停止推流,会回调此方法;被讲师下麦,会停止推流,回调此方法;推流出错,停止推流,会回调此方法。
 */
- (void)room:(VHCInteractiveRoom *)room didUnpublish:(VHRenderView *)cameraView;

/**
 @brief 某用户被讲师下麦回调
 @param byUserId 操作者户参会id,一般的自己被讲师下麦,此id为讲师参会id
 @param toUserId 被操作者户参会id,如果是自己的参会id,则表示自己被讲师下麦。
 */
- (void)room:(VHCInteractiveRoom *)room leaveRoomByUserId:(NSString *)byUserId toUser:(NSString *)toUserId;

/**
 @brief 某用户上麦结果回调
 @param joinId 上麦用户的参会id
 @param error error为nil时上麦成功
 @param info 其他信息
 @discussion  当error为nil时,表示上麦成功。
 */
- (void)room:(VHCInteractiveRoom *)room microUpWithJoinId:(NSString *)joinId attributes:(NSDictionary *)info error:(VHCError *)error;
/**
 @brief 某用户下麦回调
 @param info 其他信息
 @param joinId 下麦用户的参会id
 */
- (void)room:(VHCInteractiveRoom *)room microDownWithJoinId:(NSString *)joinId attributes:(NSDictionary *)info;

/**
 @brief 用户与直播间的连接状态回调
 @param connectedStatus 用户与直播间的连接状态 @see VHCInteractiveRoomConnectedStatus
 @discussion 失去连接则表示该用户已经在主播端下麦,建议在此回调中处理下麦后的业务;当状态为VHCInteractiveRoomConnectedStatusConnected时,表示已成功上麦;当状态为VHCInteractiveRoomConnectedStatusDisConnected时,表示自己已下麦。
 */
- (void)room:(VHCInteractiveRoom *)room connectedStatusChanged:(VHCInteractiveRoomConnectedStatus)connectedStatus;
//
/////--------------------
///// @name 互动相关事件回调
/////--------------------

/**
 @brief 新加入一路流(有成员进入互动房间,即有人上麦)
 @discussion 流id:attendView.streamId;上麦用户参会id:attendView.userId。
 */
- (void)room:(VHCInteractiveRoom *)room didAddAttendView:(VHRenderView *)attendView;

/**
 @brief 减少一路流(有成员离开房间,即有人下麦)
 @discussion 流id:attendView.streamId;上麦用户参会id:attendView.userId。
 */
- (void)room:(VHCInteractiveRoom *)room didRemovedAttendView:(VHRenderView *)attendView;

/**
 @brief 关闭画面回调
 @param isClose YES:关闭,NO:打开
 @discussion byUserId操作者参会id,toUserId被操作者参会id。
 @warning 自己操作自己的设备byUserId和toUserId都是自己的参会id。
 */
- (void)room:(VHCInteractiveRoom *)room screenClosed:(BOOL)isClose byUser:(NSString *)byUserId toUser:(NSString *)toUserId;

/**
 @brief 关闭麦克风回调,即静音操作回调
 @param isClose YES:关闭,NO:打开
 @discussion byUserId操作者参会id,toUserId被操作者参会id。
 @warning 自己操作自己的设备byUserId和toUserId都是自己的参会id。当toUserId == nil时候,表示全体静音。全体禁音针对的群体是除讲师外的所有学员,因此将时端开启全体禁音时,讲师并不会被禁音,除非讲师自己禁音。
 */
- (void)room:(VHCInteractiveRoom *)room microphoneClosed:(BOOL)isClose byUser:(NSString *)byUserId toUser:(NSString *)toUserId;

###2.VHRenderView

VHRenderView类是推流摄像头view类,该类定义了摄像头视图的创建、推流等Api,通过此类进行互动推流。 此类提供了摄像头的创建、前后转换、静音、取消静音等Api,另外也提供了摄像头和麦克风的开关操作。

2.上麦互动

1.创建本地摄像头

- (VHRenderView *)cameraView {
    if (!_cameraView) {
        //语音上麦,只推语音流
        NSDictionary *option = nil;
        if (_type == MicroTypeOnlyVoice) {
            option = @{VHVideoWidthKey:@"192",VHVideoHeightKey:@"144",VHVideoFpsKey:@(25),
							VHMaxVideoBitrateKey:@(200),VHStreamOptionStreamType:@(5)}; }
        _cameraView = [[VHRenderView alloc] 
								initCameraViewWithFrame:CGRectZero pushType:VHPushTypeSD options:option];
        _cameraView.scalingMode = VHRenderViewScalingModeAspectFill;
    }
    return _cameraView;
}

####2.添加本地摄像头

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    ///防止摄像头卡顿再此添加摄像头
    self.cameraView.frame = self.view.bounds;
    [self.view insertSubview:self.cameraView atIndex:0];
}

3.处理进入直播间回调

成功进入,则开始推流上麦

/**
 @brief 进入互动直播间结果回调
 @param data   互动直播间数据
 @param error  错误
 @discussion   当error为nil时候,表示已进入互动直播间;error不为空时,表示进入失败,失败原因描述:error.errorDescription。成功进入互动直播间成功就可以开始推流上麦了。
 */
- (void)room:(VHCInteractiveRoom *)room didEnteredWithRoomMetaData:(NSDictionary *)data error:(VHCError *)error
{
    if (error) {
        VHCLog(@"互动房间连接出错");
        return;
    }
    VHCLog(@"互动房间连接成功,开始推流");
    
    dispatch_async(dispatch_get_main_queue(), ^{
        //上麦推流
        [room publishWithCameraView:self.cameraView];
    });
}

4.处理上麦结果

/**
 @brief 某用户上麦结果回调
 @param joinId 上麦用户的参会id
 @param error error为nil时上麦成功
 @discussion  当error为nil时,表示上麦成功。
 */
- (void)room:(VHCInteractiveRoom *)room microUpWithJoinId:(NSString *)joinId error:(VHCError *)error
{
    if (error) {
        if ([joinId isEqualToString:[User defaultUser].joinId]) {
            VHCLog(@"上麦失败!");
            [VHCTool showAlertWithMessage:@"上麦失败!"];
            //上麦失败,退到看直播
            [self closeButtonClick:nil];
        }
        return;
    }

    if ([joinId isEqualToString:[User defaultUser].joinId])
    {
        VHCLog(@"上麦成功!");
        [VHCTool showAlertWithMessage:@"您已上麦"];
    }
    else {
        [VHCTool showAlertWithMessage:[NSString stringWithFormat:@"用户%@上麦了",joinId]];
    }
}

上麦结果回调会回调每个进入互动直播间的用户上麦消息,根据joinId区分不同的用户,收到上麦结果,error为空时,才算上麦成功,否则上麦失败。上麦失败建议退出互动直播间,重新进入。

其他具体见demo。

三、注意

VHRenderView和VHCInteractiveRoom类都提供了摄像头和麦克风的开关Api:

/*
 * 关闭音频
 */
- (void) muteAudio;

/*
 * 取消关闭音频
 */
- (void) unmuteAudio;

/*
 * 关闭视频
 */
- (void) muteVideo;

/*
 * 取消关闭视频
 */
- (void) unmuteVideo;

以上Api直接对自己的设备进行操作,关闭或者打开自己的摄像头。

/**
 @brief 设置麦克风开关
 @warning 推流后设置才可生效
 @return VHCError 设置失败 错误码:VHCErrorType_NoAuthority无权操作; VHCErrorType_NotEnterClass:未进入课堂或已掉线;VHCErrorType_InVaild:设置无效,未推流前设置都是无效的。
 */
- (VHCError *)closeMicphone:(BOOL)isClose;
/**
 @brief 设置摄像头开关
 @warning 推流后设置才可生效
 @return VHCError 设置失败 错误码:VHCErrorType_NoAuthority无权操作; VHCErrorType_NotEnterClass:未进入课堂或已掉线;VHCErrorType_InVaild:设置无效,未推流前设置都是无效的。
 */
- (VHCError *)closeVideo:(BOOL)isClose;

两者是有区别的,VHRenderView只是单纯的关闭或者打开自己的摄像头,但是不会通知主播端,VHCInteractiveRoom中的Api操作设备后会通知主播端。建议使用VHCInteractiveRoom中提供的Api。