Skip to content

Instantly share code, notes, and snippets.

@JayGoldberg
Created August 6, 2025 17:43
Show Gist options
  • Save JayGoldberg/c0d209a7385551515bff1a259f51b755 to your computer and use it in GitHub Desktop.
Save JayGoldberg/c0d209a7385551515bff1a259f51b755 to your computer and use it in GitHub Desktop.
A "push-to-talk" app. This example uses plain HTML and JavaScript, leveraging the MediaDevices API for microphone access and the MediaRecorder API to handle the recording. Handles all the logic: requesting microphone access, starting and stopping the recording based on button presses, and creating a downloadable link for the final audio file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Push-to-Talk Recorder</title>
<style>
body {
font-family: sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
#recordButton {
padding: 20px 40px;
font-size: 1.5em;
cursor: pointer;
border: none;
border-radius: 10px;
background-color: #007bff;
color: white;
transition: background-color 0.2s ease;
}
#recordButton:active {
background-color: #0056b3;
}
#download-link {
margin-top: 20px;
display: none; /* Initially hidden */
font-size: 1.2em;
}
</style>
</head>
<body>
<h1>Hold to Talk</h1>
<button id="recordButton">Push to Talk</button>
<a id="download-link" href="#" download="my-recording.webm">Download Recording</a>
<script src="app.js"></script>
</body>
<script>
let mediaRecorder;
let audioChunks = [];
let stream;
const recordButton = document.getElementById('recordButton');
const downloadLink = document.getElementById('download-link');
// Request microphone access when the page loads
navigator.mediaDevices.getUserMedia({ audio: true })
.then(s => {
stream = s;
console.log('Microphone access granted!');
})
.catch(err => {
console.error('Microphone access denied:', err);
alert('Please allow microphone access to use this feature.');
});
// Start recording when the button is held down
recordButton.addEventListener('mousedown', () => {
if (!stream) {
alert('Microphone access not granted yet. Please refresh and allow.');
return;
}
// Create a new MediaRecorder instance
mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' });
// Store audio data chunks as they become available
mediaRecorder.ondataavailable = e => {
audioChunks.push(e.data);
};
// Begin recording
mediaRecorder.start();
recordButton.textContent = 'Recording...';
downloadLink.style.display = 'none'; // Hide the download link while recording
console.log('Recording started.');
});
// Stop recording when the button is released
recordButton.addEventListener('mouseup', () => {
if (mediaRecorder && mediaRecorder.state === 'recording') {
// Stop the recorder
mediaRecorder.stop();
recordButton.textContent = 'Push to Talk';
console.log('Recording stopped.');
// This event is fired when the recording is stopped
mediaRecorder.onstop = () => {
// Combine all recorded chunks into a single Blob
const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
// Create a URL for the Blob
const audioUrl = URL.createObjectURL(audioBlob);
// Update the download link
downloadLink.href = audioUrl;
downloadLink.style.display = 'block'; // Show the download link
// Clear the chunks array for the next recording
audioChunks = [];
};
}
});
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment