Download Stems button now zips all stem files into a single .zip
- New /admin/request/<id>/download-stems endpoint - Parses stems_url (label: url; label: url format), fetches each stem file, bundles them into a zip served as an attachment download - If MusicGPT returns a single .zip bundle URL, redirects directly - Template button now points to the zip endpoint instead of raw CDN URLs
This commit is contained in:
parent
c676acd32f
commit
f2c64848dd
2 changed files with 73 additions and 1 deletions
72
app.py
72
app.py
|
|
@ -34,6 +34,9 @@ import hmac
|
|||
import shutil
|
||||
import time
|
||||
import json
|
||||
import io
|
||||
import zipfile
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
# Flask and related imports
|
||||
|
|
@ -790,6 +793,75 @@ def audio(token, version):
|
|||
abort(404)
|
||||
|
||||
|
||||
@app.route('/admin/request/<int:rid>/download-stems')
|
||||
def admin_download_stems(rid):
|
||||
"""Download all stems files for a request as a single .zip archive."""
|
||||
redir = require_admin()
|
||||
if redir:
|
||||
return redir
|
||||
req = get_request_by_id(rid)
|
||||
if not req:
|
||||
abort(404)
|
||||
req = dict(req)
|
||||
|
||||
stems_url = req.get('stems_url') or ''
|
||||
if not stems_url:
|
||||
flash('No stems available to download.', 'error')
|
||||
return redirect(url_for('admin_request', rid=rid))
|
||||
|
||||
# Parse the stems_url field. It can be:
|
||||
# 1. A single bundle/zip URL (use directly)
|
||||
# 2. "label1: url1; label2: url2" (multiple individual stem files)
|
||||
# 3. Just a bare URL
|
||||
urls = []
|
||||
if ';' in stems_url or ': ' in stems_url:
|
||||
# Multiple stems: "instrumental: https://...; vocals: https://..."
|
||||
parts = stems_url.split(';')
|
||||
for part in parts:
|
||||
part = part.strip()
|
||||
if not part:
|
||||
continue
|
||||
# Split on first ": " to separate label from URL
|
||||
if ': ' in part:
|
||||
label, url = part.split(': ', 1)
|
||||
urls.append((label.strip(), url.strip()))
|
||||
else:
|
||||
urls.append(('stem', part))
|
||||
else:
|
||||
urls.append(('stems', stems_url.strip()))
|
||||
|
||||
if not urls:
|
||||
flash('No stems files found.', 'error')
|
||||
return redirect(url_for('admin_request', rid=rid))
|
||||
|
||||
# If there's only one URL and it's already a .zip, redirect directly.
|
||||
if len(urls) == 1 and urls[0][1].endswith('.zip'):
|
||||
return redirect(urls[0][1])
|
||||
|
||||
# Download each stem file and bundle them into a zip in memory.
|
||||
import requests as req_lib
|
||||
buf = io.BytesIO()
|
||||
with zipfile.ZipFile(buf, 'w', zipfile.ZIP_DEFLATED) as zf:
|
||||
for label, url in urls:
|
||||
try:
|
||||
r = req_lib.get(url, timeout=60)
|
||||
r.raise_for_status()
|
||||
# Derive a filename from the URL or label.
|
||||
filename = url.split('/')[-1] if '/' in url else f"{label}.mp3"
|
||||
# If the URL has no extension, use the label.
|
||||
if '.' not in filename:
|
||||
filename = f"{label}.mp3"
|
||||
zf.writestr(filename, r.content)
|
||||
except Exception:
|
||||
# Skip files that fail to download, but include the rest.
|
||||
pass
|
||||
buf.seek(0)
|
||||
|
||||
title = req.get('suno_title') or req.get('name') or f'request_{rid}'
|
||||
download_name = f"stems_{title}.zip"
|
||||
return send_file(buf, mimetype='application/zip', as_attachment=True, download_name=download_name)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Admin routes
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -618,7 +618,7 @@
|
|||
{% endif %}
|
||||
{% if req.stems_url %}
|
||||
<div class="actions">
|
||||
<a href="{{ req.stems_url }}" target="_blank" rel="noopener noreferrer" class="button-link" style="display:inline-flex;align-items:center;gap:.4rem;padding:.5rem 1rem;background:#4b5563;border-radius:.375rem;color:#fff;text-decoration:none;font-size:.875rem">⬇ Download Stems</a>
|
||||
<a href="{{ url_for('admin_download_stems', rid=req.id) }}" class="button-link" style="display:inline-flex;align-items:center;gap:.4rem;padding:.5rem 1rem;background:#4b5563;border-radius:.375rem;color:#fff;text-decoration:none;font-size:.875rem">⬇ Download Stems (zip)</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue