本地双录 SDK

通过阅读本文,您可以快速了解本地双录 MPIDRSProcess iOS SDK 的相关功能及调用方法。

iOS 接入

创建项目工程

使用 xcode 创建一个新的项目。

环境配置

  1. SDK 环境依赖

    MPIDRSProcess SDK依赖 APMUtilsTexelMPIDRSSDK(动态库)。

  2. 参数配置

    1. 添加 MPIDRSSDK.framework 动态库,同时添加其他必要的库文件,如下图所示。

      2
    2. 添加 MPIDRSProcess.bundle 资源。

    3. 将 Other Linker Flags 设置为 -ObjC。

    4. 支持 HTTP 请求,即在 App Transport Security Settings字段下加入 Allow Arbitrary Loads,并配置为 YES,如下图所示。

      5
    5. 允许使用相机、麦克风权限。

      6

MPIDRSProcess 功能

初始化 MPIDRSProcess SDK

FlowCreateConfig * config = [[FlowCreateConfig alloc] init];
 config.ak = Ak;
 config.sk = Sk;
 config.appId = AppId;
 config.userId = [DemoSetting sharedInstance].userId;
 config.packageName = PackageName;//包名、暂时手动传输
 config.processId = ProcessId;//控制台生成的流程Json的Id
 config.ocrroi = @[@0.2,@0.2,@0.6,@0.6];//身份证ROI设置
 config.ocrRotate = 0;//身份证检测角度
 config.isOcrFront = true;//检测身份证哪一面
 config.presetSize = FlowRecorderPresetSize360P;
 config.isHorizontal = true;//是否横屏录制
 
 self.processSdk = [[IDRSFlow alloc] initIDRSWithDelegate:self Config:config success:^(NSString *string, JsonBlock jsonBlock) {
 //接收流程Json
 //string:流程Json ----- 需要自行添加人脸图片及文本中姓名的替换
 //事例见:Demo
 NSLog(@"%@",string);
 
 //、、、
 //修改流程Json---添加检测人的照片base64---修改播报字段最终的姓名内容
 NSString * jsonxx = newString;
 //返回给SDK
 jsonBlock(jsonxx);//返回给SDK
 }];

开启摄像头

//Orientation确定了视频流角度、而检测需要这个角度、如果此处角度为您页面角度、则检测角度为0即可 
[self.processSdk startCameraWithOrientation:AVCaptureVideoOrientationLandscapeRight back:^(UIView *cameraView) {
 dispatch_async(dispatch_get_main_queue(), ^{
 [self.view addSubview:cameraView];
 [self.view sendSubviewToBack:cameraView];
 cameraView.frame = self.view.frame;
 });
}];

切换摄像头

[self.processSdk switchCamera:^(BOOL result) {
 NSLog(@"Demo :: 切换摄像头 %@",result?@"成功":@"失败");
}];

开始流程

[self.processSdk startFlow];
//流程说明:如果有语音,语音播放完毕后、自动开启第一个检测项、其他检测项需要手动调用下一项
// 如果没有语音,则自动开始第一个检测项、之后操作与上述一致

开始下一个检测项

[self.processSdk startNextDetection];

开始上一章

[self.processSdk reLastPage];

重新检测当前项

[self.processSdk repeatCurrentDetection];

重新播放当前章节

[self.processSdk replayCurChapter];

暂停/恢复播放

[self.processSdk flowPause];//播放暂停
[self.processSdk flowResume];//恢复播放

添加当前自定义章节的结果

[self.processSdk AddCurChapterCustomResult:@"自定义结果"];

清空默认路径下的视频及 meta/result 文件

[self.processSdk wipeCache];

销毁

请及时使用销毁、否则可能影响下次初始化。

[self.processSdk destroy];

MPIDRSProcess 回调

相机流的回调

- (void)flowCameraView:(UIView *)cameraView didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
{
 //相机流回调
}

人脸位置回调

//人脸位置
-(void)onFaceDetectUi:(NSArray<faceUIAndName *> *)resules
{
 self.faceView.detectResult = resules;
 //可根据resules判断人是否齐全等检验操作
}

手位置回调

- (void)onHandDetectUi:(NSArray<HandDetectionOutput *> *)results
{
 self.handView.detectResult = results;
}

音频文件下载状态回调

- (void)downloadAudio:(float)per percent:(NSString *)percent isAll:(BOOL)isAll error:(NSError *)error{
 if (error) {
 return;
 }
 dispatch_async(dispatch_get_main_queue(), ^{
 
 self.operateResult.text = [NSString stringWithFormat:@"当前文件进度:%.2f %% \n 总文件下载进度:%@\n是否全部下载完成:%@",per,percent,isAll?@"下载完成":@"未完成"];
 });
}

章节开始回调

//章节开始
- (void)onPhaseStarted:(CheckResult *)phase
{
 dispatch_async(dispatch_get_main_queue(), ^{
 NSLog(@"------xxxxx----:%u",phase.Type);
 switch (phase.Type) {
 case id_card_recognize:
 NSLog(@"------xxxxx----:身份证框出现");
 self.imageView.hidden = false;
 break;
 case sign_classify_recognize:
 NSLog(@"------xxxxx----:签名框出现");
 self->_greenpick.hidden = false;
 break;
 default:
 break;
 }
 
 self.operateResult.text = [NSString stringWithFormat:@"%@\n%@\n%@",phase.phaseId,phase.detectionId,phase.content];
 if (![phase.phaseId isEqual:self->_curPhaseId]) {
 self->_curPhaseId = phase.phaseId;
 [[scollLabelView shareManager] setTextViewWithString:phase.content];
 [[scollLabelView shareManager] setTextViewLocation:0];
 }
 });
 NSLog(@"%@",phase.content);
}

