阿里巴巴语音识别 funasr的android部署

阿里巴巴语音识别----安卓APK本地部署教程 funasr安卓部署

讲述一下部署安卓APK的过程:参考fawai-asr的github代码完成的!主要就是写了CMakeLists.txt的信息,找到onnxruntime-android和FFmpeg-android的.so文件供给安卓app去调用。

主要就是三个文件去生成想要的东西! GITHUB地址:https://github.com/jianyangshi/funasr-android

需要生成的ffmpeg.so 这里的SO需要给安卓调用,只需要从github上去下载源码生成即可!安卓的SO包都有,所以不需要自己编译!

编译build_androidv8.sh 可以直接复制下面的代码进去

#!/bin/bash
 
NDK=/home/sjy/Android/android-ndk-r26b
HOST_TAG=linux-x86_64
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
 
#ANDROID_LIB_PATH="$(pwd)/android"
 
ARCH=arm64
CPU=armv8-a
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
PREFIX=$(pwd)/android/$CPU
CROSS_PREFIX=$TOOLCHAIN/bin/llvm-
#OPTIMIZE_CFLAGS="-march=$ARCH"
API=29
BASEPATH=$(cd `dirname $0`; pwd)
echo $BASEPATH
NM=$TOOLCHAIN/bin/llvm-nm
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
#FDK_INCLUDE=$BASEPATH/fdk-aac/android/$CPU/include
echo $CC
echo $CXX
 
function build_android_arm
{
echo "build ffmpeg for android $CPU"
./configure \
--prefix=$PREFIX \
--disable-gpl \
--disable-postproc \
--enable-shared \
--enable-jni \
--enable-neon \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-hwaccel=h264_mediacodec \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-symver \
--disable-stripping \
--extra-cflags="-Os -fpic -mfpu=neon -mfloat-abi=softfp -marm" \
--enable-nonfree \
--enable-gpl \
--enable-cross-compile \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--nm=$NM \
--cc=$CC \
--cxx=$CXX \
--sysroot=$SYSROOT
 
#make clean
#make -j2
#make install
echo "configure ffmpeg for android $CPU completed"
}
 
export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$TOOLCHAIN/bin/llvm-as
export LD=$TOOLCHAIN/bin/llvm-ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
 
build_android_arm
 
#make clean
#make && make install

等待生成文件夹下面的ANDROID即可。把ANDROID的文件夹放到CMakeLists.txt里面的FFMPEG_DIR即可。
可以参照一些博客的参数介绍

编译FAWASR-SJY目录下的asr_engine/androidlib/build-android.sh CMakeLists.txt fawasr2pass.cc 编辑这三个文件先!

# build-android.sh
dir=$PWD/build

mkdir -p $dir
cd $dir
    # -DFFMPEG_DIR=/home/sjy/ffmpeg-master-latest-armv8-gpl-shared \ 
cmake -DCMAKE_BUILD_TYPE=release \
    -DBUILD_SHARED_LIBS=ON  \
    -DCMAKE_TOOLCHAIN_FILE="/home/sjy/Android/Sdk/ndk/25.1.8937393/build/cmake/android.toolchain.cmake" \
    -DANDROID_ABI="arm64-v8a" \
    -DANDROID_PLATFORM="android-26" \
    -DCMAKE_INSTALL_PREFIX=./install ..

make -j4
// fawasr2pass.cc 你可以选择搞什么模式下的安卓JNI调用
#include "jni.h" 
#include "precomp.h"
#ifdef __cplusplus 

namespace funasroff {
    FUNASR_HANDLE tpass_handle = nullptr;
    FUNASR_HANDLE tpass_online_handle = nullptr;
    // FUNASR_RESULT FunTpassInferBuffer = nullptr;
   

    FUNASR_RESULT result = nullptr;
    FUNASR_DEC_HANDLE decoder_handle = nullptr;

    std::string vad_sub_dir = "/vad_res";
    std::string asr_offline_sub_dir = "/asr_offline_res";
    std::string asr_online_sub_dir = "/asr_online_res";
    std::string punc_sub_dir = "/punc_res";
    std::string online_res = "";
    std::string tpass_res = "";
    std::string nn_hotwords_ = "";
    std::string hotword = "/hotword";

