视频通话

更新时间:2024-04-26 08:49:27下载pdf

IPC SDK 提供视频通话能力,由 音视频功能呼叫管理 模块构成。可用于实现带屏 IPC 和中控屏等设备双向视频通话功能。

视频通话流程

双向视频通话功能包括 SDK 呼出设备呼入 两部分。

  1. 初始化双向视频通话 SDK,注册消息模块监听。
  2. App 发起呼叫,判断设备是否有支持双向视频对讲能力,支持呼叫则进入 步骤 4
  3. 设备呼入:
    • 设备呼入,App 收到 MQTT 消息,弹出呼叫页面并进入 步骤 4
    • 设备呼入,App 收到推送,单击推送进入 App,弹出呼叫页面并进入 步骤 4
  4. 通话管理,状态监听同步。
  5. 进行音视频功能的相关操作,P2P 连接,开启本地摄像头,拉流,开启音频并进行视频对讲。
  6. App 挂断,App 取消,设备挂断,网络异常超时等通话结束退出。

是否支持双向视频对讲

判断设备是否支持双向视频对讲高级能力。

接口说明

 - (void)fetchDeviceCallAbilityByDevId:(NSString *)devId completion:(ThingSmartCallFetchCompletion)completion

参数说明

参数 说明
devId 设备 ID
completion 方法回调,返回 BOOL 值,YES 表示支持

示例代码

 [ThingSmartCallChannel.sharedInstance fetchDeviceCallAbilityByDevId:devId completion:^(BOOL result, NSError * _Nullable error) {}];

初始化/配置 SDK

初始化注册视频呼叫模块,用于处理呼叫通话的各种状态。建议放在登录后初始化。

在使用SDK呼叫功能前,必须完成SDK前置初始化和配置。

启动呼叫服务

接口说明

- (void)launch;

注册呼叫 UI

- (BOOL)registerCallInterfaceManager:(id<ThingCallInterfaceManager>)callInterfaceManager;

callInterfaceManager

呼叫页面管理类,负责生成、跳转和退出呼叫页面。

注册模块标识

目前仅支持 ThingCallInterfaceManagerScreenIPCIdentifier,与呼叫消息对应。

@property (nonatomic, copy) ThingCallInterfaceManagerIdentifier identifier;

生成呼叫页面

- (id<ThingSmartCallInterface>)generateCallInterfaceWithCall:(id<ThingSmartCallProtocol>)call;

跳转呼叫页面

- (void)presentInterface:(id<ThingSmartCallInterface>)interface completion:(ThingCallInterfaceManagerCompletion)completion;

退出呼叫页面

- (void)dismissInterface:(id<ThingSmartCallInterface>)interface completion:(ThingCallInterfaceManagerCompletion)completion;

注册代理

异常呼叫回调。

- (BOOL)addDelegate:(id<ThingSmartCallChannelDelegate>)delegate;

MQTT/Push Call

MQTT 和 Push 呼入通话信息传给视频通话 SDK,统一进行状态管理,包括检查通话状态是否过期,已被其他人接听,繁忙等。如果出现异常状态,则返回具体的错误状态 ThingSmartCallError

- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error;
- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidPushCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error;

拦截所有 MQTT 呼叫事件消息

不推荐

- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveCallEventsMessage:(id<ThingSmartCallEventMessage>)message;

ThingSmartCallType 说明

typedef NS_ENUM(NSUInteger, ThingSmartCallType) {
    ThingSmartCallTypeOneToOne = 1, //one to one
    ThingSmartCallTypeOneToMore = 2, //one to more,if one reject, the call stops.
    ThingSmartCallTypeOneToMoreSpecial = 3, //one to more, if one reject, the call has no effect.
};

ThingSmartCallProtocol 说明

呼叫模型,包括呼叫中的状态。

参数 说明
curId 呼叫方 ID
targetId 接收方 ID
sessionId 呼叫会话 ID
timeout 超时时间
extra 扩展参数 Map 类型,转换 JSON 格式:{"bizType":"screen_ipc","channelType":2,"category":"sp_dpsxj"}
accepted 呼叫是否已接听,BOOL
answered 呼叫是否已响应,BOOL
end 呼叫是否已结束,BOOL
connected P2P 是否已连接,BOOL
outgoing 是否是主叫方
callType 呼叫类型,ThingSmartCallType 枚举值

ThingSmartCallEventMessage 说明

呼叫事件消息。

