diff --git a/.claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc b/.claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc deleted file mode 100644 index 39222d1a1a..0000000000 Binary files a/.claude/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-312.pyc and /dev/null differ diff --git a/frontend/app/web-gold/src/views/kling/stores/useDigitalHumanStore.ts b/frontend/app/web-gold/src/views/kling/stores/useDigitalHumanStore.ts index a16035dad7..ca4e77af0a 100644 --- a/frontend/app/web-gold/src/views/kling/stores/useDigitalHumanStore.ts +++ b/frontend/app/web-gold/src/views/kling/stores/useDigitalHumanStore.ts @@ -70,6 +70,9 @@ export const useDigitalHumanStore = defineStore('digitalHuman', () => { /** 视频预览URL */ const videoPreviewUrl = ref('') + /** 素材库视频的签名URL(用于识别API,不用于播放) */ + let signedVideoUrl = '' + /** 错误信息 */ const error = ref('') @@ -278,7 +281,19 @@ export const useDigitalHumanStore = defineStore('digitalHuman', () => { if (urlRes.code !== 0 || !urlRes.data) { throw new Error(urlRes.msg || '获取播放链接失败') } - videoPreviewUrl.value = urlRes.data + // 保存签名URL用于识别API + signedVideoUrl = urlRes.data + + // 下载视频到本地生成blob URL,确保浏览器能正常播放 + videoStep.value = 'uploading' + const response = await fetch(urlRes.data) + if (!response.ok) throw new Error('视频下载失败') + const blob = await response.blob() + // 释放旧的blob URL + if (videoPreviewUrl.value?.startsWith('blob:')) { + URL.revokeObjectURL(videoPreviewUrl.value) + } + videoPreviewUrl.value = URL.createObjectURL(blob) } catch (err: any) { videoStep.value = 'error' error.value = err.message || '获取播放链接失败' @@ -350,8 +365,8 @@ export const useDigitalHumanStore = defineStore('digitalHuman', () => { /** 识别已存在的视频 */ async function recognizeExistingVideo(video: Video): Promise { - // 使用已获取的带签名预览URL - return performFaceRecognition(video.id, videoPreviewUrl.value, false) + // 使用签名URL调用识别API(blob URL不可被外部API访问) + return performFaceRecognition(video.id, signedVideoUrl, false) } /** 执行人脸识别 */ @@ -564,6 +579,7 @@ export const useDigitalHumanStore = defineStore('digitalHuman', () => { videoFile.value = null selectedVideo.value = null videoPreviewUrl.value = '' + signedVideoUrl = '' videoSelectorVisible.value = false resetProcess() diff --git a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/file/service/TikUserFileServiceImpl.java b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/file/service/TikUserFileServiceImpl.java index 52c88f2251..f697fbb712 100644 --- a/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/file/service/TikUserFileServiceImpl.java +++ b/yudao-module-tik/src/main/java/cn/iocoder/yudao/module/tik/file/service/TikUserFileServiceImpl.java @@ -339,9 +339,7 @@ public class TikUserFileServiceImpl implements TikUserFileService { } // 视频播放URL不缓存,每次都生成新的签名URL(使用 filePath 而非 fileUrl,避免域名匹配问题) - // 根据文件扩展名推断 Content-Type,确保浏览器