开放平台
首页平台概述
开发者
  • API文档
  • SDK
产品功能
  • 新手入门
  • 产品功能
常见问题
首页平台概述
开发者
  • API文档
  • SDK
产品功能
  • 新手入门
  • 产品功能
常见问题
  1. iOS SDK
  • demo
  • JS SDK
    • 产品介绍
    • 快速接入
    • SDK 对接示例
    • 观看直播
    • 暖场视频
    • 房间消息说明
    • 互动连麦
    • 文档白板
    • 全局事件
    • 全局错误码
    • 版本更新记录
    • 互动工具
      • 互动-抽奖
      • 互动-礼物
      • 互动-签到
      • 互动-问卷
      • 互动-公告
      • 互动-商品
      • 互动-问答
      • 互动-推屏卡片
      • 互动-快问快答
      • 互动-聊天
      • 互动-优惠券
      • 互动-点赞
    • 直播间拓展功能
      • 资料下载
      • 观看限制验证
      • 观看协议
      • 回放章节
  • 点播SDK
    • 点播上传SDK
    • 更新记录
  • iOS SDK
    • 整体介绍
    • 快速接入
    • SDK 登录
    • 暖场视频
    • 视频轮询
    • 直播彩排
    • 高级美颜
    • 云导播
    • 观看协议
    • 文档白板演示
    • 聊天功能
    • 视频直播
      • 发起视频直播
      • 观看视频直播
    • 互动直播
      • 观众互动
      • 推流摄像头
      • 互动直播API
      • 主播发起互动直播
      • 嘉宾加入互动直播
    • 无延迟直播
      • 主播发起无延迟直播
      • 观众观看无延迟直播
    • 互动工具
      • 互动-抽奖
      • 互动-礼物
      • 互动-签到
      • 互动-问卷
      • 互动-章节打点
      • 互动-公告
      • 互动-商品
      • 互动-计时器
      • 互动-问答
      • 互动-推屏卡片
      • 互动-快问快答
      • 互动-优惠券
      • 互动-点赞
    • 直播间拓展能力
      • 直播间特色功能配置项
      • 文件下载
      • 修改角色昵称
      • 观看权限校验
      • 投屏
      • 虚拟人数
    • 观看回放
      • 观看回放
    • 防录屏
      • 跑马灯
    • 字段说明
      • 互动活动详情字段
      • 错误码说明
      • 常量定义
      • 活动详情字段说明
    • 版本更新说明
      • 版本更新信息
      • v2.3.0 到 v2.4.0 升级说明
      • v3.0.1 到 v3.2.0 升级说明
      • V2.9.0到v3.0.1升级说明
      • v6.3.0
      • v6.2.1
      • v3.2.0 到 v4.0.1
      • v2.7.0 到 v2.8.0、v2.9.0 升级说明
      • 6.5.0
      • v5.0.x 到 v6.0.0
      • v6.4.0
  • Adroid SDK
    • 整体介绍
    • 快速接入
    • SDK登录
    • 暖场视频
    • 视频轮巡功能
    • 直播彩排
    • 高级美颜
    • 云导播功能
    • 观看协议
    • 文档白板
    • 聊天功能
    • 房间消息
    • 信息采集说明
    • 视频直播
      • 发起视频直播
      • 观看视频直播
    • 互动直播
      • 互动直播API
      • 主播发起互动直播
      • 嘉宾加入互动直播
      • 观众观看互动直播
    • 无延迟直播
      • 主播发起无延迟直播
      • 观众观看无延迟直播
    • 互动工具
      • 互动-抽奖
      • 互动-礼物
      • 互动-签到
      • 互动-问卷
      • 互动-公告
      • 互动-商品
      • 互动-计时器
      • 互动-问答
      • 互动-推屏卡片
      • 互动-快问快答
      • 互动-优惠券
      • 互动-点赞
    • 直播拓展功能
      • 修改角色名称
      • 文件下载
      • 投屏演示
      • 虚拟人数
      • 观看权限校验
      • 直播间特色功能配置项
    • 观看回放
      • 观看回放/点播
    • 防录屏
      • 直播水印
      • 跑马灯
    • 字段说明
      • 房间消息字段说明
      • 聊天消息字段说明
      • 活动详情字段说明
    • 版本更新说明
      • 更新记录
      • v6.4.0
      • v6.3.0
      • v6.2.3
      • v6.2.1
      • v6.2.0
      • v6.1.0
      • v6.0.0
      • v5.0.0
      • v4.1.0
      • v4.0.0
      • v3.3.0
  • APP嵌入支付说明
    • 支付调起说明
    • Scheme规则说明
  1. iOS SDK

