Pepguy commited on
Commit
99f646e
·
verified ·
1 Parent(s): c57bd11

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -88
app.py CHANGED
@@ -2,140 +2,164 @@ import os
2
  import uuid
3
  import subprocess
4
  import requests
5
- import base64
6
- from fastapi import FastAPI, UploadFile, File, Form, HTTPException, Request
7
- from fastapi.responses import HTMLResponse, JSONResponse
8
- from fastapi.middleware.cors import CORSMiddleware
9
 
10
  app = FastAPI()
11
 
12
- # Allow CORS for testing
13
- app.add_middleware(
14
- CORSMiddleware,
15
- allow_origins=["*"],
16
- allow_credentials=True,
17
- allow_methods=["*"],
18
- allow_headers=["*"],
19
- )
20
-
21
  # Base directory to store task files
22
  BASE_DIR = "tasks"
23
  os.makedirs(BASE_DIR, exist_ok=True)
24
 
 
 
 
 
25
  @app.post("/process")
26
- async def process_audio(
27
- request: Request,
28
- file: UploadFile = File(None),
29
- url: str = Form(None)
30
- ):
31
- if not file and not url:
32
- raise HTTPException(status_code=400, detail="Provide either a file or a URL.")
 
33
 
34
- # Generate unique task ID and create folder for this task
35
  task_id = str(uuid.uuid4())
36
  task_dir = os.path.join(BASE_DIR, task_id)
