Spaces:
Paused
Paused
AndrianBalanescu commited on
Commit ·
fa05447
1
Parent(s): a18d805
studio: expose karaoke_video in vault/music + flag karaoke videos in vault/videos
Browse files- vault/music items now carry karaoke_video/karaoke_video_file so the
Music Studio vault browser can present song+video as one entity
- vault/videos marks _karaoke.mp4 entries with topic 'Auto karaoke
lyrics video', style '16:9 Karaoke' and karaoke:true
- unit test covers both listing integration boundaries
Live-verified on :8090 (28 songs, 1 linked; 13 videos, 3 flagged).
moldovan-qwen/studio_server.py
CHANGED
|
@@ -2117,6 +2117,8 @@ async def list_vault_music():
|
|
| 2117 |
"vocal_style": d.get("vocal_style", ""),
|
| 2118 |
"dialect_level": d.get("dialect_level", 2),
|
| 2119 |
"suno_style_prompt": d.get("suno_style_prompt", ""),
|
|
|
|
|
|
|
| 2120 |
"created_at": d.get("created_at", os.path.getmtime(fpath))
|
| 2121 |
})
|
| 2122 |
except Exception:
|
|
@@ -2354,12 +2356,14 @@ async def list_vault_videos():
|
|
| 2354 |
for fpath in sorted(glob.glob(os.path.join(VIDEOS_OUT_DIR, "*.mp4")), reverse=True):
|
| 2355 |
fname = os.path.basename(fpath)
|
| 2356 |
if not any(it.get("video_file") == fname for it in items):
|
|
|
|
| 2357 |
items.append({
|
| 2358 |
"id": fname,
|
| 2359 |
"title": fname.replace(".mp4", "").replace("_", " ").title(),
|
| 2360 |
-
"topic": "Rendered MP4",
|
| 2361 |
-
"style": "9:16 Vertical",
|
| 2362 |
"video_file": fname,
|
|
|
|
| 2363 |
"scenes_count": 4,
|
| 2364 |
"created_at": os.path.getmtime(fpath)
|
| 2365 |
})
|
|
|
|
| 2117 |
"vocal_style": d.get("vocal_style", ""),
|
| 2118 |
"dialect_level": d.get("dialect_level", 2),
|
| 2119 |
"suno_style_prompt": d.get("suno_style_prompt", ""),
|
| 2120 |
+
"karaoke_video": d.get("karaoke_video"),
|
| 2121 |
+
"karaoke_video_file": d.get("karaoke_video_file"),
|
| 2122 |
"created_at": d.get("created_at", os.path.getmtime(fpath))
|
| 2123 |
})
|
| 2124 |
except Exception:
|
|
|
|
| 2356 |
for fpath in sorted(glob.glob(os.path.join(VIDEOS_OUT_DIR, "*.mp4")), reverse=True):
|
| 2357 |
fname = os.path.basename(fpath)
|
| 2358 |
if not any(it.get("video_file") == fname for it in items):
|
| 2359 |
+
is_karaoke = fname.endswith("_karaoke.mp4")
|
| 2360 |
items.append({
|
| 2361 |
"id": fname,
|
| 2362 |
"title": fname.replace(".mp4", "").replace("_", " ").title(),
|
| 2363 |
+
"topic": "Auto karaoke lyrics video" if is_karaoke else "Rendered MP4",
|
| 2364 |
+
"style": "16:9 Karaoke" if is_karaoke else "9:16 Vertical",
|
| 2365 |
"video_file": fname,
|
| 2366 |
+
"karaoke": is_karaoke,
|
| 2367 |
"scenes_count": 4,
|
| 2368 |
"created_at": os.path.getmtime(fpath)
|
| 2369 |
})
|
tests/unit/test_karaoke_auto_pipeline.py
CHANGED
|
@@ -96,6 +96,29 @@ def test_karaoke_success_links_video_into_song_manifest(client, monkeypatch):
|
|
| 96 |
os.remove(os.path.join(AUDIO_DIR, wav_name))
|
| 97 |
|
| 98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
def test_kick_off_karaoke_skips_when_audio_missing(client):
|
| 100 |
"""Missing audio file → karaoke status skipped, no exception raised."""
|
| 101 |
import threading as _th
|
|
|
|
| 96 |
os.remove(os.path.join(AUDIO_DIR, wav_name))
|
| 97 |
|
| 98 |
|
| 99 |
+
def test_vault_music_and_videos_expose_karaoke_fields(client):
|
| 100 |
+
"""Integration boundary: vault/music and vault/videos listings expose
|
| 101 |
+
karaoke metadata so UI browsers can present song+video as one entity."""
|
| 102 |
+
import studio_server as ss
|
| 103 |
+
track_id = f"song_vaultfields_{int(time.time())}"
|
| 104 |
+
wav_name = f"{track_id}.wav"
|
| 105 |
+
song_file = os.path.join(ss.MUSIC_DIR, f"{track_id}.json")
|
| 106 |
+
with open(song_file, "w", encoding="utf-8") as f:
|
| 107 |
+
json.dump({"id": track_id, "title": "Vault Fields Test", "audio_file": wav_name,
|
| 108 |
+
"full_lyrics": "vers"}, f)
|
| 109 |
+
r = client.get("/api/media/vault/music")
|
| 110 |
+
assert r.status_code == 200
|
| 111 |
+
mine = [i for i in r.json().get("items", []) if i["id"] == track_id]
|
| 112 |
+
assert mine, "song missing from vault/music"
|
| 113 |
+
assert "karaoke_video" in mine[0] and "karaoke_video_file" in mine[0]
|
| 114 |
+
|
| 115 |
+
r2 = client.get("/api/media/vault/videos")
|
| 116 |
+
assert r2.status_code == 200
|
| 117 |
+
kara = [v for v in r2.json().get("items", []) if v.get("karaoke")]
|
| 118 |
+
assert kara, "no karaoke-flagged videos in vault/videos"
|
| 119 |
+
assert all(v["video_file"].endswith("_karaoke.mp4") for v in kara)
|
| 120 |
+
|
| 121 |
+
|
| 122 |
def test_kick_off_karaoke_skips_when_audio_missing(client):
|
| 123 |
"""Missing audio file → karaoke status skipped, no exception raised."""
|
| 124 |
import threading as _th
|