实现科大讯飞版语音唤醒功能纯净版

首先需要获取唤醒信息:控制台-讯飞开放平台

通过开通唤醒功能,获取测试名额

1、通过控制台创建新应用: 控制台-讯飞开放平台

2、点击应用,选择语音唤醒(新版)

3、申请装机量(免费10个), 获取对应的APPID, APISecret, APIKey信息

剩下的就是代码开发了,对于一个纯小白,我最大的难点在于SDK工作路径的理解。

我以为这是个固定名称,实际为app的sdk存储路径, 不明白他们为什么不在代码内部直接实现

这里的实际内容是将resource文件夹中的资源 拷贝直 app的sdk文件夹中,已方便使用。

将资源复制到assets下, 然后再将资源拷贝到app的sdk下,封装了一个工具类,对科大讯飞的所有sdk均可用

package com.example.xiaobei;

import android.content.Context;
import android.content.res.AssetManager;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class AssetCopyUtils {
    private static final String TAG = "AssetFolderCopyUtils";

    public static void copyAssetFolder(Context context, String assetFolderPath, String destinationFolderPath) {
        AssetManager assetManager = context.getAssets();
        try {
            String[] files = assetManager.list(assetFolderPath);
            if (files!= null) {
                File destinationFolder = new File(destinationFolderPath);
                if (!destinationFolder.exists()) {
                    if (!destinationFolder.mkdirs()) {
                        Log.e(TAG, "Failed to create destination folder: " + destinationFolderPath);
                        return;
                    }
                }
                for (String file : files) {
                    String fullAssetPath = assetFolderPath + File.separator + file;
                    String fullDestinationPath = destinationFolderPath + File.separator + file;
                    if (isAssetDirectory(assetManager, fullAssetPath)) {
                        copyAssetFolder(context, fullAssetPath, fullDestinationPath);
                    } else {
                        copyAssetFile(context, fullAssetPath, fullDestinationPath);
                    }
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "Error copying asset folder: " + e.getMessage());
        }
    }

    private static boolean isAssetDirectory(AssetManager assetManager, String assetPath) {
        try {
            String[] subFiles = assetManager.list(assetPath);
            return subFiles!= null && subFiles.length > 0;
        } catch (IOException e) {
            Log.e(TAG, "Error checking asset directory: " + e.getMessage());
            return false;
        }
    }

    private static void copyAssetFile(Context context, String assetPath, String destinationPath) {
        AssetManager assetManager = context.getAssets();
        try (InputStream in = assetManager.open(assetPath);
             OutputStream out = new FileOutputStream(destinationPath)) {
            byte[] buffer = new byte[1024];
            int read;
            while ((read = in.read(buffer))!= -1) {
                out.write(buffer, 0, read);
            }
            Log.d(TAG, "Copied asset file: " + assetPath);
        } catch (IOException e) {
            Log.e(TAG, "Error copying asset file: " + assetPath + " - " + e.getMessage());
        }
    }
}

剩下的就是对资源的初始化,以及设置回调处理。

我这里没有使用他们demo里的方式,而是获取音频后直接进行唤醒操作,

int read = audioRecord.read(buffer, 0, BUFFER_SIZE);
if (read > 0) {
    // 发送 PCM 数据
    if (AIKIT_STATUS){
        write(buffer, status);
        if (status == AiStatus.BEGIN) {
            status = AiStatus.CONTINUE;
        }
    }
    else {
    // 语音做ASR识别
    //sendDataToRecognize(buffer);
    Log.d(TAG, "audioRecording......");
}

唤醒词是通过resource中的keyword.txt决定的,如果需要变更,修改即可使用。

通过回调函数,获取唤醒词,并使用阈值进行筛选,以获取自己的唤醒词。

demo下载

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