atlury commited on
Commit
c379827
·
verified ·
1 Parent(s): cf77c1f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +52 -6
index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Voice Chat Bot with Echo Cancellation</title>
7
  <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.js"></script>
8
  <script src="https://cdn.jsdelivr.net/npm/@ricky0123/[email protected]/dist/bundle.min.js"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/@xenova/[email protected]"></script>
@@ -136,7 +136,7 @@
136
  font-size: 14px;
137
  padding: 5px 10px;
138
  }
139
- #localVideo {
140
  display: none;
141
  }
142
  </style>
@@ -169,7 +169,8 @@
169
  <div id="logs"></div>
170
  <button id="clear-logs">Clear</button>
171
  </div>
172
- <video id="localVideo" autoplay muted></video>
 
173
 
174
  <script type="module">
175
  import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/[email protected]';
@@ -183,6 +184,7 @@
183
  const logsDiv = document.getElementById('logs');
184
  const clearLogsButton = document.getElementById('clear-logs');
185
  const localVideo = document.getElementById('localVideo');
 
186
 
187
  let myvad;
188
  let sttPipeline;
@@ -196,6 +198,9 @@
196
  let microphoneStream;
197
  let isSpeaking = false;
198
  let currentAudioSource = null;
 
 
 
199
 
200
  function createVisualizer() {
201
  const barCount = 64;
@@ -305,8 +310,13 @@
305
  analyser.fftSize = 128;
306
  dataArray = new Uint8Array(analyser.frequencyBinCount);
307
 
308
- localVideo.muted = true;
309
  localVideo.volume = 0;
 
 
 
 
 
 
310
 
311
  // Request both audio and video streams
312
  microphoneStream = await navigator.mediaDevices.getUserMedia({
@@ -320,7 +330,31 @@
320
  console.log('Active constraints:', microphoneStream.getAudioTracks()[0].getConstraints());
321
  console.log('Microphone stream settings:', microphoneStream.getAudioTracks()[0].getSettings());
322
 
323
- const source = audioContext.createMediaStreamSource(microphoneStream);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  source.connect(analyser);
325
 
326
  myvad = await vad.MicVAD.new({
@@ -370,13 +404,25 @@
370
  if (localVideo) {
371
  localVideo.srcObject = null;
372
  }
 
 
 
 
 
 
 
 
 
 
 
 
373
  stopCurrentAudio();
374
  startButton.textContent = 'Begin Call';
375
  isListening = false;
376
  addLog('System: Stopped listening.');
377
  cancelAnimationFrame(animationId);
378
  addLog('System: Microphone closed');
379
- }
380
 
381
  startButton.addEventListener('click', toggleListening);
382
  clearLogsButton.addEventListener('click', () => {
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Voice Chat Bot with Advanced Echo Cancellation</title>
7
  <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.js"></script>
8
  <script src="https://cdn.jsdelivr.net/npm/@ricky0123/[email protected]/dist/bundle.min.js"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/@xenova/[email protected]"></script>
 
136
  font-size: 14px;
137
  padding: 5px 10px;
138
  }
139
+ #localVideo, #remoteVideo {
140
  display: none;
141
  }
142
  </style>
 
169
  <div id="logs"></div>
170
  <button id="clear-logs">Clear</button>
171
  </div>
172
+ <video id="localVideo" autoplay></video>
173
+ <video id="remoteVideo" autoplay></video>
174
 
175
  <script type="module">
176
  import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/[email protected]';
 
184
  const logsDiv = document.getElementById('logs');
185
  const clearLogsButton = document.getElementById('clear-logs');
186
  const localVideo = document.getElementById('localVideo');
187
+ const remoteVideo = document.getElementById('remoteVideo');
188
 
189
  let myvad;
190
  let sttPipeline;
 
198
  let microphoneStream;
199
  let isSpeaking = false;
200
  let currentAudioSource = null;
201
+ let rtcConnection = null;
202
+ let rtcLoopbackConnection = null;
203
+ let loopbackStream = new MediaStream();
204
 
205
  function createVisualizer() {
206
  const barCount = 64;
 
310
  analyser.fftSize = 128;
311
  dataArray = new Uint8Array(analyser.frequencyBinCount);
312
 
 
313
  localVideo.volume = 0;
314
+ localVideo.muted = true;
315
+ document.getElementById('localVideo').volume = 0;
316
+
317
+ remoteVideo.volume = 0;
318
+ remoteVideo.muted = true;
319
+ document.getElementById('remoteVideo').volume = 0;
320
 
321
  // Request both audio and video streams
322
  microphoneStream = await navigator.mediaDevices.getUserMedia({
 
330
  console.log('Active constraints:', microphoneStream.getAudioTracks()[0].getConstraints());
331
  console.log('Microphone stream settings:', microphoneStream.getAudioTracks()[0].getSettings());
332
 
333
+ // Implement loopback hack for improved echo cancellation
334
+ const offerOptions = {
335
+ offerToReceiveAudio: true,
336
+ offerToReceiveVideo: false,
337
+ };
338
+
339
+ rtcConnection = new RTCPeerConnection();
340
+ rtcLoopbackConnection = new RTCPeerConnection();
341
+
342
+ rtcConnection.onicecandidate = e => e.candidate && rtcLoopbackConnection.addIceCandidate(new RTCIceCandidate(e.candidate));
343
+ rtcLoopbackConnection.onicecandidate = e => e.candidate && rtcConnection.addIceCandidate(new RTCIceCandidate(e.candidate));
344
+
345
+ rtcLoopbackConnection.ontrack = e => e.streams[0].getTracks().forEach(track => loopbackStream.addTrack(track));
346
+
347
+ microphoneStream.getTracks().forEach(track => rtcConnection.addTrack(track, microphoneStream));
348
+
349
+ const offer = await rtcConnection.createOffer(offerOptions);
350
+ await rtcConnection.setLocalDescription(offer);
351
+ await rtcLoopbackConnection.setRemoteDescription(offer);
352
+ const answer = await rtcLoopbackConnection.createAnswer();
353
+ await rtcLoopbackConnection.setLocalDescription(answer);
354
+ await rtcConnection.setRemoteDescription(answer);
355
+
356
+ // Use the loopback stream for audio processing
357
+ const source = audioContext.createMediaStreamSource(loopbackStream);
358
  source.connect(analyser);
359
 
360
  myvad = await vad.MicVAD.new({
 
404
  if (localVideo) {
405
  localVideo.srcObject = null;
406
  }
407
+ if (remoteVideo) {
408
+ remoteVideo.srcObject = null;
409
+ }
410
+ if (rtcConnection) {
411
+ rtcConnection.close();
412
+ rtcConnection = null;
413
+ }
414
+ if (rtcLoopbackConnection) {
415
+ rtcLoopbackConnection.close();
416
+ rtcLoopbackConnection = null;
417
+ }
418
+ loopbackStream = new MediaStream();
419
  stopCurrentAudio();
420
  startButton.textContent = 'Begin Call';
421
  isListening = false;
422
  addLog('System: Stopped listening.');
423
  cancelAnimationFrame(animationId);
424
  addLog('System: Microphone closed');
425
+ }
426
 
427
  startButton.addEventListener('click', toggleListening);
428
  clearLogsButton.addEventListener('click', () => {