File size: 7,233 Bytes
a8336db
 
3938d12
a8336db
436a01d
ce39a4a
99f646e
 
07221e5
 
 
436a01d
a8336db
 
 
99f646e
 
05a9187
99f646e
a8336db
99f646e
 
ce39a4a
 
99f646e
 
 
 
 
ce39a4a
 
a8336db
 
 
99f646e
ce39a4a
99f646e
 
 
 
 
 
 
 
 
 
 
 
 
ce39a4a
99f646e
 
 
 
 
 
 
 
 
 
 
 
ce39a4a
 
99f646e
 
 
 
 
 
 
ce39a4a
05a9187
ce39a4a
436a01d
ce39a4a
99f646e
 
ce39a4a
99f646e
 
 
 
 
 
 
ce39a4a
99f646e
 
 
ce39a4a
05a9187
ce39a4a
99f646e
a8336db
 
ce39a4a
 
a8336db
99f646e
ce39a4a
a8336db
ce39a4a
99f646e
a8336db
99f646e
 
ce39a4a
05a9187
ce39a4a
99f646e
 
 
ce39a4a
99f646e
 
 
 
 
ce39a4a
05a9187
436a01d
 
 
 
 
 
 
 
 
 
 
a8336db
 
436a01d
 
99f646e
a8336db
3938d12
a8336db
 
 
 
 
 
99f646e
a8336db
 
99f646e
 
 
a8336db
 
99f646e
a8336db
 
 
 
 
99f646e
a8336db
 
99f646e
 
a8336db
 
99f646e
 
 
 
 
436a01d
 
 
 
 
 
 
 
99f646e
 
a8336db
99f646e
a8336db
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import os
import uuid
import subprocess
import requests
import base64
from urllib.parse import urlparse
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse, HTMLResponse

app = FastAPI()

# Base directory to store task files
BASE_DIR = "tasks"
os.makedirs(BASE_DIR, exist_ok=True)

def add_status(log_list, message):
    log_list.append(message)
    print(message)  # Also log to console

