Ravisil commited on
Commit
6e694cf
·
verified ·
1 Parent(s): 254adb3

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +317 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Teste Microphone
3
- emoji:
4
- colorFrom: yellow
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: teste-microphone
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,317 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Microphone Checker | Teste seu Microfone</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .waveform {
11
+ height: 80px;
12
+ background: linear-gradient(90deg, #3b82f6, #8b5cf6);
13
+ position: relative;
14
+ overflow: hidden;
15
+ }
16
+
17
+ .waveform::before {
18
+ content: '';
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ right: 0;
23
+ bottom: 0;
24
+ background: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 80' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 40 Q 25 10, 50 40 T 100 40 T 150 40 T 200 40' stroke='%23ffffff10' fill='none' stroke-width='2'/%3E%3C/svg%3E");
25
+ opacity: 0.3;
26
+ }
27
+
28
+ .audio-level {
29
+ height: 100%;
30
+ width: 0;
31
+ background-color: rgba(255, 255, 255, 0.2);
32
+ transition: width 0.05s ease-out;
33
+ }
34
+
35
+ @keyframes pulse {
36
+ 0% { transform: scale(1); }
37
+ 50% { transform: scale(1.05); }
38
+ 100% { transform: scale(1); }
39
+ }
40
+
41
+ .pulse {
42
+ animation: pulse 2s infinite;
43
+ }
44
+ </style>
45
+ </head>
46
+ <body class="bg-gradient-to-br from-blue-50 to-purple-50 min-h-screen">
47
+ <div class="container mx-auto px-4 py-12">
48
+ <div class="max-w-3xl mx-auto">
49
+ <!-- Header -->
50
+ <div class="text-center mb-12">
51
+ <h1 class="text-4xl font-bold text-gray-800 mb-2">Microphone Checker</h1>
52
+ <p class="text-lg text-gray-600">Verifique e teste seus dispositivos de microfone</p>
53
+ </div>
54
+
55
+ <!-- Main Card -->
56
+ <div class="bg-white rounded-xl shadow-xl overflow-hidden transition-all duration-300 hover:shadow-2xl">
57
+ <!-- Status Section -->
58
+ <div class="p-8 border-b border-gray-100">
59
+ <div class="flex items-center justify-between">
60
+ <div>
61
+ <h2 class="text-2xl font-semibold text-gray-800">Status do Microfone</h2>
62
+ <p class="text-gray-500" id="status-text">Verificando dispositivos...</p>
63
+ </div>
64
+ <div id="status-icon" class="text-4xl text-gray-400">
65
+ <i class="fas fa-microphone-slash"></i>
66
+ </div>
67
+ </div>
68
+ </div>
69
+
70
+ <!-- Device Selection -->
71
+ <div class="p-8 border-b border-gray-100" id="device-section" style="display: none;">
72
+ <h3 class="text-lg font-medium text-gray-700 mb-4">Selecione seu microfone</h3>
73
+ <select id="device-select" class="w-full p-3 border border-gray-200 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
74
+ <option value="">Carregando dispositivos...</option>
75
+ </select>
76
+ </div>
77
+
78
+ <!-- Visualizer -->
79
+ <div class="waveform" id="visualizer">
80
+ <div class="audio-level" id="audio-level"></div>
81
+ </div>
82
+
83
+ <!-- Controls -->
84
+ <div class="p-8">
85
+ <div class="flex flex-col sm:flex-row gap-4">
86
+ <button id="test-btn" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
87
+ <i class="fas fa-play"></i> Testar Microfone
88
+ </button>
89
+ <button id="stop-btn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
90
+ <i class="fas fa-stop"></i> Parar Teste
91
+ </button>
92
+ </div>
93
+
94
+ <div class="mt-8 bg-blue-50 border border-blue-100 rounded-lg p-4" id="instructions">
95
+ <h3 class="font-medium text-blue-800 mb-2 flex items-center gap-2">
96
+ <i class="fas fa-info-circle"></i> Instruções
97
+ </h3>
98
+ <ol class="list-decimal list-inside text-blue-700 space-y-1">
99
+ <li>Permita o acesso ao microfone quando solicitado</li>
100
+ <li>Selecione seu dispositivo de microfone</li>
101
+ <li>Clique em "Testar Microfone" e comece a falar</li>
102
+ <li>O visualizador mostrará o nível de entrada de áudio</li>
103
+ </ol>
104
+ </div>
105
+ </div>
106
+ </div>
107
+
108
+ <!-- Footer -->
109
+ <div class="mt-12 text-center text-gray-500 text-sm">
110
+ <p>© 2023 Microphone Checker | Desenvolvido com <i class="fas fa-heart text-red-500"></i> para testar seus dispositivos de áudio</p>
111
+ </div>
112
+ </div>
113
+ </div>
114
+
115
+ <script>
116
+ document.addEventListener('DOMContentLoaded', () => {
117
+ const statusText = document.getElementById('status-text');
118
+ const statusIcon = document.getElementById('status-icon');
119
+ const deviceSection = document.getElementById('device-section');
120
+ const deviceSelect = document.getElementById('device-select');
121
+ const testBtn = document.getElementById('test-btn');
122
+ const stopBtn = document.getElementById('stop-btn');
123
+ const audioLevel = document.getElementById('audio-level');
124
+ const visualizer = document.getElementById('visualizer');
125
+ const instructions = document.getElementById('instructions');
126
+
127
+ let audioContext;
128
+ let microphone;
129
+ let analyser;
130
+ let isTesting = false;
131
+ let devices = [];
132
+
133
+ // Check microphone availability
134
+ checkMicrophoneAvailability();
135
+
136
+ async function checkMicrophoneAvailability() {
137
+ try {
138
+ // Request permission to list devices
139
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
140
+ stream.getTracks().forEach(track => track.stop());
141
+
142
+ // List audio devices
143
+ devices = await navigator.mediaDevices.enumerateDevices();
144
+ const audioDevices = devices.filter(device => device.kind === 'audioinput');
145
+
146
+ if (audioDevices.length > 0) {
147
+ // Update status
148
+ statusText.textContent = `${audioDevices.length} microfone(s) disponível(is)`;
149
+ statusIcon.innerHTML = '<i class="fas fa-microphone text-green-500 pulse"></i>';
150
+
151
+ // Show device selection
152
+ deviceSection.style.display = 'block';
153
+ populateDeviceSelect(audioDevices);
154
+
155
+ // Enable test button
156
+ testBtn.disabled = false;
157
+ } else {
158
+ statusText.textContent = 'Nenhum microfone encontrado';
159
+ statusIcon.innerHTML = '<i class="fas fa-microphone-slash text-red-500"></i>';
160
+ }
161
+ } catch (error) {
162
+ console.error('Error accessing microphone:', error);
163
+ statusText.textContent = 'Acesso ao microfone negado ou erro ao acessar';
164
+ statusIcon.innerHTML = '<i class="fas fa-microphone-slash text-red-500"></i>';
165
+
166
+ // Update instructions
167
+ instructions.querySelector('ol').innerHTML = `
168
+ <li class="text-red-500">Permissão para acessar o microfone foi negada</li>
169
+ <li>Atualize a página e permita o acesso ao microfone</li>
170
+ <li>Verifique as configurações de privacidade do seu navegador</li>
171
+ `;
172
+ }
173
+ }
174
+
175
+ function populateDeviceSelect(audioDevices) {
176
+ deviceSelect.innerHTML = '';
177
+
178
+ if (audioDevices.length === 0) {
179
+ deviceSelect.innerHTML = '<option value="">Nenhum microfone encontrado</option>';
180
+ return;
181
+ }
182
+
183
+ // Add default option
184
+ const defaultOption = document.createElement('option');
185
+ defaultOption.value = '';
186
+ defaultOption.textContent = 'Selecione um microfone...';
187
+ deviceSelect.appendChild(defaultOption);
188
+
189
+ // Add devices
190
+ audioDevices.forEach(device => {
191
+ const option = document.createElement('option');
192
+ option.value = device.deviceId;
193
+ option.textContent = device.label || `Microfone ${deviceSelect.options.length}`;
194
+ deviceSelect.appendChild(option);
195
+ });
196
+ }
197
+
198
+ testBtn.addEventListener('click', startTest);
199
+ stopBtn.addEventListener('click', stopTest);
200
+
201
+ async function startTest() {
202
+ if (isTesting) return;
203
+
204
+ const deviceId = deviceSelect.value;
205
+ if (!deviceId) {
206
+ alert('Por favor, selecione um microfone primeiro');
207
+ return;
208
+ }
209
+
210
+ try {
211
+ isTesting = true;
212
+ testBtn.disabled = true;
213
+ stopBtn.disabled = false;
214
+ visualizer.style.background = 'linear-gradient(90deg, #10b981, #3b82f6)';
215
+
216
+ // Initialize audio context
217
+ audioContext = new (window.AudioContext || window.webkitAudioContext)();
218
+ analyser = audioContext.createAnalyser();
219
+ analyser.fftSize = 32;
220
+
221
+ // Get microphone stream
222
+ const constraints = {
223
+ audio: {
224
+ deviceId: deviceId ? { exact: deviceId } : undefined,
225
+ echoCancellation: false,
226
+ noiseSuppression: false,
227
+ autoGainControl: false
228
+ }
229
+ };
230
+
231
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
232
+ microphone = audioContext.createMediaStreamSource(stream);
233
+ microphone.connect(analyser);
234
+
235
+ // Update UI
236
+ statusText.textContent = 'Testando microfone... Fale agora';
237
+ statusIcon.innerHTML = '<i class="fas fa-microphone text-green-500 animate-pulse"></i>';
238
+
239
+ // Start visualization
240
+ visualize();
241
+ } catch (error) {
242
+ console.error('Error starting test:', error);
243
+ statusText.textContent = 'Erro ao iniciar o teste do microfone';
244
+ statusIcon.innerHTML = '<i class="fas fa-microphone-slash text-red-500"></i>';
245
+ stopTest();
246
+ }
247
+ }
248
+
249
+ function stopTest() {
250
+ if (!isTesting) return;
251
+
252
+ isTesting = false;
253
+ testBtn.disabled = false;
254
+ stopBtn.disabled = true;
255
+ visualizer.style.background = 'linear-gradient(90deg, #3b82f6, #8b5cf6)';
256
+
257
+ // Stop all tracks
258
+ if (microphone && microphone.mediaStream) {
259
+ microphone.mediaStream.getTracks().forEach(track => track.stop());
260
+ }
261
+
262
+ // Disconnect audio nodes
263
+ if (microphone && analyser) {
264
+ microphone.disconnect();
265
+ }
266
+
267
+ // Update UI
268
+ statusText.textContent = 'Teste concluído';
269
+ statusIcon.innerHTML = '<i class="fas fa-microphone text-green-500"></i>';
270
+ audioLevel.style.width = '0';
271
+ }
272
+
273
+ function visualize() {
274
+ if (!isTesting) return;
275
+
276
+ const dataArray = new Uint8Array(analyser.frequencyBinCount);
277
+ analyser.getByteFrequencyData(dataArray);
278
+
279
+ // Calculate average volume
280
+ let sum = 0;
281
+ for (let i = 0; i < dataArray.length; i++) {
282
+ sum += dataArray[i];
283
+ }
284
+ const average = sum / dataArray.length;
285
+
286
+ // Update visualizer
287
+ audioLevel.style.width = `${average}%`;
288
+
289
+ // Color intensity based on volume
290
+ const intensity = Math.min(average / 100, 1);
291
+ const r = Math.floor(16 + (255 - 16) * intensity);
292
+ const g = Math.floor(182 + (255 - 182) * intensity);
293
+ const b = Math.floor(255 * intensity);
294
+ audioLevel.style.backgroundColor = `rgba(${r}, ${g}, ${b}, 0.5)`;
295
+
296
+ // Continue animation
297
+ requestAnimationFrame(visualize);
298
+ }
299
+
300
+ // Handle device changes
301
+ navigator.mediaDevices.addEventListener('devicechange', async () => {
302
+ devices = await navigator.mediaDevices.enumerateDevices();
303
+ const audioDevices = devices.filter(device => device.kind === 'audioinput');
304
+ populateDeviceSelect(audioDevices);
305
+
306
+ if (audioDevices.length > 0) {
307
+ statusText.textContent = `${audioDevices.length} microfone(s) disponível(is)`;
308
+ statusIcon.innerHTML = '<i class="fas fa-microphone text-green-500 pulse"></i>';
309
+ } else {
310
+ statusText.textContent = 'Nenhum microfone encontrado';
311
+ statusIcon.innerHTML = '<i class="fas fa-microphone-slash text-red-500"></i>';
312
+ }
313
+ });
314
+ });
315
+ </script>
316
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=Ravisil/teste-microphone" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
317
+ </html>