zshashz commited on
Commit
6a27243
·
1 Parent(s): 6a7ea1e
Files changed (1) hide show
  1. index.html +81 -9
index.html CHANGED
@@ -66,21 +66,30 @@
66
  this.recordButton.addEventListener('click', () => this.toggleRecording());
67
 
68
  // Replace with your Eleven Labs API key
69
- this.ELEVEN_LABS_API_KEY = 'sk_4202af01226d4d527984c445a2e729d21ec28c5cfb309df7';
70
  }
71
 
72
  async setupMediaRecorder() {
73
  try {
74
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
75
- this.mediaRecorder = new MediaRecorder(stream);
 
 
 
 
 
 
 
 
 
76
 
77
  this.mediaRecorder.ondataavailable = (event) => {
78
  this.audioChunks.push(event.data);
79
  };
80
 
81
  this.mediaRecorder.onstop = async () => {
82
- const audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
83
- await this.sendToElevenLabs(audioBlob);
84
  this.audioChunks = [];
85
  };
86
 
@@ -117,22 +126,85 @@
117
  this.recordButton.classList.remove('recording');
118
  this.statusDiv.textContent = 'Processing audio...';
119
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- async sendToElevenLabs(audioBlob) {
122
  try {
123
  const formData = new FormData();
124
- formData.append('audio', audioBlob);
125
 
126
  const response = await fetch('https://api.elevenlabs.io/v1/speech-to-text', {
127
  method: 'POST',
128
  headers: {
129
  'xi-api-key': this.ELEVEN_LABS_API_KEY,
 
130
  },
131
  body: formData
132
  });
133
 
134
  if (!response.ok) {
135
- throw new Error(`HTTP error! status: ${response.status}`);
 
136
  }
137
 
138
  const data = await response.json();
@@ -141,7 +213,7 @@
141
 
142
  } catch (error) {
143
  console.error('Error sending to Eleven Labs:', error);
144
- this.statusDiv.textContent = 'Error processing audio. Please try again.';
145
  }
146
  }
147
  }
 
66
  this.recordButton.addEventListener('click', () => this.toggleRecording());
67
 
68
  // Replace with your Eleven Labs API key
69
+ this.ELEVEN_LABS_API_KEY = 'sk_d31f32025dda541dcd4f0aad95d3c7d1b31d36db7116dc1f';
70
  }
71
 
72
  async setupMediaRecorder() {
73
  try {
74
+ const stream = await navigator.mediaDevices.getUserMedia({
75
+ audio: {
76
+ sampleRate: 16000,
77
+ channelCount: 1
78
+ }
79
+ });
80
+
81
+ this.mediaRecorder = new MediaRecorder(stream, {
82
+ mimeType: 'audio/webm',
83
+ audioBitsPerSecond: 128000
84
+ });
85
 
86
  this.mediaRecorder.ondataavailable = (event) => {
87
  this.audioChunks.push(event.data);
88
  };
89
 
90
  this.mediaRecorder.onstop = async () => {
91
+ const audioBlob = new Blob(this.audioChunks, { type: 'audio/webm' });
92
+ await this.convertAndSend(audioBlob);
93
  this.audioChunks = [];
94
  };
95
 
 
126
  this.recordButton.classList.remove('recording');
127
  this.statusDiv.textContent = 'Processing audio...';
128
  }
129
+
130
+ async convertAndSend(audioBlob) {
131
+ try {
132
+ // Convert to audio buffer
133
+ const arrayBuffer = await audioBlob.arrayBuffer();
134
+ const audioContext = new AudioContext();
135
+ const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
136
+
137
+ // Create WAV file
138
+ const wavBuffer = this.audioBufferToWav(audioBuffer);
139
+ const wavBlob = new Blob([wavBuffer], { type: 'audio/wav' });
140
+
141
+ await this.sendToElevenLabs(wavBlob);
142
+ } catch (error) {
143
+ console.error('Error converting audio:', error);
144
+ this.statusDiv.textContent = 'Error converting audio. Please try again.';
145
+ }
146
+ }
147
+
148
+ audioBufferToWav(audioBuffer) {
149
+ const numberOfChannels = 1; // Mono
150
+ const sampleRate = 16000;
151
+ const format = 1; // PCM
152
+ const bitDepth = 16;
153
+
154
+ const length = audioBuffer.length * numberOfChannels * (bitDepth / 8);
155
+ const buffer = new ArrayBuffer(44 + length);
156
+ const view = new DataView(buffer);
157
+
158
+ // Write WAV header
159
+ const writeString = (view, offset, string) => {
160
+ for (let i = 0; i < string.length; i++) {
161
+ view.setUint8(offset + i, string.charCodeAt(i));
162
+ }
163
+ };
164
+
165
+ writeString(view, 0, 'RIFF');
166
+ view.setUint32(4, 36 + length, true);
167
+ writeString(view, 8, 'WAVE');
168
+ writeString(view, 12, 'fmt ');
169
+ view.setUint32(16, 16, true);
170
+ view.setUint16(20, format, true);
171
+ view.setUint16(22, numberOfChannels, true);
172
+ view.setUint32(24, sampleRate, true);
173
+ view.setUint32(28, sampleRate * numberOfChannels * (bitDepth / 8), true);
174
+ view.setUint16(32, numberOfChannels * (bitDepth / 8), true);
175
+ view.setUint16(34, bitDepth, true);
176
+ writeString(view, 36, 'data');
177
+ view.setUint32(40, length, true);
178
+
179
+ // Write audio data
180
+ const channelData = audioBuffer.getChannelData(0);
181
+ let offset = 44;
182
+ for (let i = 0; i < channelData.length; i++) {
183
+ const sample = Math.max(-1, Math.min(1, channelData[i]));
184
+ view.setInt16(offset, sample < 0 ? sample * 0x8000 : sample * 0x7FFF, true);
185
+ offset += 2;
186
+ }
187
+
188
+ return buffer;
189
+ }
190
 
191
+ async sendToElevenLabs(wavBlob) {
192
  try {
193
  const formData = new FormData();
194
+ formData.append('audio', wavBlob, 'recording.wav');
195
 
196
  const response = await fetch('https://api.elevenlabs.io/v1/speech-to-text', {
197
  method: 'POST',
198
  headers: {
199
  'xi-api-key': this.ELEVEN_LABS_API_KEY,
200
+ 'Accept': 'application/json'
201
  },
202
  body: formData
203
  });
204
 
205
  if (!response.ok) {
206
+ const errorText = await response.text();
207
+ throw new Error(`HTTP error! status: ${response.status}, ${errorText}`);
208
  }
209
 
210
  const data = await response.json();
 
213
 
214
  } catch (error) {
215
  console.error('Error sending to Eleven Labs:', error);
216
+ this.statusDiv.textContent = 'Error sending to Eleven Labs API. Please check your API key and try again.';
217
  }
218
  }
219
  }