Files
AIGC/demo/frontend/src/api/imageToVideo.js
AIGC Developer 1e71ae6a26 feat: 系统优化和功能完善
主要更新:
- 调整并发配置为50人(数据库连接池30,Tomcat线程150,异步线程池5/20)
- 实现无界阻塞队列(LinkedBlockingQueue)任务处理
- 实现分镜视频保存功能(保存到uploads目录)
- 统一管理页面导航栏和右上角样式
- 添加日活用户统计功能
- 优化视频拼接和保存逻辑
- 添加部署文档和快速部署指南
- 更新.gitignore排除敏感配置文件
2025-11-07 19:09:50 +08:00

190 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import request from './request'
/**
* 图生视频API服务
*/
export const imageToVideoApi = {
/**
* 创建图生视频任务
* @param {Object} params - 任务参数
* @param {File} params.firstFrame - 首帧图片
* @param {File} params.lastFrame - 尾帧图片(可选)
* @param {string} params.prompt - 描述文字
* @param {string} params.aspectRatio - 视频比例
* @param {number} params.duration - 视频时长
* @param {boolean} params.hdMode - 是否高清模式
* @returns {Promise} API响应
*/
createTask(params) {
// 参数验证
if (!params) {
throw new Error('参数不能为空')
}
if (!params.firstFrame) {
throw new Error('首帧图片不能为空')
}
if (!params.prompt || params.prompt.trim() === '') {
throw new Error('描述文字不能为空')
}
if (!params.aspectRatio) {
throw new Error('视频比例不能为空')
}
if (!params.duration || params.duration < 1 || params.duration > 60) {
throw new Error('视频时长必须在1-60秒之间')
}
const formData = new FormData()
// 添加必填参数
formData.append('firstFrame', params.firstFrame)
formData.append('prompt', params.prompt.trim())
formData.append('aspectRatio', params.aspectRatio)
formData.append('duration', params.duration.toString())
formData.append('hdMode', params.hdMode.toString())
// 添加可选参数
if (params.lastFrame) {
formData.append('lastFrame', params.lastFrame)
}
return request({
url: '/image-to-video/create',
method: 'POST',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
})
},
/**
* 获取用户任务列表
* @param {number} page - 页码
* @param {number} size - 每页数量
* @returns {Promise} API响应
*/
getTasks(page = 0, size = 10) {
return request({
url: '/image-to-video/tasks',
method: 'GET',
params: { page, size }
})
},
/**
* 获取任务详情
* @param {string} taskId - 任务ID
* @returns {Promise} API响应
*/
getTaskDetail(taskId) {
return request({
url: `/image-to-video/tasks/${taskId}`,
method: 'GET'
})
},
/**
* 获取任务状态
* @param {string} taskId - 任务ID
* @returns {Promise} API响应
*/
getTaskStatus(taskId) {
return request({
url: `/image-to-video/tasks/${taskId}/status`,
method: 'GET'
})
},
/**
* 轮询任务状态
* @param {string} taskId - 任务ID
* @param {Function} onProgress - 进度回调
* @param {Function} onComplete - 完成回调
* @param {Function} onError - 错误回调
* @returns {Function} 停止轮询的函数
*/
pollTaskStatus(taskId, onProgress, onComplete, onError) {
let isPolling = true
let pollCount = 0
const maxPolls = 30 // 最大轮询次数1小时每2分钟一次
const poll = async () => {
if (!isPolling || pollCount >= maxPolls) {
if (pollCount >= maxPolls) {
onError && onError(new Error('任务超时'))
}
return
}
try {
const response = await request({
url: `/image-to-video/tasks/${taskId}/status`,
method: 'GET'
})
// 检查响应是否有效
if (!response || !response.data || !response.data.success) {
onError && onError(new Error('获取任务状态失败'))
isPolling = false
return
}
const taskData = response.data.data
// 检查taskData是否有效
if (!taskData || !taskData.status) {
onError && onError(new Error('无效的任务数据'))
isPolling = false
return
}
if (taskData.status === 'COMPLETED') {
onComplete && onComplete(taskData)
isPolling = false
return
}
if (taskData.status === 'FAILED' || taskData.status === 'CANCELLED') {
console.error('任务失败:', {
taskId: taskId,
status: taskData.status,
errorMessage: taskData.errorMessage,
pollCount: pollCount
})
onError && onError(new Error(taskData.errorMessage || '任务失败'))
isPolling = false
return
}
// 调用进度回调
onProgress && onProgress({
status: taskData.status,
progress: taskData.progress || 0,
resultUrl: taskData.resultUrl
})
pollCount++
// 继续轮询
setTimeout(poll, 120000) // 每2分钟轮询一次
} catch (error) {
console.error('轮询任务状态失败:', error)
onError && onError(error)
isPolling = false
}
}
// 开始轮询
poll()
// 返回停止轮询的函数
return () => {
isPolling = false
}
}
}
export default imageToVideoApi