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

Firebase Functions上传ElevenLabs API音频至Storage生成空文件问题

解决Firebase Functions上传ElevenLabs音频到Storage生成空文件的问题

问题根源

调用ElevenLabs流式文本转语音接口时,axios默认会将响应解析为JSON或字符串格式,但音频属于二进制数据,这种解析方式会直接导致原始音频数据丢失,最终上传到Firebase Storage的自然是空文件。

修复方案

核心修改是在axios请求配置中添加**responseType: 'arraybuffer'**,让axios以二进制数组形式接收音频响应,确保上传到Storage的是完整的音频内容。

另外需要注意:ElevenLabs接口路径/text-to-speech/{voice_id}/stream中的参数是语音ID,而非模型ID,你当前代码里传入的clipData.model如果是模型ID的话,需要替换为正确的语音ID,否则API可能返回错误(这也是空文件的潜在诱因)。

修改后的完整代码

import axios from "axios";
import {FieldValue} from "firebase-admin/firestore";
import {firestore, logger} from "firebase-functions/v1";
import {db, storage} from "./lib";

export const generateClip = firestore
  .document("clips/{clipId}")
  .onCreate(async (snapshot, context) => {
    const clipData = snapshot.data();
    if (!clipData) {
      logger.error("No data found");
      return;
    }
    const clipId = context.params.clipId;

    try {
      const res = await axios.post(
        // 注意:路径参数需替换为有效的ElevenLabs语音ID
        `https://api.elevenlabs.io/v1/text-to-speech/${clipData.voiceId}/stream`,
        {
          "text": clipData.text,
          "model_id": "eleven_monolingual_v1",
          "voice_settings": {
            "stability": 0.5,
            "similarity_boost": 0.5,
          },
        },
        {
          headers: {
            "xi-api-key": process.env.VOICE_KEY,
            "Accept": "audio/mpeg",
          },
          // 关键修改:指定响应类型为二进制数组
          responseType: 'arraybuffer'
        }
      );

      const path = `clips/${clipId}.mp3`;
      const file = storage.bucket(process.env.FIREBASE_BUCKET).file(path);
      // 保存二进制音频数据,同时指定MIME类型
      await file.save(res.data, {
        contentType: 'audio/mpeg'
      });

      const tokensCount = (clipData.text as string).length;

      await db.doc(`clips/${clipId}`).update({
        status: "COMPLETED",
        tokens: tokensCount,
        file_path: path,
      });

      await db.doc(`users/${clipData.uid}`).update({
        tokens: FieldValue.increment(-tokensCount),
      });

      logger.info("Clip generated", {
        clipId,
        tokensCount,
        path,
      });
    } catch (error) {
      logger.error("Error generate clip", error);
      await db.doc(`clips/${clipId}`).update({
        status: "FAILED",
      });
    }
  });

额外检查项

  • 确认process.env.VOICE_KEY已正确配置ElevenLabs的有效API密钥,且密钥具备文本转语音接口的调用权限。
  • 确保clipData.voiceId是ElevenLabs控制台中存在的语音ID。
  • 上传时指定contentType: 'audio/mpeg',保证Storage中的文件能被正确识别为MP3格式。

内容的提问来源于stack exchange,提问作者Ashik Chapagain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:47:29