v0.8.8: Fix stems extraction — upload MP3 file instead of audio_url

The MusicGPT Extraction API's audio_url field only accepts YouTube URLs,
not direct MP3 links. Sending our /api/audio-source/ endpoint URL resulted
in 'Error fetching audio length from YouTube' because MusicGPT tried to
parse it as a YouTube video.

Switch to the audio_file upload option: open the local MP3 and upload it
directly as multipart/form-data to the Extraction API.

Bumped timeout from 30s to 60s for file upload.
This commit is contained in:
Troll (Hermes Agent) 2026-08-12 03:37:43 +00:00
parent 8df735d88c
commit 9575464be2
4 changed files with 15 additions and 10 deletions

View file

@ -1,6 +1,6 @@
# Theme Song Booth (MusicGPT Edition) # Theme Song Booth (MusicGPT Edition)
![Version](https://img.shields.io/badge/version-v0.8.7-blue) ![Version](https://img.shields.io/badge/version-v0.8.8-blue)
A Flask web application for running a convention booth where visitors request a custom AI-generated theme song. Operators manage the queue from an admin dashboard, generate prompts via Hermes, queue generations through the MusicGPT API, and deliver final songs by email. A Flask web application for running a convention booth where visitors request a custom AI-generated theme song. Operators manage the queue from an admin dashboard, generate prompts via Hermes, queue generations through the MusicGPT API, and deliver final songs by email.
@ -169,7 +169,7 @@ A global toggle in `/admin/settings` controls whether the generated album cover
2. Select the source MP3 using the **radio buttons** — Version A or Version B. Only versions with files ready are selectable; unavailable versions are greyed out. 2. Select the source MP3 using the **radio buttons** — Version A or Version B. Only versions with files ready are selectable; unavailable versions are greyed out.
3. Click **Generate Stems**. 3. Click **Generate Stems**.
The app constructs a public URL for the selected MP3 via the `/api/audio-source/<token>/<version>.mp3` endpoint and sends it to the MusicGPT Extraction API. The Extraction API downloads the audio, separates vocals and instrumental tracks, and posts the result to the webhook. The app uploads the selected MP3 file directly to the MusicGPT Extraction API (the API's `audio_url` field only accepts YouTube URLs, so we use the `audio_file` upload option). The Extraction API separates vocals and instrumental tracks and posts the result to the webhook.
### Stems webhook and Gokapi upload ### Stems webhook and Gokapi upload

View file

@ -1 +1 @@
0.8.7 0.8.8

6
app.py
View file

@ -1267,10 +1267,10 @@ def admin_request(rid):
if not song_path or not Path(song_path).exists(): if not song_path or not Path(song_path).exists():
flash(f'Version {selected.upper()} MP3 is not available. Generate or upload it first.', 'error') flash(f'Version {selected.upper()} MP3 is not available. Generate or upload it first.', 'error')
return redirect(url_for('admin_request', rid=rid)) return redirect(url_for('admin_request', rid=rid))
# Build a public URL the MusicGPT Extraction API can fetch. # Upload the MP3 file directly to the Extraction API.
audio_url = f"{current_app.config['PUBLIC_BASE_URL'].rstrip('/')}/api/audio-source/{req['player_token']}/{selected}.mp3" # The API's audio_url field only supports YouTube URLs, not direct MP3 links.
stems = request.form.getlist('stems') or ['vocals', 'instrumental'] stems = request.form.getlist('stems') or ['vocals', 'instrumental']
task_id, conv_id, estimate, error = musicgpt_queue_stems(rid, audio_url, stems=stems) task_id, conv_id, estimate, error = musicgpt_queue_stems(rid, song_path, stems=stems)
if error: if error:
update_request(rid, stems_status='ERROR', stems_error=error) update_request(rid, stems_status='ERROR', stems_error=error)
flash(f'Failed to queue stems extraction: {error}', 'error') flash(f'Failed to queue stems extraction: {error}', 'error')

View file

@ -619,21 +619,26 @@ def musicgpt_poll_status(task_id):
return {"error": str(e)} return {"error": str(e)}
def musicgpt_queue_stems(rid, audio_url, stems=None): def musicgpt_queue_stems(rid, audio_file_path, stems=None):
""" """
Queue a stem extraction job for a generated audio URL. Queue a stem extraction job by uploading the MP3 file directly.
The MusicGPT Extraction API's audio_url field only accepts YouTube URLs,
not direct MP3 URLs. We use the audio_file upload option instead.
Returns (task_id, conversion_id, credit_estimate, error_message). Returns (task_id, conversion_id, credit_estimate, error_message).
""" """
url = f"{MUSICGPT_API_BASE}/v2/Extraction" url = f"{MUSICGPT_API_BASE}/v2/Extraction"
if stems is None: if stems is None:
stems = ["vocals", "instrumental"] stems = ["vocals", "instrumental"]
payload = { payload = {
"audio_url": audio_url,
"stems": json.dumps(stems), "stems": json.dumps(stems),
"webhook_url": build_musicgpt_webhook_url(), "webhook_url": build_musicgpt_webhook_url(),
} }
try: try:
resp = requests.post(url, data=payload, headers={"Authorization": get_musicgpt_api_key()}, timeout=30) with open(audio_file_path, "rb") as f:
files = {"audio_file": f}
resp = requests.post(url, data=payload, files=files, headers={"Authorization": get_musicgpt_api_key()}, timeout=60)
try: try:
data = resp.json() data = resp.json()
except Exception: except Exception: