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

如何将视频URL转MP3并保存至Firebase Storage?

问题:Node.js+Express服务提取视频音频保存至Firebase Storage后仍为原视频格式

使用Node.js搭配Express v4.18.2开发部署在Firebase的服务,需求是接收视频URL,提取音频转成MP3后保存到Firebase Storage。本地测试时能正常生成MP3文件,但生产环境无法用fs本地存储文件,且保存到Storage的文件虽后缀设为.mp3、contentType配置为audio/mpeg,实际仍是原视频格式,浏览器打开会播放视频。

已实现功能

  • 通过Axios成功下载视频流
  • 可正常将文件保存至Firebase Storage(无初始化或存储桶引用问题)
  • 本地测试时能生成名为output.mp3的正确音频文件
  • 可获取extractAudioFromVideo函数返回的Buffer数据

存在问题

  1. 生产环境无法使用fs本地保存文件
  2. 上传至Firebase Storage的文件仅修改了后缀和元数据,实际内容仍包含视频流,并非纯MP3音频

核心代码

下载视频函数

async function downloadVideo(videoUrl) {
    try {
      const response = await axios.get(videoUrl, {
        responseType: 'stream',
      });
  
      if (response.status === 200) {
        return response.data;
      } else {
        throw new Error('Failed to fetch the video');
      }
    } catch (error) {
      throw new Error('Error fetching the video: ' + error.message);
    }
  }

提取音频函数

async function extractAudioFromVideo(videoUrl) {
    try {
      const videoStream = await downloadVideo(videoUrl);
  
      // Create a PassThrough stream to pipe the video data
      const passThrough = new PassThrough();
      videoStream.pipe(passThrough);

      const outputFile = 'output.mp3';
      const outputStream = fs.createWriteStream(outputFile);
  
        return new Promise((resolve, reject) => {
            const audioBuffers = [];

            passThrough.on('data', chunk => {
                audioBuffers.push(chunk)
                outputStream.write(chunk); // Write chunks to a local file
              });
        
              passThrough.on('error', err => {
                reject(err);
              });
        

            ffmpeg()
            .input(passThrough)
            .output('/dev/null') // Null output as a placeholder
            .outputOptions('-vn') // Extract audio only
            .noVideo()
            .audioQuality(0)
            .audioCodec('libmp3lame') // Set audio codec
            .format('mp3')
            .on('end', () => {
                const audioBuffer = Buffer.concat(audioBuffers)
                if (audioBuffer.length > 0) {
                    resolve(audioBuffer);
                  } else {
                    reject(new Error('Empty audio buffer'));
                  }
              })
            .on('error', err => reject(err))
            .run();
        })
    } catch (error) {
      throw new Error('Error extracting audio: ' + error.message);
    }
  }

保存至Firebase Storage函数

async function saveAudioToFirebase(audioBuffer, fileName) {
    try {
        let storage = admin.storage()
    let storageRef = storage.bucket(serviceAccount.storage_bucket_content)
      const file = storageRef.file(fileName) // Specify the desired file name here

      const renamedFileName = fileName.replace(/\.[^/.]+$/, '.mp3'); // Change the file extension to .mp3
  
      await file.save(audioBuffer, {
        metadata: {
          contentType: 'audio/mpeg', // Adjust the content type as needed
        },
      });

      await file.setMetadata({
        contentType: 'audio/mpeg'
      })

      await file.move(renamedFileName); // Rename the file with the .mp3 extension
  
      console.log('Audio saved to Firebase Storage.');
    } catch (error) {
      console.error('Error saving audio to Firebase Storage:', error);
    }
  }

愿意尝试tmp等第三方库,只要能解决问题。

内容的提问来源于stack exchange,提问作者Hello World

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:35:30