开放能力
开发平台
行业应用
生态合作
开发与教学
资讯 社区 控制台
技术能力
语音技术
图像技术
文字识别
人脸与人体识别
视频技术
AR与VR
自然语言处理
知识图谱
数据智能
场景方案
部署方案
行业应用
智能教育
智能医疗
智能零售
智能工业
企业服务
智能政务
智能农业
信息服务
智能园区
智能硬件
人脸识别

    虚拟人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();
    }
    上一篇
    产品简介
    下一篇
    人脸特征值同步