feat: 功能
This commit is contained in:
@@ -2,18 +2,66 @@
|
||||
* 可灵数字人 API
|
||||
*/
|
||||
import request from './http'
|
||||
import { message } from "ant-design-vue"
|
||||
import { MaterialService } from './material'
|
||||
|
||||
/**
|
||||
* 显示加载提示
|
||||
*/
|
||||
const showLoading = (text) => message.loading(text, 0)
|
||||
// ========== 辅助函数 ==========
|
||||
|
||||
/**
|
||||
* 销毁加载提示
|
||||
* 从视频中提取封面(可选操作)
|
||||
*/
|
||||
const hideLoading = () => message.destroy()
|
||||
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({
|
||||
@@ -38,93 +86,46 @@ export function getLipSyncTask(taskId) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 识别已上传的视频
|
||||
*/
|
||||
export async function identifyUploadedVideo(videoFile) {
|
||||
try {
|
||||
showLoading('正在识别视频中的人脸...')
|
||||
const identifyRes = await identifyFace({ video_url: videoFile.fileUrl })
|
||||
hideLoading()
|
||||
|
||||
if (identifyRes.code !== 0) {
|
||||
throw new Error(identifyRes.msg || '识别失败')
|
||||
const urlRes = await MaterialService.getVideoPlayUrl(videoFile.fileId)
|
||||
if (urlRes.code !== 0 || !urlRes.data) {
|
||||
throw new Error(urlRes.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
|
||||
}
|
||||
}
|
||||
const identifyData = await performFaceIdentification(urlRes.data)
|
||||
return buildIdentifyResponse(videoFile.id, urlRes.data, identifyData, false)
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传视频并识别
|
||||
*/
|
||||
export async function uploadAndIdentifyVideo(file) {
|
||||
const coverBase64 = await extractVideoCoverOptional(file)
|
||||
|
||||
try {
|
||||
showLoading('正在提取视频封面...')
|
||||
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) {
|
||||
// 封面提取失败不影响主流程
|
||||
}
|
||||
hideLoading()
|
||||
|
||||
showLoading('正在上传视频...')
|
||||
|
||||
// 使用useUpload Hook(注意:这里需要在组件中使用,这里先用MaterialService)
|
||||
// TODO: 在组件中集成useUpload Hook
|
||||
const uploadRes = await MaterialService.uploadFile(file, 'video', coverBase64, null, null)
|
||||
hideLoading()
|
||||
|
||||
if (uploadRes.code !== 0) {
|
||||
throw new Error(uploadRes.msg || '上传失败')
|
||||
}
|
||||
|
||||
const fileId = uploadRes.data
|
||||
|
||||
showLoading('正在生成播放链接...')
|
||||
const urlRes = await MaterialService.getVideoPlayUrl(fileId)
|
||||
hideLoading()
|
||||
|
||||
if (urlRes.code !== 0) {
|
||||
throw new Error(urlRes.msg || '获取播放链接失败')
|
||||
}
|
||||
|
||||
const videoUrl = urlRes.data
|
||||
|
||||
showLoading('正在识别视频中的人脸...')
|
||||
const identifyRes = await identifyFace({ video_url: videoUrl })
|
||||
hideLoading()
|
||||
|
||||
if (identifyRes.code !== 0) {
|
||||
throw new Error(identifyRes.msg || '识别失败')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
fileId,
|
||||
videoUrl,
|
||||
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
|
||||
}
|
||||
}
|
||||
const identifyData = await performFaceIdentification(urlRes.data)
|
||||
return buildIdentifyResponse(fileId, urlRes.data, identifyData, true)
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user