参数 说明
curId 呼叫方 ID
targetId 接收方 ID
sessionId 呼叫会话 ID
timeout 超时时间
extra 扩展参数 Map 类型,转换 JSON 格式:{"bizType":"screen_ipc","channelType":2,"category":"sp_dpsxj"}
callEvent 呼叫事件枚举 ThingSmartCallEvent
eventName 呼叫事件名称 ThingSmartCallEventName
callType 呼叫类型,ThingSmartCallType 枚举值

示例代码

#import <ThingSmartCallChannelKit/ThingSmartCallChannelKit.h>

@interface DemoCallManager : NSObject <ThingSmartCallChannelDelegate>

@end

@implementation DemoCallManager

+ (void)load {
    [DemoCallManager.sharedInstance configurateCallSDK];
}

+ (instancetype)sharedInstance {
    static DemoCallManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[DemoCallManager alloc] init];
    });
    return instance;
}

- (void)configurateCallSDK {
    [ThingSmartCallChannel.sharedInstance launch];
    [ThingSmartCallChannel.sharedInstance addDelegate:self];
    CameraCallInterfaceManager *interfaceManager = [[CameraCallInterfaceManager alloc] init];
    interfaceManager.identifier = ThingCallInterfaceManagerScreenIPCIdentifier;
    [ThingSmartCallChannel.sharedInstance registerCallInterfaceManager:interfaceManager];
}

#pragma mark - ThingSmartCallChannelDelegate

//receive a call, but it is an invalid call, then will call it, eg: go to device panel or an error page.
- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidPushCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error {
    if ([call.targetId isKindOfClass:NSString.class] && call.targetId.length) {
        NSLog(@"The call is invalid");
    }
}

- (void)callChannel:(ThingSmartCallChannel *)callChannel didReceiveInvalidCall:(id<ThingSmartCallProtocol>)call error:(NSError *)error {
    if (error.code == ThingSmartCallErrorOnCalling) {
        NSLog(@"is on calling");
    }
}

@end

通话呼出

IPC SDK 发起视频通话。

是否有视频通话

检查 SDK 是否正进行视频通话,SDK 限制同时仅一个会话存在。如果正在通话中,会返回 YES

接口说明

- (BOOL)isOnCalling;

发起呼叫

接口说明

- (void)startCallWithTargetId:(NSString *)targetId timeout:(NSInteger)timeout extra:(NSDictionary *)extra success:(nullable ThingSmartCallSuccess)success failure:(nullable ThingSmartCallFailure)failure;

参数说明

参数 说明
targetId 被叫方 ID (一般指设备 ID)
timeout 超时时间
extra 扩展参数 Map 类型,转换 JSON 格式:{"bizType":"screen_ipc","channelType":2,"category":"sp_dpsxj","keepConnect":false}
success ThingSmartCallSuccess 成功回调
failure ThingSmartCallFailure 失败回调,返回 NSError

ThingSmartCallError

typedef NS_ENUM(NSInteger, ThingSmartCallError) {

    ThingSmartCallErrorInvalidParams = -2500,
    ThingSmartCallErrorRequestFailed = -2501,
    ThingSmartCallErrorInvalidResponse = -2502,
    ThingSmartCallErrorInvalidData = -2503,
    ThingSmartCallErrorInterfaceManagerNotFound = -2504,//did not register call interface manager

    ThingSmartCallErrorUndefinedSessionId = -2508,

    //sender
    ThingSmartCallErrorRejected = -2510, //reject
    ThingSmartCallErrorPeerBusy = -2511, //busy
    ThingSmartCallErrorNotAnswer = -2512, //not answer
    ThingSmartCallErrorPeerHangUp = -2513, //hang up

    //receiver
    ThingSmartCallErrorOnCalling = -2520, //on calling
    ThingSmartCallErrorRejectedByOthers = -2521, //rejected by others
    ThingSmartCallErrorAnsweredByOthers = -2522, //answered by others
    ThingSmartCallErrorCancel = -2523, //sender cancel

    //sender & receiver
    ThingSmartCallErrorTimeout = -2530, //timeout
    ThingSmartCallErrorConnectFail = -2531, //connect failed
    ThingSmartCallErrorDisconnect = -2532, //disconnect
    ThingSmartCallErrorStop = -2533, //remote stop

    //others
    ThingSmartCallErrorNetworkChanged = -2570,//network changed
    ThingSmartCallErrorEnterBackground = -2571 //enter background
};

示例代码

 [ThingSmartCallChannel.sharedInstance startCallWithTargetId:devId timeout:30 extra:extra success:^{} failure:^(NSError * _Nullable error){}];

Push 消息接入

SDK 不具备推送相关能力,因此需要主动调用SDK方法进行呼叫推送消息中转。

接口说明

 - (void)handlePushMessage:(NSDictionary *)message;

参数说明

参数 说明
message 推送字典 NSDictionary,推送消息详细解析请参考 Demo

示例代码

@interface AppDelegate ()

@end

@implementation AppDelegate

- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {

    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSDictionary *userInfo = response.notification.request.content.userInfo;
        if (userInfo) {
            [self handleRemoteNotificationWithHigherVersion:userInfo];
        }
    }else {
        //本地通知处理

    }
    completionHandler();
}

- (void)handleRemoteNotificationWithHigherVersion:(NSDictionary *)userInfo {
    NSString *link = [userInfo objectForKey:@"link"];
    NSNumber *ts = [userInfo objectForKey:@"ts"];
    NSNumber *voipEnable = [userInfo objectForKey:@"voipEnable"];

    if ([link isKindOfClass:NSString.class] && link.length > 0 && [link containsString:@"://rtcCall"]) {
        NSURL *url = [NSURL URLWithString:link];
        if ([url.host isEqualToString:@"rtcCall"]) {
            //解析 url 中的参数
            NSDictionary *info = [url queryDictionary];//伪代码
            NSString *param = [info thing_stringForKey:@"param"];
            if (![param isKindOfClass:NSString.class]) {
                return;
            }


            NSError *error;
            NSData *jsonData = [param dataUsingEncoding:NSUTF8StringEncoding];
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingAllowFragments error:&error];
            if (error == nil) {
                return;
            }

            if (dic == nil && ![dic isKindOfClass:NSDictionary.class]) {
                return;
            }

            NSMutableDictionary *map = [dic mutableCopy];
            if (voipEnable) [map setObject:voipEnable forKey:@"voipEnable"];

            [ThingSmartCallChannel.sharedInstance handlePushMessage:map];

            return;
        }
    }
}
@end

呼叫页面

SDK 只提供呼叫能力,不提供呼叫页面 UI,需要页面遵从 ThingSmartCallInterface 协议,实现 UI 和 SDK 的联动。建议使用系统的 presentViewController:dismissViewControllerAnimated: 弹出和退出页面。

初始化呼叫页面

- (instancetype)initWithCall:(id<ThingSmartCallProtocol>)call;

参数说明

参数 说明
call 视频呼叫模型

通话前准备工作

进行通话前准备工作,例如同步设备数据。

- (void)setupCompleted:(void(^)(NSError *error))completed;

参数说明

参数 说明
completed 完成回调

对端已响应呼叫

- (void)callPeerDidRespond;

呼叫失败

- (void)callEndWithError:(nullable NSError *)error;

参数说明

参数 说明
error 错误 NSError

执行影响主线程的任务

执行影响主线程的任务,例如开启音频对讲和视频对讲等。

- (void)executeHeavyTasksCompleted:(void(^ __nullable)(NSError * _Nullable error))completed;

参数说明

参数 说明
error 错误 NSError

动作执行器

视频通话操作并同步 SDK,SDK 进行会话状态管理。

@property (nonatomic, weak) id<ThingCallActionExecuter> actionExecuter;

响铃

设备呼入,App 有响铃,给设备发送 ring,App 播放铃声自主实现。

- (void)interface:(id<ThingSmartCallInterface>)interface onRing:(id<ThingSmartCallProtocol>)call;

取消

App 呼出,设备未响应之前,App 取消呼叫。

- (void)interface:(id<ThingSmartCallInterface>)interface onCancel:(id<ThingSmartCallProtocol>)call;

挂断

App 呼出或者设备呼入,已接听,App 挂断。

- (void)interface:(id<ThingSmartCallInterface>)interface onHangUp:(id<ThingSmartCallProtocol>)call;

拒接

设备呼入,App 拒接。

- (void)interface:(id<ThingSmartCallInterface>)interface onReject:(id<ThingSmartCallProtocol>)call;

接听

设备呼入,App 接听。

- (void)interface:(id<ThingSmartCallInterface>)interface onAccept:(id<ThingSmartCallProtocol>)call;

P2P 已连接

App P2P 连接成功。

- (void)interface:(id<ThingSmartCallInterface>)interface onConnected:(id<ThingSmartCallProtocol>)call;

异常中断

出现异常中断,例如进入后台,网络变化等。

- (void)interface:(id<ThingSmartCallInterface>)interface onException:(id<ThingSmartCallProtocol>)call error:(nullable NSError *)error;

示例代码

更多信息,参考 Demo