视频轮询

企业培训和培训课堂场景下,想监控培训学员的学习状态,使用微吼提供的视频轮巡功能,可以通过摄像头实时采集学员画面展示在监控端。从 SDK 进入的观众支持加入视频轮巡。

所属类#

类名描述
VHRoom互动类
VHLocalRenderView推流 view
VHVideoRoundObject视频轮询类
VHallChat聊天类

获取轮询用户#

方法 API
+ (void)getRoundUsers:(NSString *)room_id is_next:(NSString *)is_next success:(void(^)(NSDictionary *response))success fail:(void(^)(NSError *error))fail;
方法入参
参数名称是否必须示例备注
room_id是lss_xxxxx房间 id
is_next是10:当前组, 1:下一组
方法示例
[VHVideoRoundObject getRoundUsers:pass_room_id is_next:@"0" success:^(NSDictionary *response) {
    NSDictionary * data = response[@"data"];
    NSMutableArray * users = [NSMutableArray array];
    for (NSDictionary * dic in data[@"list"]) {
        [users addObject:dic[@"account_id"]];
    }
    [weakSelf videoRoundUsers:users webinar_id:weakSelf.webinar_id pass_room_id:weakSelf.pass_room_id];
} fail:^(NSError *error) {

}];

VHallChatDelegate 代理方法#

方法方法描述
videoRoundStart轮巡开始
reciveChatMsg轮巡结束
reciveCustomMsg轮巡列表

轮巡开始#

方法 API
- (void)videoRoundStart;

轮巡结束#

方法 API
- (void)videoRoundEnd;

轮巡列表#

方法 API
- (void)videoRoundUsers:(NSArray *)uids;

整体代码示例#

//
//  VHVideoRoundModel.m
//  UIModel
//
//  Created by 郭超 on 2022/6/21.
//  Copyright © 2022 www.vhall.com. All rights reserved.
//

#import "VHVideoRoundModel.h"
#import "Reachability.h"
#import <VHInteractive/VHRoom.h>

@interface VHVideoRoundModel ()<VHRoomDelegate>
/// 互动房间
@property (nonatomic, strong) VHRoom * videoRoundRoom;
/// 视频轮巡RenderView
@property (nonatomic, strong) VHLocalRenderView * videoRoundRenderView;
/// 网络监听
@property(nonatomic, strong) Reachability * reachAbility;
/// 活动id
@property (nonatomic, copy) NSString * webinar_id;
/// 房间id
@property (nonatomic, copy) NSString * pass_room_id;

@end

@implementation VHVideoRoundModel

- (void)dealloc
{
    [_reachAbility stopNotifier];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (instancetype)init
{
    if ([super init]) {
        //程序进入前后台监听
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
        //监听网络变化
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange:) name:kReachabilityChangedNotification object:nil];
        _reachAbility = [Reachability reachabilityForInternetConnection];
        [_reachAbility startNotifier];
    }return self;
}
#pragma mark  网络变化
- (void)networkChange:(NSNotification *)notification
{
    Reachability *currReach = [notification object];

    NSParameterAssert([currReach isKindOfClass:[Reachability class]]);

    //对连接改变做出响应处理动作
    NetworkStatus status = [currReach currentReachabilityStatus];

    switch (status) {
        case NotReachable:
        {
            //如果没有连接到网络就弹出提醒实况
            VH_ShowToast(@"网络断开");
            [self closeVideoRound];
        }
            break;
        case ReachableViaWiFi:
        {
            //wifi
            //请求最新数据
            [self getRoundUsers:self.webinar_id pass_room_id:self.pass_room_id];
        }
            break;
        case ReachableViaWWAN:
        {
            //数据网络
            //请求最新数据
            [self getRoundUsers:self.webinar_id pass_room_id:self.pass_room_id];
        }
            break;
        default:
            break;
    }
}

#pragma mark - 开启轮询
- (void)videoRoundUsers:(NSArray *)uids webinar_id:(NSString *)webinar_id pass_room_id:(NSString *)pass_room_id
{
    self.webinar_id = webinar_id;
    self.pass_room_id = pass_room_id;

    BOOL isHave = NO;
    for (NSString * userId in uids) {
        if ([userId isEqualToString:[VHallApi currentUserID]]) {
            isHave = YES;
            break;
        }
    }
    if (isHave) {
        // 开始轮询
        [self startVideoRound:webinar_id pass_room_id:pass_room_id];
    }else{
        // 关闭轮询
        [self closeVideoRound];
    }
}

