使用Bun FFI调用Microsoft Speech C SDK失败,原生C脚本正常
问题:Bun FFI调用Microsoft Speech C SDK创建关键词识别器失败
背景
我有一个可正常运行的C脚本,能通过Microsoft Speech C SDK检测音频文件中的关键词。由于官方JS SDK未实现本地关键词检测功能,官方建议使用C/C++ SDK结合Node封装调用,因此尝试通过Bun FFI实现相同逻辑。
原生C脚本(可正常运行)
编译命令
gcc main.c -o main -I./speechsdk/include/c_api/ -L./speechsdk/lib/x64/ -lMicrosoft.CognitiveServices.Speech.core -Wl,-rpath=./speechsdk/lib/x64/ -g
C代码
#include "./speechsdk/include/c_api/speechapi_c.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #define CHECK_RESULT(result, message) \ if ((result) != SPX_NOERROR) { \ fprintf(stderr, message ": %lu\n", (result)); \ exit(-1); \ } int main() { SPXAUDIOCONFIGHANDLE audioConfig; AZACHR audioConfigResult = audio_config_create_audio_input_from_wav_file_name(&audioConfig, "./file.wav"); CHECK_RESULT(audioConfigResult, "Failed to create audio config."); printf("Created audio config.\n"); SPXKEYWORDHANDLE keywordModel; AZACHR keywordModelResult = keyword_recognition_model_create_from_file( "./keyword_models/hey_bumblebee.table", &keywordModel); CHECK_RESULT(keywordModelResult, "Failed to create keyword model."); printf("Created keyword model.\n"); SPXRECOHANDLE recognizer; AZACHR recognizerResult = recognizer_create_keyword_recognizer_from_audio_config(&recognizer, audioConfig); CHECK_RESULT(recognizerResult, "Failed to create recognizer."); printf("Created recognizer.\n"); SPXRESULTHANDLE resultHandle = NULL; AZACHR recognizeKeywordResult = recognizer_recognize_keyword_once( recognizer, keywordModel, &resultHandle); CHECK_RESULT(recognizeKeywordResult, "Failed to to start recognition."); Result_Reason reason; AZACHR reasonResult = result_get_reason(resultHandle, &reason); CHECK_RESULT(reasonResult, "Failed to get result reason."); if (reason == ResultReason_RecognizedKeyword) { char textBuffer[256]; AZACHR textResult = result_get_text(resultHandle, textBuffer, sizeof(textBuffer)); CHECK_RESULT(textResult, "Failed to get recognized text."); printf("Recognized: \"%s\"\n", textBuffer); } else if (reason == ResultReason_NoMatch) { Result_NoMatchReason noMatchReason; AZACHR noMatchReasonResult = result_get_no_match_reason(resultHandle, &noMatchReason); CHECK_RESULT(noMatchReasonResult, "Failed to get no match reason."); printf("No match. Reason: %d.\n", noMatchReason); } else if (reason == ResultReason_Canceled) { Result_CancellationReason cancellationReason; Result_CancellationErrorCode cancelationCode; AZACHR canceledReasonResult = result_get_reason_canceled(resultHandle, &cancellationReason); CHECK_RESULT(canceledReasonResult, "Failed to get canceled reason."); AZACHR canceledCodeResult = result_get_canceled_error_code(resultHandle, &cancelationCode); CHECK_RESULT(canceledCodeResult, "Failed to get canceled error code."); printf("Canceled. Reason: %d. Code: %d.\n", cancellationReason, cancelationCode); } else { printf("Unknown.\n"); } return 0; }
Bun FFI调用代码(创建识别器失败)
运行时创建audioConfig和keywordModel返回SPX_NOERROR(0),表示成功,但创建recognizer时返回无对应错误码的大数值,导致失败。相关代码如下:
import { dlopen, FFIType, CString, ptr } from "bun:ffi"; const cwd = process.cwd(); // Enum derived from the SDK enum ResultReason { NoMatch = 0, Canceled = 1, RecognizingSpeech = 2, RecognizedSpeech = 3, RecognizingIntent = 4, RecognizedIntent = 5, TranslatingSpeech = 6, TranslatedSpeech = 7, SynthesizingAudio = 8, SynthesizingAudioComplete = 9, RecognizingKeyword = 10, RecognizedKeyword = 11, SynthesizingAudioStart = 12, } const speechSdkPath = `${cwd}/speechsdk/lib/x64/libMicrosoft.CognitiveServices.Speech.core.so`; // Load the Speech SDK shared library const speechSdk = dlopen(speechSdkPath, { audio_config_create_audio_input_from_wav_file_name: { args: [FFIType.cstring, FFIType.ptr], returns: FFIType.u64_fast, }, keyword_recognition_model_create_from_file: { args: [FFIType.cstring, FFIType.ptr], returns: FFIType.u64_fast, }, recognizer_create_keyword_recognizer_from_audio_config: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.u64_fast, }, recognizer_recognize_keyword_once: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.u64_fast, }, result_get_reason: { args: [FFIType.ptr, FFIType.ptr], returns: FFIType.u64_fast, }, result_get_text: { args: [FFIType.ptr, FFIType.ptr, FFIType.u32], returns: FFIType.u64_fast, }, }); const textEncoder = new TextEncoder(); const textDecoder = new TextDecoder(); const checkResult = (result: number | bigint) => { if (result !== 0) { throw new Error(`Error: ${result}`); } }; // Replace these with the actual file paths const audioFilePath = textEncoder.encode(`${cwd}/file.wav`); const keywordModelFilePath = textEncoder.encode( `${cwd}/keyword_models/hey_bumblebee.table` ); // Create audio config console.log( `Creating audio config from file: ${textDecoder.decode(audioFilePath)}` ); const audioConfig = ptr(new Uint8Array(8)); const audioConfigResult = speechSdk.symbols.audio_config_create_audio_input_from_wav_file_name( audioFilePath, audioConfig ); checkResult(audioConfigResult); console.log("Created audio config."); // Create keyword model console.log( `Creating keyword model from file: ${textDecoder.decode( keywordModelFilePath )}` ); const keywordModel = ptr(new Uint8Array(8)); const keywordModelResult = speechSdk.symbols.keyword_recognition_model_create_from_file( keywordModelFilePath, keywordModel ); checkResult(keywordModelResult); console.log("Created keyword model."); // Create recognizer console.log("Creating recognizer..."); const recognizer = ptr(new Uint8Array(8)); const recognizerResult = speechSdk.symbols.recognizer_create_keyword_recognizer_from_audio_config( recognizer, audioConfig ); console.log(); checkResult(recognizerResult!); console.log("Created recognizer."); // // Start recognition // console.log("Starting recognition..."); // const resultHandle = ptr(new Uint8Array(16)); // const recognizeKeywordResult = // speechSdk.symbols.recognizer_recognize_keyword_once( // recognizer, // keywordModel, // resultHandle // ); // checkResult(recognizeKeywordResult); // console.log("Recognition finished."); // // // Get result reason // console.log("Getting result reason..."); // const reason = ptr(new Uint8Array(8)); // const reasonResult = speechSdk.symbols.result_get_reason(resultHandle, reason); // checkResult(reasonResult); // console.log("Got result reason:", new CString(reason)); // // // Check the reason and handle accordingly // if (reason === ResultReason.RecognizedKeyword) { // // Assuming a buffer size, adjust as needed // const textBuffer = new Uint8Array(256); // const textResult = speechSdk.symbols.result_get_text( // resultHandle, // textBuffer, // textBuffer.length // ); // checkResult(textResult); // console.log("Recognized:", new CString(ptr(textBuffer))); // } else { // console.error("Recognition failed:", reason); // }
疑问
不确定是否是符号类型映射错误导致创建识别器失败,寻求解决办法。
内容的提问来源于stack exchange,提问作者ChevCast
相关产品推荐
相关产品推荐

