ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Mastra 语音集成实战:使用 @mastra/voice-azure 接入 Azure Speech Services 实现 TTS 与 STT

Mastra 语音集成实战:使用 @mastra/voice-azure 接入 Azure Speech Services 实现 TTS 与 STT Mastra 语音集成实战使用 mastra/voice-azure 接入 Azure Speech Services 实现 TTS 与 STT【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra本篇技术指南围绕 Mastra 框架的语音提供方集成包mastra/voice-azure展开系统讲解如何通过 Azure 语音服务 为 Mastra Agent 添加文本转语音TTS与语音转文本STT能力。读完本文你将掌握该包的环境变量配置、speechModel / listeningModel 双模型配置方式、getSpeakers/speak/listen/getListener四个核心 API 的调用方法并从源码层面理解其底层实现、错误处理与资源管理机制能够直接在自己的 Mastra 项目中落地可运行的语音交互方案。安装与快速开始mastra/voice-azure是 Mastra 官方维护的语音集成包其唯一核心外部依赖是微软官方 SDKmicrosoft-cognitiveservices-speech-sdk见 voice/azure/package.json包内以 ESM 与 CommonJS 双格式对外分发engines要求 Node.js 22.13.0。安装命令npm install mastra/voice-azure安装完成后即可创建一个同时具备说话TTS与听话STT能力的语音实例import { AzureVoice } from mastra/voice-azure; // 同时配置语音合成与语音识别两个模型 const voice new AzureVoice({ speechModel: { apiKey: your-api-key, // 可选可改用 AZURE_API_KEY 环境变量 region: your-region, // 可选可改用 AZURE_REGION 环境变量 voiceName: en-US-AriaNeural, // 可选默认音色 }, listeningModel: { apiKey: your-api-key, // 可选可改用 AZURE_API_KEY 环境变量 region: your-region, // 可选可改用 AZURE_REGION 环境变量 language: en-US, // 可选识别语言 }, }); // 列出可用音色 const voices await voice.getSpeakers(); // 生成语音 const audioStream await voice.speak(Hello from Mastra!, { speaker: en-US-JennyNeural, // 可选覆盖默认音色 }); // 语音转文本 const text await voice.listen(audioStream);这段代码覆盖了该包的全部核心能力speechModel负责 TTS 方向的配置listeningModel负责 STT 方向的配置二者相互独立、可以只配置其中一个。getSpeakers()返回可用音色列表speak()将文本合成为音频流listen()将 WAV 音频流转写为文本。配置详解speechModel 与 listeningModelAzureVoice构造函数接收一个可选的配置对象包含三个顶层属性其完整类型定义位于 voice/azure/src/index.ts配置项类型用途关键字段speechModelAzureVoiceConfig文本转语音TTS配置apiKey、region、voiceNamelisteningModelAzureVoiceConfig语音转文本STT配置apiKey、region、languagespeakerVoiceId全局默认音色 ID可选其中AzureVoiceConfig内部类型为interface AzureVoiceConfig { apiKey?: string; region?: string; voiceName?: string; language?: string; }环境变量回退机制从构造函数实现voice/azure/src/index.ts可以看到apiKey与region均支持环境变量回退AZURE_API_KEY同时作为 speechModel 与 listeningModel 的默认 API KeyAZURE_REGION同时作为两个模型的默认区域。也就是说如果在.env中配置了这两个变量代码里甚至可以完全不传凭证// 依赖 AZURE_API_KEY 与 AZURE_REGION 环境变量 const voice new AzureVoice({ speechModel: {}, listeningModel: { language: zh-CN }, });凭证校验与独立配置构造函数对两个模型分别做凭证校验voice/azure/src/index.ts配置了speechModel但缺少apiKey时抛出No Azure API key provided for speech model缺少region时抛出No region provided for speech modellisteningModel同理错误信息为No Azure API key provided for listening model/No region provided for listening model。因此只要传入某个 model 配置块就必须同时提供 apiKey 与 region或依赖环境变量。TTS 与 STT 是独立初始化的只传speechModel时不会创建识别器调用listen()会报Listening model (Azure) not configured。默认音色的确定顺序语音合成的默认音色按以下优先级确定voice/azure/src/index.tsthis.speechConfig.speechSynthesisVoiceName speechModel.voiceName || speaker || en-US-AriaNeural;即speechModel.voiceName 构造时的speaker参数 内置兜底en-US-AriaNeural。识别语言listeningModel.language会被写入 Azure SDK 的speechRecognitionLanguagevoice/azure/src/index.ts用于设置 STT 识别的源语言例如en-US、zh-CN。TTS 场景下language字段不参与合成逻辑。核心 API 使用指南getSpeakers()获取可用音色列表getSpeakers()返回PromiseArray{ voiceId: string; language: string; region: string }。其实现非常轻量直接遍历内置的AZURE_VOICES常量数组按音色 ID 的{语言}-{区域}-{名称}格式解析出 language 与 region 两个元数据字段voice/azure/src/index.ts。例如en-US-AriaNeural会被解析为{ voiceId: en-US-AriaNeural, language: en-US, region: US }。调用方式const voices await voice.getSpeakers(); for (const v of voices.slice(0, 5)) { console.log(${v.voiceId} | ${v.language} | ${v.region}); }该列表全部来自 voice/azure/src/voices.ts 中的静态定义涵盖 50 语言、200 音色并且通过as const断言导出严格类型VoiceIdexport type VoiceId (typeof AZURE_VOICES)[number];这意味着在 TypeScript 中传入不存在的音色 ID 会在编译期直接报错获得完整的类型安全。speak()文本转语音speak(input, options?)是 TTS 的核心方法voice/azure/src/index.tsasync speak( input: string | NodeJS.ReadableStream, options?: { speaker?: string; [key: string]: any }, ): PromiseNodeJS.ReadableStream其内部处理流程为输入归一化如果input是流而非字符串会先异步读取全部 chunk 并拼接为 UTF-8 字符串空文本校验!input?.trim()时抛出Input text is empty音色切换如果传入options.speaker则动态改写speechConfig.speechSynthesisVoiceNameSDK 合成为每次请求创建新的SpeechSynthesizer调用 Azure 的speakTextAsync超时保护通过Promise.race实现 5 秒超时超时抛出Speech synthesis timed out结果校验只有ResultReason.SynthesizingAudioCompleted才视为成功否则抛出含errorDetails的错误流式返回将result.audioData包装为Readable.from([...])返回。典型用法// 基础合成使用默认音色 const audio await voice.speak(Hello World); // 指定音色 const audio2 await voice.speak(Bonjour le monde, { speaker: fr-FR-DeniseNeural, }); // 传入文本流Node.js ReadableStream import { Readable } from node:stream; const inputStream Readable.from([Hello from stream]); const audio3 await voice.speak(inputStream);返回值是一个包含单个 Buffer 的 Node.js Readable 流音频格式由 Azure SDK 默认决定通常为 16kHz、16-bit、单声道 PCM WAV可以直接写盘或进一步转码。listen()语音转文本listen(audioStream)接收 Node.js ReadableStream返回识别出的文本字符串voice/azure/src/index.ts。注意输入音频必须是 Azure 兼容的 WAV 格式。其处理流程为全量缓冲将整个音频流读取到内存中构建推送流通过Azure.AudioInputStream.createPushStream()创建推送流并用AudioConfig.fromStreamInput生成音频配置逐块写入以 4096 字节为块将音频数据写入推送流voice/azure/src/index.ts单次识别调用recognizeOnceAsync进行单次话语识别结果校验仅当ResultReason.RecognizedSpeech时返回result.text否则抛出包含 reason 码与 errorDetails 的错误资源释放finally块中关闭 recognizer。典型用法// 直接转写 speak() 的输出round-trip 验证 const audio await voice.speak(This is a test for transcription); const text await voice.listen(audio); console.log(text); // 转写本地 WAV 文件 import { createReadStream } from node:fs; const text2 await voice.listen(createReadStream(recording.wav));getListener()监听能力探测getListener()恒定返回{ enabled: true }voice/azure/src/index.ts。这是 Mastra 框架用于探测语音提供方是否具备 STT 能力的约定方法返回false时框架会认为该提供方只支持 TTS。源码级原理MastraVoice 基类契约AzureVoice继承自MastraVoice抽象基类见 packages/_internals/voice/src/voice/voice.ts该类实现了IMastraVoice接口并定义了所有语音提供方必须遵守的抽象契约speak(input, options?)文本转语音返回音频流listen(audioStream, options?)语音转文本返回文本或音频流getSpeakers()返回{ voiceId } TSpeakerMetadata数组getListener()返回{ enabled: boolean }以及updateConfig、connect、send、addInstructions、事件订阅on/off等实时语音相关能力。AzureVoice在构造函数中调用super()时会把speechModel/listeningModel的 name 与 apiKey、以及speaker传给基类voice/azure/src/index.ts这样 Mastra 框架内部可以追踪各提供方配置了哪些模型并在可观测性 span 中序列化这些信息——基类的serializeForSpan()会输出组件类型VOICE、speaker、模型名等字段且刻意排除 apiKey避免敏感凭证进入追踪数据。从类结构看AzureVoice维护四个私有状态voice/azure/src/index.ts私有属性类型职责speechConfigAzure.SpeechConfigTTS 配置订阅凭证、默认音色listeningConfigAzure.SpeechConfigSTT 配置订阅凭证、识别语言speechSynthesizerAzure.SpeechSynthesizer构造期创建的合成器实例speechRecognizerAzure.SpeechRecognizer构造期创建的识别器实例值得注意的细节是构造函数中虽然创建了合成器/识别器实例但speak()与listen()在方法内部每次请求都会重新 new 一个实例用完即 closevoice/azure/src/index.ts、voice/azure/src/index.ts这是一种以资源开销换取状态隔离的取舍从源码结构看目前没有做实例池复用。音色清单200 声音与 VoiceId 类型voice/azure/src/voices.ts 是整个包的静态数据核心以const数组形式声明了 200 个音色 ID。这些音色覆盖阿拉伯语、德语、英语、西班牙语、中文、印地语等 50 种语言并为英语、德语等提供了多区域变体如en-US、en-GB、en-AU、de-DE。从命名后缀可以区分四类音色类别命名特征示例标准神经音色{语言}-{区域}-{名称}Neuralen-US-AriaNeural、de-DE-ConradNeural多语言音色后缀Multilingualen-US-EmmaMultilingualNeural、de-DE-SeraphinaMultilingualNeuralHD 音色后缀:DragonHDLatestNeuralen-US-Aria:DragonHDLatestNeural、en-US-Andrew2:DragonHDLatestNeuralAI 生成 / Turbo 音色前缀AIGenerate或后缀TurboMultilingualNeuralen-US-AIGenerate1Neural、en-US-AlloyTurboMultilingualNeural由于该数组使用as const断言导出的VoiceId是字面量联合类型IDE 补全与编译期校验都能直接生效——这是本包相比直接使用 Azure SDK 的一大类型安全优势。测试验证集成测试覆盖的行为边界包内自带的集成测试套件 voice/azure/src/index.test.ts 完整验证了上述 API 行为可作为实践参考初始化默认参数初始化、环境变量回退、缺少 API Key 时抛错expect(() new AzureVoice({ speechModel: { region: eastus } })).toThrow(No Azure API key provided for speech model)getSpeakers()返回数组非空、每个元素包含voiceId/language/region三个属性speak()默认参数合成、指定音色合成、传入文本流合成断言音频 Buffer 长度大于 0并将结果写入test-outputs/目录下的 WAV 文件供人工检查listen()默认参数识别、从 WAV 文件转写、以及speak → listen 回环验证合成后再转写断言文本包含原始关键词错误处理空文本输入抛出Input text is empty。需要说明的是这套测试是真实的 Azure 集成测试运行前提是环境中配置了有效的AZURE_API_KEY与AZURE_REGION测试代码中以fake-key/eastus兜底但实际调用会失败。它展示了合成 → 转写回环自检的完整实践模式非常适合作为你自己验证语音链路的模板。实战注意事项与建议综合源码实现与架构文档在实际项目中使用mastra/voice-azure时有几点值得关注凭证管理推荐通过AZURE_API_KEY/AZURE_REGION环境变量注入凭证避免把密钥硬编码在配置对象中不要在日志或追踪数据中打印 apiKey。listen() 的内存占用listen()会把整个音频流缓冲进内存超长音频可能造成内存压力生产环境建议控制单次转写的音频时长或关注后续版本是否引入增量流式处理。speak() 的超时合成内置 5 秒超时Speech synthesis timed out超长文本可能触发需要根据业务文本长度评估是否够用。音频格式约束listen()输入必须是 Azure 兼容的 WAV 格式如果音频来自其他来源需先做格式转换。错误信息暴露部分异常会把 Azure 内部errorDetails透出生产环境对外暴露接口时建议做一层错误包装与脱敏。与框架集成作为MastraVoice的实现类AzureVoice可以直接接入 Mastra 的语音 Agent 编排流程框架通过getListener()探测 STT 能力、通过getSpeakers()枚举音色这些约定的接口保证你后续可以无痛切换到其他语音提供方。小结mastra/voice-azure以约 200 行核心实现voice/azure/src/index.ts为 Mastra 提供了一套简洁、TypeScript 原生、类型安全的 Azure 语音能力封装TTS 与 STT 配置完全解耦凭证支持环境变量回退音色选择具备编译期类型约束内部包含超时保护与资源清理。它完整实现了MastraVoice抽象契约packages/_internals/voice/src/voice/voice.ts并附带覆盖回环验证的集成测试voice/azure/src/index.test.ts。对需要在 Mastra 中快速接入 Azure 语音合成与识别的开发者而言安装、配置、三个 API 即可打通完整语音链路是最直接的落地路径。【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表