302 lines
8.9 KiB
HTML
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> |