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

Node.js中处理OpenAI TTS API响应:转MP3缓冲区并存储

解决OpenAI TTS API的二进制响应处理与MP3存储问题

核心问题分析

你的代码未配置axios的响应类型,默认情况下axios会把二进制分块响应解析成字符串,导致音频数据损坏。必须明确指定响应类型为二进制格式,才能正确处理audio/mpeg的流数据。

修改后的实现方案

以下是两种常用处理方式,按需选择:


方式1:获取MP3 Buffer并存储

适合需要先对音频数据做处理再存储的场景:

const fs = require('fs').promises;
const axios = require('axios');
const speechUrl = 'https://api.openai.com/v1/audio/speech';
    
const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
};

async function voiceGenerator(text) {
    console.log('voiceGenerator is triggered');
    console.log('text: ', text);
    const body = {
        "model": "tts-1",
        "input": text,
        "voice": "alloy",
        "response_format": "mp3",
        "speed": 0.9
    };

    try {
        const res = await axios.post(speechUrl, body, { 
            headers: headers,
            responseType: 'arraybuffer' // 关键配置:以二进制数组形式接收响应
        });

        if (res.status === 200) {
            // 将ArrayBuffer转换为Node.js Buffer
            const mp3Buffer = Buffer.from(res.data);
            
            // 示例:存储为本地MP3文件
            await fs.writeFile('./output.mp3', mp3Buffer);
            console.log('MP3文件已成功存储');
            
            return mp3Buffer;
        } else {
            console.error('请求失败,状态码:', res.status);
            throw new Error(`请求失败,状态码: ${res.status}`);
        }
    } catch (err) {
        console.error('OpenAI API调用失败:', err.response?.data || err.message);
        throw err;
    }
}

方式2:直接通过流存储(更高效,适合大文件)

如果不需要对音频数据做中间处理,直接用流可以减少内存占用:

const fs = require('fs');
const axios = require('axios');
const speechUrl = 'https://api.openai.com/v1/audio/speech';
    
const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
};

async function voiceGenerator(text) {
    console.log('voiceGenerator is triggered');
    console.log('text: ', text);
    const body = {
        "model": "tts-1",
        "input": text,
        "voice": "alloy",
        "response_format": "mp3",
        "speed": 0.9
    };

    try {
        const res = await axios.post(speechUrl, body, { 
            headers: headers,
            responseType: 'stream' // 关键配置:以流形式接收响应
        });

        if (res.status === 200) {
            return new Promise((resolve, reject) => {
                const writeStream = fs.createWriteStream('./output.mp3');
                // 将响应流管道到文件写入流
                res.data.pipe(writeStream);
                
                writeStream.on('finish', () => {
                    console.log('MP3文件已成功存储');
                    resolve();
                });
                
                writeStream.on('error', (err) => {
                    console.error('文件写入失败:', err);
                    reject(err);
                });
            });
        } else {
            console.error('请求失败,状态码:', res.status);
            throw new Error(`请求失败,状态码: ${res.status}`);
        }
    } catch (err) {
        console.error('OpenAI API调用失败:', err.response?.data || err.message);
        throw err;
    }
}

关键说明

  1. responseType配置:必须设置为arraybuffer或stream,否则axios会把二进制数据转成UTF-8字符串,导致MP3文件损坏无法播放。
  2. 状态码判断:OpenAI TTS接口成功响应的状态码是200,204代表无内容,无需保留该判断。
  3. 错误处理优化:捕获错误时优先读取err.response?.data,可以拿到OpenAI返回的具体错误信息(比如API密钥无效、输入文本过长等)。

内容的提问来源于stack exchange,提问作者Terry Windwalker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 04:43:37