    std::vector<std::vector<float>> hotwords_embedding = CompileHotwordEmbedding(tpass_handle, nn_hotwords_, ASR_TWO_PASS);
    std::string offline_res = "";
    std::vector<std::vector<std::string>> punc_cache(2);


    int thread_num = 1;

    extern "C"
    JNIEXPORT void JNICALL Java_com_fawai_asr_OnnxInter_ASRInitOffline(
        JNIEnv *env, jobject /*obj*/, jstring jModelDir)
    {
        const char* pModelDir = env->GetStringUTFChars(jModelDir, nullptr);
        std::cout << "pModelDir" << pModelDir << std::endl;
        std::map<std::string, std::string> model_path;
       

        model_path.insert({VAD_DIR, std::string(pModelDir) + vad_sub_dir});
        model_path.insert({VAD_QUANT, "true"});

        model_path.insert({OFFLINE_MODEL_DIR, std::string(pModelDir) + asr_offline_sub_dir});
        model_path.insert({ONLINE_MODEL_DIR, std::string(pModelDir) + asr_online_sub_dir});
        model_path.insert({QUANTIZE, "true"});

        model_path.insert({PUNC_DIR, std::string(pModelDir) + punc_sub_dir});
        model_path.insert({PUNC_QUANT, "true"});


        try {
            tpass_handle = FunTpassInit(model_path, thread_num);
            if (!tpass_handle) {
                LOG(ERROR) << "FunTpassInit init failed";
            }
            // std::vector<int> chunk_size_vec = {5, 10, 5};
            std::vector<int> chunk_size = {5,10,5};
            float glob_beam = 3.0f;
            float lat_beam = 3.0f;
            float am_sc = 10.0f;
            tpass_online_handle = FunTpassOnlineInit(tpass_handle, chunk_size);
            decoder_handle = FunASRWfstDecoderInit(tpass_handle, ASR_TWO_PASS, glob_beam, lat_beam, am_sc);
            if (!tpass_handle) {
                LOG(ERROR) << "FunASRWfstDecoderInit init failed";
            }
        } catch (const std::exception& e) {
            LOG(INFO) << e.what();
        }
    }


    extern "C"
    JNIEXPORT jstring JNICALL Java_com_fawai_asr_OnnxInter_ASRInferOffline(
        JNIEnv *env, jobject /*obj*/, jbyteArray jWaveform, jboolean input_finished)
    {
        int size = env->GetArrayLength(jWaveform);
        jbyte* waveform = env->GetByteArrayElements(jWaveform, 0);
        
        std::vector<char> subvector(waveform, waveform + size);
        
        try{
            // result = FunOfflineInferBuffer(asr_handle, subvector.data(), subvector.size(), RASR_NONE, NULL, 
            // hotwords_embedding,  16000, "pcm", true, decoder_handle);

            result = FunTpassInferBuffer(tpass_handle, tpass_online_handle,
                                        subvector.data(), subvector.size(), punc_cache,
                                        input_finished==JNI_TRUE, 16000, "pcm", (ASR_TYPE)2, hotwords_embedding, true, decoder_handle
                                        );

            if (result) {
                // std::string msg = FunASRGetResult(result, 0);
                // offline_res += msg;

                // if (msg != "") {
                //     LOG(INFO) << "offline results :" << msg;
                // }
                //  asr_handle,subvector.data(), subvector.size(), 
                //                                -1, null    , hotwords_embedding,
				// 							 16000,  "pcm", true, dec_handle
                // std::string  tmp_sent_msg = FunASRGetStampSents(result, 0);
                // tmp_sent += tmp_sent_msg;
                // if (tmp_sent_msg != "") {
                //     LOG(INFO) << "tmp_sent results : " << tmp_sent_msg;
                //     offline_res = tmp_sent;
                // }
                std::string tmp_online_msg = FunASRGetResult(result, 0);
                online_res += tmp_online_msg;

                if (tmp_online_msg != "") {
                    LOG(INFO) << "online_res :" << tmp_online_msg;
                }
                std::string tmp_tpass_msg = FunASRGetTpassResult(result, 0);
                tpass_res += tmp_tpass_msg;
                if (tmp_tpass_msg != "") {
                    LOG(INFO) << "offline results : " << tmp_tpass_msg;
                    online_res = tpass_res;
                }

                FunASRFreeResult(result);
            }
        } catch (std::exception const &e)
        {
            LOG(ERROR) << e.what();
        } 

        return env->NewStringUTF(online_res.c_str());

    }

}

