Update TVAI functionality across desktop app and cargo modules
This commit is contained in:
parent
0a742f1e6b
commit
d0845c3933
|
|
@ -198,6 +198,7 @@ pub async fn quick_upscale_video_command(
|
||||||
input_path: String,
|
input_path: String,
|
||||||
output_path: String,
|
output_path: String,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
|
model: Option<String>,
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
let task_id = Uuid::new_v4().to_string();
|
let task_id = Uuid::new_v4().to_string();
|
||||||
|
|
||||||
|
|
@ -242,12 +243,38 @@ pub async fn quick_upscale_video_command(
|
||||||
app_handle_clone.emit("tvai_task_updated", &task_id_clone).unwrap();
|
app_handle_clone.emit("tvai_task_updated", &task_id_clone).unwrap();
|
||||||
|
|
||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
|
|
||||||
|
// 解析模型参数
|
||||||
|
let upscale_model = if let Some(model_str) = model {
|
||||||
|
match model_str.as_str() {
|
||||||
|
"aaa-9" => Some(UpscaleModel::Aaa9),
|
||||||
|
"ahq-12" => Some(UpscaleModel::Ahq12),
|
||||||
|
"alq-13" => Some(UpscaleModel::Alq13),
|
||||||
|
"alqs-2" => Some(UpscaleModel::Alqs2),
|
||||||
|
"amq-13" => Some(UpscaleModel::Amq13),
|
||||||
|
"amqs-2" => Some(UpscaleModel::Amqs2),
|
||||||
|
"ghq-5" => Some(UpscaleModel::Ghq5),
|
||||||
|
"iris-2" => Some(UpscaleModel::Iris2),
|
||||||
|
"iris-3" => Some(UpscaleModel::Iris3),
|
||||||
|
"nyx-3" => Some(UpscaleModel::Nyx3),
|
||||||
|
"prob-4" => Some(UpscaleModel::Prob4),
|
||||||
|
"thf-4" => Some(UpscaleModel::Thf4),
|
||||||
|
"thd-3" => Some(UpscaleModel::Thd3),
|
||||||
|
"thm-2" => Some(UpscaleModel::Thm2),
|
||||||
|
"rhea-1" => Some(UpscaleModel::Rhea1),
|
||||||
|
"rxl-1" => Some(UpscaleModel::Rxl1),
|
||||||
|
_ => None, // 使用默认模型
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None // 使用默认模型
|
||||||
|
};
|
||||||
|
|
||||||
// 执行处理
|
// 执行处理
|
||||||
let result = quick_upscale_video(
|
let result = tvai::quick_upscale_video_with_model(
|
||||||
Path::new(&input_path),
|
Path::new(&input_path),
|
||||||
Path::new(&output_path),
|
Path::new(&output_path),
|
||||||
scale_factor,
|
scale_factor,
|
||||||
|
upscale_model,
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
let processing_time = start_time.elapsed();
|
let processing_time = start_time.elapsed();
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ export function TvaiExample() {
|
||||||
|
|
||||||
// 高级参数
|
// 高级参数
|
||||||
const [selectedModel, setSelectedModel] = useState<UpscaleModel>('iris-3');
|
const [selectedModel, setSelectedModel] = useState<UpscaleModel>('iris-3');
|
||||||
|
const [selectedInterpolationModel, setSelectedInterpolationModel] = useState<'apo-8' | 'apf-1' | 'chr-2' | 'chf-3'>('apo-8');
|
||||||
const [compression, setCompression] = useState(0.0);
|
const [compression, setCompression] = useState(0.0);
|
||||||
const [blend, setBlend] = useState(0.0);
|
const [blend, setBlend] = useState(0.0);
|
||||||
|
|
||||||
|
|
@ -112,7 +113,7 @@ export function TvaiExample() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (processingType === 'video') {
|
if (processingType === 'video') {
|
||||||
await tvaiService.quickUpscaleVideo(inputPath, outputPath, scaleFactor);
|
await tvaiService.quickUpscaleVideo(inputPath, outputPath, scaleFactor, selectedModel);
|
||||||
} else if (processingType === 'interpolation') {
|
} else if (processingType === 'interpolation') {
|
||||||
// 插帧处理 - 需要先获取视频信息来确定帧率
|
// 插帧处理 - 需要先获取视频信息来确定帧率
|
||||||
try {
|
try {
|
||||||
|
|
@ -396,7 +397,7 @@ export function TvaiExample() {
|
||||||
key={preset.key}
|
key={preset.key}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedPreset(preset.key);
|
setSelectedPreset(preset.key);
|
||||||
setSelectedModel(preset.model as UpscaleModel);
|
setSelectedInterpolationModel(preset.model as 'apo-8' | 'apf-1' | 'chr-2' | 'chf-3');
|
||||||
}}
|
}}
|
||||||
className={`p-3 rounded-lg border text-sm transition-all ${
|
className={`p-3 rounded-lg border text-sm transition-all ${
|
||||||
selectedPreset === preset.key
|
selectedPreset === preset.key
|
||||||
|
|
@ -463,8 +464,14 @@ export function TvaiExample() {
|
||||||
{processingType === 'interpolation' ? '插帧模型' : 'AI 放大模型'}
|
{processingType === 'interpolation' ? '插帧模型' : 'AI 放大模型'}
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={selectedModel}
|
value={processingType === 'interpolation' ? selectedInterpolationModel : selectedModel}
|
||||||
onChange={(e) => setSelectedModel(e.target.value as UpscaleModel)}
|
onChange={(e) => {
|
||||||
|
if (processingType === 'interpolation') {
|
||||||
|
setSelectedInterpolationModel(e.target.value as 'apo-8' | 'apf-1' | 'chr-2' | 'chf-3');
|
||||||
|
} else {
|
||||||
|
setSelectedModel(e.target.value as UpscaleModel);
|
||||||
|
}
|
||||||
|
}}
|
||||||
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
>
|
>
|
||||||
{processingType === 'interpolation' ? (
|
{processingType === 'interpolation' ? (
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export interface UseTvaiReturn {
|
||||||
* TVAI 任务管理 Hook
|
* TVAI 任务管理 Hook
|
||||||
*/
|
*/
|
||||||
export function useTvai(options: UseTvaiOptions = {}): UseTvaiReturn {
|
export function useTvai(options: UseTvaiOptions = {}): UseTvaiReturn {
|
||||||
const { autoRefresh = true, refreshInterval = 5000 } = options;
|
const { autoRefresh = true, refreshInterval = 10000 } = options; // 增加轮询间隔,主要依赖事件推送
|
||||||
|
|
||||||
const [tasks, setTasks] = useState<TvaiTask[]>([]);
|
const [tasks, setTasks] = useState<TvaiTask[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
@ -95,16 +95,38 @@ export function useTvai(options: UseTvaiOptions = {}): UseTvaiReturn {
|
||||||
return tasks.filter(task => task.status === 'Failed').length;
|
return tasks.filter(task => task.status === 'Failed').length;
|
||||||
}, [tasks]);
|
}, [tasks]);
|
||||||
|
|
||||||
// 处理任务事件
|
// 处理任务事件 - 实时推送机制
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleTaskCreated = (taskId: string) => {
|
const handleTaskCreated = async (taskId: string) => {
|
||||||
console.log('Task created:', taskId);
|
console.log('Task created (real-time):', taskId);
|
||||||
refreshTasks();
|
// 立即刷新任务列表以获取新任务
|
||||||
|
await refreshTasks();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTaskUpdated = (taskId: string) => {
|
const handleTaskUpdated = async (taskId: string) => {
|
||||||
console.log('Task updated:', taskId);
|
console.log('Task updated (real-time):', taskId);
|
||||||
refreshTasks();
|
// 获取单个任务的最新状态并更新
|
||||||
|
try {
|
||||||
|
const updatedTask = await tvaiService.getTvaiTaskStatus(taskId);
|
||||||
|
if (updatedTask) {
|
||||||
|
setTasks(prevTasks => {
|
||||||
|
const taskIndex = prevTasks.findIndex(task => task.id === taskId);
|
||||||
|
if (taskIndex >= 0) {
|
||||||
|
// 更新现有任务
|
||||||
|
const newTasks = [...prevTasks];
|
||||||
|
newTasks[taskIndex] = updatedTask;
|
||||||
|
return newTasks;
|
||||||
|
} else {
|
||||||
|
// 添加新任务(如果不存在)
|
||||||
|
return [...prevTasks, updatedTask];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update task:', error);
|
||||||
|
// 如果单个任务更新失败,回退到全量刷新
|
||||||
|
await refreshTasks();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加事件监听器
|
// 添加事件监听器
|
||||||
|
|
@ -118,13 +140,23 @@ export function useTvai(options: UseTvaiOptions = {}): UseTvaiReturn {
|
||||||
};
|
};
|
||||||
}, [refreshTasks]);
|
}, [refreshTasks]);
|
||||||
|
|
||||||
// 自动刷新
|
// 智能轮询 - 只在有运行中的任务时才轮询
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!autoRefresh) return;
|
if (!autoRefresh) return;
|
||||||
|
|
||||||
const interval = setInterval(refreshTasks, refreshInterval);
|
const hasRunningTasks = tasks.some(task =>
|
||||||
|
task.status === 'Pending' || task.status === 'Processing'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasRunningTasks) return; // 没有运行中的任务时不进行轮询
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
console.log('Polling for task updates (fallback mechanism)');
|
||||||
|
refreshTasks();
|
||||||
|
}, refreshInterval);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [autoRefresh, refreshInterval, refreshTasks]);
|
}, [autoRefresh, refreshInterval, refreshTasks, tasks]);
|
||||||
|
|
||||||
// 初始加载
|
// 初始加载
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -120,12 +120,14 @@ export class TvaiServiceImpl implements TvaiService {
|
||||||
async quickUpscaleVideo(
|
async quickUpscaleVideo(
|
||||||
inputPath: string,
|
inputPath: string,
|
||||||
outputPath: string,
|
outputPath: string,
|
||||||
scaleFactor: number
|
scaleFactor: number,
|
||||||
|
model?: UpscaleModel
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return await invoke('quick_upscale_video_command', {
|
return await invoke('quick_upscale_video_command', {
|
||||||
inputPath,
|
inputPath,
|
||||||
outputPath,
|
outputPath,
|
||||||
scaleFactor,
|
scaleFactor,
|
||||||
|
model,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,9 +170,10 @@ export interface TvaiService {
|
||||||
|
|
||||||
// 快速处理
|
// 快速处理
|
||||||
quickUpscaleVideo(
|
quickUpscaleVideo(
|
||||||
inputPath: string,
|
inputPath: string,
|
||||||
outputPath: string,
|
outputPath: string,
|
||||||
scaleFactor: number
|
scaleFactor: number,
|
||||||
|
model?: UpscaleModel
|
||||||
): Promise<string>;
|
): Promise<string>;
|
||||||
|
|
||||||
quickUpscaleImage(
|
quickUpscaleImage(
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ pub type Result<T> = std::result::Result<T, TvaiError>;
|
||||||
|
|
||||||
// Quick processing functions
|
// Quick processing functions
|
||||||
pub use video::quick_upscale_video;
|
pub use video::quick_upscale_video;
|
||||||
|
pub use video::quick_upscale_video_with_model;
|
||||||
pub use video::quick_interpolate_video;
|
pub use video::quick_interpolate_video;
|
||||||
pub use image::quick_upscale_image;
|
pub use image::quick_upscale_image;
|
||||||
pub use video::auto_enhance_video;
|
pub use video::auto_enhance_video;
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,16 @@ pub async fn quick_upscale_video(
|
||||||
input: &Path,
|
input: &Path,
|
||||||
output: &Path,
|
output: &Path,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
|
) -> Result<ProcessResult, TvaiError> {
|
||||||
|
quick_upscale_video_with_model(input, output, scale, None).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Quick video upscaling function with model selection
|
||||||
|
pub async fn quick_upscale_video_with_model(
|
||||||
|
input: &Path,
|
||||||
|
output: &Path,
|
||||||
|
scale: f32,
|
||||||
|
model: Option<UpscaleModel>,
|
||||||
) -> Result<ProcessResult, TvaiError> {
|
) -> Result<ProcessResult, TvaiError> {
|
||||||
// Detect Topaz installation
|
// Detect Topaz installation
|
||||||
let topaz_path = crate::utils::detect_topaz_installation()
|
let topaz_path = crate::utils::detect_topaz_installation()
|
||||||
|
|
@ -387,10 +397,10 @@ pub async fn quick_upscale_video(
|
||||||
// Create processor
|
// Create processor
|
||||||
let mut processor = TvaiProcessor::new(config)?;
|
let mut processor = TvaiProcessor::new(config)?;
|
||||||
|
|
||||||
// Create default upscaling parameters
|
// Create upscaling parameters with specified or default model
|
||||||
let params = VideoUpscaleParams {
|
let params = VideoUpscaleParams {
|
||||||
scale_factor: scale,
|
scale_factor: scale,
|
||||||
model: crate::config::UpscaleModel::Iris3, // Best general purpose model
|
model: model.unwrap_or(crate::config::UpscaleModel::Iris3), // Use specified model or default to Iris3
|
||||||
compression: 0.0,
|
compression: 0.0,
|
||||||
blend: 0.0,
|
blend: 0.0,
|
||||||
quality_preset: crate::config::QualityPreset::HighQuality,
|
quality_preset: crate::config::QualityPreset::HighQuality,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue