File size: 3,868 Bytes
e434719 44a0949 e434719 9e27c20 e434719 9e27c20 e434719 9e27c20 e434719 9e27c20 b888737 e434719 | 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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | """Pre-render the 'Try an Example' showcase bundles → examples/.
Drives the LIVE Space end to end for each persona in src.examples.EXAMPLES and
writes the cached bundle the app serves with zero quota:
examples/<id>.lyrics.txt examples/<id>.trace.json examples/<id>.song.mp3
and, IF a headshot is provided, examples/<id>.video.mp4 (demo-video footage).
Drop examples/<id>.photo.(jpg|png) before running to get the full talking-head
video for that persona; otherwise it renders song-only (no photo needed).
Run (after the Space is deployed with this code, on the new render):
python scripts/render_examples.py # all personas
python scripts/render_examples.py --only datasci_unhinged
Costs a few ZeroGPU minutes total (one lyrics call + one render per persona).
"""
import argparse
import glob
import json
import os
import shutil
import sys
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
from src.examples import EX_DIR, EXAMPLES # noqa: E402
DEFAULT_SPACE = "build-small-hackathon/open-to-work-musical"
VOICE = "🎲 Surprise me"
def _photo_for(eid):
for ext in ("jpg", "jpeg", "png", "webp"):
hits = glob.glob(os.path.join(EX_DIR, f"{eid}.photo.{ext}"))
if hits:
return hits[0]
return None
def render_one(client, ex):
from gradio_client import handle_file
eid = ex["id"]
print(f"\n=== {eid} · level {ex['level']} · {ex['genre']} ===", flush=True)
# new on_write_lyrics signature: (resume, jd, genre, level, tiny_mode, voice_type)
# returns (lyrics, trace_html) ← trace is rendered HTML now, not a dict
lyrics, trace_html = client.predict(
ex["resume"], ex["jd"], ex["genre"], ex["level"], False, VOICE,
api_name="/on_write_lyrics",
)
if not lyrics or not lyrics.strip():
print(" !! no lyrics produced — skipping", flush=True)
return False
os.makedirs(EX_DIR, exist_ok=True)
with open(os.path.join(EX_DIR, f"{eid}.lyrics.txt"), "w", encoding="utf-8") as f:
f.write(lyrics)
with open(os.path.join(EX_DIR, f"{eid}.trace.html"), "w", encoding="utf-8") as f:
f.write(trace_html or "")
print(" lyrics+trace saved", flush=True)
photo = _photo_for(eid)
print(f" rendering {'song+video' if photo else 'song-only'}…", flush=True)
# new on_render signature: (lyrics, photo, voice_sample, voice_consent, level, genre, voice_type)
try:
song, video, _dbg = client.predict(
lyrics, handle_file(photo) if photo else None, None, False,
ex["level"], ex["genre"], VOICE,
api_name="/on_render",
)
except Exception as e:
msg = str(e).splitlines()[-1][:200]
print(f" !! render skipped (lyrics+trace kept): {msg}", flush=True)
return False
if song and os.path.isfile(song):
shutil.copy(song, os.path.join(EX_DIR, f"{eid}.song.mp3"))
print(" song saved.", flush=True)
else:
print(" !! no song produced", flush=True)
return False
if video and os.path.isfile(video):
shutil.copy(video, os.path.join(EX_DIR, f"{eid}.video.mp4"))
print(" video saved.", flush=True)
return True
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--space", default=DEFAULT_SPACE)
ap.add_argument("--only", help="render a single example id")
args = ap.parse_args()
from gradio_client import Client
from huggingface_hub import get_token
client = Client(args.space, token=get_token(), verbose=False)
todo = [e for e in EXAMPLES if not args.only or e["id"] == args.only]
ok = sum(render_one(client, e) for e in todo)
print(f"\nDone: {ok}/{len(todo)} bundles rendered into {EX_DIR}", flush=True)
sys.exit(0 if ok == len(todo) else 1)
if __name__ == "__main__":
main()
|