fix(media): 视频播放 - 资源视频改走 playback 变体,失败后刷新签名并重试

画布预览、生成回填和项目水合都解析浏览器可播地址;播放失败时绕过展示缓存,等待转码完成后强制刷新 playback 地址。
This commit is contained in:
ddcat666
2026-10-08 10:54:40 +08:00
parent 2b3c6ceeaa
commit b4e5eb22a6
8 changed files with 285 additions and 101 deletions

View File

@@ -120,6 +120,11 @@ export type ResourceAccess = {
originalHeight?: number;
};
export type ResourceAccessFetchOptions = {
/** Bypass both in-memory and persisted display-address caches. */
forceRefresh?: boolean;
};
type ResourceAccessBatchItem = { resourceId: string; access?: ResourceAccess; error?: { msg?: string } };
type CachedResourceAccess = { value: ResourceAccess; expiresAt: number };
const accessCache = new Map<string, CachedResourceAccess>();
@@ -373,12 +378,24 @@ function assertResourceRequestCurrent(generation: number, scope: string) {
}
}
export async function getResourceAccess(storageKey: string | undefined, purpose: ResourceAccessPurpose = "display", variant: ResourceAccessVariant = "original", downloadName = "") {
export async function getResourceAccess(storageKey: string | undefined, purpose: ResourceAccessPurpose = "display", variant: ResourceAccessVariant = "original", downloadName = "", fetchOptions: ResourceAccessFetchOptions = {}) {
const id = resourceIdFromStorageKey(storageKey);
if (!id) throw new Error("当前媒体尚未上传到后端资源存储");
const scope = getActiveUserScope();
const generation = accessGeneration;
const key = `${scope}:${id}:${purpose}:${variant}:${downloadName}`;
const forceRefresh = fetchOptions.forceRefresh === true;
if (forceRefresh) {
accessCache.delete(key);
accessRequests.delete(key);
if (purpose === "display") {
try {
await localForageStorageForScope(scope).removeItem(persistedDisplayAccessKey(id, variant));
} catch {
// Persisted address caching is optional; the network request below remains authoritative.
}
}
}
const cached = accessCache.get(key);
if (cached && cached.expiresAt > Date.now()) return cached.value;
const pending = accessRequests.get(key);