mot / variants.py
digidau's picture
Update variants.py
a50623d verified
Raw
History Blame Contribute Delete
5.95 kB
# variants.py
import random
import subprocess
from config import (
CLIPS_DIR,
TARGET_WIDTH,
TARGET_HEIGHT,
TARGET_FPS,
MIN_CLIP_DURATION,
MAX_CLIP_DURATION,
MIN_SOURCE_DURATION,
VIDEO_CODEC,
PRESET,
CRF,
VARIANT_RULES,
)
from probe import get_duration
# =====================================================
# VARIANT NAMES
# =====================================================
VARIANT_NAMES = [
"A", "B", "C", "D", "E",
"F", "G", "H", "I", "J"
]
# =====================================================
# RANDOM CLIP DURATION
# =====================================================
def random_clip_duration():
return round(
random.uniform(
MIN_CLIP_DURATION,
MAX_CLIP_DURATION
),
2
)
# =====================================================
# VARIANT COUNT
# =====================================================
def get_variant_count(duration):
for min_dur, max_dur, count in VARIANT_RULES:
if min_dur <= duration < max_dur:
return count
return 3
# =====================================================
# BUILD DYNAMIC ZONES
# =====================================================
def build_dynamic_zones(
duration,
count
):
zone_size = duration / count
zones = []
current = 0
for _ in range(count):
zones.append(
(
current,
current + zone_size
)
)
current += zone_size
return zones
# =====================================================
# RANDOM START INSIDE ZONE
# =====================================================
def random_start_in_zone(
zone_start,
zone_end,
clip_duration
):
available = (
zone_end
- zone_start
- clip_duration
)
if available <= 0:
return zone_start
return round(
random.uniform(
zone_start,
zone_start + available
),
2
)
# =====================================================
# RENDER SINGLE VARIANT
# =====================================================
def render_variant(
source_file,
output_file,
start_time,
clip_duration,
hflip=False
):
filters = [
(
f"scale={TARGET_WIDTH}:{TARGET_HEIGHT}:"
"force_original_aspect_ratio=increase"
),
(
f"crop={TARGET_WIDTH}:{TARGET_HEIGHT}"
),
f"fps={TARGET_FPS}",
"fade=t=in:st=0:d=0.2",
(
f"fade=t=out:"
f"st={max(0, clip_duration - 0.2)}:d=0.2"
),
]
if hflip:
filters.append("hflip")
vf = ",".join(filters)
cmd = [
"ffmpeg",
"-y",
"-ss",
str(start_time),
"-i",
str(source_file),
"-t",
str(clip_duration),
"-an",
"-vf",
vf,
"-c:v",
VIDEO_CODEC,
"-preset",
PRESET,
"-crf",
str(CRF),
"-pix_fmt",
"yuv420p",
str(output_file),
]
subprocess.run(
cmd,
check=True,
capture_output=True
)
return str(output_file)
# =====================================================
# GENERATE VARIANTS
# =====================================================
def generate_variants(
source_file,
source_id
):
duration = get_duration(
source_file
)
if duration < MIN_SOURCE_DURATION:
return []
variant_count = get_variant_count(
duration
)
zones = build_dynamic_zones(
duration,
variant_count
)
scene_pool = []
for idx, zone in enumerate(zones):
variant_name = VARIANT_NAMES[idx]
clip_duration = random_clip_duration()
start_time = random_start_in_zone(
zone[0],
zone[1],
clip_duration
)
# --------------------------------
# hflip setiap variant ke-3
# --------------------------------
hflip = (
(idx + 1) % 3 == 0
)
output_file = (
CLIPS_DIR
/ f"{source_id}_{variant_name}.mp4"
)
render_variant(
source_file=source_file,
output_file=output_file,
start_time=start_time,
clip_duration=clip_duration,
hflip=hflip
)
scene_pool.append(
{
"source_id": source_id,
"family": source_id,
"variant": variant_name,
"path": str(output_file),
"duration": clip_duration,
}
)
return scene_pool
# =====================================================
# GENERATE MANY
# =====================================================
def generate_many(
source_files
):
all_scenes = []
for idx, source_file in enumerate(
source_files,
start=1
):
try:
scenes = generate_variants(
source_file,
idx
)
all_scenes.extend(
scenes
)
print(
f"[Variants] "
f"Source {idx} "
f"-> {len(scenes)} variants"
)
except Exception as e:
print(
f"[Variants] Error:"
f" {source_file}"
)
print(e)
return all_scenes
# =====================================================
# TEST
# =====================================================
if __name__ == "__main__":
scenes = generate_variants(
"downloads/source_0001.mp4",
1
)
print()
print(
f"Generated: "
f"{len(scenes)} scenes"
)
print()
for scene in scenes:
print(scene)