深入解读 @mastra/voice-deepgram:Mastra 语音集成包的完整使用指南与版本演进
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
本篇文章以 voice/deepgram/CHANGELOG.md 为骨架,结合@mastra/voice-deepgram包的 README、核心实现 与测试用例,系统讲解如何在 Mastra 框架中接入 Deepgram 的文本转语音(TTS)与语音转文本(STT)能力。读完本文,你将掌握DeepgramVoice的完整配置方式、说话人分离(speaker diarization)的实战用法、包内模型与音色清单,以及从版本变更记录中梳理出的架构演进、运行环境要求与安全修复要点。
一、包概览:一个类同时提供 TTS 与 STT
@mastra/voice-deepgram是 Mastra 官方维护的 Deepgram 语音集成包,当前仓库内版本为0.13.1(见 package.json)。它的定位非常明确:通过一个DeepgramVoice类同时提供两种能力:
- 文本转语音(TTS):基于 Deepgram 的
aura系列模型合成语音; - 语音转文本(STT):基于 Deepgram 的
nova/whisper等系列模型做流式或预录制音频转录。
安装方式与任意 npm 包一致:
npm install @mastra/voice-deepgram安装后,包会在node_modules中提供 ESM(dist/index.js)与 CJS(dist/index.cjs)双格式产物,TypeScript 声明文件为dist/index.d.ts。根据 package.json 的声明,该包要求zod@^3.25.0 || ^4.0.0作为 peer dependency,这一约束源于 changelog 中 0.11.0 版本“Bump zod peerdep to 3.25.0 to support both v3/v4”的调整——即同时兼容 zod v3 与 v4,方便与不同版本的 Mastra 项目共存。
二、快速上手:创建语音实例并完成一次“说话—听话”闭环
2.1 实例化与 API Key 处理
import { DeepgramVoice } from '@mastra/voice-deepgram'; const voice = new DeepgramVoice({ speechModel: { name: 'aura', // TTS 模型家族 apiKey: 'your-api-key', // 可选,缺省时读取 DEEPGRAM_API_KEY 环境变量 }, listeningModel: { name: 'nova', // STT 模型家族 apiKey: 'your-api-key', // 可选,缺省时读取 DEEPGRAM_API_KEY 环境变量 }, speaker: 'asteria-en', // 默认音色 ID,见 src/voices.ts });从源码看,构造函数 的关键逻辑包括:
speechModel与listeningModel未显式传apiKey时,会自动回退到process.env.DEEPGRAM_API_KEY;- 如果三个来源(环境变量、
speechModel.apiKey、listeningModel.apiKey)都没有 key,会直接抛出At least one of DEEPGRAM_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set错误; - speech 与 listening 各自维护独立的 Deepgram 客户端(
createClient),允许为 TTS 和 STT 使用不同的 API Key; - 默认音色为
asteria-en,默认 TTS 模型为aura,默认 STT 模型为nova。
2.2 完整使用示例
// 1. 列出所有可用音色 const voices = await voice.getSpeakers(); // => [{ voiceId: 'asteria-en' }, { voiceId: 'luna-en' }, ...] // 2. 文本合成语音(默认音色) const audioStream = await voice.speak('Hello from Mastra!', { speaker: 'hera-en', // 按需覆盖音色 }); // 3. 语音转文本,并开启说话人分离 const result = await voice.listen(audioStream, { diarize: true, diarize_speaker_count: 2, }); console.log(result.transcript);这段示例即 README 中的标准用法,它展示了本包“双模型 + 可覆盖音色 + 可选说话人分离”的完整工作流。
三、TTS 能力详解:speak 方法
3.1 方法签名与返回值
speak接受一个字符串(或可读流)作为输入,返回一个 Node.jsReadableStream(具体为PassThrough):
async speak( input: string | NodeJS.ReadableStream, options?: { speaker?: string; // 覆盖默认音色 [key: string]: any; // 其余参数透传给 Deepgram API }, ): Promise<NodeJS.ReadableStream>3.2 底层行为(源码级)
从 index.ts 可以看到三个值得注意的实现细节:
- 输入归一化:若传入的是流,内部会先聚合成 Buffer 再转为 UTF-8 文本;空文本或纯空白文本会抛出
Input text is empty错误; - 模型名拼接:最终请求模型名由
baseModel + '-' + speakerId拼接而成,例如默认aura+ 音色asteria-en会生成aura-asteria-en;若 speakerId 本身已带模型前缀则直接复用; - Web Stream 转 Node Stream:Deepgram SDK 返回的是 Web Stream,包内通过
getReader()逐块读取并写入PassThrough,同时做了完善的错误销毁(nodeStream.destroy(error))处理,避免流异常泄漏。
其余options(除speaker外)会原样透传给speakClient.request,因此你可以直接传入 Deepgram TTS 支持的参数(如encoding、container、sample_rate等)。
3.3 可用模型与音色清单
音色列表定义在 src/voices.ts,共 12 个英语音色:
| 音色 ID | 说明 |
|---|---|
| asteria-en / luna-en / stella-en | Aura 家族基础音色 |
| athena-en / hera-en / orion-en | 不同音质与语调选择 |
| arcas-en / perseus-en / angus-en | 男声/中性音色选择 |
| orpheus-en / helios-en / zeus-en | 更多合成音色 |
可用模型(DeepgramModel)为:aura(TTS)、whisper、base、enhanced、nova、nova-2、nova-3(STT),见 src/voices.ts。测试用例中即使用了aura(TTS)与whisper(STT)的组合(见 index.test.ts)。
四、STT 能力详解:listen 方法与说话人分离
4.1 方法签名与返回值
async listen( audioStream: NodeJS.ReadableStream, options?: { diarize?: boolean; // 是否开启说话人分离 [key: string]: any; // 其余参数透传给 Deepgram 转录 API }, ): Promise<any>返回对象的结构随diarize是否开启而变化(源码注释见 index.ts):
| 字段 | 说明 | 是否依赖 diarize |
|---|---|---|
transcript | 完整转录文本 | 否 |
words | 单词数组,含时间戳与置信度 | 否 |
raw | Deepgram API 完整原始响应 | 否 |
speakerSegments | { word, speaker, start, end }数组,区分说话人 | 是 |
4.2 说话人分离(Diarization)是核心新特性
changelog 在0.12.0 版本(对应 PR #10206)明确记录:“Add speaker diarization support for STT”,并在0.12.0-beta.1中以feat(voice-deepgram)前缀标记。这是该包近几个版本中最具业务价值的能力更新。
从实现看,listen会把diarize和diarize_speaker_count从透传参数中单独提取,前者作为布尔开关传给transcribeFile,后者(如果传了)用于提示 Deepgram 预设说话人数。开启后,包会遍历返回的alt.words,为每个词附加speaker编号并组装speakerSegments(见 index.ts)。
典型应用场景:会议纪要自动区分发言者、客服通话质检中定位坐席与客户的对话轮次、访谈内容的角色标注等。配合diarize_speaker_count可以进一步提高分离精度:
const result = await voice.listen(audioStream, { diarize: true, diarize_speaker_count: 2, // 明确告诉模型只有两个说话人 }); for (const seg of result.speakerSegments) { console.log(`[说话人 ${seg.speaker}] ${seg.word} (${seg.start}ms-${seg.end}ms)`); }4.3 预录制音频转录
listen基于listeningClient.listen.prerecorded.transcribeFile实现,属于预录制(pre-recorded)转录路径:先把整个输入流聚合成 Buffer,再一次性提交给 Deepgram。测试中通过createReadStream读取__fixtures__/voice-test.m4a并显式传入filetype: 'm4a'完成转录(见 index.test.ts),说明处理m4a等非默认格式时需在 options 中补充filetype。
五、从 Changelog 看包的架构演进
5.1 命名继承:从 @mastra/speech-deepgram 迁移而来
0.1.0 版本(2024 年)即记录:deprecate @mastra/speech-deepgram for @mastra/voice-deepgram,原包所有功能迁移到新命名下,导入路径统一更新为@mastra/voice-deepgram。这次更名是 Mastra 将“语音”能力统一收敛到MastraVoice抽象体系的一部分。
5.2 0.12.1:语音原语下沉到 @internal/voice
0.12.1 是一个重要的架构里程碑,changelog 记录:“Moved shared voice primitives and route metadata into the new@internal/voicepackage so voice providers no longer depend on@mastra/coreand server voice routes share the same route definitions”,同时说明@mastra/core/voice仍会继续 re-export 这些 API 以保持向后兼容。
这一点在源码中得到印证:DeepgramVoice类继承自@internal/voice包导出的MastraVoice基类(见 index.ts),而不再直接依赖@mastra/core。仓库中的packages/_internals/voice/src/voice/voice.ts、packages/_internals/voice/src/routes/index.ts等文件即承载了共享语音原语与路由定义。带来的收益包括:
- 解除核心包耦合:各语音 provider 不再被迫绑定
@mastra/core的具体版本; - 路由统一:服务端语音相关路由(如
/api/voice/...)在 provider 之间共享同一套定义; - 兼容性保障:通过
@mastra/core/voice的 re-export,老代码无需改动即可继续使用。
5.3 0.12.0:运行环境要求收紧
0.12.0 版本同时带来两个重要的环境变更:
- Node.js 最低版本提升至 22.13.0(PR #9706)。当前 package.json 中
engines.node字段即">=22.13.0",使用低于该版本的 Node 运行时会收到引擎不兼容警告; - 移除基于 OpenTelemetry 的旧 tracing 代码(PR #9237),并同步将 peer dependency 对齐到
@mastra/core@1.0.0的版本号体系。
5.4 0.12.0:随包发布内嵌文档
0.12.0 还引入了“embedded documentation”机制:Mastra 各包发布到 npm 时会携带dist/docs/目录,包含SKILL.md(包的用途与能力说明)、SOURCE_MAP.json(导出符号到类型/实现文件的机器可读索引)以及按功能域组织的 Topic 目录。这套机制让编码 Agent 与 AI 助手可以直接从node_modules读取文档来理解并调用本包。package.json 中的prepack脚本(tsx ../../scripts/generate-package-docs.ts)正是该文档生成流程的入口。
5.5 0.12.2:供应链安全修复
0.12.2 是一次安全补丁发布,changelog 记录其为 2026-06-17 “easy-day-js” 供应链事件的 remediation:发布干净版本并将latestdist-tag 前移,取代声明了恶意easy-day-js依赖的受影响版本。对于使用者而言,这意味着务必升级到 0.12.2 及以上版本,并留意安装日志中的依赖来源。
5.6 0.13.1:包体瘦身与文档更新
0.13.1 包含两项 Patch 变更:
- 从发布到 npm 的产物中移除
CHANGELOG.md,减小包体积(PR #22737); - 更新 README 以保证信息准确、与当前 API 一致(PR #22858)。
5.7 其他值得留意的变更
- 0.10.2:
@deepgram/sdk从^3.11.2升级到^3.13.0,当前 package.json 即锁定该依赖; - 0.10.7:修复 TypeScript 声明文件导入以保证 ESM 兼容;
- 0.1.3:调整 CJS 打包,确保产物文件正确拆分;
- 0.1.1:新增 CommonJS 支持;
- 0.1.13:包启用 Elastic-2.0 许可(注:当前仓库该包 package.json 中
license字段为 Apache-2.0,以实际安装版本为准)。
六、测试与验证:如何确认包行为符合预期
包内自带 Vitest 集成测试(index.test.ts),可运行:
cd voice/deepgram pnpm test测试覆盖了以下关键行为:
getSpeakers能返回asteria-en、stella-en、luna-en等内置音色;speak能生成非空音频文件(deepgram-speech-test.mp3),且支持覆盖 speaker 参数;- 空文本 / 纯空白文本 / 非法音色都会正确抛出错误;
listen能转录voice-test.m4afixture,非法音频会被拒绝。
这些用例直接印证了本文章前面描述的 API 契约与错误处理逻辑,可作为你自行验证时的参考基线(注意:真实转录需要有效的 Deepgram API Key)。
七、最佳实践与注意事项
- API Key 优先走环境变量:
DEEPGRAM_API_KEY一次配置,speech 与 listening 自动共享;需要拆分权限时再分别传入speechModel.apiKey与listeningModel.apiKey; - 多说话人场景务必开启 diarize:区分对话轮次是语音 Agent 走向真实业务的常用能力,
diarize_speaker_count在说话人数已知时能显著提升稳定性; - 注意运行环境:Node.js 需 ≥ 22.13.0,且需要
zod ^3.25.0 || ^4.0.0peer dependency; - 及时升级:0.12.2 包含供应链安全修复,低于该版本的安装应视为存在风险;
- 格式处理:转录
m4a等格式时记得传filetype参数,见 index.test.ts; - 流错误处理:
speak返回的流在底层已做错误销毁兜底,消费端仍建议监听error事件以避免未捕获异常。
八、结语
@mastra/voice-deepgram是一个麻雀虽小、五脏俱全的语音集成包:一个类完成 TTS/STT 双能力、支持说话人分离、模型与音色可自由组合,并在最近的版本中完成了与@internal/voice的解耦、Node 版本收紧与供应链安全修复。无论是构建带语音对话的 Agent、会议纪要应用还是客服质检系统,本文梳理的配置参数、API 契约与版本演进都能帮助你快速上手并规避踩坑点。
【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考