beat_tracking / templates /index.html
ginchiostro's picture
Update templates/index.html
f20dfcc verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="#">
<title>Beat Finder</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
:root {
--primary-color: #00a8e8;
--secondary-color: #00c4ff;
--background-start: #0d1b2a;
--background-end: #1b263b;
--container-bg: rgba(255, 255, 255, 0.05);
--text-color: #f0f0f0;
--text-muted-color: #c0c0c0;
--success-color: #57cc99;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, var(--background-start), var(--background-end));
background-attachment: fixed;
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.container {
width: 100%;
max-width: 800px;
background: var(--container-bg);
padding: 2rem 3rem;
border-radius: 20px;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
text-align: center;
}
h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
color: #fff;
}
p {
font-size: 1.1rem;
font-weight: 300;
color: var(--text-muted-color);
margin-bottom: 2rem;
line-height: 1.6;
}
#upload-form {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
margin-bottom: 2rem;
}
input[type="file"] {
display: none;
}
.file-label {
display: inline-block;
padding: 12px 25px;
background-color: var(--primary-color);
color: white;
border-radius: 50px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.file-label:hover {
background-color: var(--secondary-color);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
#selected-file-name {
color: var(--text-muted-color);
margin: -0.5rem 0;
font-size: 0.9rem;
min-height: 1.2rem;
font-style: italic;
}
#submitButton {
width: 100%;
max-width: 200px;
}
.btn, input[type="submit"] {
background-color: transparent;
color: var(--text-color);
border: 2px solid var(--primary-color);
padding: 12px 25px;
border-radius: 50px;
font-size: 1rem;
font-weight: 600;
font-family: 'Poppins', sans-serif;
cursor: pointer;
transition: all 0.3s ease;
}
.btn:disabled, input[type="submit"]:disabled {
opacity: 0.5;
cursor: not-allowed;
background-color: transparent !important;
color: var(--text-color) !important;
}
.btn:hover, input[type="submit"]:hover {
background-color: var(--primary-color);
color: white;
}
.btn:disabled:hover, input[type="submit"]:disabled:hover {
transform: none;
box-shadow: none;
}
.btn.primary {
background-color: var(--primary-color);
color: white;
}
.btn.primary:hover {
background-color: var(--secondary-color);
}
#buttonAddClicks, #buttonNewSong {
margin-top: 1rem;
}
#song_uploaded_succesfully {
color: var(--success-color);
font-weight: 600;
font-size: 1.1rem;
margin-top: 1rem;
margin-bottom: 1rem;
min-height: 1.5rem;
}
.audio-players-container {
display: flex;
justify-content: center;
align-items: flex-start;
gap: 2rem;
width: 100%;
margin-top: 1.5rem;
flex-wrap: wrap;
transition: justify-content 0.5s ease;
}
.audio-players-container.two-up {
justify-content: space-between;
}
.player-wrapper {
flex: 1 1 250px;
min-width: 250px;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.player-wrapper h3 {
font-weight: 400;
color: var(--text-muted-color);
font-size: 1rem;
margin-bottom: 0.5rem;
}
audio {
width: 100%;
filter: invert(1) hue-rotate(180deg);
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
backdrop-filter: blur(5px);
}
.modal-content {
background: var(--container-bg);
padding: 2rem;
border-radius: 20px;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
border: 1px solid rgba(255, 255, 255, 0.18);
text-align: center;
max-width: 90%;
width: 450px;
}
.modal-content h2 {
margin-bottom: 1rem;
color: #fff;
}
.modal-content p {
font-size: 1rem;
}
.modal-buttons {
display: flex;
justify-content: center;
gap: 1rem;
margin-top: 2rem;
}
.spinner {
border: 4px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 4px solid var(--primary-color);
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 1.5rem auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.modal-content .spinner + p {
margin-top: 0;
}
[hidden] {
display: none !important;
}
</style>
</head>
<body>
<div class="container">
<h1>Beat Finder</h1>
<p>After uploading your music track, it will be preprocessed, passed to a neural network, and postprocessed to add the beats to it. For optimal performance, upload a music track of about 10 seconds.</p>
<form action="/upload" method="post" enctype="multipart/form-data" id="upload-form">
<label for="file_id" class="file-label">Select a file</label>
<input type="file" name="file" id="file_id">
<p id="selected-file-name" hidden></p>
<input type="submit" id="submitButton" value="Upload File" hidden>
</form>
<p id='song_uploaded_succesfully' aria-live="polite"></p>
<div id="audio-players-container" class="audio-players-container" hidden>
<div id="player1-wrapper" class="player-wrapper" hidden>
<h3>Original Song</h3>
<audio controls id="audioPlayer1">
Your browser does not support the audio element.
</audio>
</div>
<div id="player2-wrapper" class="player-wrapper" hidden>
<h3>Song with Beats</h3>
<audio id="audioPlayer" controls>
Your browser does not support the audio element.
</audio>
</div>
</div>
<button type="button" id='buttonAddClicks' class="btn" hidden>Add beats</button>
<button type="button" id='buttonNewSong' class="btn" hidden>New song</button>
</div>
<div id="confirmation-modal" class="modal-overlay" hidden>
<div class="modal-content">
<h2>Are you sure?</h2>
<p>Starting a new song will discard the current one and its processed version. This action cannot be undone.</p>
<div class="modal-buttons">
<button id="cancel-new-song" class="btn">No, go back</button>
<button id="confirm-new-song" class="btn primary">Yes, new song</button>
</div>
</div>
</div>
<div id="loading-modal" class="modal-overlay" hidden>
<div class="modal-content">
<h2>Processing Song...</h2>
<div class="spinner"></div>
<p>Adding beats, please wait a moment.</p>
</div>
</div>
<script>
let song_name = 'placeholder';
const fileInput = document.getElementById('file_id');
const fileLabel = document.querySelector('.file-label');
const playersContainer = document.getElementById('audio-players-container');
const selectedFileNameP = document.getElementById('selected-file-name');
fileInput.addEventListener('change', function() {
const submitButton = document.getElementById('submitButton');
if (this.files && this.files.length > 0) {
selectedFileNameP.textContent = `You selected ${this.files[0].name}`;
selectedFileNameP.hidden = false;
submitButton.hidden = false;
} else {
selectedFileNameP.textContent = '';
selectedFileNameP.hidden = true;
submitButton.hidden = true;
}
});
function showElement(elementId) {
const element = document.getElementById(elementId);
element.hidden = false;
}
function hideElement(elementId) {
const element = document.getElementById(elementId);
element.hidden = true;
}
function setControlsDisabled(disabled) {
document.getElementById('file_id').disabled = disabled;
document.getElementById('submitButton').disabled = disabled;
document.getElementById('buttonAddClicks').disabled = disabled;
document.getElementById('buttonNewSong').disabled = disabled;
const fileLabel = document.querySelector('.file-label');
if (disabled) {
fileLabel.style.opacity = '0.5';
fileLabel.style.cursor = 'not-allowed';
} else {
fileLabel.style.opacity = '1';
fileLabel.style.cursor = 'pointer';
}
}
document.getElementById('upload-form').addEventListener('submit', function(event) {
event.preventDefault();
if (!fileInput.files || fileInput.files.length === 0) {
alert('Please select a file first!');
return;
}
const form = event.target;
const formData = new FormData(form);
song_name = document.getElementById('file_id').files[0].name;
fetch('/upload', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(message => {
console.log(message);
form.reset();
document.getElementById('submitButton').hidden = true;
selectedFileNameP.textContent = '';
selectedFileNameP.hidden = true;
const successMessage = song_name + ' song uploaded successfully';
document.getElementById('song_uploaded_succesfully').innerText = successMessage;
showElement('buttonAddClicks');
showElement('audio-players-container');
showElement('player1-wrapper');
const audioSourceUrl = "/static/uploaded_songs/" + song_name;
const audioPlayer1 = document.getElementById('audioPlayer1');
audioPlayer1.src = audioSourceUrl;
audioPlayer1.load();
});
});
document.getElementById('buttonAddClicks').addEventListener('click', function(event) {
showElement('loading-modal');
setControlsDisabled(true);
fetch('/get_beat', {
method: 'POST',
body: JSON.stringify(song_name)
})
.then(response => response.text())
.then(message => {
console.log(message);
hideElement('loading-modal');
const audioSourceUrl = "/static/" + song_name.slice(0, -4) + '_clicks.wav';
const audioPlayer = document.getElementById('audioPlayer');
audioPlayer.src = audioSourceUrl;
audioPlayer.load();
audioPlayer.addEventListener('canplaythrough', function() {
showElement('player2-wrapper');
playersContainer.classList.add('two-up');
const newSongButton = document.getElementById('buttonNewSong');
newSongButton.hidden = false;
newSongButton.disabled = false;
hideElement('buttonAddClicks');
hideElement('upload-form');
}, { once: true });
})
.catch(error => {
console.error("Error adding beats:", error);
hideElement('loading-modal');
setControlsDisabled(false);
alert('An error occurred while adding beats. Please try again.');
});
});
function resetApp() {
document.getElementById('song_uploaded_succesfully').innerText = '';
const addBeatsButton = document.getElementById('buttonAddClicks');
addBeatsButton.innerText = 'Add beats';
addBeatsButton.disabled = false;
hideElement('buttonAddClicks');
const audioPlayer = document.getElementById('audioPlayer');
audioPlayer.pause();
audioPlayer.src = '';
const audioPlayer1 = document.getElementById('audioPlayer1');
audioPlayer1.pause();
audioPlayer1.src = '';
hideElement('player1-wrapper');
hideElement('player2-wrapper');
hideElement('audio-players-container');
playersContainer.classList.remove('two-up');
hideElement('buttonNewSong');
showElement('upload-form');
setControlsDisabled(false);
document.getElementById('submitButton').hidden = true;
fileInput.value = '';
selectedFileNameP.textContent = '';
selectedFileNameP.hidden = true;
}
document.getElementById('buttonNewSong').addEventListener('click', function() {
showElement('confirmation-modal');
});
document.getElementById('cancel-new-song').addEventListener('click', function() {
hideElement('confirmation-modal');
});
document.getElementById('confirm-new-song').addEventListener('click', function() {
hideElement('confirmation-modal');
resetApp();
});
</script>
</body>
</html>