#pragma mark - 开始轮询
- (void)startVideoRound:(NSString *)webinar_id pass_room_id:(NSString *)pass_room_id
{
    self.webinar_id = webinar_id;
    self.pass_room_id = pass_room_id;

    // 如果在推流 则不去调用加入房间等操作
    if (self.videoRoundRoom.isPublishing && self.videoRoundRoom.status == VHRoomStatusConnected) {
        return;
    }
    [self.videoRoundRoom enterRoomWithRoomId:webinar_id];
}

#pragma mark - 关闭轮询
- (void)closeVideoRound
{
    if (_videoRoundRoom) {
        [_videoRoundRoom leaveRoom];
        _videoRoundRoom = nil;
    }
    if (_videoRoundRenderView) {
        _videoRoundRenderView = nil;
    }
}

#pragma mark - VHRoomDelegate
- (void)room:(VHRoom *)room enterRoomWithError:(NSError *)error {
    if(error == nil) { //加入房间成功
        [self.videoRoundRoom publishWithCameraView:self.videoRoundRenderView];
    }else{
        VHLog(@"加入错误:%@",error.description);
    }
}

// 房间连接成功回调
- (void)room:(VHRoom *)room didConnect:(NSDictionary *)roomMetadata {
    VUI_Log(@"房间连接成功");
}

//推流成功
- (void)room:(VHRoom *)room didPublish:(VHRenderView *)cameraView {
    VUI_Log(@"推流成功");
}

// 停止推流成功
- (void)room:(VHRoom *)room didUnpublish:(VHRenderView *)cameraView {
    VUI_Log(@"停止推流成功");
}

//错误回调
- (void)room:(VHRoom *)room didError:(VHRoomErrorStatus)status reason:(NSString *)reason {
    VUI_Log(@"房间错误:%@---status:%zd",reason,status);
}

//房间状态变化
- (void)room:(VHRoom *)room didChangeStatus:(VHRoomStatus)status {
    VUI_Log(@"房间状态变化:%zd",status);
}

#pragma mark - 轮询列表
- (void)getRoundUsers:(NSString *)webinar_id pass_room_id:(NSString *)pass_room_id
{
    self.webinar_id = webinar_id;
    self.pass_room_id = pass_room_id;

    __weak __typeof(self)weakSelf = self;

    [VHVideoRoundObject getRoundUsers:pass_room_id is_next:@"0" success:^(NSDictionary *response) {
        NSDictionary * data = response[@"data"];
        NSMutableArray * users = [NSMutableArray array];
        for (NSDictionary * dic in data[@"list"]) {
            [users addObject:dic[@"account_id"]];
        }
        [weakSelf videoRoundUsers:users webinar_id:weakSelf.webinar_id pass_room_id:weakSelf.pass_room_id];
    } fail:^(NSError *error) {

    }];
}
#pragma mark - 切换前后台
//前台
- (void)appWillEnterForeground {
    [self getRoundUsers:self.webinar_id pass_room_id:self.pass_room_id];
}

//后台
- (void)appEnterBackground {
    // 关闭轮询
    [self closeVideoRound];
}

#pragma mark - 懒加载

- (VHRoom *)videoRoundRoom {
    if (!_videoRoundRoom) {
        _videoRoundRoom = [[VHRoom alloc] init];
        _videoRoundRoom.delegate = self;
    }
    return _videoRoundRoom;
}

- (VHLocalRenderView *)videoRoundRenderView {
    if (!_videoRoundRenderView) {
        NSDictionary *options = @{VHStreamOptionMixVideo:@NO,VHStreamOptionMixAudio:@NO,VHStreamOptionStreamType:@(VHInteractiveStreamTypeVideoPatrol)};
        _videoRoundRenderView = [[VHLocalRenderView alloc] initCameraViewWithFrame:CGRectMake(0, 0, VHScreenWidth, VHScreenHeight) options:options];
        _videoRoundRenderView.scalingMode = VHRenderViewScalingModeAspectFit;
        [_videoRoundRenderView muteAudio];
    }
    return _videoRoundRenderView;
}

@end
修改于 2025-05-27 11:59:31
上一页
暖场视频
下一页
直播彩排
Built with