InstantASRforYouNow / index.html
awacke1's picture
Update index.html
621a9fb verified
raw
history blame
8.55 kB
<!DOCTYPE html>
<html>
<head>
<title>Audio Recorder with Silence Detection</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.controls {
margin: 20px 0;
}
button {
padding: 10px 20px;
margin: 5px;
cursor: pointer;
}
#recordingsList {
margin-top: 20px;
border: 1px solid #ccc;
padding: 10px;
min-height: 100px;
}
.recording-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
#timer {
font-size: 1.2em;
margin: 10px 0;
}
#volumeMeter {
width: 300px;
height: 20px;
border: 1px solid #ccc;
margin: 10px 0;
}
#volumeBar {
height: 100%;
width: 0%;
background-color: #4CAF50;
transition: width 0.1s;
}
</style>
</head>
<body>
<h1>Audio Recorder with Silence Detection</h1>
<div class="controls">
<button id="startButton">Start Recording</button>
<button id="stopButton" disabled>Stop Recording</button>
</div>
<div id="timer">00:00</div>
<div id="volumeMeter">
<div id="volumeBar"></div>
</div>
<div id="recordingsList"></div>
<script>
let mediaRecorder;
let audioChunks = [];
let recordings = [];
let startTime;
let timerInterval;
let silenceTimeout;
let audioContext;
let analyser;
let isRecording = false;
let totalDuration = 0;
const SILENCE_THRESHOLD = -50; // dB
const SILENCE_DURATION = 1000; // 1 second
document.getElementById('startButton').addEventListener('click', startRecording);
document.getElementById('stopButton').addEventListener('click', stopRecording);
async function startRecording() {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
setupAudioAnalysis(stream);
mediaRecorder = new MediaRecorder(stream);
audioChunks = [];
isRecording = true;
startTime = Date.now();
mediaRecorder.ondataavailable = event => {
audioChunks.push(event.data);
};
mediaRecorder.onstop = () => {
if (audioChunks.length > 0) {
saveRecording();
}
};
mediaRecorder.start();
updateUI(true);
startTimer();
} catch (err) {
console.error('Error:', err);
alert('Error accessing microphone');
}
}
function setupAudioAnalysis(stream) {
audioContext = new AudioContext();
analyser = audioContext.createAnalyser();
const source = audioContext.createMediaStreamSource(stream);
source.connect(analyser);
analyser.fftSize = 2048;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Float32Array(bufferLength);
function checkAudioLevel() {
if (!isRecording) return;
analyser.getFloatTimeDomainData(dataArray);
let sum = 0;
for (let i = 0; i < bufferLength; i++) {
sum += Math.abs(dataArray[i]);
}
const average = sum / bufferLength;
const db = 20 * Math.log10(average);
// Update volume meter
const volumeBar = document.getElementById('volumeBar');
const normalizedVolume = Math.max(0, (db + 90) / 90) * 100;
volumeBar.style.width = `${normalizedVolume}%`;
if (db < SILENCE_THRESHOLD) {
if (!silenceTimeout) {
silenceTimeout = setTimeout(() => {
if (mediaRecorder.state === 'recording') {
mediaRecorder.stop();
startNewRecording();
}
}, SILENCE_DURATION);
}
} else {
if (silenceTimeout) {
clearTimeout(silenceTimeout);
silenceTimeout = null;
}
if (mediaRecorder.state === 'inactive' && isRecording) {
startNewRecording();
}
}
requestAnimationFrame(checkAudioLevel);
}
checkAudioLevel();
}
function startNewRecording() {
if (isRecording) {
audioChunks = [];
mediaRecorder.start();
}
}
function stopRecording() {
isRecording = false;
if (mediaRecorder.state === 'recording') {
mediaRecorder.stop();
}
clearInterval(timerInterval);
updateUI(false);
if (audioContext) {
audioContext.close();
}
if (silenceTimeout) {
clearTimeout(silenceTimeout);
}
}
function saveRecording() {
const blob = new Blob(audioChunks, { type: 'audio/webm' });
const reader = new FileReader();
reader.onload = function() {
const base64String = reader.result.split(',')[1];
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const filename = `recording-${timestamp}.webm`;
recordings.push({
filename,
base64: base64String,
duration: (Date.now() - startTime) / 1000
});
updateRecordingsList();
};
reader.readAsDataURL(blob);
}
function updateRecordingsList() {
const list = document.getElementById('recordingsList');
list.innerHTML = '';
recordings.forEach((recording, index) => {
const item = document.createElement('div');
item.className = 'recording-item';
const info = document.createElement('span');
info.textContent = `${recording.filename} (${recording.duration.toFixed(1)}s)`;
const downloadBtn = document.createElement('button');
downloadBtn.textContent = 'Download';
downloadBtn.onclick = () => downloadRecording(recording);
item.appendChild(info);
item.appendChild(downloadBtn);
list.appendChild(item);
});
}
function downloadRecording(recording) {
const link = document.createElement('a');
link.href = `data:audio/webm;base64,${recording.base64}`;
link.download = recording.filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
function startTimer() {
const timerElement = document.getElementById('timer');
const startTime = Date.now();
timerInterval = setInterval(() => {
const elapsed = Date.now() - startTime;
const seconds = Math.floor(elapsed / 1000);
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
timerElement.textContent = `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
}, 1000);
}
function updateUI(recording) {
document.getElementById('startButton').disabled = recording;
document.getElementById('stopButton').disabled = !recording;
}
</script>
</body>
</html>