voice-isolation-live / docs /step-3-frontend.md
TonyLikeDev's picture
initial commit
0f623ae
|
Raw
History Blame Contribute Delete
3.89 kB

Step 3 β€” Frontend

Status: TODO

Goal

A simple webpage where the user uploads an audio file, waits while Demucs processes it, then plays back both the original and the cleaned vocal track side by side.


Files to create

frontend/
β”œβ”€β”€ index.html    # Upload form + audio players
β”œβ”€β”€ style.css     # Basic layout and styling
└── app.js        # Handles upload, polling, and playback

How to build it

1. Create frontend/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Voice Isolation</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="card">
    <h1>Voice Isolation</h1>
    <p>Upload an audio file to remove background noise.</p>

    <input type="file" id="fileInput" accept="audio/*">
    <button id="uploadBtn">Upload & Clean</button>

    <div id="status"></div>

    <div class="players" id="players" hidden>
      <div>
        <p>Original</p>
        <audio id="originalPlayer" controls></audio>
      </div>
      <div>
        <p>Cleaned</p>
        <audio id="cleanedPlayer" controls></audio>
      </div>
    </div>
  </div>

  <script src="app.js"></script>
</body>
</html>

2. Create frontend/app.js

const uploadBtn = document.getElementById('uploadBtn');
const fileInput = document.getElementById('fileInput');
const status = document.getElementById('status');
const players = document.getElementById('players');
const originalPlayer = document.getElementById('originalPlayer');
const cleanedPlayer = document.getElementById('cleanedPlayer');

uploadBtn.addEventListener('click', async () => {
  const file = fileInput.files[0];
  if (!file) {
    status.textContent = 'Please select a file first.';
    return;
  }

  status.textContent = 'Uploading and processing... this takes 1-3 minutes.';
  players.hidden = true;

  const formData = new FormData();
  formData.append('file', file);

  const response = await fetch('http://localhost:8000/upload', {
    method: 'POST',
    body: formData,
  });

  const data = await response.json();

  originalPlayer.src = URL.createObjectURL(file);
  cleanedPlayer.src = `http://localhost:8000${data.download_url}`;

  players.hidden = false;
  status.textContent = 'Done!';
});

3. Create frontend/style.css

body {
  font-family: sans-serif;
  background: #f4f4f4;
  display: flex;
  justify-content: center;
  padding: 40px 20px;
}

.card {
  background: white;
  padding: 32px;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.1);
  max-width: 560px;
  width: 100%;
}

h1 { margin-top: 0; }

input[type="file"] { display: block; margin: 16px 0; }

button {
  background: #2563eb;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 16px;
}

button:hover { background: #1d4ed8; }

#status { margin: 16px 0; color: #555; }

.players {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 16px;
}

How to open it

Just open the HTML file directly in the browser β€” no server needed for the frontend:

xdg-open frontend/index.html   # Linux

Make sure the FastAPI backend is running first:

source venv/bin/activate
uvicorn backend.main:app --reload

What the user sees

  1. Opens the page β€” sees a clean upload card
  2. Selects an audio file
  3. Clicks "Upload & Clean"
  4. Status shows "Processing..." while Demucs runs
  5. Two audio players appear: original and cleaned
  6. User hits play on both to compare

Notes

  • The backend URL is hardcoded to localhost:8000 β€” update this to the live Hugging Face URL after deployment
  • No file type validation on the frontend yet β€” the backend will reject non-audio files anyway
  • Processing takes 1–3 minutes on CPU β€” the status message sets that expectation for the user