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

如何在Next.js(Node.js)中从视频提取音频并转录?

实现视频文件转录的解决方案

要实现从视频文件中提取音频并转录的需求,我们可以使用FFmpeg在内存中直接处理视频文件,无需第三方API或云存储。以下是具体步骤:

1. 安装依赖包

首先安装用于处理音视频的工具库:

npm install fluent-ffmpeg ffmpeg-static
  • fluent-ffmpeg:Node.js环境下的FFmpeg封装库
  • ffmpeg-static:预编译的FFmpeg二进制文件,确保服务器环境中存在FFmpeg

2. 修改API路由代码

替换原有的API路由代码为以下内容:

import { NextRequest, NextResponse } from 'next/server';
import { SpeechClient } from '@google-cloud/speech';
import { Buffer } from 'buffer';
import ffmpeg from 'fluent-ffmpeg';
import ffmpegPath from 'ffmpeg-static';
import { Readable } from 'stream';

// 设置FFmpeg二进制文件路径
ffmpeg.setFfmpegPath(ffmpegPath);

// 解码环境变量中的Base64格式Google凭据
const base64EncodedCredentials = process.env.GOOGLE_APPLICATION_CREDENTIALS_BASE64;
if (!base64EncodedCredentials) {
  throw new Error('Google Cloud服务账号凭据未提供');
}

const credentialsBuffer = Buffer.from(base64EncodedCredentials, 'base64');
const credentials = JSON.parse(credentialsBuffer.toString('utf8'));

// 初始化Google Speech客户端
const client = new SpeechClient({
  credentials: {
    client_email: credentials.client_email,
    private_key: credentials.private_key,
  },
  projectId: credentials.project_id,
});

export async function POST(req: NextRequest) {
  try {
    const formData = await req.formData();
    const file = formData.get('file') as File | null;

    if (!file) {
      return new NextResponse(JSON.stringify({ error: '未提供视频文件' }), { status: 400 });
    }

    // 将视频文件转换为Buffer
    const videoBuffer = Buffer.from(await file.arrayBuffer());
    // 创建可读流供FFmpeg处理
    const videoStream = Readable.from(videoBuffer);

    // 使用FFmpeg提取音频并转换为MP3格式
    const audioBuffer = await new Promise<Buffer>((resolve, reject) => {
      const audioChunks: Buffer[] = [];
      ffmpeg(videoStream)
        .noVideo() // 仅处理音频
        .audioCodec('libmp3lame') // 使用MP3编码器
        .format('mp3') // 输出格式为MP3
        .on('error', (err) => {
          console.error('[ERROR_EXTRACTING_AUDIO]', err);
          reject(new Error('音频提取失败'));
        })
        .on('data', (chunk) => audioChunks.push(chunk))
        .on('end', () => resolve(Buffer.concat(audioChunks)))
        .pipe(); // 启动处理流程
    });

    // 将音频Buffer转换为Base64字符串
    const audioBytes = audioBuffer.toString('base64');

    // 调用Google Speech-to-Text API进行转录
    const [response] = await client.recognize({
      audio: {
        content: audioBytes,
      },
      config: {
        encoding: 'MP3',
        sampleRateHertz: 16000,
        languageCode: 'en-US',
        model: 'default',
        useEnhanced: true,
        speechContexts: [
          {
            phrases: ['google cloud'],
            boost: 20.0,
          },
        ],
        enableWordTimeOffsets: true,
      },
    });

    if (!response.results || response.results.length === 0) {
      throw new Error('未获取到转录结果');
    }

    // 提取转录文本
    const transcription = response.results
      .map(result => {
        if (!result.alternatives || result.alternatives.length === 0) {
          return '';
        }
        return result.alternatives[0].transcript;
      })
      .join('\n');

    return new NextResponse(JSON.stringify({ transcription }), { status: 200 });

  } catch (error) {
    console.error('[ERROR_TRANSCRIBING]', error);
    return new NextResponse('内部服务器错误', { status: 500 });
  }
}

关键代码说明

  • FFmpeg音频提取:通过ffmpeg(videoStream)读取视频流,使用.noVideo()禁用视频处理,指定MP3编码格式,将输出的音频数据收集为Buffer。
  • 内存处理:整个过程无需写入磁盘,所有数据都在内存中流转,符合不使用云存储或本地文件的要求。
  • 错误处理:新增了音频提取阶段的错误捕获,确保异常情况能被正确处理并返回对应错误信息。

注意事项

  • 运行环境兼容性:ffmpeg-static会根据当前操作系统和架构自动下载对应的FFmpeg二进制文件,确保部署环境(如Vercel、AWS等)支持该依赖。
  • 视频大小限制:过大的视频文件可能导致内存占用过高或请求超时,建议在前端添加文件大小限制,或在服务器端配置更长的超时时间。
  • 音频格式适配:如果需要支持其他音频输出格式(如WAV),可修改FFmpeg的format和audioCodec参数,并同步更新Google Speech配置中的encoding字段。

内容的提问来源于stack exchange,提问作者Mohammed Bekele

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:40:24