For the complete documentation index, see llms.txt. This page is also available as Markdown.

对话流程

了解语音输入、播放状态、转写事件、动作队列执行、叙事触发以及中断处理。

在会话建立后,玩家组件会转发音频或文本输入,Convai 返回转录内容和角色输出,而 chatbot 组件会播放音频、更新面部和情绪数据,并排队动作。了解当前 SDK 中哪些部分是事件驱动的,以及哪些辅助函数是可靠的,有助于 Blueprint 在不依赖不受支持的状态假设的情况下驱动 UI 和游戏玩法。

播放与辅助状态

UConvaiChatbotComponent 提供若干 BlueprintPure 状态和播放辅助函数:

函数
Blueprint 显示名称
当前行为

GetIsTalking

正在说话

返回组件当前的音频播放标志。可用于字幕时机、动画过渡和中断按钮。

GetTalkingTimeElapsed

返回当前音频响应的已播放时间。

GetTalkingTimeRemaining

返回估计的剩余播放时间。

IsListening

Is Listening

存在于 Blueprint API 中,但当前返回 false 在 SDK 源码中。

IsProcessing

正在思考

存在于 Blueprint API 中,但当前返回 false 在 SDK 源码中。

IsInConversation

Is In Conversation

组合这些辅助状态。因为 IsListeningIsProcessing 当前返回 false,所以这实际上在 GetIsTalking 于当前 SDK 中绑定。

对于当前版本,请将 GetIsTalking、音频播放委托、转录事件和动作事件视为可靠的运行时信号。在 SDK 实现发生变化之前,不要围绕 IsListeningIsProcessing 构建关键 UI 逻辑。

上图展示了概念上的理想流程。它并不是当前 SDK 中所有辅助函数的一一对应映射。

语音输入模式

UConvaiPlayerComponent 支持两种模式来控制何时将音频转发给 Convai。

按住说话

在按住说话模式下,游戏逻辑会显式打开和关闭音频流。请在玩家开始说话时调用 UnmuteStreamingAudioUConvaiPlayerComponent ,并在 MuteStreamingAudio 时调用。玩家组件仅在打开窗口期间转发音频。

在存在环境噪音的训练模拟中使用按住说话——如机器声、教室环境音或多个同处一地的用户——因为自动语音检测可能会产生错误的句尾截断。

语音活动检测

可通过在玩家组件上调用 UpdateVadBP(bool EnableVAD)来切换语音活动检测(VAD)。详细的 VAD 阈值位于 FConvaiVADSettings 中的 Convai 项目设置对象上,可通过实用设置函数读取或修改。

字段
类型
默认值
描述

bUseServerDefault

bool

true

true时,下面所有按字段设置的值都会被忽略,Convai 将应用其默认值。设置为 false 以覆盖单独字段。

Confidence

float

0.7

帧中包含语音的最低 VAD 模型概率。提高该值可减少背景噪音造成的误报;如果角色漏掉了轻声说话者,则降低该值。

StartSecs

float

0.2

在触发“用户开始说话”事件之前持续语音的秒数。更高的值会忽略短暂的语音片段。

StopSecs

float

2.2

VAD 到达终点前的静音秒数。更低的值会更快检测到句尾,但代价是可能截断语速较慢的说话者。

MinVolume

float

0.6

归一化振幅下限,低于该值的音频会被视为静音。提高该值可拒绝较轻的背景声音。

VAD 适用于免手操作或移动场景,在这些场景中按住说话按钮并不现实。

转录

转录通过 OnTranscriptionReceivedDelegate公开, BlueprintAssignable 委托,位于 UConvaiConversationComponent (由 chatbot 和 player 组件共同继承)。该子系统会将用户转录内容转发到玩家会话,并将机器人转录内容转发到 chatbot 会话。

委托参数如下:

参数
类型
描述

Speaker

UConvaiConversationComponent*

广播该转录事件的组件。当前广播位置传入 this.

Listener

UConvaiConversationComponent*

在委托签名中存在。当前广播位置传入 nullptr.

转录

FString

此时该发言中的转录文本。

IsTranscriptionReady

bool

当前转录路径中的就绪标记。机器人的转录文本通过 true转发;用户转录文本可能以 false到达,随后再以空的最终标记 true.

IsFinal

bool

true 表示这是该发言的最终更新。

当你需要用户发言转录时,绑定到玩家组件。当你需要机器人回复转录时,绑定到 chatbot 组件。对于用户字幕,请显示非空的 转录 载荷,而不是只根据 IsTranscriptionReady.

文本输入

玩家也可以发送文本而不是音频。 UConvaiPlayerComponent::SendText 接收一个目标 UConvaiConversationComponent 参数和一个 FString,但当前实现会将文本作为 user_text_message 通过子系统发送,并且不会使用目标参数进行路由。它也不会直接广播 OnTranscriptionReceivedDelegate 与提交的文本。可将此路径用于无障碍输入、训练模拟中由主持人控制的覆盖输入,以及注入脚本化对话且不使用麦克风输入的自动化测试框架。

动作队列执行

当 Convai 返回包含角色动作的响应时, OnActionReceivedEvent_V2 会触发,并且该序列会被添加到 ActionsQueue中。如果队列为空,新序列会成为队列。如果队列中已经包含一个动作,则当前第一个动作会被保留,而新序列会替换剩余的排队项。

Blueprint 中标准的队列驱动执行模式:

  1. 绑定到 OnActionReceivedEvent_V2BeginPlay.

  2. 当事件触发时,调用 FetchFirstAction 以读取队列中的第一个 FConvaiResultAction

  3. 在你的游戏逻辑中执行该动作(移动到某个位置、播放动画、打开门等)。

  4. 调用 HandleActionCompletion(true) 在成功时调用

  5. 调用 HandleActionCompletion(false) 在失败时调用。Convai 会收到通知,并可能生成恢复响应。

  6. 如果某个动作发生无法恢复的失败——例如目标 Actor 不再存在——请调用 AbortActionSequence 以丢弃队列中所有剩余动作。

bWaitForBotSpeech 动作模板上的标志会门控 StartFirstAction ,用于新到达序列中的第一个动作。该门控可在机器人开始说话、机器人说话结束、响应没有机器人音频,或等待计时器到期时释放。后续队列推进由 HandleActionCompletion.

中断

InterruptSpeechUConvaiChatbotComponent 通过在 InVoiceFadeOutDuration 秒内淡出音频,来停止角色当前的播放。淡出时长也可通过组件上的默认 InterruptVoiceFadeOutDuration 属性进行配置。

该类还公开了 Broadcast_InterruptSpeech 作为一个 NetMulticast Reliable RPC,用于全网络范围的中断路径。 InterruptSpeech 本身会在调用它的组件上应用淡出请求。

OnInterruptedEvent 委托会在聊天机器人正在说话或处理中应用中断时触发。当前实现会广播聊天机器人组件并传入 nullptr 适用于玩家组件。

插件支持渐进式淡出而不是瞬时切断的原因在于,突兀的音频停止会产生感知伪影。淡出时长让设计师可以控制中断听起来是自然还是突兀。

调用语音和叙事触发器

两个 BlueprintCallable 这些函数让 Blueprint 可以在没有玩家输入的情况下驱动角色说话:

  • ExecuteNarrativeTrigger (Blueprint 显示名称 Invoke Speech)——将提供的文本作为动态上下文事件添加,并使用 EC_RunLLMOption::Always。Blueprint 节点标记为 Invoke Speech;C++ 名称 ExecuteNarrativeTrigger 仅在代码中可见。

  • InvokeNarrativeDesignTrigger (Blueprint 显示名称 Invoke Narrative Design Trigger)——通过 chatbot 组件排队或调用一个命名的 Narrative Design 触发器。

使用 ExecuteNarrativeTrigger 适用于一次性、自由形式的提示,其精确措辞可在运行时变化。当触发器名称是与 Narrative Design 约定好的稳定契约时,请使用 InvokeNarrativeDesignTrigger

这两个函数都在 Blueprint API 中公开了 InGenerateActionsInReplicateOnNetwork 参数。在当前实现中, ExecuteNarrativeTrigger 通过 AddContextEvent 进行路由,并且不使用这两个参数。 InvokeNarrativeDesignTrigger 使用内部触发器路径,并在会话建立之前将断开的触发调用排队。

使用示例

按住说话进行角色交互

一个医学训练模拟,学习者通过按住按钮与患者角色对话。

  1. 绑定一个 Pressed 事件到交互输入动作,以 Unmute Streaming Audio 调用在玩家组件上——这会打开音频流。

  2. 绑定 Released 事件到 Mute Streaming Audio ——这会关闭音频流。

  3. 从输入事件中跟踪你自己的录音指示器。使用 GetIsTalking 和音频播放委托,在角色响应播放时显示字幕或说话指示器。

预期结果:患者角色只会在玩家按住按钮时接收音频。响应播放指示器会跟随 GetIsTalking 或播放委托。

主持人文本注入

一个训练模拟场景,主持人可以输入一条消息,让 AI 角色接收并回应,而无需使用麦克风。

  1. 在编辑器内或运行时构建一个简单的 UI 小部件,包含一个文本字段和一个 发送 按钮。

  2. 发送 按钮的 On Clicked 事件到 Send Text 连到玩家组件,并将文本字段的内容作为输入字符串传入。

预期结果:玩家组件会通过子系统将输入的消息作为文本输入发送。如果你需要为主持人消息显示本地字幕,可从你的 UI 状态中显示已提交的文本。

故障排查

症状
可能原因
修复
验证

输入后角色没有开始说话

会话未连接、音频未发送,或者文本消息未提交

检查 GetChatbotConnectionState,确认玩家组件已初始化,并验证你的输入事件是否调用了 MuteStreamingAudioSendText.

GetIsTalking 变为 true ,在第一段音频响应播放时。

录音指示器从不关闭

UI 绑定到了 IsListening,而该函数当前返回 false

请根据输入的按下/释放事件来驱动录音 UI,而不是依赖 IsListening.

该指示器会完全跟随按钮状态。

动作已到达 OnActionReceivedEvent_V2 但没有执行任何操作

FetchFirstAction 未在事件处理器内部调用,或者 HandleActionCompletion 未在每次动作执行后调用

调用 Fetch First ActionOn Actions Received 处理器。执行动作后,务必调用 Handle Action Completiontrue 在成功时调用,或 false 失败时。

一个 打印字符串 在获取到的动作名称上调用,以确认已接收。每次完成调用后,序列中的下一个动作就会变为可用。

InterruptSpeech 没有明显效果

GetIsTalkingfalse 期间调用——没有音频在播放

用一个 Get Is Talking 检查来保护该调用。仅在角色处于说话状态时调用 InterruptSpeech

GetIsTalking 返回 false 在淡出完成后。

相关概念

会话生命周期事件系统

最后更新于

这有帮助吗?