awacke1 commited on
Commit
5454980
·
verified ·
1 Parent(s): 1989ff8

Create index.html

Browse files
Files changed (1) hide show
  1. index.html +229 -0
index.html ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Audio Recorder with Silence Detection</title>
7
+ <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
10
+ max-width: 800px;
11
+ margin: 20px auto;
12
+ padding: 20px;
13
+ background-color: #f5f5f5;
14
+ }
15
+ .container {
16
+ background-color: white;
17
+ padding: 20px;
18
+ border-radius: 8px;
19
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
20
+ }
21
+ button {
22
+ background-color: #4CAF50;
23
+ color: white;
24
+ padding: 10px 20px;
25
+ border: none;
26
+ border-radius: 4px;
27
+ cursor: pointer;
28
+ margin: 5px;
29
+ }
30
+ button:disabled {
31
+ background-color: #cccccc;
32
+ cursor: not-allowed;
33
+ }
34
+ #status {
35
+ margin: 10px 0;
36
+ padding: 10px;
37
+ border-radius: 4px;
38
+ }
39
+ #visualizer {
40
+ width: 100%;
41
+ height: 100px;
42
+ background-color: #f0f0f0;
43
+ margin: 10px 0;
44
+ }
45
+ .recording {
46
+ background-color: #ffebee !important;
47
+ }
48
+ </style>
49
+ </head>
50
+ <body>
51
+ <div class="container">
52
+ <h1>Audio Recorder</h1>
53
+ <div id="status">Ready to record</div>
54
+ <canvas id="visualizer"></canvas>
55
+ <div>
56
+ <button id="recordButton">Start Recording</button>
57
+ <button id="playButton" disabled>Play Recording</button>
58
+ </div>
59
+ <audio id="audioPlayer" controls style="display: none; margin-top: 20px;"></audio>
60
+ </div>
61
+
62
+ <script>
63
+ let mediaRecorder;
64
+ let audioChunks = [];
65
+ let audioContext;
66
+ let analyser;
67
+ let silenceTimeout;
68
+ let isRecording = false;
69
+ let recordingStartTime;
70
+
71
+ const recordButton = document.getElementById('recordButton');
72
+ const playButton = document.getElementById('playButton');
73
+ const status = document.getElementById('status');
74
+ const audioPlayer = document.getElementById('audioPlayer');
75
+ const canvas = document.getElementById('visualizer');
76
+ const canvasCtx = canvas.getContext('2d');
77
+
78
+ // Set up canvas size
79
+ canvas.width = canvas.offsetWidth;
80
+ canvas.height = canvas.offsetHeight;
81
+
82
+ recordButton.addEventListener('click', toggleRecording);
83
+ playButton.addEventListener('click', playRecording);
84
+
85
+ async function toggleRecording() {
86
+ if (!isRecording) {
87
+ startRecording();
88
+ } else {
89
+ stopRecording();
90
+ }
91
+ }
92
+
93
+ async function startRecording() {
94
+ try {
95
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
96
+ audioContext = new AudioContext();
97
+ analyser = audioContext.createAnalyser();
98
+ const source = audioContext.createMediaStreamSource(stream);
99
+ source.connect(analyser);
100
+
101
+ mediaRecorder = new MediaRecorder(stream);
102
+ audioChunks = [];
103
+
104
+ mediaRecorder.ondataavailable = (event) => {
105
+ audioChunks.push(event.data);
106
+ };
107
+
108
+ mediaRecorder.onstop = () => {
109
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
110
+ const audioUrl = URL.createObjectURL(audioBlob);
111
+ audioPlayer.src = audioUrl;
112
+ audioPlayer.style.display = 'block';
113
+ playButton.disabled = false;
114
+
115
+ // Auto-download the file
116
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
117
+ const link = document.createElement('a');
118
+ link.href = audioUrl;
119
+ link.download = `recording-${timestamp}.wav`;
120
+ link.click();
121
+ };
122
+
123
+ mediaRecorder.start();
124
+ isRecording = true;
125
+ recordingStartTime = Date.now();
126
+ status.textContent = 'Recording...';
127
+ recordButton.textContent = 'Stop Recording';
128
+ document.querySelector('.container').classList.add('recording');
129
+
130
+ // Start silence detection
131
+ detectSilence();
132
+ // Start visualizer
133
+ drawVisualizer();
134
+
135
+ } catch (err) {
136
+ console.error('Error:', err);
137
+ status.textContent = 'Error: ' + err.message;
138
+ }
139
+ }
140
+
141
+ function detectSilence() {
142
+ const bufferLength = analyser.frequencyBinCount;
143
+ const dataArray = new Uint8Array(bufferLength);
144
+
145
+ function checkAudioLevel() {
146
+ if (!isRecording) return;
147
+
148
+ analyser.getByteFrequencyData(dataArray);
149
+ const average = dataArray.reduce((a, b) => a + b) / bufferLength;
150
+
151
+ if (average < 5) { // Silence threshold
152
+ if (!silenceTimeout) {
153
+ silenceTimeout = setTimeout(() => {
154
+ if (Date.now() - recordingStartTime > 3000) { // Minimum 3 seconds
155
+ stopRecording();
156
+ }
157
+ }, 3000); // Wait 3 seconds of silence
158
+ }
159
+ } else {
160
+ if (silenceTimeout) {
161
+ clearTimeout(silenceTimeout);
162
+ silenceTimeout = null;
163
+ }
164
+ }
165
+
166
+ requestAnimationFrame(checkAudioLevel);
167
+ }
168
+
169
+ checkAudioLevel();
170
+ }
171
+
172
+ function drawVisualizer() {
173
+ if (!isRecording) return;
174
+
175
+ const bufferLength = analyser.frequencyBinCount;
176
+ const dataArray = new Uint8Array(bufferLength);
177
+
178
+ analyser.getByteTimeDomainData(dataArray);
179
+
180
+ canvasCtx.fillStyle = '#f0f0f0';
181
+ canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
182
+ canvasCtx.lineWidth = 2;
183
+ canvasCtx.strokeStyle = '#4CAF50';
184
+ canvasCtx.beginPath();
185
+
186
+ const sliceWidth = canvas.width * 1.0 / bufferLength;
187
+ let x = 0;
188
+
189
+ for (let i = 0; i < bufferLength; i++) {
190
+ const v = dataArray[i] / 128.0;
191
+ const y = v * canvas.height / 2;
192
+
193
+ if (i === 0) {
194
+ canvasCtx.moveTo(x, y);
195
+ } else {
196
+ canvasCtx.lineTo(x, y);
197
+ }
198
+
199
+ x += sliceWidth;
200
+ }
201
+
202
+ canvasCtx.lineTo(canvas.width, canvas.height / 2);
203
+ canvasCtx.stroke();
204
+
205
+ requestAnimationFrame(drawVisualizer);
206
+ }
207
+
208
+ function stopRecording() {
209
+ if (mediaRecorder && mediaRecorder.state !== 'inactive') {
210
+ mediaRecorder.stop();
211
+ mediaRecorder.stream.getTracks().forEach(track => track.stop());
212
+ isRecording = false;
213
+ status.textContent = 'Recording stopped';
214
+ recordButton.textContent = 'Start Recording';
215
+ document.querySelector('.container').classList.remove('recording');
216
+ if (silenceTimeout) {
217
+ clearTimeout(silenceTimeout);
218
+ silenceTimeout = null;
219
+ }
220
+ }
221
+ }
222
+
223
+ function playRecording() {
224
+ audioPlayer.play();
225
+ }
226
+ </script>
227
+ </div>
228
+ </body>
229
+ </html>