gaandrade99's picture
Upload folder using huggingface_hub
36a5020 verified
Raw
History Blame Contribute Delete
8.45 kB
import torch
import scipy
import tempfile
import os
import uuid
from pathlib import Path
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, FileResponse, JSONResponse
import uvicorn
from diffusers import AudioLDMPipeline
print("Loading AudioLDM Small model...")
pipe = AudioLDMPipeline.from_pretrained(
"cvssp/audioldm-s-full-v2",
torch_dtype=torch.float32,
)
print("Model loaded successfully!")
app = FastAPI()
OUTPUT_DIR = Path(tempfile.gettempdir()) / "sfx_outputs"
OUTPUT_DIR.mkdir(exist_ok=True)
HTML_PAGE = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🔊 AudioLDM - Sound Effects Generator</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Segoe UI', sans-serif; background: #0b0f19; color: #e5e7eb; min-height: 100vh; display: flex; justify-content: center; padding: 2rem; }
.container { max-width: 600px; width: 100%; }
h1 { text-align: center; font-size: 1.8rem; margin-bottom: 0.5rem; }
.subtitle { text-align: center; color: #9ca3af; margin-bottom: 2rem; font-size: 0.9rem; }
.field { margin-bottom: 1.2rem; }
label { display: block; font-weight: 600; margin-bottom: 0.4rem; font-size: 0.9rem; }
input[type=text], textarea { width: 100%; padding: 0.7rem; border-radius: 8px; border: 1px solid #374151; background: #1f2937; color: #e5e7eb; font-size: 0.95rem; }
input[type=range] { width: 100%; accent-color: #6366f1; }
.range-info { display: flex; justify-content: space-between; font-size: 0.8rem; color: #9ca3af; }
button { width: 100%; padding: 0.9rem; background: #6366f1; color: white; border: none; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; margin-top: 0.5rem; }
button:hover { background: #4f46e5; }
button:disabled { background: #374151; cursor: not-allowed; }
.status { text-align: center; margin-top: 1rem; padding: 0.8rem; border-radius: 8px; display: none; }
.status.loading { display: block; background: #1e3a5f; color: #93c5fd; }
.status.error { display: block; background: #3b1111; color: #fca5a5; }
.status.success { display: block; background: #0f2e1a; color: #86efac; }
.result { margin-top: 1.5rem; display: none; }
.result.show { display: block; }
audio { width: 100%; margin-top: 0.5rem; }
.download { display: inline-block; margin-top: 0.5rem; color: #818cf8; text-decoration: none; }
.examples { margin-top: 2rem; }
.examples h3 { font-size: 0.9rem; margin-bottom: 0.5rem; color: #9ca3af; }
.example-btn { display: inline-block; padding: 0.4rem 0.8rem; background: #1f2937; border: 1px solid #374151; border-radius: 6px; margin: 0.2rem; cursor: pointer; font-size: 0.8rem; color: #d1d5db; }
.example-btn:hover { border-color: #6366f1; color: #a5b4fc; }
</style>
</head>
<body>
<div class="container">
<h1>🔊 AudioLDM SFX Generator</h1>
<p class="subtitle">Generate sound effects from text using AudioLDM (fast model)</p>
<div class="field">
<label for="prompt">Prompt</label>
<input type="text" id="prompt" placeholder="cinematic whoosh, explosion, footsteps on gravel...">
</div>
<div class="field">
<label for="neg">Negative Prompt</label>
<input type="text" id="neg" value="Low quality, distorted, noise, music.">
</div>
<div class="field">
<label>Duration: <span id="dur-val">3</span>s</label>
<input type="range" id="duration" min="1" max="10" value="3" step="1" oninput="document.getElementById('dur-val').textContent=this.value">
<div class="range-info"><span>1s</span><span>10s</span></div>
</div>
<div class="field">
<label>Steps: <span id="steps-val">20</span></label>
<input type="range" id="steps" min="10" max="50" value="20" step="5" oninput="document.getElementById('steps-val').textContent=this.value">
<div class="range-info"><span>10 (fast)</span><span>50 (quality)</span></div>
</div>
<button id="gen-btn" onclick="generate()">🎵 Generate Sound Effect</button>
<div id="status" class="status"></div>
<div id="result" class="result">
<audio id="audio" controls></audio><br>
<a id="dl-link" class="download" href="#" download="sfx.wav">⬇ Download WAV</a>
</div>
<div class="examples">
<h3>Examples (click to fill):</h3>
<span class="example-btn" onclick="fillExample('cinematic whoosh transition sound')">cinematic whoosh</span>
<span class="example-btn" onclick="fillExample('deep bass impact hit')">bass impact</span>
<span class="example-btn" onclick="fillExample('footsteps walking on gravel')">footsteps gravel</span>
<span class="example-btn" onclick="fillExample('thunder and rain storm')">thunder rain</span>
<span class="example-btn" onclick="fillExample('digital glitch notification beep')">glitch beep</span>
<span class="example-btn" onclick="fillExample('sword swing slash whoosh')">sword slash</span>
<span class="example-btn" onclick="fillExample('car engine revving')">car engine</span>
<span class="example-btn" onclick="fillExample('ocean waves crashing on shore')">ocean waves</span>
</div>
</div>
<script>
function fillExample(t) { document.getElementById('prompt').value = t; }
async function generate() {
const btn = document.getElementById('gen-btn');
const status = document.getElementById('status');
const result = document.getElementById('result');
const prompt = document.getElementById('prompt').value.trim();
if (!prompt) { status.className='status error'; status.textContent='Please enter a prompt.'; return; }
btn.disabled = true;
btn.textContent = '⏳ Generating...';
status.className = 'status loading';
status.textContent = 'Generating sound effect... ~5-15 seconds.';
result.className = 'result';
try {
const res = await fetch('/api/generate', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: prompt,
negative_prompt: document.getElementById('neg').value,
duration: parseInt(document.getElementById('duration').value),
steps: parseInt(document.getElementById('steps').value)
})
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.detail || 'Generation failed');
}
const data = await res.json();
document.getElementById('audio').src = data.url;
document.getElementById('dl-link').href = data.url;
result.className = 'result show';
status.className = 'status success';
status.textContent = 'Done! Generation time: ' + data.generation_time.toFixed(1) + 's';
} catch(e) {
status.className = 'status error';
status.textContent = 'Error: ' + e.message;
} finally {
btn.disabled = false;
btn.textContent = '🎵 Generate Sound Effect';
}
}
</script>
</body>
</html>"""
@app.get("/", response_class=HTMLResponse)
async def index():
return HTML_PAGE
@app.post("/api/generate")
async def generate(request: Request):
import time
body = await request.json()
prompt = body.get("prompt", "").strip()
if not prompt:
return JSONResponse({"detail": "Prompt is required"}, status_code=400)
negative_prompt = body.get("negative_prompt", "Low quality, distorted.")
duration = min(max(int(body.get("duration", 3)), 1), 10)
steps = min(max(int(body.get("steps", 20)), 10), 50)
start = time.time()
audio = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=steps,
audio_length_in_s=float(duration),
guidance_scale=2.5,
num_waveforms_per_prompt=1,
).audios[0]
gen_time = time.time() - start
filename = f"sfx_{uuid.uuid4().hex[:8]}.wav"
out_path = OUTPUT_DIR / filename
scipy.io.wavfile.write(str(out_path), rate=16000, data=audio)
return {"url": f"/files/{filename}", "generation_time": gen_time}
@app.get("/files/{filename}")
async def get_file(filename: str):
filepath = OUTPUT_DIR / filename
if not filepath.exists():
return JSONResponse({"detail": "File not found"}, status_code=404)
return FileResponse(str(filepath), media_type="audio/wav", filename=filename)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860)