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_file,
|
||||
commands::system_commands::open_file_directory,
|
||||
commands::system_commands::play_video_segment,
|
||||
commands::system_commands::get_app_info,
|
||||
commands::system_commands::validate_directory,
|
||||
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">
|
||||
<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} />
|
||||
</button>
|
||||
<button className="p-1 text-gray-400 hover:text-gray-600 transition-colors">
|
||||
|
|
|
|||
Loading…
Reference in New Issue