awacke1 commited on
Commit
2da09a8
·
verified ·
1 Parent(s): 2b113b3

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +64 -141
index.html CHANGED
@@ -3,175 +3,98 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>ASR Client</title>
 
 
 
 
 
 
 
7
  <style>
8
  body {
9
- font-family: system-ui, -apple-system, sans-serif;
10
  max-width: 800px;
11
- margin: 2rem auto;
12
- padding: 0 1rem;
13
- }
14
- .container {
15
- display: flex;
16
- flex-direction: column;
17
- gap: 1rem;
18
- align-items: center;
19
  }
20
- #status {
21
- margin: 1rem 0;
22
- padding: 0.5rem;
23
- border-radius: 4px;
24
- }
25
- #transcription {
26
- width: 100%;
27
- min-height: 200px;
28
- padding: 1rem;
29
  border: 1px solid #ccc;
30
- border-radius: 4px;
31
- margin: 1rem 0;
32
- }
33
- button {
34
- padding: 0.5rem 1rem;
35
- font-size: 1rem;
36
- cursor: pointer;
37
- background: #0066ff;
38
- color: white;
39
- border: none;
40
- border-radius: 4px;
41
- }
42
- button:disabled {
43
- background: #cccccc;
44
- cursor: not-allowed;
45
- }
46
- .status-loading {
47
- background: #fff3cd;
48
- }
49
- .status-ready {
50
- background: #d4edda;
51
- }
52
- .status-error {
53
- background: #f8d7da;
54
- }
55
- #progress {
56
- width: 100%;
57
- margin-top: 10px;
58
  }
59
  </style>
60
  </head>
61
  <body>
62
- <div class="container">
63
- <h1>Speech Recognition Client</h1>
64
- <div id="status">Loading model...</div>
65
- <div id="progress"></div>
66
- <button id="startButton" disabled>Start Recording</button>
67
- <div id="transcription"></div>
68
- </div>
69
 
70
  <script type="module">
71
- import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.9.0/+esm';
72
 
73
  let isRecording = false;
74
- let model = null;
75
- const startButton = document.getElementById('startButton');
76
- const statusDiv = document.getElementById('status');
77
- const progressDiv = document.getElementById('progress');
78
- const transcriptionDiv = document.getElementById('transcription');
79
-
80
- // Set environment variables for better progress tracking
81
- env.allowLocalModels = false;
82
- env.backends.onnx.wasm.numThreads = 1;
83
-
84
- class MyProgressCallback {
85
- constructor() {
86
- this.progress = 0;
87
- }
88
-
89
- onDownloadProgress(progress) {
90
- progressDiv.textContent = `Downloading: ${(progress * 100).toFixed(2)}%`;
91
- }
92
-
93
- onProgress(progress) {
94
- progressDiv.textContent = `Loading: ${(progress * 100).toFixed(2)}%`;
95
- }
96
- }
97
 
98
  // Initialize the model
99
- async function initializeModel() {
100
- try {
101
- statusDiv.textContent = 'Loading model...';
102
- statusDiv.className = 'status-loading';
103
-
104
- // Initialize model with progress callback
105
- model = await pipeline('automatic-speech-recognition', 'Xenova/whisper-tiny', {
106
- progress_callback: new MyProgressCallback(),
107
- });
108
-
109
- statusDiv.textContent = 'Model ready! Click Start Recording to begin.';
110
- statusDiv.className = 'status-ready';
111
- progressDiv.textContent = '';
112
- startButton.disabled = false;
113
-
114
- console.log('Model loaded successfully');
115
- } catch (error) {
116
- console.error('Model loading error:', error);
117
- statusDiv.textContent = 'Error loading model: ' + error.message;
118
- statusDiv.className = 'status-error';
119
- }
120
  }
121
 
122
- // Handle recording
123
- async function toggleRecording() {
124
  if (!isRecording) {
 
125
  try {
126
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
127
- isRecording = true;
128
- startButton.textContent = 'Stop Recording';
129
- statusDiv.textContent = 'Recording...';
130
- statusDiv.className = 'status-loading';
 
 
131
 
132
- // Create processor and start processing audio
133
- const audioTrack = stream.getAudioTracks()[0];
134
- const processor = new MediaStreamTrackProcessor({ track: audioTrack });
135
-
136
- const transformer = new TransformStream({
137
- async transform(chunk, controller) {
138
- try {
139
- const result = await model(chunk.data);
140
- if (result && result.text) {
141
- transcriptionDiv.textContent += ' ' + result.text;
142
- }
143
- } catch (error) {
144
- console.error('Error processing audio:', error);
145
- }
146
  }
147
- });
 
148
 
149
- await processor.readable.pipeTo(transformer.writable);
150
- } catch (error) {
151
- console.error('Recording error:', error);
152
- statusDiv.textContent = 'Error accessing microphone: ' + error.message;
153
- statusDiv.className = 'status-error';
154
- isRecording = false;
 
155
  }
156
  } else {
157
  // Stop recording
 
 
158
  isRecording = false;
159
- startButton.textContent = 'Start Recording';
160
- statusDiv.textContent = 'Recording stopped. Click Start Recording to begin again.';
161
- statusDiv.className = 'status-ready';
162
  }
163
- }
164
-
165
- // Initialize the app
166
- startButton.addEventListener('click', toggleRecording);
167
- window.addEventListener('load', initializeModel);
168
-
169
- // Add error logging
170
- window.addEventListener('error', function(e) {
171
- console.error('Global error:', e.error);
172
- statusDiv.textContent = 'An error occurred: ' + e.error.message;
173
- statusDiv.className = 'status-error';
174
- });
175
  </script>
176
  </body>
177
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Simple ASR Client</title>
7
+ <script type="importmap">
8
+ {
9
+ "imports": {
10
+ "@xenova/transformers": "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.9.0/+esm"
11
+ }
12
+ }
13
+ </script>
14
  <style>
15
  body {
16
+ font-family: Arial, sans-serif;
17
  max-width: 800px;
18
+ margin: 20px auto;
19
+ padding: 20px;
 
 
 
 
 
 
20
  }
21
+ #output {
22
+ margin-top: 20px;
23
+ padding: 10px;
 
 
 
 
 
 
24
  border: 1px solid #ccc;
25
+ min-height: 100px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
  </style>
28
  </head>
29
  <body>
30
+ <h1>Simple Speech Recognition</h1>
31
+ <div id="status">Loading model...</div>
32
+ <button id="startBtn" disabled>Start Recording</button>
33
+ <div id="output"></div>
 
 
 
34
 
35
  <script type="module">
36
+ import { pipeline } from '@xenova/transformers';
37
 
38
  let isRecording = false;
39
+ let mediaRecorder = null;
40
+ let audioChunks = [];
41
+
42
+ const statusElement = document.getElementById('status');
43
+ const startBtn = document.getElementById('startBtn');
44
+ const output = document.getElementById('output');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  // Initialize the model
47
+ let model;
48
+ try {
49
+ model = await pipeline('automatic-speech-recognition', 'Xenova/whisper-tiny');
50
+ statusElement.textContent = 'Model loaded! Ready to record.';
51
+ startBtn.disabled = false;
52
+ } catch (e) {
53
+ statusElement.textContent = 'Error loading model: ' + e.message;
54
+ console.error(e);
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  }
56
 
57
+ startBtn.onclick = async () => {
 
58
  if (!isRecording) {
59
+ // Start recording
60
  try {
61
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
62
+ mediaRecorder = new MediaRecorder(stream);
63
+ audioChunks = [];
64
+
65
+ mediaRecorder.ondataavailable = (event) => {
66
+ audioChunks.push(event.data);
67
+ };
68
 
69
+ mediaRecorder.onstop = async () => {
70
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
71
+ try {
72
+ const result = await model(audioBlob);
73
+ output.textContent += result.text + ' ';
74
+ } catch (e) {
75
+ console.error('Transcription error:', e);
76
+ statusElement.textContent = 'Error during transcription';
 
 
 
 
 
 
77
  }
78
+ audioChunks = [];
79
+ };
80
 
81
+ mediaRecorder.start(1000);
82
+ isRecording = true;
83
+ startBtn.textContent = 'Stop Recording';
84
+ statusElement.textContent = 'Recording...';
85
+ } catch (e) {
86
+ console.error('Recording error:', e);
87
+ statusElement.textContent = 'Error accessing microphone';
88
  }
89
  } else {
90
  // Stop recording
91
+ mediaRecorder.stop();
92
+ mediaRecorder.stream.getTracks().forEach(track => track.stop());
93
  isRecording = false;
94
+ startBtn.textContent = 'Start Recording';
95
+ statusElement.textContent = 'Processing...';
 
96
  }
97
+ };
 
 
 
 
 
 
 
 
 
 
 
98
  </script>
99
  </body>
100
  </html>