超时回调

//超时
- (void)onDetectionFail:(id)body
{
 NSLog(@"DetectionFail--%@",body);
 dispatch_async(dispatch_get_main_queue(), ^{
 self.operateResult.text = body;
 //可以在超时之后再显示下一步(跳过)按钮
 });
}

检测成功回调

//检测成功
- (void)onDetectionSuccess:(SuccessModel*)body
{
 dispatch_async(dispatch_get_main_queue(), ^{
 NSString *zhangjie = body.checkResult.phaseId;
 NSString *jiancexiang = body.checkResult.detectionId;//=检测类型
 NSString *neirong = @"";
 switch (body.checkResult.Type) {
 case face_track:
 break;
 case face_recognize:
 break;
 case liveness_track:
 break;
 case speech_word_detect:
 neirong = body.speech_word_Result;
 self.operateResult.text = neirong;
 break;
 case id_card_recognize:{
 if (body.ocrOutput.num.length > 0) {
 neirong = body.ocrOutput.num;
 }else {
 neirong = body.ocrOutput.date;
 }
 self.imageView.hidden = true;
 self.operateResult.text = neirong;
 }
 break;
 case sign_action_recognize:
 neirong = body.sign_action_Result;
 self.operateResult.text = neirong;
 break;
 case static_hand_recognize:
 neirong = [NSString stringWithFormat:@"%@",body.static_hand_Result];
 self.operateResult.text = neirong;
 break;
 case sign_classify_recognize:
 neirong = body.sign_classify_Result==0?@"手写":@"非手写";
 self.operateResult.text = neirong;
 self->_greenpick.hidden = true;
 break;
 case other:
 neirong = body.other;
 self.operateResult.text = neirong;
 break;
 default:
 break;
 }
 NSLog(@"onDetectionSuccess 章节:%@ 检测项:%@ 内容:%@",zhangjie,jiancexiang,neirong);
 });
}

章节结束回调

//章节完成
- (void)onPhaseComleted:(CheckResult *)phase
{
 dispatch_async(dispatch_get_main_queue(), ^{
 NSLog(@"------xxxxx----:%u",phase.Type);
 switch (phase.Type) {
 case id_card_recognize:{
 dispatch_async(dispatch_get_main_queue(), ^{
 NSLog(@"------xxxxx----:身份证框隐藏");
 self.imageView.hidden = true;
 });
 }
 break;
 case sign_classify_recognize:{
 dispatch_async(dispatch_get_main_queue(), ^{
 NSLog(@"------xxxxx----:签名框隐藏");
 self->_greenpick.hidden = true;
 });
 }
 break;
 default:
 break;
 }
 });
 NSLog(@"%@",phase.content);
}

TTS 合成数据回调

//tts合成数据返回
- (void)onTTSCallBackwithText:(char *)text word_idx:(int)word_idx buffer:(char *)buffer len:(int)len taskid:(char *)taskid
{
 NSLog(@"TTSCallBack:%s----%d",text,word_idx);
 [[scollLabelView shareManager] setTextViewLocation:word_idx];
}

文件上传状态回调

- (void)ossUploadWithStarted:(BOOL)isRun msg:(NSString *)msg
{
 dispatch_async(dispatch_get_main_queue(), ^{
 self.maskView.label.text = msg;
 self.maskView.label.numberOfLines = 0;
 [self.maskView.label sizeToFit];
 if (isRun) {
 self->_maskView.hidden = false;
 //蒙层旋转等待
 //可标注当前上传的文件信息 msg
 [self.maskView loadingViewShow];
 }else {
 //蒙层按钮状态
 [self.maskView loadingViewHidden];
 }
 });
}

全部流程完成回调

//全部流程完成
- (void)onFlowCompleted
{
 self.operateResult.text = @"章节,全部完成";
 NSLog(@"章节,全部完成");
 //如需录制下一单、需要退出后重新进入
}

报错信息回调

//报错信息
- (void)onError:(NSDictionary *)errorDic withParam:(IDRSUploadManagerParam *)param
{
// NSDictionary *errorDic = @{
// @"domain":domain,
// @"code":@(code),
// @"position":position,
// @"msg":msg
// };
 if (param) {
 //上传失败后、返回来的可用于重试/以后上传的参数信息
 __unused IDRSUploadManagerParam * sasda = param;
 }
 NSString *domain = errorDic[@"domain"];
 int code = [errorDic[@"code"] intValue];
 NSString *position = errorDic[@"position"];
 NSString *errorString = [NSString stringWithFormat:@"%@\ncode: -%d\n位置:%@",domain,code,position];
 [[DemoToast shareInstance] makeToast:errorString duration:3];
}

资源下载状态回调

//资源下载
-(void)onRemoteDownLoadModuleType:(IDRSDownLoadModuleType)type progress:(float)per allPro:(NSString *)percent error:(NSError *)error
{
    NSLog(@"进度状态:%@ - 下载进度:%.2f - 文件总进度:%@",type == IDRSDownLoadModuleTypeDone ? @"下载完成":@"下载中", per,percent);
    if (error) {
        NSLog(@"进度状态:下载异常 :%@",error);
        _circleView.msgLab.text = @"下载异常";
    }
    if (type == IDRSDownLoadModuleTypeDone) {
        _circleView.msgLab.text = @"下载完成";
    }
    [_circleView setPercent:per andText:percent];
}