#endif
//这里的代码主要是看的 onnxruntime下的bin中的funasr-onnx-2passs.cpp还有include下的funasrrunonnxtime.h来构造JAVA下的函数
# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)

project(FunASRWebscoket) 

set(CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ version to be used.")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# set 设置 文件路径啥的 
set(ONNXRUNTIME_DIR /home/sjy/cpp_ws/onnxruntime-android-1.14.0)
 # 设置 ONNXRUNTIME_DIR 的路径是以下的文件路径:/home/sunyujia/cpp_ws/onnxruntime-android-1.14.0
link_directories(${ONNXRUNTIME_DIR}/lib) # 以上路径下的lib文件夹
include_directories(${ONNXRUNTIME_DIR}/include) # 以上路径下的include文件夹

set(FFMPEG_DIR /home/sjy/ffmpeg-master-latest-armv8-gpl-shared)
#  设置 FFMPEG_DIR 的路径是以下的文件路径:/home/sunyujia/cpp_ws/onnxruntime-android-1.14.0
link_directories(${FFMPEG_DIR}/lib) # 以上路径下的lib文件夹
include_directories(${FFMPEG_DIR}/include) # 以上路径下的include文件夹



include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/include/) # 关联文件夹下的.h文件 也就是头文件
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/yaml-cpp/include/)
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/kaldi-native-fbank)
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/openfst/src/include/)
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/src)
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/gflags/src)
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/kaldi)
include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/jieba/include)
# include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/jieba/include/limonp/)
# include_directories(/home/sjy/ffmpeg-master-latest-armv8-gpl-shared/include)



add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/yaml-cpp yaml-cpp) # 在当前的文件夹下 完成.a文件的生成
add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/kaldi-native-fbank/kaldi-native-fbank/csrc csrc)
add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/src src)
add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/kaldi kaldi)
add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/gflags gflags)
add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/openfst/src openfst)

include_directories(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/glog)
set(BUILD_TESTING OFF) # 设置不开启
add_subdirectory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/glog glog) # 在当前的文件夹下 完成.a文件的生成

aux_source_directory(${PROJECT_SOURCE_DIR}/../onnxruntime/src src_files) # 查找路径下的所有源文件 保存在src_files这个变量中去!
# aux_source_directory(${PROJECT_SOURCE_DIR}/../onnxruntime/third_party/kaldi kaldi_files) # 查找路径下的所有源文件 保存在src_files这个变量中去!
add_library(fawasr2pass-jni SHARED fawasr2pass.cc ${src_files}  ) 
# add_library生成静态或者动态库 参数解析(生成的库名字, 决定是动态还是静态(默认是静态的),参数指定生成库的源文件) 
target_link_libraries(fawasr2pass-jni PUBLIC avcodec avformat avutil avfilter swresample swscale  )
# avcodec avformat avutil avfilter swresample swscale
target_link_libraries(fawasr2pass-jni PUBLIC onnxruntime  -pthread gflags fst  kaldi-util kaldi-decoder yaml-cpp dl  csrc glog log)
# target_link_libraries(fawasroff-jni PUBLIC -pthread)
# target_link_libraries 添加头文件目录. -pthread

最后进入到/home/sjy/fawasr-sjy/asr_engine/androidlib目录下,运行命令行,输入 bash ./build-android.sh即可。最后把build下生成的.so都放到安卓APP中去,运行软件在手机上就算是配置成功了!

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值