video-flow-b/api/video-analysis.ts
qikongjian cf5d86c840 feat: Dashboard optimization with custom scrollbar styles and layout improvements
- 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
2025-08-23 23:26:06 +08:00

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
};
}