fix(assets): 智能选素材传 limit 参数,避免「有几个选几个」
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2m54s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m29s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 4m4s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 4m36s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m0s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 5m14s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m42s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m49s
AI Code Review / AI Code Review (pull_request) Successful in 6m52s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m14s
CI/CD Pipeline / CI Gate (pull_request) Successful in 30s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 385h18m46s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 385h18m47s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 385h18m48s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 385h18m48s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 385h18m48s
CI/CD Pipeline / PR Build Worker Image (pull_request) Failing after 385h24m8s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 385h26m58s
CI/CD Pipeline / PR Build API Image (pull_request) Failing after 385h24m10s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 385h26m58s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 385h26m59s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 385h27m2s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 385h27m3s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 385h27m4s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 385h27m5s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 385h27m6s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 385h52m58s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 385h52m59s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 385h58m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 386h1m9s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 386h1m13s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 386h1m16s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2m54s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m17s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m29s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 4m4s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 4m36s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m0s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 5m14s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m42s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m49s
AI Code Review / AI Code Review (pull_request) Successful in 6m52s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m14s
CI/CD Pipeline / CI Gate (pull_request) Successful in 30s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 385h18m46s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 385h18m47s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 385h18m48s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 385h18m48s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 385h18m48s
CI/CD Pipeline / PR Build Worker Image (pull_request) Failing after 385h24m8s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 385h26m58s
CI/CD Pipeline / PR Build API Image (pull_request) Failing after 385h24m10s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 385h26m58s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 385h26m59s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 385h27m2s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 385h27m3s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 385h27m4s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 385h27m5s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 385h27m6s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 385h52m58s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 385h52m59s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 385h58m21s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 386h1m9s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 386h1m13s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 386h1m16s
- smartMatchAssets 增加可选 limit 参数,传给后端 /assets/smart-match - useSmartMatch 根据模板 segments 总时长按 15s/素材估算 limit,钳制 [1,200] - 拿不到时长信息时默认 limit=10(后端上限 200) - useStep2Materials 透传 templateSegments 到 useSmartMatch
This commit is contained in:
@@ -69,10 +69,13 @@ interface SmartMatchWrappedItem {
|
||||
breakdown?: unknown
|
||||
}
|
||||
|
||||
export const smartMatchAssets = async (libraryId: string): Promise<SmartMatchResult> => {
|
||||
const response = await apiClient.post("/assets/smart-match", {
|
||||
library_id: libraryId,
|
||||
})
|
||||
export const smartMatchAssets = async (
|
||||
libraryId: string,
|
||||
limit?: number,
|
||||
): Promise<SmartMatchResult> => {
|
||||
const payload: Record<string, unknown> = { library_id: libraryId }
|
||||
if (limit && limit > 0) payload.limit = limit
|
||||
const response = await apiClient.post("/assets/smart-match", payload)
|
||||
const rawItems: SmartMatchWrappedItem[] = response.data?.items ?? []
|
||||
const items = rawItems
|
||||
.map((it) =>
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import { useState, useCallback } from "react"
|
||||
import { message } from "antd"
|
||||
import type { AssetItem } from "@/api/assets"
|
||||
import type { TemplateSegment } from "@/api/templates/types"
|
||||
import { smartMatchAssets, isAssetUsable } from "@/api/assets"
|
||||
|
||||
interface UseSmartMatchOptions {
|
||||
libraryId: string
|
||||
materials: { items: AssetItem[]; total: number }
|
||||
onSmartSelectedIdsChange: (ids: string[]) => void
|
||||
/** 当前模板的 segments,用于根据总时长计算 limit */
|
||||
templateSegments?: TemplateSegment[]
|
||||
}
|
||||
|
||||
/** 默认 limit(拿不到目标时长时的兜底上限) */
|
||||
const DEFAULT_LIMIT = 10
|
||||
/** 每个素材切片按 15 秒估算所需素材数 */
|
||||
const SECONDS_PER_ASSET = 15
|
||||
|
||||
/**
|
||||
* 根据模板 segments 计算所需素材数量上限。
|
||||
* 取每个 segment 的 duration_min 之和作为目标视频总时长,
|
||||
* 再按 15 秒/素材估算需要多少个素材;结果钳制到 [1, 200] 区间(后端 limit 上限 200)。
|
||||
*/
|
||||
function computeLimitFromSegments(segments?: TemplateSegment[]): number {
|
||||
if (!segments || segments.length === 0) return DEFAULT_LIMIT
|
||||
const totalSeconds = segments.reduce((sum, seg) => sum + (seg.duration_min || 0), 0)
|
||||
if (totalSeconds <= 0) return DEFAULT_LIMIT
|
||||
const limit = Math.ceil(totalSeconds / SECONDS_PER_ASSET)
|
||||
return Math.max(1, Math.min(limit, 200))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18,6 +39,7 @@ export function useSmartMatch({
|
||||
libraryId,
|
||||
materials,
|
||||
onSmartSelectedIdsChange,
|
||||
templateSegments,
|
||||
}: UseSmartMatchOptions) {
|
||||
const [smartMatching, setSmartMatching] = useState(false)
|
||||
const [hasMatched, setHasMatched] = useState(false)
|
||||
@@ -42,12 +64,13 @@ export function useSmartMatch({
|
||||
setSmartMatching(true)
|
||||
|
||||
try {
|
||||
// 根据目标视频时长计算合理的素材数量上限,避免"有几个选几个"
|
||||
const limit = computeLimitFromSegments(templateSegments)
|
||||
|
||||
// 调用后端智能匹配 API(后端也会排除已用尽素材,这里前端兜底过滤)
|
||||
// items 已在 API 层归一化(兼容后端 {asset, score} 包装结构);
|
||||
// 这里再过滤一遍无 id/已用尽项,杜绝 undefined id 流入预览链路
|
||||
const result = await smartMatchAssets(libraryId)
|
||||
const matched = (result.items ?? []).filter((a) => !!a?.id && isAssetUsable(a))
|
||||
const matchedIds = matched.map((a) => a.id)
|
||||
const result = await smartMatchAssets(libraryId, limit)
|
||||
const matched = (result.items ?? []).filter(isAssetUsable)
|
||||
const matchedIds = matched.map((a: AssetItem) => a.id)
|
||||
|
||||
if (matchedIds.length > 0) {
|
||||
onSmartSelectedIdsChange(matchedIds)
|
||||
@@ -67,7 +90,7 @@ export function useSmartMatch({
|
||||
} finally {
|
||||
setSmartMatching(false)
|
||||
}
|
||||
}, [libraryId, materials.items, onSmartSelectedIdsChange])
|
||||
}, [libraryId, materials.items, onSmartSelectedIdsChange, templateSegments])
|
||||
|
||||
/* ── 换一批 = 重新触发智能匹配 ── */
|
||||
const handleRefreshMatch = useCallback(async () => {
|
||||
|
||||
@@ -51,6 +51,7 @@ export function useStep2Materials({
|
||||
libraryId: selectedLibraryId,
|
||||
materials: selectableMaterials,
|
||||
onSmartSelectedIdsChange,
|
||||
templateSegments,
|
||||
})
|
||||
|
||||
/* ── 自动触发智能匹配:选择视频库后自动调用 ── */
|
||||
|
||||
Reference in New Issue
Block a user