style: auto-format with black + isort + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 26s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 27s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m34s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m10s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m51s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m5s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 49s
AI Code Review / AI Code Review (pull_request) Successful in 6m41s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Failing after 12m53s
Preview Cleanup / Cleanup Preview Environment (pull_request) Failing after 13m1s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 20m23s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 26s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 27s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 1m34s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m44s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m10s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m51s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m5s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 49s
AI Code Review / AI Code Review (pull_request) Successful in 6m41s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Failing after 12m53s
Preview Cleanup / Cleanup Preview Environment (pull_request) Failing after 13m1s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 20m23s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
This commit is contained in:
@@ -928,10 +928,7 @@ class EditPlanService:
|
||||
for idx in range(len(plan_ids)):
|
||||
# 每个变体用不同的 seed 选择节奏模板
|
||||
variant_seed = rng.randint(0, 999999)
|
||||
template = adapt_template_length(
|
||||
RHYTHM_TEMPLATES[variant_seed % len(RHYTHM_TEMPLATES)],
|
||||
clip_count
|
||||
)
|
||||
template = adapt_template_length(RHYTHM_TEMPLATES[variant_seed % len(RHYTHM_TEMPLATES)], clip_count)
|
||||
rhythm_templates_for_variants.append(template)
|
||||
logger.info("变体 %d 节奏模板: plan=%s template=%s", idx, plan_ids[idx], template)
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ TOTAL_DURATION_TOLERANCE = 0.5
|
||||
# 每种模板是权重序列,权重值代表相对时长比例
|
||||
# 变体基于 variant_seed 随机选一个模板,实现不同变体时长结构不同
|
||||
RHYTHM_TEMPLATES: list[list[int]] = [
|
||||
[1, 1, 1, 1, 1], # 平均(基准)
|
||||
[2, 1, 3, 1, 2], # 中间长,两端短
|
||||
[1, 2, 1, 2, 1], # 偶数段长
|
||||
[3, 1, 1, 1, 3], # 两端长,中间短
|
||||
[1, 1, 3, 2, 1], # 后段渐长
|
||||
[2, 1, 1, 3, 1], # 前段较长 + 第4段最长
|
||||
[1, 1, 1, 1, 1], # 平均(基准)
|
||||
[2, 1, 3, 1, 2], # 中间长,两端短
|
||||
[1, 2, 1, 2, 1], # 偶数段长
|
||||
[3, 1, 1, 1, 3], # 两端长,中间短
|
||||
[1, 1, 3, 2, 1], # 后段渐长
|
||||
[2, 1, 1, 3, 1], # 前段较长 + 第4段最长
|
||||
]
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ def adapt_template_length(template: list[int], clip_count: int) -> list[int]:
|
||||
result.append(template[i % len(template)])
|
||||
return result
|
||||
|
||||
|
||||
#: 单段最小时长(秒):低于此值播放器/渲染链路易出问题
|
||||
MIN_CLIP_DURATION = 1.0
|
||||
|
||||
@@ -164,12 +165,12 @@ def plan_clip_durations(
|
||||
|
||||
# #1764:按节奏模板权重分配(无模板时全 1 = 平均分配)
|
||||
weights = rhythm_template if rhythm_template and len(rhythm_template) == clip_count else [1] * clip_count
|
||||
|
||||
|
||||
# 确保每个片段 >= MIN_CLIP_DURATION
|
||||
# 先按权重分配,再检查最小值
|
||||
total_weight = sum(weights)
|
||||
raw_durations = [(w / total_weight) * gross for w in weights]
|
||||
|
||||
|
||||
# 保底检查:如果有片段 < MIN_CLIP_DURATION,提升它并从最长片段扣
|
||||
result = [round(d, 3) for d in raw_durations]
|
||||
for _ in range(3): # 最多迭代 3 次
|
||||
@@ -185,13 +186,13 @@ def plan_clip_durations(
|
||||
deficit = MIN_CLIP_DURATION - result[min_idx]
|
||||
result[min_idx] = MIN_CLIP_DURATION
|
||||
result[max_idx] = round(result[max_idx] - deficit, 3)
|
||||
|
||||
|
||||
# 末段吸收舍入误差
|
||||
total_assigned = sum(result[:-1])
|
||||
result[-1] = round(gross - total_assigned, 3)
|
||||
if result[-1] < MIN_CLIP_DURATION:
|
||||
result[-1] = MIN_CLIP_DURATION
|
||||
|
||||
|
||||
return result
|
||||
|
||||
|
||||
|
||||
@@ -105,10 +105,10 @@ class TestPlanClipDurationsWithRhythm:
|
||||
# 权重 [2, 1, 3, 1, 2]:第 3 段最长,第 2/4 段最短
|
||||
template = [2, 1, 3, 1, 2]
|
||||
result = plan_clip_durations(clips, voice, rhythm_template=template)
|
||||
|
||||
|
||||
# 总时长 ≈ 配音时长
|
||||
assert abs(sum(result) - voice) < 0.5
|
||||
|
||||
|
||||
# 第 3 段应该最长
|
||||
assert result[2] > result[1]
|
||||
assert result[2] > result[3]
|
||||
@@ -120,7 +120,7 @@ class TestPlanClipDurationsWithRhythm:
|
||||
# 极端权重:某段权重极低
|
||||
template = [10, 1, 1, 1, 1]
|
||||
result = plan_clip_durations(clips, voice, rhythm_template=template)
|
||||
|
||||
|
||||
for d in result:
|
||||
assert d >= MIN_CLIP_DURATION
|
||||
|
||||
@@ -131,14 +131,15 @@ class TestPlanClipDurationsWithRhythm:
|
||||
effects = [None, "xfade", "fade", "cut"]
|
||||
durations = [0.0, 0.5, 0.3, 0.0]
|
||||
template = [2, 1, 1, 2]
|
||||
|
||||
|
||||
result = plan_clip_durations(
|
||||
clips, voice,
|
||||
clips,
|
||||
voice,
|
||||
transition_effects=effects,
|
||||
transition_durations=durations,
|
||||
rhythm_template=template,
|
||||
)
|
||||
|
||||
|
||||
# 成片净时长 = Σ段长 - Σ转场重叠 ≈ 配音时长
|
||||
output = total_output_duration(result, effects, durations)
|
||||
assert abs(output - voice) < 0.5
|
||||
@@ -155,13 +156,13 @@ class TestPlanClipDurationsWithRhythm:
|
||||
voice = 25.0
|
||||
clips = 5
|
||||
structures = set()
|
||||
|
||||
|
||||
for tpl in RHYTHM_TEMPLATES:
|
||||
result = plan_clip_durations(clips, voice, rhythm_template=tpl)
|
||||
# 用 round 后的元组作为结构指纹
|
||||
structure = tuple(round(d, 1) for d in result)
|
||||
structures.add(structure)
|
||||
|
||||
|
||||
# 至少 4 种不同结构
|
||||
assert len(structures) >= 4
|
||||
|
||||
@@ -173,17 +174,17 @@ class TestIssue1764Acceptance:
|
||||
"""批量 3 个变体,至少 2 组不同片段时长序列。"""
|
||||
voice = 20.0
|
||||
clips = 5
|
||||
|
||||
|
||||
# 模拟 3 个变体用不同 seed
|
||||
seeds = [100, 200, 300]
|
||||
structures = []
|
||||
|
||||
|
||||
for seed in seeds:
|
||||
template = get_rhythm_template(seed)
|
||||
adapted = adapt_template_length(template, clips)
|
||||
durations = plan_clip_durations(clips, voice, rhythm_template=adapted)
|
||||
structures.append(tuple(round(d, 1) for d in durations))
|
||||
|
||||
|
||||
# 至少 2 种不同结构
|
||||
unique = len(set(structures))
|
||||
assert unique >= 2, f"Expected >= 2 unique structures, got {unique}: {structures}"
|
||||
|
||||
Reference in New Issue
Block a user