feat: 将视频转写重构为纯文字异步语音识别
This commit is contained in:
+16
-6
@@ -111,17 +111,17 @@ export async function getVideoDuration(
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 ffmpeg 将视频二进制转换为音频,返回音频 Buffer
|
||||
* 使用 ffmpeg 将视频 Buffer 或本地文件转换为音频,返回音频 Buffer
|
||||
*
|
||||
* 默认输出 mp3,可通过 opts.format 指定 'mp3' | 'aac' | 'wav'
|
||||
* - mp3: 使用 libmp3lame,contentType 为 'audio/mpeg'
|
||||
* - mp3: 使用 libmp3lame,16 kHz 单声道,contentType 为 'audio/mpeg'
|
||||
* - aac: 输出 m4a 容器(AAC 编码),contentType 为 'audio/mp4'
|
||||
* - wav: PCM 16-bit,44100Hz,双声道,contentType 为 'audio/wav'
|
||||
*
|
||||
* 若系统未安装 ffmpeg 或未在 PATH 中,返回 null 并给出提示。
|
||||
*/
|
||||
export async function extractAudio(
|
||||
videoBuffer: Buffer,
|
||||
videoBuffer: Buffer | string,
|
||||
opts?: { format?: "mp3" | "aac" | "wav"; bitrateKbps?: number },
|
||||
): Promise<{ buffer: Buffer; contentType: string; ext: string } | null> {
|
||||
const ffmpegCmd = process.env.FFMPEG_PATH || "ffmpeg";
|
||||
@@ -129,6 +129,7 @@ export async function extractAudio(
|
||||
const base = `dy_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
||||
const inPath = path.join(tmpDir, `${base}.mp4`);
|
||||
|
||||
const inputPath = typeof videoBuffer === "string" ? videoBuffer : inPath;
|
||||
const format = opts?.format ?? "mp3";
|
||||
const bitrate = Math.max(32, Math.min(512, opts?.bitrateKbps ?? 192)); // 安全范围 32~512 kbps
|
||||
|
||||
@@ -174,19 +175,28 @@ export async function extractAudio(
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.writeFile(inPath, videoBuffer);
|
||||
if (typeof videoBuffer !== "string") await fs.writeFile(inPath, videoBuffer);
|
||||
const args = [
|
||||
"-hide_banner",
|
||||
"-loglevel",
|
||||
"error",
|
||||
"-i",
|
||||
inPath,
|
||||
inputPath,
|
||||
"-map",
|
||||
"0:a:0",
|
||||
"-ac",
|
||||
"1",
|
||||
"-ar",
|
||||
"16000",
|
||||
"-vn", // 丢弃视频流
|
||||
...codecArgs,
|
||||
"-y",
|
||||
outPath,
|
||||
];
|
||||
await execFileAsync(ffmpegCmd, args, { windowsHide: true });
|
||||
await execFileAsync(ffmpegCmd, args, {
|
||||
windowsHide: true,
|
||||
timeout: 60 * 60 * 1000,
|
||||
});
|
||||
const audio = await fs.readFile(outPath);
|
||||
return { buffer: audio, contentType, ext };
|
||||
} catch (e: any) {
|
||||
|
||||
Reference in New Issue
Block a user