You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
53 lines
2.0 KiB
53 lines
2.0 KiB
#!/usr/bin/env python3
|
|
"""Phase 3 Step 3.3: Match generated preview blobs back to candidates via filename.
|
|
|
|
Usage: python3 scripts/match_preview_blobs.py
|
|
|
|
Reads preview_plan.json + assets.json, matches blobs by filename,
|
|
and updates preview_plan.json with blob_path for each candidate.
|
|
"""
|
|
import json, os
|
|
from pathlib import Path
|
|
|
|
PROJECT_DIR = Path(os.getcwd())
|
|
AUDIOBOOK_ROOT = PROJECT_DIR / ".audiobook"
|
|
BOOK_DIR = next(d for d in sorted(AUDIOBOOK_ROOT.iterdir()) if d.is_dir() and (d / ".audiobook-state.json").exists())
|
|
|
|
assets_path = PROJECT_DIR / ".hilo" / "assets.json"
|
|
plan_path = BOOK_DIR / "voice_samples" / "preview_plan.json"
|
|
|
|
assets = json.loads(assets_path.read_text(encoding="utf-8"))
|
|
plan = json.loads(plan_path.read_text(encoding="utf-8"))
|
|
|
|
# Build lookup: filename (without extension) -> asset entry
|
|
# Iterate forward so later entries (retries) overwrite earlier ones
|
|
name_to_asset = {}
|
|
for a in assets:
|
|
if a.get("type") == "audio" and a.get("name"):
|
|
name_key = a["name"].rsplit(".", 1)[0] # strip .mp3
|
|
name_to_asset[name_key] = a
|
|
|
|
# Match each candidate
|
|
results = []
|
|
for role in plan:
|
|
for c in role["candidates"]:
|
|
asset = name_to_asset.get(c["filename"])
|
|
if asset and asset.get("blobRef"):
|
|
blob_path = str(PROJECT_DIR / ".hilo" / ".blobs" / asset["blobRef"])
|
|
c["blob_path"] = blob_path
|
|
status = "ok"
|
|
else:
|
|
c["blob_path"] = None
|
|
status = "MISSING"
|
|
results.append((status, role["role"], c["voice_id"], c["filename"]))
|
|
print(f'{"ok" if status == "ok" else "MISSING":>7s} {role["role"]:20s} {c["voice_id"]:35s} {c["filename"]}')
|
|
|
|
# Save updated plan with blob_path
|
|
with open(plan_path, "w", encoding="utf-8") as f:
|
|
json.dump(plan, f, ensure_ascii=False, indent=2)
|
|
|
|
missing = [r for r in results if r[0] == "MISSING"]
|
|
if missing:
|
|
print(f"\nWARNING: {len(missing)} samples not matched -- retry the failed calls")
|
|
else:
|
|
print(f"\nAll {len(results)} samples matched. Proceed to Step 4.")
|
|
|