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

Azure TTS WebSocket流式传输报错:Input stream cannot be null 求助

Azure TTS WebSocket流式文本转语音:"Input stream cannot be null"错误调试

错误输出

WebSocket connection established
--------------open done------------------
Received message: X-RequestId:13604750-2bxd-42a2-b523-cdesadas3d47
Content-Type:application/json; charset=utf-8
Path:turn.start

{
  "context": {
    "serviceTag": "9a23ce3549axdf7ddfg1d42317bcx5210"
  }
}
WebSocket connection closed with code 1007. Reason: Input stream cannot be null

核心实现代码

import WebSocket from 'ws';
import axios from 'axios';
import crypto from 'crypto';

async function streamTextToSpeech(textStream) {
  const accessToken = await getAccessToken();
  const ws = new WebSocket(
    `wss://${region}.tts.speech.microsoft.com/cognitiveservices/websocket/v2?Authorization=Bearer ${accessToken}`
  );

  ws.on('open', () => {
    // 发送配置消息
    const configMessage = {
      context: {
        synthesis: {
          audio: {
            metadataOptions: {
              sentenceBoundaryEnabled: 'false',
              wordBoundaryEnabled: 'false'
            },
            outputFormat: 'audio-24khz-48kbitrate-mono-mp3'
          },
          language: {
            autoDetection: false
          },
          voice: {
            languageId: 'en-US',
            name: 'en-US-JennyNeural'
          }
        }
      }
    };
    
    const configMessageString = `Content-Type:application/json\r\nPath:speech.config\r\n\r\n${JSON.stringify(configMessage)}`;
    ws.send(configMessageString);

    // 报错位置
    const initialSsml = `<speak version='1.0' xml:lang='en-US'><voice name='en-US-JennyNeural'>Initializing speech synthesis.</voice></speak>`;
    const initialMessage = `Path:ssml\r\nX-RequestId:${crypto.randomUUID()}\r\nContent-Type:application/ssml+xml\r\n\r\n${initialSsml}`;
    ws.send(initialMessage);
  });

  // 错误处理及消息处理代码...
}

环境信息

  • Node.js: 14.17.0
  • ws: 8.2.3
  • axios: 0.24.0
  • Azure Cognitive Services API: v2

已尝试排查步骤

  • 验证WebSocket连接参数与认证信息
  • 对照Azure文档核对SSML格式
  • 确认访问令牌有效且格式正确
  • 尝试查找Python SDK源码但未找到

疑问

  1. 发送初始SSML消息时“Input stream cannot be null”错误的原因是什么?
  2. 针对Azure TTS API的WebSocket消息格式是否正确?
  3. 使用WebSocket API时SSML格式有哪些特定要求?

问题分析与解决方案

1. "Input stream cannot be null"错误原因

核心原因是消息时序违规:发送speech.config后未等待服务端返回turn.start确认,就直接发送SSML消息。Azure TTS WebSocket协议明确要求,必须在收到服务端的turn.start响应后,才能开始发送SSML内容,否则服务端会判定输入流未完成初始化,抛出该错误。

2. WebSocket消息格式修正

当前实现存在两个关键问题:

  • 时序错误:需监听服务端turn.start消息后再发送SSML
  • 消息头缺失:SSML消息必须携带Content-Length字段,服务端依赖该字段解析内容

修正后的核心逻辑:

ws.on('open', () => {
  // 发送配置消息逻辑不变
  const configMessage = { /* ... */ };
  const configMessageString = `Content-Type:application/json\r\nPath:speech.config\r\n\r\n${JSON.stringify(configMessage)}`;
  ws.send(configMessageString);
});

// 新增消息监听,等待turn.start后发送SSML
ws.on('message', (data) => {
  const messageStr = data.toString();
  if (messageStr.includes('Path:turn.start')) {
    const initialSsml = `<speak version="1.0" xml:lang="en-US"><voice name="en-US-JennyNeural">Initializing speech synthesis.</voice></speak>`;
    const contentLength = Buffer.byteLength(initialSsml, 'utf8');
    const initialMessage = `Path:ssml\r\nX-RequestId:${crypto.randomUUID()}\r\nContent-Type:application/ssml+xml\r\nContent-Length:${contentLength}\r\n\r\n${initialSsml}`;
    ws.send(initialMessage);
  }
});

3. WebSocket API的SSML格式要求

  • 严格遵循XML规范:属性值必须使用双引号(避免单引号,部分解析器会触发语法错误)
  • <speak>标签必须同时指定version和xml:lang属性,且xml:lang需与语音配置的languageId完全一致
  • <voice>标签的name必须是Azure官方支持的神经语音名称,可通过Azure门户或产品文档确认有效列表
  • 禁止包含未闭合标签、非法XML字符(如未转义的&、<),否则服务端会直接断开连接

内容的提问来源于stack exchange,提问作者Darius Andrei Rozemberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:16:01