Compare commits

..
Author SHA1 Message Date
lanyeeee 6331032757 fix: 修复目录命名的episode_title字段映射错误的问题 2026-08-08 05:01:18 +08:00
8 changed files with 128 additions and 107 deletions
-16
View File
@@ -315,7 +315,6 @@ dependencies = [
"tauri-plugin-dialog", "tauri-plugin-dialog",
"tauri-plugin-opener", "tauri-plugin-opener",
"tauri-plugin-os", "tauri-plugin-os",
"tauri-plugin-window-state",
"tauri-specta", "tauri-specta",
"tokio", "tokio",
"tracing", "tracing",
@@ -4464,21 +4463,6 @@ dependencies = [
"thiserror 2.0.12", "thiserror 2.0.12",
] ]
[[package]]
name = "tauri-plugin-window-state"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d5f6fe3291bfa609c7e0b0ee3bedac294d94c7018934086ce782c1d0f2a468e"
dependencies = [
"bitflags 2.9.1",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.12",
]
[[package]] [[package]]
name = "tauri-runtime" name = "tauri-runtime"
version = "2.7.0" version = "2.7.0"
-1
View File
@@ -22,7 +22,6 @@ tauri = { version = "2", features = [] }
tauri-plugin-opener = "2" tauri-plugin-opener = "2"
tauri-plugin-os = "2" tauri-plugin-os = "2"
tauri-plugin-dialog = "2" tauri-plugin-dialog = "2"
tauri-plugin-window-state = "2"
dlopen2 = { version = "0.8.2" } dlopen2 = { version = "0.8.2" }
bilibili-video-downloader-plugin-api = { path = "../src-plugin/plugin-api" } bilibili-video-downloader-plugin-api = { path = "../src-plugin/plugin-api" }
+1 -2
View File
@@ -351,8 +351,7 @@ impl BiliClient {
.read() .read()
.get("https://api.bilibili.com/x/space/wbi/arc/search") .get("https://api.bilibili.com/x/space/wbi/arc/search")
.query(&params) .query(&params)
// 不带DedeUserID会随机触发412错误 .header("cookie", self.get_cookie());
.header("cookie", format!("DedeUserID=1; {}", self.get_cookie()));
let http_resp = request.send().await?; let http_resp = request.send().await?;
// 检查http响应状态码 // 检查http响应状态码
let status = http_resp.status(); let status = http_resp.status();
@@ -1,4 +1,4 @@
use std::{io, path::PathBuf, sync::Arc}; use std::{path::PathBuf, sync::Arc};
use eyre::{WrapErr, eyre}; use eyre::{WrapErr, eyre};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -98,11 +98,21 @@ impl VideoProcessTask {
let output_path = episode_dir.join(format!("{filename}-merged.mp4")); let output_path = episode_dir.join(format!("{filename}-merged.mp4"));
let (tx, rx) = tokio::sync::oneshot::channel();
let video_path_clone = video_path.clone();
let audio_path_clone = audio_path.clone();
let metadata_path_clone = metadata_path.clone();
let output_path_clone = output_path.clone();
let current_span = tracing::Span::current();
tauri::async_runtime::spawn_blocking(move || {
let _enter = current_span.enter();
let mut command = std::process::Command::new(ffmpeg_program); let mut command = std::process::Command::new(ffmpeg_program);
command.arg("-i").arg(&video_path); command.arg("-i").arg(video_path_clone);
command.arg("-i").arg(&audio_path); command.arg("-i").arg(audio_path_clone);
if let Some(metadata_path) = &metadata_path { if let Some(metadata_path) = metadata_path_clone {
command.arg("-i").arg(metadata_path); command.arg("-i").arg(metadata_path);
command.arg("-map_metadata").arg("2"); command.arg("-map_metadata").arg("2");
} }
@@ -110,7 +120,8 @@ impl VideoProcessTask {
command.arg("-c").arg("copy"); command.arg("-c").arg("copy");
command.arg("-map").arg("0:v:0"); command.arg("-map").arg("0:v:0");
command.arg("-map").arg("1:a:0"); command.arg("-map").arg("1:a:0");
command.arg(&output_path).arg("-y");
command.arg(output_path_clone).arg("-y");
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
{ {
@@ -119,7 +130,21 @@ impl VideoProcessTask {
command.creation_flags(0x0800_0000); command.creation_flags(0x0800_0000);
} }
execute_ffmpeg(command).await.wrap_err("执行FFmpeg失败")?; let output = command.output();
let _ = tx.send(output);
});
let output = rx.await??;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
let err = eyre!(format!("STDOUT: {stdout}"))
.wrap_err(format!("STDERR: {stderr}"))
.wrap_err("原因可能是视频或音频文件损坏,建议[重来]试试");
return Err(err);
}
std::fs::remove_file(&video_path) std::fs::remove_file(&video_path)
.wrap_err(format!("删除视频文件`{}`失败", video_path.display()))?; .wrap_err(format!("删除视频文件`{}`失败", video_path.display()))?;
@@ -167,14 +192,25 @@ impl VideoProcessTask {
let ffmpeg_program = utils::get_ffmpeg_program().wrap_err("获取FFmpeg程序路径失败")?; let ffmpeg_program = utils::get_ffmpeg_program().wrap_err("获取FFmpeg程序路径失败")?;
let (tx, rx) = tokio::sync::oneshot::channel();
let video_path_clone = video_path.clone();
let audio_path_clone = audio_path.clone();
let output_path_clone = output_path.clone();
let current_span = tracing::Span::current();
tauri::async_runtime::spawn_blocking(move || {
let _enter = current_span.enter();
let mut command = std::process::Command::new(ffmpeg_program); let mut command = std::process::Command::new(ffmpeg_program);
command.arg("-i").arg(&video_path); command.arg("-i").arg(video_path_clone);
command.arg("-i").arg(&audio_path); command.arg("-i").arg(audio_path_clone);
command.arg("-c").arg("copy"); command.arg("-c").arg("copy");
command.arg("-map").arg("0:v:0"); command.arg("-map").arg("0:v:0");
command.arg("-map").arg("1:a:0"); command.arg("-map").arg("1:a:0");
command.arg(&output_path).arg("-y");
command.arg(output_path_clone).arg("-y");
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
{ {
@@ -183,7 +219,21 @@ impl VideoProcessTask {
command.creation_flags(0x0800_0000); command.creation_flags(0x0800_0000);
} }
execute_ffmpeg(command).await.wrap_err("执行FFmpeg失败")?; let output = command.output();
let _ = tx.send(output);
});
let output = rx.await??;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
let err = eyre!(format!("STDOUT: {stdout}"))
.wrap_err(format!("STDERR: {stderr}"))
.wrap_err("原因可能是视频或音频文件损坏,建议[重来]试试");
return Err(err);
}
std::fs::remove_file(&video_path) std::fs::remove_file(&video_path)
.wrap_err(format!("删除视频文件`{}`失败", video_path.display()))?; .wrap_err(format!("删除视频文件`{}`失败", video_path.display()))?;
@@ -229,13 +279,24 @@ impl VideoProcessTask {
return Ok(()); return Ok(());
}; };
let (tx, rx) = tokio::sync::oneshot::channel();
let video_path_clone = video_path.clone();
let metadata_path_clone = metadata_path.clone();
let output_path_clone = output_path.clone();
let current_span = tracing::Span::current();
tauri::async_runtime::spawn_blocking(move || {
let _enter = current_span.enter();
let mut command = std::process::Command::new(ffmpeg_program); let mut command = std::process::Command::new(ffmpeg_program);
command.arg("-i").arg(&video_path); command.arg("-i").arg(video_path_clone);
command.arg("-i").arg(&metadata_path); command.arg("-i").arg(metadata_path_clone);
command.arg("-map_metadata").arg("1"); command.arg("-map_metadata").arg("1");
command.arg("-c").arg("copy"); command.arg("-c").arg("copy");
command.arg(&output_path).arg("-y");
command.arg(output_path_clone).arg("-y");
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
{ {
@@ -244,7 +305,21 @@ impl VideoProcessTask {
command.creation_flags(0x0800_0000); command.creation_flags(0x0800_0000);
} }
execute_ffmpeg(command).await.wrap_err("执行FFmpeg失败")?; let output = command.output();
let _ = tx.send(output);
});
let output = rx.await??;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
let err = eyre!(format!("STDOUT: {stdout}"))
.wrap_err(format!("STDERR: {stderr}"))
.wrap_err("原因可能是视频或音频文件损坏,建议[重来]试试");
return Err(err);
}
std::fs::remove_file(&video_path) std::fs::remove_file(&video_path)
.wrap_err(format!("删除视频文件`{}`失败", video_path.display()))?; .wrap_err(format!("删除视频文件`{}`失败", video_path.display()))?;
@@ -292,10 +367,7 @@ impl VideoProcessTask {
let bili_client = app.get_bili_client(); let bili_client = app.get_bili_client();
let cid = Some(progress.cid); let cid = Some(progress.cid);
let skip_segments = bili_client let skip_segments = bili_client.get_skip_segments(bvid, cid).await?;
.get_skip_segments(bvid, cid)
.await
.wrap_err("获取广告片段失败,请[继续]以重试。如果重试多次依旧失败,请在设置中取消勾选[标记广告]")?;
for segment in skip_segments.0 { for segment in skip_segments.0 {
if let Some(chapter_segment) = segment.into_chapter_segment() { if let Some(chapter_segment) = segment.into_chapter_segment() {
chapter_segments.insert(chapter_segment); chapter_segments.insert(chapter_segment);
@@ -316,32 +388,3 @@ impl VideoProcessTask {
Ok(Some(metadata_path)) Ok(Some(metadata_path))
} }
} }
#[instrument(level = "error", skip_all)]
async fn execute_ffmpeg(mut command: std::process::Command) -> eyre::Result<()> {
let span = tracing::Span::current();
tauri::async_runtime::spawn_blocking(move || {
let _enter = span.enter();
let program = command.get_program().to_string_lossy().into_owned();
let output = command.output().map_err(|err| {
if err.kind() == io::ErrorKind::NotFound {
eyre!(err).wrap_err(format!("找不到FFmpeg `{program}`"))
} else {
eyre!(err)
}
})?;
if output.status.success() {
return Ok(());
}
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
Err(eyre!(format!("STDOUT: {stdout}")))
.wrap_err(format!("STDERR: {stderr}"))
.wrap_err("原因可能是视频或音频文件损坏,建议[重来]试试")
})
.await?
}
-1
View File
@@ -106,7 +106,6 @@ pub fn run() {
} }
tauri::Builder::default() tauri::Builder::default()
.plugin(tauri_plugin_window_state::Builder::default().build())
.plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_opener::init())
-1
View File
@@ -8,7 +8,6 @@
"height": 600, "height": 600,
"minWidth": 800, "minWidth": 800,
"minHeight": 600, "minHeight": 600,
"visible": false,
"decorations": false, "decorations": false,
"theme": "Light" "theme": "Light"
} }
-1
View File
@@ -8,7 +8,6 @@
"height": 600, "height": 600,
"minWidth": 800, "minWidth": 800,
"minHeight": 600, "minHeight": 600,
"visible": false,
"hiddenTitle": true, "hiddenTitle": true,
"titleBarStyle": "Overlay", "titleBarStyle": "Overlay",
"theme": "Light" "theme": "Light"
-1
View File
@@ -8,7 +8,6 @@
"height": 600, "height": 600,
"minWidth": 800, "minWidth": 800,
"minHeight": 600, "minHeight": 600,
"visible": false,
"decorations": false, "decorations": false,
"shadow": true, "shadow": true,
"theme": "Light" "theme": "Light"