Files
Genarrative/src/hooks/useResolvedAssetReadUrl.ts
T
kdletters 10dcc2b403 修复图片画布素材与宣发尺寸问题
修复画布上传素材持久化回填和项目重进资源元数据恢复

修复图片、音频、视频图层的私有资源换签与视频裸路径回退

修复宣发素材切换模型后卡片尺寸变成1024x1024的问题

修复音视频预览、媒体导出格式、音频默认提示词和前端去背边界

修复角色动作生成在编辑器路径缺少ffprobe时的已知时长兜底

补充图片画布、资源换签、宣发尺寸、媒体导出和chromaKey回归测试

更新图片画布编辑器技术文档
2026-06-19 23:16:59 +08:00

101 lines
2.5 KiB
TypeScript

import { useEffect, useState } from 'react';
import {
getSignedAssetReadUrl,
resolveAssetReadUrl,
shouldResolveAssetReadUrl,
} from '../services/assetReadUrlService';
type UseResolvedAssetReadUrlOptions = {
enabled?: boolean;
expireSeconds?: number;
objectKey?: string | null;
refreshKey?: string | number | null;
};
export function useResolvedAssetReadUrl(
source: string | null | undefined,
options: UseResolvedAssetReadUrlOptions = {},
) {
const enabled = options.enabled !== false;
const normalizedSource = source?.trim() ?? '';
const normalizedObjectKey = options.objectKey?.trim() ?? '';
const shouldResolve =
enabled &&
(Boolean(normalizedObjectKey) ||
shouldResolveAssetReadUrl(normalizedSource));
const [resolvedUrl, setResolvedUrl] = useState(
shouldResolve ? '' : normalizedSource,
);
const [isResolving, setIsResolving] = useState(shouldResolve);
useEffect(() => {
if (!normalizedSource && !normalizedObjectKey) {
setResolvedUrl('');
setIsResolving(false);
return;
}
if (!shouldResolve) {
setResolvedUrl(normalizedSource);
setIsResolving(false);
return;
}
let cancelled = false;
// 生成资源通常是 OSS 私有对象;签名 URL 未就绪前不能把裸 generated 路径交给 img 触发无鉴权 GET。
setResolvedUrl('');
setIsResolving(true);
const resolvePromise = normalizedObjectKey
? getSignedAssetReadUrl(
{
objectKey: normalizedObjectKey,
expireSeconds: options.expireSeconds,
},
undefined,
{
cacheVersion: options.refreshKey,
},
)
: resolveAssetReadUrl(normalizedSource, {
expireSeconds: options.expireSeconds,
refreshKey: options.refreshKey,
});
void resolvePromise
.then((nextUrl) => {
if (!cancelled) {
setResolvedUrl(nextUrl);
}
})
.catch(() => {
if (!cancelled) {
// 签名失败时保持空 src,避免继续请求无签名的私有对象兼容路径。
setResolvedUrl('');
}
})
.finally(() => {
if (!cancelled) {
setIsResolving(false);
}
});
return () => {
cancelled = true;
};
}, [
normalizedSource,
normalizedObjectKey,
options.expireSeconds,
options.refreshKey,
shouldResolve,
]);
return {
resolvedUrl,
isResolving,
shouldResolve,
};
}