优化
This commit is contained in:
@@ -2,51 +2,10 @@
|
||||
* 可灵数字人 API
|
||||
*/
|
||||
import request from './http'
|
||||
import { MaterialService } from './material'
|
||||
|
||||
// ========== 辅助函数 ==========
|
||||
|
||||
/**
|
||||
* 执行人脸识别并返回结果
|
||||
* 人脸识别
|
||||
*/
|
||||
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',
|
||||
@@ -55,6 +14,9 @@ export function identifyFace(data) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建口型同步任务
|
||||
*/
|
||||
export function createLipSyncTask(data) {
|
||||
return request({
|
||||
url: '/webApi/api/tik/kling/task/create',
|
||||
@@ -63,43 +25,12 @@ export function createLipSyncTask(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 uploadRes = await MaterialService.uploadFile(file, 'digital_human', 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)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,38 +9,6 @@ import { API_BASE } from '@gold/config/api'
|
||||
// 使用 webApi 前缀,确保能够被代理
|
||||
const BASE_URL = `${API_BASE.APP_TIK}/file`
|
||||
|
||||
/**
|
||||
* 获取视频时长(秒)
|
||||
* @param {File} file - 视频文件对象
|
||||
* @returns {Promise<number>} 时长(秒)
|
||||
*/
|
||||
function getVideoDuration(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 只处理视频文件
|
||||
if (!file.type.startsWith('video/')) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const video = document.createElement('video');
|
||||
video.preload = 'metadata';
|
||||
video.muted = true; // 静音,避免浏览器阻止自动播放
|
||||
|
||||
video.onloadedmetadata = function() {
|
||||
const duration = Math.round(video.duration);
|
||||
URL.revokeObjectURL(video.src);
|
||||
resolve(duration);
|
||||
};
|
||||
|
||||
video.onerror = function() {
|
||||
URL.revokeObjectURL(video.src);
|
||||
resolve(60);
|
||||
};
|
||||
|
||||
video.src = URL.createObjectURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 素材库 API 服务
|
||||
*/
|
||||
@@ -61,36 +29,6 @@ export const MaterialService = {
|
||||
return http.get(`${BASE_URL}/page`, { params })
|
||||
},
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
* @param {File} file - 文件对象
|
||||
* @param {string} fileCategory - 文件分类(video/generate/audio/mix/voice)
|
||||
* @param {number} duration - 视频时长(秒,可选,自动获取)
|
||||
* @param {number} groupId - 分组编号(可选)
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async uploadFile(file, fileCategory, duration = null, groupId = null) {
|
||||
if (duration === null && file.type.startsWith('video/')) {
|
||||
duration = await getVideoDuration(file);
|
||||
}
|
||||
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
formData.append('fileCategory', fileCategory)
|
||||
|
||||
if (duration !== null) {
|
||||
formData.append('duration', duration.toString());
|
||||
}
|
||||
|
||||
if (groupId !== null) {
|
||||
formData.append('groupId', groupId.toString())
|
||||
}
|
||||
|
||||
return http.post(`${BASE_URL}/upload`, formData, {
|
||||
timeout: 30 * 60 * 1000
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取预签名URL(直传模式)
|
||||
* @param {Object} params - 请求参数
|
||||
|
||||
Reference in New Issue
Block a user