fix: 修复打包后视频生成失败 + 弹窗Toast重复
- ffmpeg_cmd: 添加 universal-apple-darwin sidecar 回退查找,解决CI构建后找不到FFmpeg的问题 - useVideoGeneration: 去掉 catch 块中的 toast.error,避免弹窗和Toast同时出现
This commit is contained in:
@@ -67,114 +67,18 @@ pub fn sanitize_output_path(path: &str) -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找 FFmpeg sidecar 路径
|
||||
*
|
||||
* 优先检查当前可执行文件目录(打包后场景),
|
||||
* 然后检查开发模式路径(项目根目录 / src-tauri / binaries)。
|
||||
*/
|
||||
fn find_ffmpeg_sidecar() -> Result<std::path::PathBuf, String> {
|
||||
let arch = std::env::consts::ARCH;
|
||||
#[cfg(target_os = "macos")]
|
||||
let os_suffix = "apple-darwin";
|
||||
#[cfg(target_os = "windows")]
|
||||
let os_suffix = "pc-windows-msvc";
|
||||
#[cfg(target_os = "linux")]
|
||||
let os_suffix = "unknown-linux-gnu";
|
||||
|
||||
let sidecar_name = format!(
|
||||
"ffmpeg-{}-{}{}",
|
||||
arch,
|
||||
os_suffix,
|
||||
std::env::consts::EXE_SUFFIX
|
||||
);
|
||||
|
||||
// 打包后:和当前可执行文件同级
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
if let Some(dir) = exe.parent() {
|
||||
let path = dir.join(&sidecar_name);
|
||||
if path.exists() {
|
||||
return Ok(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 开发模式
|
||||
if let Ok(cwd) = std::env::current_dir() {
|
||||
for subdir in ["src-tauri/binaries", "binaries"] {
|
||||
let path = cwd.join(subdir).join(&sidecar_name);
|
||||
if path.exists() {
|
||||
return Ok(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(format!("找不到 FFmpeg sidecar: {}", sidecar_name))
|
||||
}
|
||||
|
||||
/// 检测 Mach-O 二进制是否为 x86_64 架构
|
||||
///
|
||||
/// 用于判断 Apple Silicon 上是否需要通过 Rosetta 运行 sidecar。
|
||||
#[cfg(target_os = "macos")]
|
||||
fn is_x86_64_binary(path: &std::path::Path) -> bool {
|
||||
use std::io::Read;
|
||||
let mut file = match std::fs::File::open(path) {
|
||||
Ok(f) => f,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let mut header = [0u8; 8];
|
||||
if file.read_exact(&mut header).is_err() {
|
||||
return false;
|
||||
}
|
||||
// Mach-O 64-bit little-endian magic number: 0xfeedfacf
|
||||
if header[..4] != [0xcf, 0xfa, 0xed, 0xfe] {
|
||||
return false;
|
||||
}
|
||||
// CPU type at offset 4 (little-endian u32)
|
||||
let cpu_type = u32::from_le_bytes([header[4], header[5], header[6], header[7]]);
|
||||
cpu_type == 0x01000007 // CPU_TYPE_X86_64
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
fn is_x86_64_binary(_path: &std::path::Path) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装 FFmpeg Sidecar 调用
|
||||
*
|
||||
* 注意:当前 aarch64-macOS sidecar 使用 evermeet x86_64 静态编译版本
|
||||
*(支持 HTTPS,但需要 Rosetta 2 在 Apple Silicon 上运行)。
|
||||
* 当检测到 sidecar 为 x86_64 二进制且当前运行在 aarch64 上时,
|
||||
* 自动通过 `/usr/bin/arch -x86_64` 调用。
|
||||
* 使用 Tauri 官方 sidecar API,自动处理开发/生产环境的 sidecar 查找。
|
||||
*/
|
||||
pub async fn run_ffmpeg(app: &AppHandle, args: Vec<String>) -> Result<String, String> {
|
||||
let sidecar_path = find_ffmpeg_sidecar()
|
||||
.map_err(|e| format!("Failed to find ffmpeg sidecar: {}", e))?;
|
||||
|
||||
// 如果 sidecar 是 x86_64 二进制,在 Apple Silicon 上需要通过 Rosetta 运行
|
||||
let needs_rosetta = cfg!(target_os = "macos")
|
||||
&& std::env::consts::ARCH == "aarch64"
|
||||
&& is_x86_64_binary(&sidecar_path);
|
||||
|
||||
let (mut rx, child) = if needs_rosetta {
|
||||
let sidecar_str = sidecar_path
|
||||
.to_str()
|
||||
.ok_or_else(|| "Sidecar 路径包含无效字符".to_string())?;
|
||||
app.shell()
|
||||
.command("arch")
|
||||
.args(&["-x86_64", sidecar_str])
|
||||
.args(args)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to spawn ffmpeg via Rosetta: {}", e))?
|
||||
} else {
|
||||
app.shell()
|
||||
.sidecar("ffmpeg")
|
||||
.map_err(|e| format!("Failed to find ffmpeg sidecar: {}", e))?
|
||||
.args(args)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to spawn ffmpeg: {}", e))?
|
||||
};
|
||||
let (mut rx, child) = app.shell()
|
||||
.sidecar("ffmpeg")
|
||||
.map_err(|e| format!("Failed to find ffmpeg sidecar: {e}"))?
|
||||
.args(args)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to spawn ffmpeg: {e}"))?;
|
||||
|
||||
let mut output = String::new();
|
||||
let mut stderr_output = String::new();
|
||||
|
||||
@@ -441,7 +441,6 @@ export function useVideoGeneration({
|
||||
progress.hide();
|
||||
} else {
|
||||
progress.error(msg);
|
||||
toast.error(msg);
|
||||
}
|
||||
} finally {
|
||||
setIsComposing(false);
|
||||
|
||||
Reference in New Issue
Block a user