2025-12-01 22:27:50 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 可灵数字人 API
|
|
|
|
|
|
*/
|
|
|
|
|
|
import request from './http'
|
|
|
|
|
|
import { message } from "ant-design-vue"
|
|
|
|
|
|
import { MaterialService } from './material'
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-12-28 00:19:17 +08:00
|
|
|
|
* 显示加载提示
|
2025-12-01 22:27:50 +08:00
|
|
|
|
*/
|
2025-12-28 00:19:17 +08:00
|
|
|
|
const showLoading = (text) => message.loading(text, 0)
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 销毁加载提示
|
|
|
|
|
|
*/
|
|
|
|
|
|
const hideLoading = () => message.destroy()
|
|
|
|
|
|
|
2025-12-01 22:27:50 +08:00
|
|
|
|
export function identifyFace(data) {
|
|
|
|
|
|
return request({
|
|
|
|
|
|
url: '/webApi/api/tik/kling/identify-face',
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function createLipSyncTask(data) {
|
|
|
|
|
|
return request({
|
2025-12-02 01:55:57 +08:00
|
|
|
|
url: '/webApi/api/tik/kling/task/create',
|
2025-12-01 22:27:50 +08:00
|
|
|
|
method: 'post',
|
|
|
|
|
|
data
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function getLipSyncTask(taskId) {
|
|
|
|
|
|
return request({
|
|
|
|
|
|
url: `/webApi/api/tik/kling/lip-sync/${taskId}`,
|
|
|
|
|
|
method: 'get'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-28 00:19:17 +08:00
|
|
|
|
export async function identifyUploadedVideo(videoFile) {
|
2025-12-01 22:27:50 +08:00
|
|
|
|
try {
|
2025-12-28 00:19:17 +08:00
|
|
|
|
showLoading('正在识别视频中的人脸...')
|
|
|
|
|
|
const identifyRes = await identifyFace({ video_url: videoFile.fileUrl })
|
|
|
|
|
|
hideLoading()
|
|
|
|
|
|
|
|
|
|
|
|
if (identifyRes.code !== 0) {
|
|
|
|
|
|
throw new Error(identifyRes.msg || '识别失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
fileId: videoFile.id,
|
|
|
|
|
|
videoUrl: videoFile.fileUrl,
|
|
|
|
|
|
sessionId: identifyRes.data.sessionId,
|
|
|
|
|
|
faceId: identifyRes.data.data.face_data[0].face_id || null,
|
|
|
|
|
|
startTime: identifyRes.data.data.face_data[0].start_time || 0,
|
|
|
|
|
|
endTime: identifyRes.data.data.face_data[0].end_time || 0
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
hideLoading()
|
|
|
|
|
|
throw error
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function uploadAndIdentifyVideo(file) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
showLoading('正在提取视频封面...')
|
2025-12-01 22:27:50 +08:00
|
|
|
|
let coverBase64 = null
|
|
|
|
|
|
try {
|
|
|
|
|
|
const { extractVideoCover } = await import('@/utils/video-cover')
|
|
|
|
|
|
const cover = await extractVideoCover(file, {
|
|
|
|
|
|
maxWidth: 800,
|
|
|
|
|
|
quality: 0.8
|
|
|
|
|
|
})
|
|
|
|
|
|
coverBase64 = cover.base64
|
|
|
|
|
|
} catch (coverError) {
|
|
|
|
|
|
// 封面提取失败不影响主流程
|
|
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
hideLoading()
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
2025-12-28 00:19:17 +08:00
|
|
|
|
showLoading('正在上传视频...')
|
2026-01-17 14:43:42 +08:00
|
|
|
|
|
|
|
|
|
|
// 使用useUpload Hook(注意:这里需要在组件中使用,这里先用MaterialService)
|
|
|
|
|
|
// TODO: 在组件中集成useUpload Hook
|
|
|
|
|
|
const uploadRes = await MaterialService.uploadFile(file, 'video', coverBase64, null, null)
|
2025-12-28 00:19:17 +08:00
|
|
|
|
hideLoading()
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
|
|
|
|
|
if (uploadRes.code !== 0) {
|
|
|
|
|
|
throw new Error(uploadRes.msg || '上传失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const fileId = uploadRes.data
|
|
|
|
|
|
|
2025-12-28 00:19:17 +08:00
|
|
|
|
showLoading('正在生成播放链接...')
|
2025-12-01 22:27:50 +08:00
|
|
|
|
const urlRes = await MaterialService.getVideoPlayUrl(fileId)
|
2025-12-28 00:19:17 +08:00
|
|
|
|
hideLoading()
|
2025-12-01 22:27:50 +08:00
|
|
|
|
|
|
|
|
|
|
if (urlRes.code !== 0) {
|
|
|
|
|
|
throw new Error(urlRes.msg || '获取播放链接失败')
|
|
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
|
2025-12-01 22:27:50 +08:00
|
|
|
|
const videoUrl = urlRes.data
|
|
|
|
|
|
|
2025-12-28 00:19:17 +08:00
|
|
|
|
showLoading('正在识别视频中的人脸...')
|
2025-12-01 22:27:50 +08:00
|
|
|
|
const identifyRes = await identifyFace({ video_url: videoUrl })
|
2025-12-28 00:19:17 +08:00
|
|
|
|
hideLoading()
|
|
|
|
|
|
|
2025-12-01 22:27:50 +08:00
|
|
|
|
if (identifyRes.code !== 0) {
|
|
|
|
|
|
throw new Error(identifyRes.msg || '识别失败')
|
|
|
|
|
|
}
|
2025-12-28 00:19:17 +08:00
|
|
|
|
|
2025-12-01 22:27:50 +08:00
|
|
|
|
return {
|
|
|
|
|
|
success: true,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
fileId,
|
|
|
|
|
|
videoUrl,
|
|
|
|
|
|
sessionId: identifyRes.data.sessionId,
|
2025-12-02 01:55:57 +08:00
|
|
|
|
faceId: identifyRes.data.data.face_data[0].face_id || null,
|
|
|
|
|
|
startTime: identifyRes.data.data.face_data[0].start_time || 0,
|
|
|
|
|
|
endTime: identifyRes.data.data.face_data[0].end_time || 0
|
2025-12-01 22:27:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-12-28 00:19:17 +08:00
|
|
|
|
hideLoading()
|
2025-12-01 22:27:50 +08:00
|
|
|
|
throw error
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|