freedge/recorder/recorder.html
Arthur Barre 20b9b17493 fix
2025-03-13 21:26:24 +01:00

302 lines
8.9 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enregistreur Audio</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f9f9f9;
color: #333;
}
h1 {
text-align: center;
color: #e67e22;
}
.container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 20px;
margin-top: 20px;
}
.recorder-controls {
display: flex;
justify-content: center;
margin: 20px 0;
}
button {
background-color: #e67e22;
color: white;
border: none;
border-radius: 4px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
button:hover {
background-color: #d35400;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.recordings {
margin-top: 20px;
}
.recording-item {
background-color: #f5f5f5;
border-radius: 4px;
padding: 15px;
margin-bottom: 10px;
}
.recording-info {
margin-bottom: 10px;
font-size: 14px;
color: #666;
}
audio {
width: 100%;
}
.status {
text-align: center;
margin: 10px 0;
font-style: italic;
color: #666;
}
.pulse {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
.mic-icon {
width: 20px;
height: 20px;
}
</style>
<!-- Charger le script vmsg avant notre script principal -->
<script src="https://unpkg.com/vmsg@0.3.0/vmsg.js"></script>
</head>
<body>
<h1>Enregistreur Audio</h1>
<div class="container">
<p>Enregistrez votre voix et écoutez le résultat. Les enregistrements sont stockés localement dans votre navigateur.
</p>
<div id="status" class="status">Prêt à enregistrer</div>
<div class="recorder-controls">
<button id="recordButton">
<svg class="mic-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</svg>
Commencer l'enregistrement
</button>
</div>
<div id="recordings" class="recordings">
<h3>Vos enregistrements</h3>
<div id="recordingsList"></div>
</div>
</div>
<script>
// Attendre que vmsg soit complètement chargé
window.onload = function () {
// Vérifier si vmsg est disponible
if (typeof vmsg === 'undefined') {
console.error("La bibliothèque vmsg n'a pas été chargée correctement");
document.getElementById('status').textContent = "Erreur: Impossible de charger l'enregistreur audio";
document.getElementById('recordButton').disabled = true;
return;
}
// Initialiser le recorder
const recorder = new vmsg.Recorder({
wasmURL: "https://unpkg.com/vmsg@0.3.0/vmsg.wasm"
});
const recordButton = document.getElementById('recordButton');
const statusElement = document.getElementById('status');
const recordingsList = document.getElementById('recordingsList');
let isLoading = false;
let isRecording = false;
let recordings = [];
// Fonction pour mettre à jour l'interface utilisateur
function updateUI() {
if (isLoading) {
recordButton.disabled = true;
statusElement.textContent = isRecording
? "Arrêt de l'enregistrement..."
: "Initialisation de l'enregistrement...";
} else if (isRecording) {
recordButton.innerHTML = `
<svg class="mic-icon pulse" viewBox="0 0 24 24" fill="none" stroke="red" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</svg>
Arrêter l'enregistrement
`;
recordButton.style.backgroundColor = '#e74c3c';
statusElement.textContent = "Enregistrement en cours...";
} else {
recordButton.disabled = false;
recordButton.innerHTML = `
<svg class="mic-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
<line x1="12" y1="19" x2="12" y2="23"></line>
<line x1="8" y1="23" x2="16" y2="23"></line>
</svg>
Commencer l'enregistrement
`;
recordButton.style.backgroundColor = '#e67e22';
statusElement.textContent = "Prêt à enregistrer";
}
}
// Fonction pour gérer l'enregistrement
async function toggleRecording() {
isLoading = true;
updateUI();
if (isRecording) {
try {
const blob = await recorder.stopRecording();
const url = URL.createObjectURL(blob);
const timestamp = new Date().toLocaleString();
const size = (blob.size / 1024).toFixed(2);
recordings.push({ url, timestamp, size });
renderRecordings();
isRecording = false;
} catch (e) {
console.error("Erreur lors de l'arrêt de l'enregistrement:", e);
alert("Une erreur est survenue lors de l'arrêt de l'enregistrement.");
}
} else {
try {
await recorder.initAudio();
await recorder.initWorker();
recorder.startRecording();
isRecording = true;
} catch (e) {
console.error("Erreur lors du démarrage de l'enregistrement:", e);
alert("Impossible d'accéder au microphone. Vérifiez les permissions.");
}
}
isLoading = false;
updateUI();
}
// Fonction pour afficher les enregistrements
function renderRecordings() {
recordingsList.innerHTML = '';
if (recordings.length === 0) {
recordingsList.innerHTML = '<p>Aucun enregistrement pour le moment.</p>';
return;
}
recordings.forEach((recording, index) => {
const recordingItem = document.createElement('div');
recordingItem.className = 'recording-item';
recordingItem.innerHTML = `
<div class="recording-info">
<strong>Enregistrement #${index + 1}</strong> - ${recording.timestamp} (${recording.size} KB)
</div>
<audio controls src="${recording.url}"></audio>
<div style="margin-top: 10px;">
<button class="download-btn" data-index="${index}" style="background-color: #3498db;">
Télécharger
</button>
<button class="delete-btn" data-index="${index}" style="background-color: #e74c3c; margin-left: 10px;">
Supprimer
</button>
</div>
`;
recordingsList.appendChild(recordingItem);
});
// Ajouter les écouteurs d'événements pour les boutons
document.querySelectorAll('.download-btn').forEach(btn => {
btn.addEventListener('click', function () {
const index = parseInt(this.dataset.index);
const recording = recordings[index];
const a = document.createElement('a');
a.href = recording.url;
a.download = `enregistrement-${index + 1}.mp3`;
a.click();
});
});
document.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', function () {
const index = parseInt(this.dataset.index);
URL.revokeObjectURL(recordings[index].url);
recordings.splice(index, 1);
renderRecordings();
});
});
}
// Initialiser l'interface
renderRecordings();
updateUI();
// Ajouter l'écouteur d'événement pour le bouton d'enregistrement
recordButton.addEventListener('click', toggleRecording);
};
</script>
</body>
</html>