NodeJS调用Azure长音频文本转语音API的JS等效代码问题
报错原因
返回Unsupported Media Type是两个核心写法错误导致的:
- node-fetch 原生不支持直接传
files、payload这类自定义字段。Python的requests库会自动完成多部分表单(multipart/form-data)的格式拼装,node-fetch 需要手动通过FormData对象构造符合格式的请求体 - 手动设置了
Content-Type: application/json。同时传输结构化参数和文件必须使用multipart/form-data格式,且不能手动写死这个请求头:合法的multipart头需要携带随机生成的boundary分隔符,手动写头会丢失这个参数,服务端无法正常解析请求内容。
可直接运行的实现代码
首先确认依赖:
- Node 18及以上版本自带原生
fetch、FormData实现,无需额外安装依赖 - 低于18版本的Node需要先安装依赖:
npm i node-fetch@2 form-data
完整代码如下:
const fs = require('fs'); const path = require('path'); // Node 18+ 可注释掉下面两行依赖引入 const fetch = require('node-fetch'); const FormData = require('form-data'); async function submitAzureTtsTask() { // 替换为你自己的配置 const requestUrl = '你的Azure长文本转语音接口地址'; const subscriptionKey = '你的Ocp-Apim-Subscription-Key'; const scriptPath = '你的txt脚本文件路径,例:./input.txt'; // 业务参数和Python示例完全对齐 const ttsConfig = { displayname: 'long audio synthesis sample', description: 'sample description', locale: 'en-US', voices: [{ voicename: '你要使用的语音名称' }], outputformat: 'riff-16khz-16bit-mono-pcm', concatenateresult: true }; // 构造多部分表单 const form = new FormData(); // 追加配置JSON字段,指定内容类型为application/json form.append('config', JSON.stringify(ttsConfig), { contentType: 'application/json' }); // 追加txt脚本文件,和Python示例的script字段对应 const scriptFileName = path.basename(scriptPath); const scriptStream = fs.createReadStream(scriptPath); form.append('script', scriptStream, { filename: scriptFileName, contentType: 'text/plain' }); // 发送请求,不要手动设置Content-Type,用form自动生成的带boundary的合法头 const res = await fetch(requestUrl, { method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': subscriptionKey, ...form.getHeaders() }, body: form }); if (!res.ok) { const errMsg = await res.text(); throw new Error(`请求失败,状态码${res.status}:${errMsg}`); } const taskInfo = await res.json(); console.log('合成任务提交成功:', taskInfo); return taskInfo; } submitAzureTtsTask().catch(err => console.error(err));
关键注意点
- 读文件优先用
fs.createReadStream而不是readFileSync:大体积脚本文件用流传输不会占用过高内存,和Python示例中open()返回的文件对象行为一致 - Azure长文本转语音接口要求JSON配置作为multipart表单中名为
config的part传入,不是直接把JSON序列化为整个请求体 - node-fetch的请求配置对象不存在
files、payload属性,所有请求内容都需要通过body字段传递
内容的提问来源于stack exchange,提问作者sebagl
相关产品推荐
相关产品推荐

