From 33bb5c5c9f948be4243fb7178f9e72ac762ed9a6 Mon Sep 17 00:00:00 2001 From: "fengchuanhn@gmail.com" Date: Sun, 17 May 2026 23:29:09 +0800 Subject: [PATCH] 11 --- main.py | 1 + scripts/nodejs/pipeline_native.js | 57 ++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 63c3291..5719b48 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,7 @@ import uvicorn if __name__ == "__main__": + print("开始启动后端") uvicorn.run( "app.main:app", host="0.0.0.0", diff --git a/scripts/nodejs/pipeline_native.js b/scripts/nodejs/pipeline_native.js index b5b8965..5f3f975 100644 --- a/scripts/nodejs/pipeline_native.js +++ b/scripts/nodejs/pipeline_native.js @@ -8,7 +8,7 @@ const fs = require("fs"); const path = require("path"); const os = require("os"); const crypto = require("crypto"); -const { spawn } = require("child_process"); +const { spawn, execFileSync } = require("child_process"); const https = require("https"); const http = require("http"); @@ -54,16 +54,63 @@ function runCommand(cmd, args, timeoutMs = 300000) { }); } -function locateFfmpeg() { - if (process.env.AICLIENT_FFMPEG_PATH && fs.existsSync(process.env.AICLIENT_FFMPEG_PATH)) { - return process.env.AICLIENT_FFMPEG_PATH; - } +function exeName() { return process.platform === "win32" ? "ffmpeg.exe" : "ffmpeg"; } +function whichSync(cmd) { + try { + if (process.platform === "win32") { + const out = execFileSync("where", [cmd], { encoding: "utf8", windowsHide: true }); + const line = out.split(/\r?\n/).map((s) => s.trim()).find(Boolean); + return line && fs.existsSync(line) ? line : null; + } + const out = execFileSync("which", [cmd], { encoding: "utf8" }); + const line = out.trim().split(/\r?\n/)[0]; + return line && fs.existsSync(line) ? line : null; + } catch { + return null; + } +} + +/** 与 Rust `ffmpeg::locate_ffmpeg` 顺序对齐 */ +function locateFfmpeg() { + const name = exeName(); + const envPath = process.env.AICLIENT_FFMPEG_PATH; + if (envPath && fs.existsSync(envPath)) { + return envPath; + } + + const candidates = []; + const nodeDir = path.dirname(process.execPath); + candidates.push(path.join(nodeDir, "binaries", name)); + candidates.push(path.join(nodeDir, name)); + candidates.push(path.join(nodeDir, "..", "binaries", name)); + candidates.push(path.join(nodeDir, "..", "..", "binaries", name)); + candidates.push(path.join(nodeDir, "..", "..", "..", "binaries", name)); + candidates.push(path.join(process.cwd(), "src-tauri", "binaries", name)); + candidates.push(path.join(process.cwd(), "binaries", name)); + + for (const p of candidates) { + try { + if (fs.existsSync(p)) return p; + } catch { + /* ignore */ + } + } + + return whichSync(name); +} + async function ffmpegExtractAudio(videoPath) { const dest = tempPath("audio", "wav"); const ffmpeg = locateFfmpeg(); + if (!ffmpeg) { + throw new Error( + "未找到 ffmpeg。请安装并加入 PATH,或将可执行文件放到 src-tauri/binaries/ffmpeg.exe," + + "或在环境变量中设置 AICLIENT_FFMPEG_PATH(桌面端会在启动 Node 时自动注入已解析路径)", + ); + } await runCommand(ffmpeg, [ "-y", "-i",