File size: 3,660 Bytes
7fb4a00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Smart Earbud Volume Controller</title>
  <!-- ONNX Runtime Web for running Silero VAD locally in browser -->
  <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
  <!-- ONNX VAD Helper library -->
  <script src="https://cdn.jsdelivr.net/npm/@vapi-ai/vads-web/dist/index.umd.js"></script>
  <style>
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      background-color: #0f172a;
      color: #f8fafc;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      margin: 0;
    }
    .card {
      background-color: #1e293b;
      padding: 2rem;
      border-radius: 12px;
      box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
      max-width: 450px;
      width: 100%;
      text-align: center;
    }
    button {
      background-color: #3b82f6;
      color: white;
      border: none;
      padding: 0.75rem 1.5rem;
      font-size: 1rem;
      font-weight: 600;
      border-radius: 8px;
      cursor: pointer;
      margin-bottom: 1rem;
      transition: background-color 0.2s;
    }
    button:hover { background-color: #2563eb; }
    button:disabled { background-color: #64748b; cursor: not-allowed; }
    .status-box {
      margin-top: 1.5rem;
      padding: 1rem;
      border-radius: 8px;
      background-color: #334155;
      font-weight: 500;
    }
    .speaking { background-color: #991b1b; color: #fca5a5; }
    .silent { background-color: #065f46; color: #a7f3d0; }
    audio { width: 100%; margin-top: 1rem; }
  </style>
</head>
<body>

<div class="card">
  <h2>Auto-Ducking Earbud Simulator</h2>
  <p>Play audio below, then start the microphone. When speech is detected, audio volume will automatically drop.</p>
  
  <audio id="audioPlayer" controls loop src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"></audio>

  <br/><br/>
  <button id="startBtn">Start Voice Detection</button>

  <div id="status" class="status-box silent">Status: Inactive</div>
</div>

<script>
  let vad;
  const audioPlayer = document.getElementById('audioPlayer');
  const startBtn = document.getElementById('startBtn');
  const statusDiv = document.getElementById('status');

  let restoreTimeout;

  startBtn.addEventListener('click', async () => {
    try {
      startBtn.disabled = true;
      startBtn.innerText = "Initializing VAD...";

      // Initialize VAD Engine
      vad = await vad.MicVAD.new({
        onSpeechStart: () => {
          statusDiv.innerText = "Speech Detected: Lowering Volume";
          statusDiv.className = "status-box speaking";
          audioPlayer.volume = 0.2; // DUCK VOLUME (20%)
          if (restoreTimeout) clearTimeout(restoreTimeout);
        },
        onSpeechEnd: () => {
          statusDiv.innerText = "Silence: Restoring Volume soon...";
          // Hold lower volume for 1.5s after speech stops
          restoreTimeout = setTimeout(() => {
            audioPlayer.volume = 1.0; // RESTORE VOLUME (100%)
            statusDiv.innerText = "Monitoring Environment...";
            statusDiv.className = "status-box silent";
          }, 1500);
        }
      });

      vad.start();
      startBtn.innerText = "Listening...";
      statusDiv.innerText = "Monitoring Environment...";
    } catch (e) {
      console.error(e);
      alert("Microphone access denied or error loading model.");
      startBtn.disabled = false;
      startBtn.innerText = "Start Voice Detection";
    }
  });
</script>

</body>
</html>