forked from 77media/video-flow
- Added custom scrollbar styles for better UX - Optimized dashboard layout components - Enhanced network timeline functionality - Cleaned up redundant dashboard components - Improved API integration for video flow
134 lines
3.2 KiB
TypeScript
134 lines
3.2 KiB
TypeScript
// 视频分析API接口
|
|
|
|
export interface VideoAnalysisResponse {
|
|
code: number;
|
|
message: string;
|
|
data: {
|
|
project_id: string;
|
|
total_videos: number;
|
|
analyzed_videos: number;
|
|
pending_count: number;
|
|
failed_count: number;
|
|
completion_rate: number;
|
|
analyzed_list: string[];
|
|
};
|
|
successful: boolean;
|
|
}
|
|
|
|
export interface VideoAnalysisRequest {
|
|
project_id: string;
|
|
}
|
|
|
|
/**
|
|
* 获取视频分析进度
|
|
* @param params 请求参数
|
|
* @returns 视频分析进度数据
|
|
*/
|
|
export async function getVideoAnalysisProgress(params: VideoAnalysisRequest): Promise<VideoAnalysisResponse> {
|
|
try {
|
|
const response = await fetch('https://77.smartvideo.py.qikongjian.com/edit-plan/analyzeProgress', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(params)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
return data;
|
|
} catch (error) {
|
|
console.error('获取视频分析进度失败:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 计算分析进度百分比
|
|
* @param analyzed 已分析数量
|
|
* @param total 总数量
|
|
* @returns 进度百分比
|
|
*/
|
|
export function calculateProgress(analyzed: number, total: number): number {
|
|
if (total === 0) return 0;
|
|
return Math.round((analyzed / total) * 100);
|
|
}
|
|
|
|
/**
|
|
* 从视频URL中提取文件名
|
|
* @param url 视频URL
|
|
* @returns 文件名
|
|
*/
|
|
export function extractVideoFileName(url: string): string {
|
|
try {
|
|
const parts = url.split('/');
|
|
const filename = parts[parts.length - 1];
|
|
|
|
// 提取FJ开头的部分作为视频名称
|
|
const match = filename.match(/^(FJ\d+)/);
|
|
if (match) {
|
|
return match[1];
|
|
}
|
|
|
|
// 如果是换脸视频,提取时间戳部分
|
|
if (filename.includes('facefusion_output')) {
|
|
const timestampMatch = filename.match(/(\d+)_facefusion_output/);
|
|
if (timestampMatch) {
|
|
return `换脸视频-${timestampMatch[1]}`;
|
|
}
|
|
}
|
|
|
|
// 默认返回文件名(去掉扩展名)
|
|
return filename.split('.')[0];
|
|
} catch (error) {
|
|
return '未知视频';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 判断视频类型
|
|
* @param url 视频URL
|
|
* @returns 视频类型
|
|
*/
|
|
export function getVideoType(url: string): 'original' | 'faceswap' {
|
|
return url.includes('facefusion_output') ? 'faceswap' : 'original';
|
|
}
|
|
|
|
/**
|
|
* 格式化视频分析数据
|
|
* @param data 原始数据
|
|
* @returns 格式化后的数据
|
|
*/
|
|
export function formatAnalysisData(data: VideoAnalysisResponse['data']) {
|
|
const analyzedVideos = data.analyzed_list.map((url, index) => ({
|
|
id: `video-${index}`,
|
|
url,
|
|
name: extractVideoFileName(url),
|
|
type: getVideoType(url),
|
|
status: 'analyzed' as const,
|
|
analyzedAt: new Date().toISOString()
|
|
}));
|
|
|
|
const pendingVideos = Array.from(
|
|
{ length: data.pending_count },
|
|
(_, index) => ({
|
|
id: `pending-${index}`,
|
|
url: '',
|
|
name: `待分析视频 ${index + 1}`,
|
|
type: 'original' as const,
|
|
status: 'pending' as const,
|
|
analyzedAt: ''
|
|
})
|
|
);
|
|
|
|
return {
|
|
...data,
|
|
analyzedVideos,
|
|
pendingVideos,
|
|
totalProgress: data.completion_rate
|
|
};
|
|
}
|