fix: #1765 generate_pixel_perturbation 支持 int seed 可复现 #1778
@@ -129,7 +129,10 @@ def reselect_clips_for_variant(
|
||||
Raises:
|
||||
ValueError: 源片段为空 / 素材池为空 / 素材时长全为 0(无法差异化选片)。
|
||||
"""
|
||||
rng = rng or random.Random()
|
||||
if rng is None:
|
||||
rng = random.Random()
|
||||
elif isinstance(rng, int):
|
||||
rng = random.Random(rng)
|
||||
if not source_clips:
|
||||
raise ValueError("源 plan 无片段,无法为变体重新选片")
|
||||
if not candidate_asset_ids:
|
||||
@@ -312,7 +315,10 @@ def generate_visual_perturbation(rng: random.Random | None = None) -> dict:
|
||||
- speed_factor: 0.95~1.05 速度微调(±5%,肉眼不太敏感但时间轴不同)
|
||||
- brightness_shift: -10~+10 亮度偏移(eq=brightness,画面明暗差异)
|
||||
"""
|
||||
rng = rng or random.Random()
|
||||
if rng is None:
|
||||
rng = random.Random()
|
||||
elif isinstance(rng, int):
|
||||
rng = random.Random(rng)
|
||||
return {
|
||||
"hflip": rng.random() < 0.3,
|
||||
"zoom_ratio": round(1.0 + rng.uniform(0, 0.08), 4),
|
||||
@@ -321,7 +327,7 @@ def generate_visual_perturbation(rng: random.Random | None = None) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def generate_pixel_perturbation(rng: random.Random | None = None) -> dict:
|
||||
def generate_pixel_perturbation(rng: random.Random | int | None = None) -> dict:
|
||||
"""为一个变体生成像素级扰动滤镜参数(Issue #1765)。
|
||||
|
||||
在现有视觉扰动(hflip/zoom/brightness)基础上,额外叠加 2-3 种
|
||||
@@ -336,7 +342,10 @@ def generate_pixel_perturbation(rng: random.Random | None = None) -> dict:
|
||||
返回 dict,可直接存入 plan.config["pixel_perturbation"]。
|
||||
渲染侧读取后追加到 ffmpeg filter chain。
|
||||
"""
|
||||
rng = rng or random.Random()
|
||||
if rng is None:
|
||||
rng = random.Random()
|
||||
elif isinstance(rng, int):
|
||||
rng = random.Random(rng)
|
||||
|
||||
# 可用滤镜池
|
||||
filter_options = ["noise", "unsharp", "curves", "color_balance"]
|
||||
|
||||
@@ -110,3 +110,32 @@ class TestPixelPerturbationAcceptance:
|
||||
# 至少 2 种不同组合
|
||||
unique = len(set(results))
|
||||
assert unique >= 2, f"Expected >= 2 unique filter combos, got {unique}: {results}"
|
||||
|
||||
|
||||
class TestIntSeedSupport:
|
||||
"""int seed 入参支持(与 get_rhythm_template(seed) 接口一致)。"""
|
||||
|
||||
def test_int_seed_returns_dict(self):
|
||||
"""int seed 正常返回 dict。"""
|
||||
result = generate_pixel_perturbation(42)
|
||||
assert isinstance(result, dict)
|
||||
assert "filters" in result
|
||||
|
||||
def test_int_seed_reproducible(self):
|
||||
"""相同 int seed 结果一致。"""
|
||||
assert generate_pixel_perturbation(42) == generate_pixel_perturbation(42)
|
||||
|
||||
def test_int_seed_differs_across_seeds(self):
|
||||
"""不同 int seed 大概率不同(遍历确认至少 2 种组合)。"""
|
||||
results = {tuple(generate_pixel_perturbation(s)["filters"]) for s in range(30)}
|
||||
assert len(results) >= 2
|
||||
|
||||
def test_int_seed_matches_random_obj(self):
|
||||
"""int seed 与等价 random.Random(seed) 结果一致。"""
|
||||
assert generate_pixel_perturbation(7) == generate_pixel_perturbation(random.Random(7))
|
||||
|
||||
def test_none_seed_works(self):
|
||||
"""None 入参(默认随机)正常返回。"""
|
||||
result = generate_pixel_perturbation(None)
|
||||
assert isinstance(result, dict)
|
||||
assert len(result["filters"]) in [2, 3]
|
||||
|
||||
Reference in New Issue
Block a user