You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用SAPI开发异步TTS DLL 跨语言调用时如何检测语音播放状态

SAPI 异步 TTS DLL 播放控制与状态查询解决方案

你可以从以下几个方向落地实现:

1. DLL 内部维护全局静态实例,完全屏蔽上层传递逻辑

  • 同进程内调用的场景下,直接将异步播放创建的 ISpVoice 实例指针存储在 DLL 内部的全局静态变量中,不需要上层传递任何实例相关数据。后续查询状态、中止播放的接口直接读写这个全局实例即可。
  • 并发调用场景下需要加读写锁,避免多线程同时操作实例引发内存异常。如果需要支持多路并行播放,可以维护全局的<整数ID-实例指针>映射表,播放接口返回给上层一个整数类型的实例ID,上层后续操作仅需传递这个ID即可,所有开发语言都支持整数类型传递,不存在跨语言兼容问题。
  • 状态查询直接调用实例的 ISpVoice::GetStatus() 方法即可获取当前播放状态,中止播放调用 ISpVoice::Speak(NULL, SPF_PURGEBEFORESPEAK, 0) 就能清空播放队列立即停止。

2. 绑定 SAPI 事件回调维护全局播放状态标记

  • 给 ISpVoice 实例注册 SPFEI(SPEI_END_INPUT_STREAM) 事件回调,播放正常结束、主动中止、播放出错都会触发该事件。你在DLL内部维护一个全局的isPlaying布尔变量,调用播放接口时设为true,事件触发时设为false即可。
  • 上层仅需要调用你封装的bool TTS_IsPlaying()接口获取这个布尔值就行,完全不需要感知内部实例的存在。

3. 封装纯C风格跨语言接口,隐藏所有内部实现

你可以仅对外暴露三个通用接口,不管上层是什么开发语言都能直接调用,不需要传递任何实例参数:

  • int TTS_Play(const wchar_t* text):传入待合成文本,内部创建/复用ISpVoice实例发起异步播放,返回码标识调用结果
  • bool TTS_IsPlaying():返回当前是否有语音正在播放
  • void TTS_Stop():立即中止当前所有播放任务,清空播放队列

4. 命名共享内存存储状态(适配多进程调用场景)

如果你的DLL会被多个进程调用,全局变量不共享的场景下,可以在DLL内部创建一块命名共享内存,用来存储当前的播放状态、实例映射信息,所有进程的查询、中止操作都读写这块共享内存即可。

内容的提问来源于stack exchange,提问作者Eric Blackburn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:24:03