37
  os.makedirs(task_dir, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- # Download or read the file
40
- if file:
41
- filename = file.filename
42
- input_path = os.path.join(task_dir, filename)
43
- with open(input_path, "wb") as f:
44
- content = await file.read()
45
- f.write(content)
46
- else:
47
- # Download file from provided URL
48
- resp = requests.get(url)
49
- if resp.status_code != 200:
50
- raise HTTPException(status_code=400, detail="Failed to download file from URL.")
51
- ext = os.path.splitext(url)[1] or ".mp3"
52
- filename = f"input{ext}"
53
- input_path = os.path.join(task_dir, filename)
54
- with open(input_path, "wb") as f:
55
- f.write(resp.content)
56
 
57
- # Run Spleeter to separate into 2 stems (vocals and accompaniment)
58
- # Spleeter will create a subfolder named after the input file (without extension)
59
- cmd = [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  "spleeter", "separate",
61
- "-i", input_path,
62
  "-p", "spleeter:2stems",
63
  "-o", task_dir
64
  ]
 
65
  try:
66
- subprocess.run(cmd, check=True)
 
 
 
 
 
 
67
  except subprocess.CalledProcessError as e:
68
- raise HTTPException(status_code=500, detail=f"Spleeter processing failed: {e}")
69
-
70
- # Determine output folder name and expected files
71
- base_name = os.path.splitext(filename)[0]
72
- output_dir = os.path.join(task_dir, base_name)
73
- vocals_path = os.path.join(output_dir, "vocals.wav")
74
- accomp_path = os.path.join(output_dir, "accompaniment.wav")
75
 
76
- if not (os.path.exists(vocals_path) and os.path.exists(accomp_path)):
77
- raise HTTPException(status_code=500, detail="Output files not found after processing.")
78
-
79
- # Read output files and encode in base64
80
- with open(vocals_path, "rb") as f:
81
- vocals_data = f.read()
82
- with open(accomp_path, "rb") as f:
83
- accomp_data = f.read()
84
-
85
- vocals_b64 = base64.b64encode(vocals_data).decode("utf-8")
86
- accomp_b64 = base64.b64encode(accomp_data).decode("utf-8")
87
 
 
88
  return JSONResponse(content={
89
  "task_id": task_id,
90
- "vocals": vocals_b64,
91
- "accompaniment": accomp_b64
92
  })
93
 
94
  @app.get("/", response_class=HTMLResponse)
95
  def index():
 
96
  html_content = """
97
  <!DOCTYPE html>
98
  <html>
99
  <head>
100
- <title>Spleeter API Test</title>
101
  </head>
102
  <body>
103
- <h1>Spleeter API Test</h1>
104
- <form id="spleeterForm" enctype="multipart/form-data">
105
- <div>
106
- <label>Upload File:</label>
107
- <input type="file" name="file">
108
- </div>
109
- <div>
110
- <label>Or Enter URL:</label>
111
- <input type="text" name="url" size="50">
112
- </div>
113
  <button type="submit">Process Audio</button>
114
  </form>
115
- <div id="result"></div>
116
  <script>
117
  const form = document.getElementById('spleeterForm');
118
  form.onsubmit = async (e) => {
119
  e.preventDefault();
120
  const formData = new FormData(form);
 
121
  const response = await fetch('/process', {
122
  method: 'POST',
123
- body: formData
 
124
  });
125
  const data = await response.json();
126
- if (response.ok) {
127
- const vocalsSrc = "data:audio/wav;base64," + data.vocals;
128
- const accompSrc = "data:audio/wav;base64," + data.accompaniment;
129
-
130
- document.getElementById('result').innerHTML = `
131
- <h3>Vocals</h3>
132
- <audio controls src="${vocalsSrc}"></audio>
133
- <h3>Accompaniment</h3>
134
- <audio controls src="${accompSrc}"></audio>
135
- `;
136
- } else {
137
- document.getElementById('result').innerHTML = `<p>Error: ${data.detail}</p>`;
138
  }
 
139
  };
140
  </script>
141
  </body>
 
2
  import uuid
3
  import subprocess
4
  import requests
5
+ from fastapi import FastAPI, HTTPException
6
+ from fastapi.responses import JSONResponse, HTMLResponse
 
 
7
 
8
  app = FastAPI()
9
 
 
 
 
 
 
 
 
 
 
10
  # Base directory to store task files
11
  BASE_DIR = "tasks"
12
  os.makedirs(BASE_DIR, exist_ok=True)
13
 
14
+ def add_status(log_list, message):
15
+ log_list.append(message)
16
+ print(message) # Optionally log to console
17
+
18
  @app.post("/process")
19
+ def process_audio(payload: dict):
20
+ status_log = []
21
+ # Check for required URL parameter in the payload
22
+ if "url" not in payload:
23
+ raise HTTPException(status_code=400, detail="Missing 'url' in payload")
24
+
25
+ audio_url = payload["url"]
26
+ add_status(status_log, "Received URL from payload.")
27
 
28
+ # Create a unique task folder
29
  task_id = str(uuid.uuid4())
30
  task_dir = os.path.join(BASE_DIR, task_id)
31
  os.makedirs(task_dir, exist_ok=True)
32
+ add_status(status_log, f"Created task directory: {task_dir}")
33
+
34
+ # Check FFmpeg version
35
+ try:
36
+ ffmpeg_ver = subprocess.run(
37
+ ["ffmpeg", "-version"],
38
+ capture_output=True,
39
+ text=True,
40
+ check=True,
41
+ )
42
+ first_line = ffmpeg_ver.stdout.splitlines()[0]
43
+ add_status(status_log, f"FFmpeg version: {first_line}")
44
+ except Exception as e:
45
+ add_status(status_log, f"Failed to get FFmpeg version: {e}")
46
+ return JSONResponse(status_code=500, content={"status": status_log})
47
+
48
+ # Check Spleeter version
49
+ try:
50
+ spleeter_ver = subprocess.run(
51
+ ["spleeter", "--version"],
52
+ capture_output=True,
53
+ text=True,
54
+ check=True,
55
+ )
56
+ add_status(status_log, f"Spleeter version: {spleeter_ver.stdout.strip()}")
57
+ except Exception as e:
58
+ add_status(status_log, f"Failed to get Spleeter version: {e}")
59
+ return JSONResponse(status_code=500, content={"status": status_log})
60
+
61
+ # Download the audio file from the URL
62
+ try:
63
+ r = requests.get(audio_url)
64
+ r.raise_for_status()
65
+ add_status(status_log, "Successfully downloaded audio file.")
66
+ except Exception as e:
67
+ add_status(status_log, f"Error downloading file: {e}")
68
+ return JSONResponse(status_code=400, content={"status": status_log})
69
 
70
+ # Determine file extension (default to .mp3 if not found)
71
+ ext = os.path.splitext(audio_url)[1] or ".mp3"
72
+ input_filename = f"input{ext}"
73
+ input_filepath = os.path.join(task_dir, input_filename)
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
+ # Save the downloaded file
76
+ try:
77
+ with open(input_filepath, "wb") as f:
78
+ f.write(r.content)
79
+ add_status(status_log, f"Saved audio file to: {input_filepath}")
80
+ except Exception as e:
81
+ add_status(status_log, f"Error saving file: {e}")
82
+ return JSONResponse(status_code=500, content={"status": status_log})
83
+
84
+ # Verify that the file exists
85
+ if not os.path.exists(input_filepath):
86
+ add_status(status_log, "Error: Input file does not exist after download.")
87
+ return JSONResponse(status_code=500, content={"status": status_log})
88
+
89
+ # Run Spleeter to separate the file using the 2-stems model (vocals and accompaniment)
90
+ base_name = os.path.splitext(input_filename)[0]
91
+ spleeter_cmd = [
92
  "spleeter", "separate",
93
+ "-i", input_filepath,
94
  "-p", "spleeter:2stems",
95
  "-o", task_dir
96
  ]
97
+ add_status(status_log, "Running Spleeter command: " + " ".join(spleeter_cmd))
98
  try:
99
+ result = subprocess.run(
100
+ spleeter_cmd,
101
+ capture_output=True,
102
+ text=True,
103
+ check=True,
104
+ )
105
+ add_status(status_log, "Spleeter command output: " + result.stdout)
106
  except subprocess.CalledProcessError as e:
107
+ add_status(status_log, "Spleeter processing failed: " + e.stderr)
108
+ return JSONResponse(status_code=500, content={"status": status_log})
 
 
 
 
 
109
 
110
+ # Define expected output files
111
+ output_folder = os.path.join(task_dir, base_name)
112
+ vocals_file = os.path.join(output_folder, "vocals.wav")
113
+ accompaniment_file = os.path.join(output_folder, "accompaniment.wav")
114
+ if not (os.path.exists(vocals_file) and os.path.exists(accompaniment_file)):
115
+ add_status(status_log, "Error: Output files not found after processing.")
116
+ return JSONResponse(status_code=500, content={"status": status_log})
117
+
118
+ add_status(status_log, "Spleeter processing completed successfully.")
 
 
119
 
120
+ # Return the task ID and status log to the frontend
121
  return JSONResponse(content={
122
  "task_id": task_id,
123
+ "status": status_log
 
124
  })
125
 
126
  @app.get("/", response_class=HTMLResponse)
127
  def index():
128
+ # Simple HTML page to test the API and display status logs.
129
  html_content = """
130
  <!DOCTYPE html>
131
  <html>
132
  <head>
133
+ <title>Spleeter Processing Test</title>
134
  </head>
135
  <body>
136
+ <h1>Spleeter Processing Test</h1>
137
+ <form id="spleeterForm">
138
+ Audio URL: <input type="text" name="url" size="50"/><br/><br/>
 
 
 
 
 
 
 
139
  <button type="submit">Process Audio</button>
140
  </form>
141
+ <div id="result" style="margin-top:20px;"></div>
142
  <script>
143
  const form = document.getElementById('spleeterForm');
144
  form.onsubmit = async (e) => {
145
  e.preventDefault();
146
  const formData = new FormData(form);
147
+ const url = formData.get('url');
148
  const response = await fetch('/process', {
149
  method: 'POST',
150
+ headers: { 'Content-Type': 'application/json' },
151
+ body: JSON.stringify({ url })
152
  });
153
  const data = await response.json();
154
+ let resultHTML = "<h3>Status Log:</h3><ul>";
155
+ for (const log of data.status) {
156
+ resultHTML += "<li>" + log + "</li>";
157
+ }
158
+ resultHTML += "</ul>";
159
+ if(data.task_id) {
160
+ resultHTML += `<p>Task ID: ${data.task_id}</p>`;
 
 
 
 
 
161
  }
162
+ document.getElementById('result').innerHTML = resultHTML;
163
  };
164
  </script>
165
  </body>