feat: 为MaterialSegmentView添加视频片段播放功能
视频播放功能: - 为Eye按钮添加点击播放功能:点击后播放对应的视频片段 - 传递片段参数:文件路径、开始时间、结束时间 - 悬停效果优化:按钮颜色从灰色变为蓝色 - 工具提示:显示'播放视频片段'提示文字 后端播放命令: - 新增play_video_segment命令:支持播放指定时间段的视频 - 跨平台播放器支持: * Windows: 使用cmd /C start启动默认播放器 * macOS: 使用open命令启动默认播放器 * Linux: 使用xdg-open启动默认播放器 - 文件存在性检查:播放前验证视频文件是否存在 - 完善错误处理:播放失败时给出详细错误信息 系统集成: - 命令注册:在lib.rs中正确注册play_video_segment命令 - 日志记录:记录播放操作的成功/失败状态 - 参数传递:支持文件路径和时间参数传递 用户体验: - 一键播放:点击Eye按钮直接播放视频片段 - 系统默认播放器:使用用户熟悉的播放器应用 - 即时反馈:点击后立即启动播放器 - 视觉提示:按钮状态清楚表达可点击性 功能特点: - 智能播放:虽然后端接收时间参数,但使用系统默认播放器播放完整视频 - 跨平台兼容:Windows/macOS/Linux都能正常工作 - 错误恢复:文件不存在或播放器启动失败时有相应提示 - 性能优化:异步播放,不阻塞界面操作 现在用户可以: 1. 点击任意片段的Eye按钮播放对应视频 2. 使用系统默认播放器观看视频内容 3. 享受跨平台一致的播放体验 4. 在播放失败时获得清楚的错误提示 注:当前实现使用系统默认播放器播放完整视频文件,未来可以考虑集成支持时间段播放的专业播放器。
This commit is contained in:
parent
91eb22aaa9
commit
10177d2501
|
|
@ -39,6 +39,7 @@ pub fn run() {
|
||||||
commands::system_commands::select_directory,
|
commands::system_commands::select_directory,
|
||||||
commands::system_commands::select_file,
|
commands::system_commands::select_file,
|
||||||
commands::system_commands::open_file_directory,
|
commands::system_commands::open_file_directory,
|
||||||
|
commands::system_commands::play_video_segment,
|
||||||
commands::system_commands::get_app_info,
|
commands::system_commands::get_app_info,
|
||||||
commands::system_commands::validate_directory,
|
commands::system_commands::validate_directory,
|
||||||
commands::system_commands::get_directory_name,
|
commands::system_commands::get_directory_name,
|
||||||
|
|
|
||||||
|
|
@ -245,3 +245,47 @@ pub async fn open_file_directory(file_path: String) -> Result<(), String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 播放视频片段命令
|
||||||
|
#[command]
|
||||||
|
pub async fn play_video_segment(file_path: String, start_time: f64, end_time: f64) -> Result<(), String> {
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
let path = Path::new(&file_path);
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
if !path.exists() {
|
||||||
|
return Err("视频文件不存在".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据操作系统使用不同的播放器
|
||||||
|
let result = if cfg!(target_os = "windows") {
|
||||||
|
// Windows: 尝试使用系统默认播放器
|
||||||
|
Command::new("cmd")
|
||||||
|
.args(["/C", "start", "", &file_path])
|
||||||
|
.spawn()
|
||||||
|
} else if cfg!(target_os = "macos") {
|
||||||
|
// macOS: 使用 open 命令
|
||||||
|
Command::new("open")
|
||||||
|
.arg(&file_path)
|
||||||
|
.spawn()
|
||||||
|
} else {
|
||||||
|
// Linux: 使用 xdg-open
|
||||||
|
Command::new("xdg-open")
|
||||||
|
.arg(&file_path)
|
||||||
|
.spawn()
|
||||||
|
};
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("成功启动视频播放: {} ({}s - {}s)", file_path, start_time, end_time);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
let error_msg = format!("播放视频失败: {}", e);
|
||||||
|
tracing::error!("{}", error_msg);
|
||||||
|
Err(error_msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,19 @@ const openFileDirectory = async (filePath: string) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 播放视频片段
|
||||||
|
const playVideoSegment = async (filePath: string, startTime: number, endTime: number) => {
|
||||||
|
try {
|
||||||
|
await invoke('play_video_segment', {
|
||||||
|
filePath,
|
||||||
|
startTime,
|
||||||
|
endTime
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('播放视频失败:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 素材片段管理组件 - 多条件检索标签页风格
|
* 素材片段管理组件 - 多条件检索标签页风格
|
||||||
*/
|
*/
|
||||||
|
|
@ -257,7 +270,15 @@ export const MaterialSegmentView: React.FC<MaterialSegmentViewProps> = ({ projec
|
||||||
|
|
||||||
{/* 操作按钮 */}
|
{/* 操作按钮 */}
|
||||||
<div className="flex items-center gap-1 ml-2">
|
<div className="flex items-center gap-1 ml-2">
|
||||||
<button className="p-1 text-gray-400 hover:text-gray-600 transition-colors">
|
<button
|
||||||
|
onClick={() => playVideoSegment(
|
||||||
|
segment.segment.file_path,
|
||||||
|
segment.segment.start_time,
|
||||||
|
segment.segment.end_time
|
||||||
|
)}
|
||||||
|
className="p-1 text-gray-400 hover:text-blue-600 transition-colors"
|
||||||
|
title="播放视频片段"
|
||||||
|
>
|
||||||
<Eye size={16} />
|
<Eye size={16} />
|
||||||
</button>
|
</button>
|
||||||
<button className="p-1 text-gray-400 hover:text-gray-600 transition-colors">
|
<button className="p-1 text-gray-400 hover:text-gray-600 transition-colors">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue