外观
azure-speech-gateway
azure-speech-gateway 是一个 Bun + TypeScript 的 Azure Speech 语音网关。它把 Azure 实时语音识别和语音合成包装成与现有本地 / 阿里云语音链路兼容的接口,便于 callflow-esl、FreeSWITCH mod_audio_fork 或管理台测试工具在不改调用方式的 情况下切换到 Azure。
服务启动后会同时监听两个端口:
- ASR WebSocket 服务:默认
0.0.0.0:10098 - TTS HTTP 服务:默认
0.0.0.0:9082
运行
在仓库根目录运行:
bash
bun install
bun run dev:azure-speech也可以进入子项目单独运行:
bash
cd apps/azure-speech-gateway
bun run dev # 监听模式
bun run start # 启动一次
bun run typecheck # TypeScript 类型检查构建可执行文件
bash
bun run build # typecheck 后构建 Windows x64
bun run build:win # 构建 dist/win_x64/azure-speech-gateway.exe
bun run build:linux # 从当前环境交叉构建 dist/linux_x64/azure-speech-gateway
bun run build:all # typecheck 后构建 Windows + Linux x64构建产物是可直接部署的目录,包含一个独立可执行文件和外置 config.json:
text
dist/win_x64/azure-speech-gateway.exe
dist/win_x64/config.json
dist/linux_x64/azure-speech-gateway
dist/linux_x64/config.json运行时默认读取可执行文件同目录下的 config.json。如需使用其它配置文件,可设置 AZURE_SPEECH_GATEWAY_CONFIG_PATH:
powershell
cd dist\win_x64
$env:AZURE_SPEECH_GATEWAY_CONFIG_PATH = "C:\deploy\azure-speech-gateway\config.json"
.\azure-speech-gateway.exeLinux 部署时把 dist/linux_x64/ 复制到目标机器,执行 chmod +x azure-speech-gateway 后运行 ./azure-speech-gateway。Linux 二进制可以在 Windows 上通过 Bun 交叉编译生成, 但仍需在目标 Linux 主机验证 Azure 网络访问、端口监听、缓存目录路径与权限。
配置
配置文件位于 apps/azure-speech-gateway/config.json。Azure Speech key 可以写在配置 文件中,也可以用环境变量覆盖,生产部署建议使用环境变量便于轮换:
powershell
$env:AZURE_SPEECH_KEY="your-subscription-key"
$env:AZURE_SPEECH_REGION="uksouth"
$env:AZURE_SPEECH_TTS_ENDPOINT="https://uksouth.tts.speech.microsoft.com/cognitiveservices/v1"
bun run --cwd apps/azure-speech-gateway start| 配置段 | 字段 | 用途 |
|---|---|---|
azure | region / endpoint / ttsEndpoint | Azure Speech 区域、资源 endpoint 与 TTS REST endpoint |
azure | subscriptionKey | Azure Speech key,可被 AZURE_SPEECH_KEY 覆盖 |
asr | host / port | ASR HTTP/WebSocket 监听地址,默认端口 10098 |
asr | healthPath / wsPath | 健康检查与音频 WebSocket 路径,默认 /health、/audio |
asr | wsSubprotocol | WebSocket 子协议,默认 audio.drachtio.org,用于兼容 mod_audio_fork |
asr | maxSessions | 最大并发 ASR 会话数 |
asr | maxQueuedAudioBytes | Azure SDK 启动完成前每路最多缓存的音频字节数,默认 524288 |
asr | startTimeoutMs | Azure SDK 启动超时时间,默认 10000 |
asr | autoDetectLanguages | Azure 自动识别候选语言,默认 ["zh-CN", "en-US"] |
asr | sampleRate / bitsPerSample / channels / format | 输入音频格式,默认 16000 / 16 / 1 / pcm |
tts | host / port | TTS HTTP 监听地址,默认端口 9082 |
tts | publicBaseUrl | 返回给调用方的公开访问基址,必须是 FreeSWITCH 可访问的地址 |
tts | defaultVoice / voices | 默认音色与 speakerId 到 Azure voice 的映射 |
tts | outputFormat / streamOutputFormat | Azure TTS REST 的 WAV 与 MP3 输出格式 |
tts | requestTimeoutMs | Azure TTS REST 请求超时时间,默认 30000 |
tts | maxTextLength | 单次合成文本长度上限 |
logging | dir / maxSize / maxFiles / level | 控制台与按天轮转文件日志配置 |
asr.autoDetectLanguages 用于同一路 ASR 服务内自动检测语音语言,默认同时支持 中文普通话 zh-CN 与美式英语 en-US。常用候选值包括:zh-CN、zh-HK、 zh-TW、yue-CN、wuu-CN、zh-CN-sichuan、en-US、en-GB、en-AU、 en-CA、en-IN、ja-JP、ko-KR、fr-FR、de-DE、es-ES、it-IT、 pt-BR、ru-RU、th-TH、vi-VN、id-ID、hi-IN。完整支持列表以 Microsoft Azure Speech language support 官方文档为准。
ASR 接口
健康检查
http
GET http://127.0.0.1:10098/health响应示例:
json
{
"ok": true,
"service": "azure-speech-gateway-asr",
"activeSessions": 0,
"maxSessions": 64,
"wsPath": "/audio",
"ioWorkers": 1
}实时识别 WebSocket
默认地址:
text
ws://127.0.0.1:10098/audio连接要求:
- 请求头
Sec-WebSocket-Protocol需要包含配置中的asr.wsSubprotocol。 - 第一个文本帧可携带 metadata,常见字段包括
channel_uuid、channelUuid、uuid、call_uuid、callUuid、sessionId、session_id。 - 后续二进制帧为 16kHz、16-bit、单声道 PCM 音频。
- 发送零长度二进制帧表示请求服务端 flush 并关闭 Azure 识别会话。
识别结果消息示例:
json
{
"type": "transcription",
"data": {
"text": "您好,请问有什么可以帮您",
"isFinal": true,
"utteranceIndex": 1,
"speechStarted": true,
"speechActive": false,
"speechSegmentDetected": true,
"speechSegmentCompleted": true,
"serverSessionId": "ws-1",
"channelUuid": "call-uuid",
"metadataText": "{\"channel_uuid\":\"call-uuid\"}",
"finalReason": "final",
"flushReason": "zero-length-binary"
}
}错误消息示例:
json
{
"type": "error",
"data": {
"message": "Azure Speech recognition canceled"
}
}TTS 接口
健康检查
http
GET http://127.0.0.1:9082/health响应会返回服务监听信息、当前采样率和可用 speakers。该结构兼容管理台对 TTS 服务的健康检查。
普通 WAV 合成
http
POST http://127.0.0.1:9082/tts
Content-Type: application/json
{
"text": "您好,欢迎致电。",
"speakerId": 0,
"speed": 1
}响应示例:
json
{
"wavUrl": "http://127.0.0.1:9082/wav/tts-0123456789abcdef.wav",
"fileName": "tts-0123456789abcdef.wav",
"sampleRate": 16000,
"cached": false
}相同 text + speakerId + speed + voice 的请求会复用 public/wav/ 下的缓存文件。 生成后的 WAV 可以通过以下接口读取:
http
GET http://127.0.0.1:9082/wav/tts-0123456789abcdef.wav
HEAD http://127.0.0.1:9082/wav/tts-0123456789abcdef.wav流式 MP3 合成
先创建一个短期流式播放链接:
http
POST http://127.0.0.1:9082/tts-stream
Content-Type: application/json
{
"text": "这是一段需要尽快开始播放的文本。",
"speakerId": 0,
"speed": 1
}响应示例:
json
{
"streamUrl": "http://127.0.0.1:9082/tts-stream/tts-0123456789abcdef.mp3",
"streamPath": "/tts-stream/tts-0123456789abcdef.mp3",
"sampleRate": 16000,
"cached": false
}随后客户端访问 streamUrl,服务会在该 GET 连接内调用 Azure TTS REST 并输出 Content-Type: audio/mpeg 的 MP3 数据流,同时写入 public/mp3/ 下的本地缓存文件。 相同 text + speakerId + speed + voice + format=mp3 的请求会复用同一个 tts-<16位hash>.mp3,缓存命中时 POST /tts-stream 会返回 cached: true。
http
GET http://127.0.0.1:9082/tts-stream/tts-0123456789abcdef.mp3
HEAD http://127.0.0.1:9082/tts-stream/tts-0123456789abcdef.mp3首次 GET 如果合成失败、客户端断开或写文件失败,服务会删除临时文件,不留下半截 正式缓存。5 分钟 TTL 只限制未生成缓存前的内存播放票据;已经落盘的 MP3 文件不受 该 TTL 限制。
对接注意事项
- 如果要让
callflow-esl使用 Azure ASR,把apps/callflow-esl/config.json的audioFork.wsUrl改为ws://<gateway-host>:10098/audio;bugName、mixType=mono、sampleRate=16k保持与本地 ASR 一致即可。 - 如果要让
callflow-esl使用 Azure TTS,把tts.profiles.wav.endpoint改为http://<gateway-host>:9082/tts,把tts.profiles.shout.endpoint改为http://<gateway-host>:9082/tts-stream。流式播放仍按tts.profiles.shout.playbackPrefix交给 FreeSWITCH 播放。 - 管理台的 TTS 试听页可以直接填
http://<gateway-host>:9082/tts;ASR 测试页可把 主机和端口改成<gateway-host>:10098,上传 16kHz mono PCM16 WAV 或用浏览器录音测试。 tts.publicBaseUrl必须配置成 FreeSWITCH 或调用方能够访问到的地址;如果服务 运行在另一台机器上,不要保留默认的127.0.0.1。- ASR 输入默认按 16kHz 单声道 PCM 处理,调用方需要保证实际音频格式与
asr.sampleRate、asr.bitsPerSample、asr.channels一致。 /wav/:fileName只允许读取本服务生成的tts-<16位hash>.wav文件名,避免 通过 URL 访问其他本地文件。/tts-stream/:fileName只允许读取本服务生成的tts-<16位hash>.mp3文件名, 避免通过 URL 访问其他本地文件。- 本服务没有内置鉴权,建议只暴露在可信网络内,或放在带鉴权的反向代理之后。
- 任务结束后如果手动启动过服务,请停止对应 Bun 进程,避免端口被后续联调占用。