File size: 3,392 Bytes
15a166a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""Generate a representative sample broadcast video demonstrating the complete LeagueForge pipeline."""

from __future__ import annotations

import time
from pathlib import Path
from rich.console import Console

from leagueforge.edl.builder import build_episode_edl
from leagueforge.league.tournament import TournamentManager
from leagueforge.map.builder import build_landscape_round_track
from leagueforge.meta.chapters import format_youtube_description, generate_episode_chapters
from leagueforge.meta.thumbnail import generate_thumbnail
from leagueforge.render.renderer import render_episode_mp4

console = Console()


def main() -> None:
    out_dir = Path("out/sample_episode")
    out_dir.mkdir(parents=True, exist_ok=True)
    out_mp4 = Path("out/league_episode_sample.mp4")

    seed = 8080
    console.print(f"[bold cyan]1. Simulating 15-Round Tournament for Seed #{seed}...[/bold cyan]")
    t0 = time.perf_counter()
    tm = TournamentManager(out_dir=out_dir)
    episode_tl, commit_rec = tm.run_episode(seed, target_round_s=15.0, fps_sim=120)
    sim_time = time.perf_counter() - t0
    console.print(f"[green]βœ“[/green] Simulation finished in {sim_time:.2f}s!")

    champ = tm.get_racer_for_slot(commit_rec, episode_tl.champion_slot)
    console.print(f"  Champion: [bold]{champ.numeral} {champ.name}[/bold] ({champ.hex_color})")
    console.print(f"  Commit Hash: {episode_tl.commit_sha256}")

    # Build EDL
    edl = build_episode_edl(episode_tl, commit_rec, fps=60, include_cold_open=True)
    console.print(f"[green]βœ“[/green] EDL constructed: {len(edl.segments)} segments, {edl.total_frames_60} frames ({edl.total_frames_60/3600:.1f} min)")

    # Build round specs and grids
    round_specs = {}
    grids = {}
    live_slots = list(range(16))
    for r_idx in range(15):
        spec, grid, solver = build_landscape_round_track(seed, r_idx, live_slots, target_round_s=15.0)
        round_specs[r_idx] = spec
        grids[r_idx] = grid
        live_slots.remove(episode_tl.rounds[r_idx].outcome.eliminated_slot)

    # Render a ~35-second highlight broadcast sample (2100 frames) covering Cold Open, Roster Card, Round 1 Race, Deciding Moment, and Elimination Sting
    max_frames = 2100
    console.print(f"[bold cyan]2. Rendering 1080p60 MP4 with Procedural Audio ({max_frames} frames)...[/bold cyan]")
    t_render = time.perf_counter()
    render_episode_mp4(
        edl=edl,
        episode_tl=episode_tl,
        commit_rec=commit_rec,
        round_specs=round_specs,
        grids=grids,
        out_mp4=out_mp4,
        quality="draft",
        max_frames=max_frames,
    )
    render_time = time.perf_counter() - t_render
    console.print(f"[green]βœ“[/green] Video rendered in {render_time:.1f}s ({max_frames/render_time:.1f} fps) to [bold]{out_mp4}[/bold]")

    # Thumbnail & Chapters
    thumb_path = Path("out/league_thumbnail_sample.png")
    generate_thumbnail(episode_tl, commit_rec, thumb_path)
    console.print(f"[green]βœ“[/green] Thumbnail generated at [bold]{thumb_path}[/bold]")

    chapters = generate_episode_chapters(edl, episode_tl, commit_rec)
    desc = format_youtube_description(episode_tl, commit_rec, chapters)
    desc_path = Path("out/episode_metadata.txt")
    desc_path.write_text(desc)
    console.print(f"[green]βœ“[/green] Description & Chapters saved to [bold]{desc_path}[/bold]")


if __name__ == "__main__":
    main()