虚拟人SDK-Android
所有文档

          人脸识别

          虚拟人SDK-Android

          1 简介

          本文档主要介绍 虚拟人SDK-Android 的集成和使用。在使用本文档前,需要了解授权逻辑,您可以通过“合作咨询”联系我们申请应用授权。

          2 快速入门

          支持的系统和硬件版本

          • 系统:支持 Android 5.0+(API Level 21)到 Android 9(API Level 28)系统。需要开发者通过minSdkVersion来保证支持系统的检测。
          • CPU架构:armeabi-v7a。
          • 硬件要求:要求设备上有相机模块,CPU 4核及以上,内存2G及以上。
          • 网络:支持WIFI及移动网络,移动网络支持使用NET网关及WAP网关(CMWAP、CTWAP、UNIWAP、3GWAP)。

          开发包说明

          虚拟人SDK.zip
              |- face-virtual                 // demo工程
              |- face_virtual                 // 模型资源文件,push到SD卡中
              |- module_virtual-release.aar   // 包含jar包,so库及依赖

          SDK提供的demo工程以Android Studio方式提供。

          3 SDK集成步骤

          3.1 模型和资源导入

          路径位置不限制,保证不被删除即可,需要在创建new Model() 对象时候,指定对应位置即可

          adb push face_virtual/ /sdcard/

          3.2 SDK接入工程

          3.2.1 配置调入aar,参考face-virtual-demo的build.gradle文件

          apply plugin: 'com.android.application'
          
          android {
              compileSdkVersion 28
              buildToolsVersion "29.0.2"
          }
          
          repositories {
              flatDir {
                  dirs 'libs'
              }
          }
          
          dependencies {
              implementation fileTree(dir: 'libs', include: ['*.jar'])
              implementation(name:'module_virtual-release', ext:'aar')
          }

          3.2.2 配置增加权限和组件,参考face-virtual-demo的AndroidManifest文件

              <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
              <uses-permission android:name="android.permission.RECORD_AUDIO" />
              <uses-permission android:name="android.permission.INTERNET" />
              <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
              <uses-permission android:name="android.permission.READ_PHONE_STATE" />
              <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
              <uses-permission android:name="android.permission.GET_TASKS" />
              <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
              <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
          
              <dist:module dist:instant="true" />
          
          
                  <!--安全设备指纹接入 start-->
                  <activity
                      android:name="com.baidu.liantian.LiantianActivity"
                      android:excludeFromRecents="true"
                      android:exported="true"
                      android:launchMode="standard"
                      android:theme="@android:style/Theme.Translucent">
                      <intent-filter><action android:name="com.baidu.action.Liantian.VIEW" />
          
                          <category android:name="com.baidu.category.liantian" />
                          <category android:name="android.intent.category.DEFAULT" />
                      </intent-filter>
                  </activity>
                  <receiver
                      android:name="com.baidu.liantian.LiantianReceiver"
                      android:exported="false">
                      <intent-filter><action android:name="com.baidu.action.Liantian.VIEW" />
          
                          <category android:name="com.baidu.category.liantian" />
                          <category android:name="android.intent.category.DEFAULT" />
                      </intent-filter>
                      <intent-filter android:priority="2147483647">
                          <action android:name="android.intent.action.BOOT_COMPLETED" />
                      </intent-filter>
                  </receiver>
                  <provider
                      android:name="com.baidu.liantian.LiantianProvider"
                      android:authorities="应用包名+.liantian.ac.provider"
                      android:exported="true" />
                  <service
                      android:name="com.baidu.liantian.LiantianService"
                      android:exported="false">
                      <intent-filter><action android:name="com.baidu.action.Liantian.VIEW" />
          
                          <category android:name="com.baidu.category.liantian" />
                          <category android:name="android.intent.category.DEFAULT" />
                      </intent-filter>
                  </service>
          
                  <meta-data
                      android:name="seckey_avscan"
                      android:value="660346260f8a841a04ec2a56815b421b" />
                  <meta-data
                      android:name="appkey_avscan"
                      android:value="100034" />
          
                  <!--安全设备指纹接入 end-->

          3.3 接口调用

          3.3.1 权限获取,参考face-virtual-demo的BaseActivity文件

          SDK 需要申请READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE、RECORD_AUDIO 权限

          3.3.2 设备ID获取,参考face-virtual-demo的MainActivity文件SetupTask 实例

          SDK 设备授权,申请需要先获取设备ID,VKAuth getDeviceId 获取String 设备ID String 字符串,提交Baidu 工作人员

          Log.v(TAG, vkAuth.getDeviceId(this.activityReference.get()));     

          3.3.3 激活授权,参考face-virtual-demo的MainActivity文件SetupTask 实例

          百度工作人员会提供新授权文件和KEY 关键密钥; 新授权文件替换face-virtual-demo asset 下的xuniren.license 文件 新的KEY替换MainActivity TEST_KEY 字段内容

          private static final String TEST_KEY = "xuniren-vivo-874ba8af";
          private static final String TEST_LICENSE_NAME = "xuniren.license_vivo-874ba8af";

          3.3.4 初始化SDK,查考face-virtual-demo的MainActivity文件SetupTask 实例

          @Override
          public void init() {
              new SetupTask(this).execute();
          }
          
                  private static class SetupTask extends AsyncTask<Void, Void, Exception> {
                  WeakReference<MainActivity> activityReference;
                  VKAuth vkAuth;
          
                  SetupTask(MainActivity activity) {
                      this.activityReference = new WeakReference<>(activity);
                      vkAuth = new VKAuth();
                      vkAuth.setActiveLog(3, 1);
                  }
          
                  @Override
                  protected Exception doInBackground(Void... params) {
          
                      vkAuth.initLicenseBatchLine(this.activityReference.get(), TEST_KEY);
                      if (vkAuth.getAuthStatus() != AndroidLicenser.ErrorCode.SUCCESS) {
                          Log.v(TAG, vkAuth.getAuthStatus()
                                  + " " + vkAuth.authGetLocalInfo(this.activityReference.get()).toString());
          
                          Log.v(TAG, vkAuth.getDeviceId(this.activityReference.get()));
                          return new Exception("授权错误");
                      }
          
                      VirtualConfig config = new VirtualConfig();
                      config.setVisualize(5);
                      config.setThread(4);
                      config.setModelPath("/sdcard/face_virtual_all/data");
                      activityReference.get().model = new Model(config);
                      activityReference.get().recognizer = new VKVirtualRecognizer(activityReference.get().model, 16000.f);
                      activityReference.get().recognizer.setListener(activityReference.get());
          
                      return null;
                  }
          
                  @Override
                  protected void onPostExecute(Exception result) {
                      if (result != null) {
                          activityReference.get().setErrorState(
                                  String.format(activityReference.get().getString(R.string.failed), result));
                          Toast.makeText(this.activityReference.get(), String.format(activityReference.get()
                                  .getString(R.string.failed), result), Toast.LENGTH_SHORT).show();
                      } else {
                          activityReference.get().setUiState(STATE_READY);
                      }
                  }
              }

          3.3.5 语言文件识别,参考face-virtual-demo的MainActivity文件RecognizeTask实例

          findViewById(R.id.recognize_file).setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View view) {
                  recognizeFile();
               }
          });
          
           public void recognizeFile() {
                  setUiState(STATE_FILE);
                  isActivateGuard = false;
              }

          3.3.6 空闲状态动作,参考face-virtual-demo的MainActivity GuardThread 任务

            private GuardThread guardThread;
              private static boolean isActivateGuard = true;
          
              @Override
              public void init() {
                  new SetupTask(this).execute();
                  guardThread = new GuardThread(this);
                  guardThread.start();
              }
          
              class GuardThread extends Thread {
                  WeakReference<MainActivity> activityReference;
          
                  public GuardThread(MainActivity activity) {
                      this.activityReference = new WeakReference<>(activity);
                  }
          
                  public void run() {
                      while (!interrupted()) {
                          if (this.activityReference.get().recognizer != null)
                              if (isActivateGuard) {
                                  int[][] actionArr = {{0, 4}};
                                  this.activityReference.get().recognizer.runSilent(actionArr);
                              } else {
                                  isActivateGuard = true;
                                  // 关闭守护任务
                                  // 新的语音输入需要重置之前状态
                                  this.activityReference.get().recognizer.resetWaveAction();
          
                                  // 静默接口runSilent,支持多个动作输入,第15帧1号动作;第60帧3号动作;第120帧4号动作.....
                                  int[][] actionArr1 = {{1, 1}, {2, 75}};
                                  // , {3, 150}, {4, 227}, {5, 300}, {6, 375}, {7, 475}, {8, 575},
                                  //        {9, 675}, {10, 775}, {11, 875}, {12, 975}, {13, 1075}, {14, 1175}};
                                  this.activityReference.get().recognizer.runSilent(actionArr1);
          
                                  // 新的语音可以是wav或者pcm,wav需要输入头字节,pcm 头字节输入0
                                  this.activityReference.get().recognizer.acceptWaveform("/sdcard/face_virtual_all/input/1_16.wav", 44 + 34);
                                  // 动作设置,1表示一号动作,130表示TTS的第130字时候会触发动作,标点符合不计入
                                  this.activityReference.get().recognizer.setWaveAction(1, 10);
                                  this.activityReference.get().recognizer.run();
          
                                  this.activityReference.get().recognizer.resetWaveAction();
                                  // 静默接口runSilent,支持多个动作输入,第15帧1号动作;第60帧3号动作;第120帧4号动作.....
                                  int[][] actionArr = {{1, 1}, {2, 75}};
                                  // , {3, 150}, {4, 227}, {5, 300}, {6, 375}, {7, 475}, {8, 575},
                                  //        {9, 675}, {10, 775}, {11, 875}, {12, 975}, {13, 1075}, {14, 1175}};
                                  this.activityReference.get().recognizer.runSilent(actionArr);
                              }
                      }
                  }
              }

          3.3.7 语言播放,参考face-virtual-demo的MainActivity文件RecognizeTask实例

                   @Override
              public void onVirtualPlayStart() {
                  Toast.makeText(MainActivity.this, "播报开始", Toast.LENGTH_SHORT).show();
              }
          
              @Override
              public void onVirtualPlayFinish() {
                  Toast.makeText(MainActivity.this, "播报完成", Toast.LENGTH_SHORT).show();
              }
          
              @Override
              public void onPartialSize(int size) {
                  playView.setPartialSize(size);
              }
          
              @Override
              public void onPartialResult(VKVirtualData videoSlice) {
                  playView.setPartialResult(videoSlice);
              }
          
              @Override
              public void onPartialFinish() {
          
              }
          
              @Override
              public void onPartialError(Exception var1) {
          
              }
          
              @Override
              protected void onResume() {
                  super.onResume();
                  playView.onResume();
              }
          
              @Override
              protected void onPause() {
                  super.onPause();
                  playView.onPause();
              }
          
              @Override
              protected void onStop() {
                  super.onStop();
                  playView.onStop();
              }
          
              @Override
              protected void onDestroy() {
                  super.onDestroy();
                  model.delete();
              }

          4 API及回调接口、消息的详细说明

          4.1 VKAuth 鉴权类

          4.1.1 构造方法

          说明:loadLibrary 动态库

          public VKAuth()

          示例代码

          vkAuth = new VKAuth();

          4.1.2 initLicense

          说明:单次设备授权,设置licenseKey与licenseName(授权文件官网下载,存放asset目录下)

          public AndroidLicenser.ErrorCode initLicense(Context context, String licenseKey,String licenseName, boolean isRemote)
          参数名 含义
          context 上下文
          licenseKey 官网申请key
          licenseName 官网申请授权文件
          isRemote 是否启动过期自动更新,默认false

          示例代码

          vkAuth.initLicense(this.activityReference.get(), TEST_KEY, TEST_LICENSE_NAME, false);

          4.1.3 initLicenseBatchLine

          说明:批量设备授权,设置licenseKey,避免每个设备都安装一次

           public AndroidLicenser.ErrorCode initLicenseBatchLine(Context context, String licenseKey) 
          参数名 含义
          context 上下文
          licenseKey 官网申请key

          示例代码

          vkAuth.initLicenseBatchLine(this.activityReference.get(), TEST_KEY);

          4.2 VirtualConfig 配置类

          4.2.1 setModelPath

          设置配置加载路径

          public void setModelPath(String modelPath)
          参数名 含义
          modelPath 路径地址

          示例代码

          config.setModelPath("/sdcard/face_virtual/data");

          4.2.2 setVisualize

          设置形象类型

          public void setVisualize(int visualize) 
          参数名 含义
          visualize 虚拟人形象类型: 1 默认女生全屏;2 默认女生半屏;3 女生半屏;4 男生半屏

          示例代码

           config.setVisualize(0);

          4.2.3 setThread

          设置预测线程个数

          public void setThread(int thread)
          参数名 含义
          thread 线程个数,一般设置为cpu 核数1/2

          示例代码

          config.setThread(3);

          4.3 Model 模型

          4.3.1 构造方法

          说明:加载指定路径下的模型,配置文件

          public Model(VirtualConfig config)
          参数名 含义
          model_path 路径地址

          示例代码

          VirtualConfig config = new VirtualConfig();
          config.setVisualize(0);
          config.setModelPath("/sdcard/face_virtual/data");
          activityReference.get().model = new Model(config);

          4.3.2 delete方法

          说明:卸载模型对象,释放内存

          public synchronized void delete()  
          参数名 含义
          void void

          示例代码

          @Override
          protected void onDestroy() {
              super.onDestroy();
              model.delete();
           }

          4.4 VKVirtualRecognizer 语音识别类

          4.4.1 构造方法

          说明:构造方法,传递model和语言频率

          public VKVirtualRecognizer(Model model, float sampleFrequency)
          参数名 含义
          model 模型对象
          sampleFrequency 采样率默认16000

          示例代码

          rec = new VKVirtualRecognizer(activityReference.get().model, 16000.f);

          4.4.2 setListener

          设置语音识别监听方法

          public void setListener(VKVirtualRecognitionListener listener)
          参数名 含义
          listener onPartialSize(int size);语音分片个数
          onPartialResult(VKVirtualData videoSlice); 语音分片结果

          示例代码

          rec.setListener(activityReference.get());

          4.4.3 resetWaveAction

          说明:动作状态重置接口,每次新语音输入前调用 示例代码

          // 新的语音输入需要重置之前状态
          rec.resetWaveAction();

          4.4.4 acceptWaveform

          说明:语音文件输入接口,新的语音可以是wav或者pcm,wav需要输入头字节,pcm 头字节输入0

          public int acceptWaveform(String dataPath, int headSize) 
          参数名 含义
          dataPath 文件绝对路径
          headSize 头字节大小

          示例代码

          // 新的语音可以是wav或者pcm,wav需要输入头字节,pcm 头字节输入0
          rec.acceptWaveform("/sdcard/face_virtual/input/cixuanfu-16.wav", 44 + 34);

          4.4.5 acceptWaveform

          说明:语音数据流输入方法

          public int acceptWaveform(byte[] data, int len)
          参数名 含义
          data 字节数据流
          len 字节数据长度

          示例代码

          VKVirtualSpeechRecognizer.this.recognizer.acceptWaveform(buffer, nread);

          4.4.6 setWaveAction

          说明:设置动作类型和触发时机

          public int setWaveAction(int actionType, int actionStart)
          参数名 含义
          actionType 1,8个动作的类型,0表示无动作,1~8表示8种不同动作:

          1)左摊手、2)右摊手、3)手正常抬起左右摇摆(见面打招呼/离开再见)、 4)手托下颌思考、5)正常抬起比OK、 6)左手向内弯曲抬起到腹部、7)右手向内弯曲抬起到腹部、 8)双手向内弯曲抬起到腹部

          2,14个动作的类型,0表示无动作,1~14表示14种不同动作:

          1) 倾听动作、2) 眨眨眼、3) 点头、4) 表述状态-单手、5) 表述状态-双手、6) 微笑、7) 张嘴笑、8) 失落、9) 惊讶、10) 打招呼-挥手、11) 自我介绍、12) OKAY、13) 摇头、14) 思考

          actionStart 动作设置,1表示一号动作,130表示TTS的第130字时候会触发动作,标点符合不计入

          示例代码

          // 动作设置,1表示一号动作,130表示TTS的第130字时候会触发动作,标点符合不计入
          rec.setWaveAction(1, 130);

          4.4.7 run

          说明:语言识别运行接口,调用run 之后,会在setListener 设置的监听方法onPartialSize 和 onPartialResult 分别回掉数据 示例代码

          rec.run();

          4.4.8 runSilent

          说明:静默接口输入,支持多个动作输入,第15帧1号动作;第60帧3号动作;第120帧4号动作.....

          public void runSilent(int[][] actionArr)
          参数名 含义
          actionArr 具体的动作序列:(具体动作, 触发帧位置)

          示例代码

          // 静默接口runSilent,支持多个动作输入,第15帧1号动作;第60帧3号动作;第120帧4号动作.....
          int[][] actionArr = {{1, 15}, {3, 60}, {4, 120}, {4, 300}, {4, 450}};
          rec.runSilent(actionArr);

          4.5 VKVirtualPlayView 虚拟视频播放类

          4.5.1 setBackground

          说明:设置播放器背景图

          public void setBackground(Bitmap bitmap)
          参数名 含义
          bitmap 图像句柄

          示例代码

          playView.setBackground(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_default));

          4.5.2 setBackground

          说明:设置播放器背景图

          public void setBackground(Bitmap bitmap)
          参数名 含义
          bitmap 图像句柄

          示例代码

          playView.setBackground(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_default));

          4.5.3 onStart接口

          说明:启动接口,初始化音频播放,视频播放,通过listener 监听语言播放状态回掉

          public void onStart(VKVirtualPlayListener listener)
          参数名 含义
          listener onVirtualPlayStart 语言播放启动
          onVirtualPlayFinish 语言播放结束

          示例代码

          playView.onStart(this);

          4.5.4 setPartialSize

          说明:设置语言切片个数,通过 onPartialSize 方法获取切片个数,设置

          public void setPartialSize(int partialSize)
          参数名 含义
          partialSize 切片个数

          示例代码

          @Override
          public void onPartialSize(int size) {
              playView.setPartialSize(size);
          }

          4.5.5 setPartialResult

          说明:虚拟语言图像设置方法,通过onPartialResult方法获取每次切片的视频信息

          public void setPartialResult(VKVirtualData data)
          参数名 含义
          data 虚拟语音,图像数据结构体

          示例代码

          @Override
          public void onPartialResult(VKVirtualData videoSlice) {
              playView.setPartialResult(videoSlice);
          }

          4.5.6 onResume接口

          说明:虚拟视频重新开始接口,图像重新开始,语音重新播放

          public void onResume()

          示例代码

          @Override
          protected void onResume() {
              super.onResume();
              playView.onResume();
          }

          4.5.7 onPause接口

          说明:虚拟视频暂停接口,图像暂停播放,语音暂停播放

          public void onPause()

          示例代码

          @Override
          protected void onPause() {
              super.onPause();
              playView.onPause();
          }

          4.5.8 onStop接口

          说明:虚拟视频暂停接口,图像暂停播放,语音暂停播放

          public void onStop()

          示例代码

          @Override
          protected void onStop() {
             super.onStop();
             playView.onStop();
          }
          上一篇
          产品简介
          下一篇
          人脸特征值同步