【UE5/UE4】超詳細教程接入科大訊飛語音喚醒SDK并初始持久監(jiān)聽(10102錯誤碼解決)
先導
Windows環(huán)境下
**UE版本為UE4.27及以下
你需要具備一定的C++基礎,或全程一對一對照我的代碼編寫你的代碼
使用Offline Voice Recognition插件作為錄音插件(僅做錄音插件使用)
基于https://github.com/zhangmei126/XunFei二次開發(fā)
語音識別部分參考CSDNUE4如何接入科大訊飛的語音識別
在此基礎上增加了語音喚醒功能,實際上語音喚醒與上述文章中是兩個模塊
由于訊飛插件的使用需要調用MSPLogin,也就是需要先注冊
其插件中的SpeechInit()方法已經(jīng)為我們注冊好了,如果可以自己寫注冊的話,后述本文語音喚醒部分是不分引擎版本的
語音喚醒環(huán)境配置
參考UE4如何接入科大訊飛的語音識別接入科大訊飛sdk以及使用Offline Voice Recognition插件了后,在plugins中確保他們都是開啟的狀態(tài)
你要確保你的SDK下載的是Windows版本以及一下SDK文件包
你要確保你的SDK下載后正確導入了且appid已經(jīng)擁有了正確的配置
你要確保你SDK下載后將Windows_awaken_exp1227_iat1226_af12f15d\bin\msc\res\ivw\wakeupresource.jet放置到了你的c盤根目錄下
to
如果你是為了10102錯誤碼來此文章:
此處是訊飛的坑,訊飛的wakeupresource.jet的路徑必須是絕對路徑
c++中也就必須要使用轉義符"\\"即const char* params = "ivw_threshold=0:5, ivw_res_path =fo|c:\\wakeupresource.jet";
至此10102解決了,就這么簡單,但是很坑
打開VisualStudio
- 打開訊飛插件文件夾
- 在SpeechActor.cpp中引入qivw.h
qivw.h語音喚醒具備以下方法 - 在SpeechActor.h中
#pragma once
#include "SpeechTask.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SpeechActor.generated.h"
UCLASS()
class XUNFEI_API ASpeechActor : public AActor
{
GENERATED_BODY()
private:
FString Result;
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FWakeUpBufferDelegate);
public:
// Sets default values for this actor's properties
ASpeechActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "SpeechInit", Keywords = "Speech Recognition Initialization"))
void SpeechInit();
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "SpeechOpen", Keywords = "Speech Recognition Open"))
void SpeechOpen();
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "SpeechStop", Keywords = "Speech Recognition Stop"))
void SpeechStop();
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "SpeechQuit", Keywords = "Speech Recognition Quit"))
void SpeechQuit();
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "SpeechResult", Keywords = "Speech Recognition GetResult"))
FString SpeechResult();
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "WakeUpStart", Keywords = "Speech Recognition GetResult"))
FString WakeUpStart();
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "WakeUpEnd", Keywords = "Speech Recognition GetResult"))
bool WakeUpEnd(FString SessionID);
UFUNCTION(BlueprintCallable, Category = "XunFei", meta = (DisplayName = "WakeUpBuffer", Keywords = "Speech Recognition GetResult"))
bool WakeUpBuffer(TArray<uint8> MyArray, FString SessionID);
//這是一個回調函數(shù)
UPROPERTY(BlueprintAssignable)
FWakeUpBufferDelegate OnWakeUpBuffer;
};
- 在SpeechActor.cpp中
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "SpeechActor.h"
#include "XunFei.h"
#include "Dom/JsonObject.h"
#include "Serialization/JsonReader.h"
#include "Serialization/JsonSerializer.h"
#include <qivw.h>
// Sets default values
ASpeechActor::ASpeechActor() :
Result{}
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
}
// Called when the game starts or when spawned
void ASpeechActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ASpeechActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void ASpeechActor::SpeechInit()
{
FAutoDeleteAsyncTask<FSpeechTask>* SpeechTask = new FAutoDeleteAsyncTask<FSpeechTask>();
if (SpeechTask)
{
SpeechTask->StartBackgroundTask();
}
else
{
UE_LOG(XunFeiLog, Error, TEXT("XunFei task object could not be create !"));
return;
}
UE_LOG(XunFeiLog, Log, TEXT("XunFei Task Stopped !"));
return;
}
void ASpeechActor::SpeechOpen()
{
xunfeispeech->SetStart();
return;
}
void ASpeechActor::SpeechStop()
{
xunfeispeech->SetStop();
return;
}
void ASpeechActor::SpeechQuit()
{
xunfeispeech->SetQuit();
Sleep(300);
return;
}
FString ASpeechActor::SpeechResult()
{
Result = FString(UTF8_TO_TCHAR(xunfeispeech->get_result()));
FString LajiString("{\"sn\":2,\"ls\":true,\"bg\":0,\"ed\":0,\"ws\":[{\"bg\":0,\"cw\":[{\"sc\":0.00,\"w\":\"\"}]}]}");
int32 LajiIndex = Result.Find(*LajiString);
if (LajiIndex != -1)
{
Result.RemoveFromEnd(LajiString);
}
TSharedPtr<FJsonObject> JsonObject;
TSharedRef< TJsonReader<TCHAR> > Reader = TJsonReaderFactory<TCHAR>::Create(Result);
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
Result.Reset();
TArray< TSharedPtr<FJsonValue> > TempArray = JsonObject->GetArrayField("ws");
for (auto rs : TempArray)
{
Result.Append((rs->AsObject()->GetArrayField("cw"))[0]->AsObject()->GetStringField("w"));
}
}
UE_LOG(XunFeiLog, Log, TEXT("%s"), *Result);
return Result;
}
// 在 cb_ivw_msg_proc 靜態(tài)函數(shù)中進行事件觸發(fā)
int cb_ivw_msg_proc(const char* sessionID1, int msg, int param1, int param2, const void* info, void* userData)
{
if (MSP_IVW_MSG_ERROR == msg) //喚醒出錯消息
{
UE_LOG(LogTemp, Warning, TEXT("不在"));
return 0;
}
else if (MSP_IVW_MSG_WAKEUP == msg) //喚醒成功消息
{
UE_LOG(LogTemp, Warning, TEXT("imhere"));
if (userData) {
ASpeechActor* MYThis = reinterpret_cast<ASpeechActor*>(userData);
if (MYThis) {
UE_LOG(LogTemp, Warning, TEXT("diaoyongle"));
MYThis->OnWakeUpBuffer.Broadcast();
return 1;
}
}
}
return 0;
}
FString ASpeechActor::WakeUpStart()
{
int err_code = MSP_SUCCESS;
const char* params = "ivw_threshold=0:5, ivw_res_path =fo|c:\\wakeupresource.jet";
int ret = 0;
const char* sessionID = QIVWSessionBegin(NULL, params, &ret);
err_code = QIVWRegisterNotify(sessionID,cb_ivw_msg_proc, this);
if (err_code != MSP_SUCCESS)
{
UE_LOG(LogTemp, Warning, TEXT("QIVWRegisterNotify failed, error code is: %d"), ret);
}
else {
UE_LOG(LogTemp, Warning, TEXT("QIVWRegisterNotify success, error code is: %d"), ret);
}
if (MSP_SUCCESS != ret)
{
UE_LOG(LogTemp, Warning, TEXT("QIVWSessionBegin failed, error code is: %d"),ret);
}
return FString(sessionID);
UE_LOG(LogTemp, Warning, TEXT("QIVWSessionBegin is working"));
}
bool ASpeechActor::WakeUpEnd(FString SessionID)
{
int ret = QIVWSessionEnd(TCHAR_TO_ANSI(*SessionID) , "normal end");
if (MSP_SUCCESS != ret)
{
UE_LOG(LogTemp, Warning, TEXT("QIVWSessionEnd failed, error code is: %d"), ret);
return false;
}
UE_LOG(LogTemp, Warning, TEXT("QIVWSessioniSEnd"));
return true;
}
bool ASpeechActor::WakeUpBuffer(TArray<uint8> BitArray, FString SessionID)
{
int ret = 0;
if (BitArray.Num() == 0)
{
return false;
}
else
{
int audio_len = BitArray.Num();
int audio_status =2; // 設置音頻狀態(tài),這里假設為MSP_AUDIO_SAMPLE_LAST
ret = QIVWAudioWrite(TCHAR_TO_ANSI(*SessionID), BitArray.GetData(), audio_len, audio_status);
if (MSP_SUCCESS != ret)
{
printf("QIVWAudioWrite failed, error code is: %d", ret);
return false;
}
return true;
}
}
至此準備工作完成
打開我們的藍圖
-
在確保你的Offline Voice Recognition插件打開的前提下添加vosk插件
-
考慮本文的應用環(huán)境需要他初始化時就持續(xù)監(jiān)聽
故而讓其開始運行時就開啟錄音(語音喚醒需要錄音文件才能監(jiān)聽)
文章來源:http://www.zghlxwxcb.cn/news/detail-845666.html
- 接下里我們需要注冊訊飛,并且在運行結束釋放訊飛注冊
4.訊飛注冊后等待兩秒注冊我們的wakeup語音喚醒 - 綁定一個喚醒事件
3. 在設置一個1.1秒的定時器
4. 定時器內部(正在語音識別默認值為false)
5. 語音喚醒的自定義事件(喚醒五秒鐘后恢復繼續(xù)監(jiān)聽)
藍圖文件以綁定
author:Dacimal
定制化開發(fā)聯(lián)系:19815779273(不閑聊)文章來源地址http://www.zghlxwxcb.cn/news/detail-845666.html
到了這里,關于【UE5/UE4】超詳細教程接入科大訊飛語音喚醒SDK并初始持久監(jiān)聽(10102錯誤碼解決)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!