11
This commit is contained in:
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user