/** * 可灵数字人 API */ import request from './http' import { MaterialService } from './material' // ========== 辅助函数 ========== /** * 从视频中提取封面(可选操作) */ async function extractVideoCoverOptional(file) { try { const { extractVideoCover } = await import('@/utils/video-cover') const cover = await extractVideoCover(file, { maxWidth: 800, quality: 0.8 }) return cover.base64 } catch { return null } } /** * 执行人脸识别并返回结果 */ async function performFaceIdentification(videoUrl) { const identifyRes = await identifyFace({ video_url: videoUrl }) if (identifyRes.code !== 0) { throw new Error(identifyRes.msg || '识别失败') } const faceData = identifyRes.data.data?.face_data?.[0] return { sessionId: identifyRes.data.sessionId, faceId: faceData?.face_id || null, startTime: faceData?.start_time || 0, endTime: faceData?.end_time || 0 } } /** * 构建标准响应格式 */ function buildIdentifyResponse(fileId, videoUrl, identifyData, isUploadedFile = false) { return { success: true, data: { fileId, videoUrl, sessionId: identifyData.sessionId, faceId: identifyData.faceId, startTime: isUploadedFile ? Math.round(identifyData.startTime * 1000) : identifyData.startTime, endTime: isUploadedFile ? Math.round(identifyData.endTime * 1000) : identifyData.endTime } } } // ========== API 方法 ========== export function identifyFace(data) { return request({ url: '/webApi/api/tik/kling/identify-face', method: 'post', data }) } export function createLipSyncTask(data) { return request({ url: '/webApi/api/tik/kling/task/create', method: 'post', data }) } export function getLipSyncTask(taskId) { return request({ url: `/webApi/api/tik/kling/lip-sync/${taskId}`, method: 'get' }) } /** * 识别已上传的视频 */ export async function identifyUploadedVideo(videoFile) { const urlRes = await MaterialService.getVideoPlayUrl(videoFile.fileId) if (urlRes.code !== 0 || !urlRes.data) { throw new Error(urlRes.msg || '获取播放链接失败') } const identifyData = await performFaceIdentification(urlRes.data) return buildIdentifyResponse(videoFile.id, urlRes.data, identifyData, false) } /** * 上传视频并识别 */ export async function uploadAndIdentifyVideo(file) { const coverBase64 = await extractVideoCoverOptional(file) const uploadRes = await MaterialService.uploadFile(file, 'digital_human', coverBase64, null, null) if (uploadRes.code !== 0) { throw new Error(uploadRes.msg || '上传失败') } const fileId = uploadRes.data const urlRes = await MaterialService.getVideoPlayUrl(fileId) if (urlRes.code !== 0) { throw new Error(urlRes.msg || '获取播放链接失败') } const identifyData = await performFaceIdentification(urlRes.data) return buildIdentifyResponse(fileId, urlRes.data, identifyData, true) }