@app.post("/process")
def process_audio(payload: dict):
    status_log = []
    
    # Validate input
    if "url" not in payload:
        raise HTTPException(status_code=400, detail="Missing 'url' in payload")
    
    audio_url = payload["url"]
    add_status(status_log, "Received URL from payload.")
    
    # Create a unique task directory
    task_id = str(uuid.uuid4())
    task_dir = os.path.join(BASE_DIR, task_id)
    os.makedirs(task_dir, exist_ok=True)
    add_status(status_log, f"Created task directory: {task_dir}")
    
    # Check FFmpeg version
    try:
        ffmpeg_ver = subprocess.run(
            ["ffmpeg", "-version"],
            capture_output=True,
            text=True,
            check=True,
        )
        first_line = ffmpeg_ver.stdout.splitlines()[0]
        add_status(status_log, f"FFmpeg version: {first_line}")
    except Exception as e:
        add_status(status_log, f"Failed to get FFmpeg version: {e}")
        return JSONResponse(status_code=500, content={"status": status_log})
    
    # Check Spleeter version
    try:
        spleeter_ver = subprocess.run(
            ["spleeter", "--version"],
            capture_output=True,
            text=True,
            check=True,
        )
        add_status(status_log, f"Spleeter version: {spleeter_ver.stdout.strip()}")
    except Exception as e:
        add_status(status_log, f"Failed to get Spleeter version: {e}")
        return JSONResponse(status_code=500, content={"status": status_log})
    
    # Download the audio file
    try:
        r = requests.get(audio_url)
        r.raise_for_status()
        add_status(status_log, "Successfully downloaded audio file.")
    except Exception as e:
        add_status(status_log, f"Error downloading file: {e}")
        return JSONResponse(status_code=400, content={"status": status_log})
    
    # Clean filename: remove query parameters using urlparse
    parsed = urlparse(audio_url)
    path = parsed.path
    ext = os.path.splitext(path)[1] or ".mp3"
    input_filename = f"input{ext}"
    input_filepath = os.path.join(task_dir, input_filename)
    
    try:
        with open(input_filepath, "wb") as f:
            f.write(r.content)
        add_status(status_log, f"Saved audio file to: {input_filepath}")
    except Exception as e:
        add_status(status_log, f"Error saving file: {e}")
        return JSONResponse(status_code=500, content={"status": status_log})
    
    if not os.path.exists(input_filepath):
        add_status(status_log, "Error: Input file does not exist after download.")
        return JSONResponse(status_code=500, content={"status": status_log})
    
    # Run Spleeter using the updated syntax:
    # spleeter separate -p spleeter:2stems -o <task_dir> <input_filepath>
    spleeter_cmd = [
        "spleeter", "separate",
        "-p", "spleeter:2stems",
        "-o", task_dir,
        input_filepath
    ]
    add_status(status_log, "Running Spleeter command: " + " ".join(spleeter_cmd))
    
    try:
        result = subprocess.run(spleeter_cmd, capture_output=True, text=True, check=True)
        add_status(status_log, "Spleeter command output: " + result.stdout)
    except subprocess.CalledProcessError as e:
        add_status(status_log, "Spleeter processing failed: " + e.stderr)
        return JSONResponse(status_code=500, content={"status": status_log})
    
    # Spleeter creates an output folder with the base name of the input file.
    base_name = os.path.splitext(input_filename)[0]
    output_folder = os.path.join(task_dir, base_name)
    vocals_file = os.path.join(output_folder, "vocals.wav")
    accompaniment_file = os.path.join(output_folder, "accompaniment.wav")
    
    if not (os.path.exists(vocals_file) and os.path.exists(accompaniment_file)):
        add_status(status_log, "Error: Output files not found after processing.")
        return JSONResponse(status_code=500, content={"status": status_log})
    
    add_status(status_log, "Spleeter processing completed successfully.")
    
    # Read output files and encode them in base64
    try:
        with open(vocals_file, "rb") as f:
            vocals_data = f.read()
        with open(accompaniment_file, "rb") as f:
            accomp_data = f.read()
        vocals_b64 = base64.b64encode(vocals_data).decode("utf-8")
        accomp_b64 = base64.b64encode(accomp_data).decode("utf-8")
    except Exception as e:
        add_status(status_log, f"Error reading output files: {e}")
        return JSONResponse(status_code=500, content={"status": status_log})
    
    return JSONResponse(content={
        "task_id": task_id,
        "vocals": vocals_b64,
        "accompaniment": accomp_b64,
        "status": status_log
    })

@app.get("/", response_class=HTMLResponse)
def index():
    html_content = """
    <!DOCTYPE html>
    <html>
    <head>
        <title>Spleeter Processing Test</title>
    </head>
    <body>
        <h1>Spleeter Processing Test</h1>
        <form id="spleeterForm">
            Audio URL: <input type="text" name="url" size="50"/><br/><br/>
            <button type="submit">Process Audio</button>
        </form>
        <div id="result" style="margin-top:20px;"></div>
        <script>
            const form = document.getElementById('spleeterForm');
            form.onsubmit = async (e) => {
                e.preventDefault();
                const formData = new FormData(form);
                const url = formData.get('url');
                const response = await fetch('/process', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ url })
                });
                const data = await response.json();
                let resultHTML = "<h3>Status Log:</h3><ul>";
                for (const log of data.status) {
                    resultHTML += "<li>" + log + "</li>";
                }
                resultHTML += "</ul>";
                if (data.vocals && data.accompaniment) {
                    const vocalsDataURI = "data:audio/wav;base64," + data.vocals;
                    const accompDataURI = "data:audio/wav;base64," + data.accompaniment;
                    resultHTML += "<h3>Vocals</h3>";
                    resultHTML += "<audio controls src='" + vocalsDataURI + "'></audio>";
                    resultHTML += "<h3>Accompaniment</h3>";
                    resultHTML += "<audio controls src='" + accompDataURI + "'></audio>";
                }
                if(data.task_id) {
                    resultHTML += `<p>Task ID: ${data.task_id}</p>`;
                }
                document.getElementById('result').innerHTML = resultHTML;
            };
        </script>
    </body>
    </html>
    """
    return HTMLResponse(content=html_content)