gongxiangp2/lib/video-material-types.ts
chenpei 7326e273e1 fix: harden media upload and release safety
Protect upload cleanup and atomic completion paths, add durable media worker leases and brand asset validation, and introduce verified migration/bootstrap/deployment gates.
2026-08-12 18:04:08 +08:00

90 lines
2.9 KiB
TypeScript

export const TAOXI_MAIN_VIDEO_TYPE = '淘系-主图视频'
export const TAOXI_GUANGGUANG_VIDEO_TYPE = '淘系-逛逛视频'
export const DOUYIN_QIANCHUAN_VIDEO_TYPE = '抖音-千川素材'
export const DOUYIN_ACCOUNT_MAINTENANCE_VIDEO_TYPE = '抖音-账号维护'
export const INSTALL_VIDEO_TYPE = '安装视频'
const MATERIAL_TYPE_ALIASES: Record<string, string> = {
主图视频: TAOXI_MAIN_VIDEO_TYPE,
种草视频: TAOXI_GUANGGUANG_VIDEO_TYPE,
}
export const CANONICAL_VIDEO_MATERIAL_TYPES = [
TAOXI_MAIN_VIDEO_TYPE,
INSTALL_VIDEO_TYPE,
TAOXI_GUANGGUANG_VIDEO_TYPE,
DOUYIN_QIANCHUAN_VIDEO_TYPE,
DOUYIN_ACCOUNT_MAINTENANCE_VIDEO_TYPE,
] as const
export const LEGACY_COMPATIBLE_VIDEO_MATERIAL_TYPES = [
'视频',
'VIDEO',
...CANONICAL_VIDEO_MATERIAL_TYPES,
...Object.keys(MATERIAL_TYPE_ALIASES),
] as const
export function normalizeVideoMaterialType(materialType?: string | null): string {
const trimmed = (materialType || '').trim()
if (!trimmed) {
return ''
}
return MATERIAL_TYPE_ALIASES[trimmed] || trimmed
}
export function getCompatibleVideoMaterialTypes(materialType?: string | null): string[] {
const trimmed = (materialType || '').trim()
if (!trimmed) {
return []
}
const normalized = normalizeVideoMaterialType(trimmed)
const candidates = new Set<string>([trimmed, normalized])
for (const [legacyType, canonicalType] of Object.entries(MATERIAL_TYPE_ALIASES)) {
if (canonicalType === normalized) {
candidates.add(legacyType)
}
}
return Array.from(candidates)
}
export function isVideoMaterialType(materialType?: string | null): boolean {
const normalized = normalizeVideoMaterialType(materialType)
return LEGACY_COMPATIBLE_VIDEO_MATERIAL_TYPES.includes(
normalized as (typeof LEGACY_COMPATIBLE_VIDEO_MATERIAL_TYPES)[number],
)
}
export function isVideoTranscodeInFlight(status?: string | null): boolean {
const normalized = String(status || '').trim().toLowerCase()
return normalized === 'pending' || normalized === 'processing'
}
/**
* 轮询只依赖可公开返回的素材类型和处理状态,不能依赖 videoSourceUrl。
* 15 天访问策略会有意隐藏源视频地址,但后台封面生成状态仍需正常刷新。
*/
export function shouldPollVideoTranscode(
materialType?: string | null,
status?: string | null,
): boolean {
return isVideoMaterialType(materialType) && isVideoTranscodeInFlight(status)
}
export function isBatchVideoMaterialType(materialType?: string | null): boolean {
return normalizeVideoMaterialType(materialType) === TAOXI_GUANGGUANG_VIDEO_TYPE
}
export function isSingleVideoUploadMaterialType(materialType?: string | null): boolean {
const normalized = normalizeVideoMaterialType(materialType)
return (
isVideoMaterialType(normalized) &&
normalized !== TAOXI_GUANGGUANG_VIDEO_TYPE &&
normalized !== '视频' &&
normalized !== 'VIDEO'
)
}