Deepti-AI commited on
Commit
c4e5a40
·
verified ·
1 Parent(s): a917add

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +50 -56
templates/index.html CHANGED
@@ -4,31 +4,42 @@
4
  <meta charset="utf-8" />
5
  <title>Ortho Buddy — Voice</title>
6
  <style>
7
- html,body { height:100%; margin:0; font-family: "Segoe UI", Roboto, Arial;
8
- background: radial-gradient(circle at 50% 10%, #144a2b, #062219); color:#bfe6c9; }
9
  .container { width:360px; margin:40px auto; text-align:center; }
10
- h1 { letter-spacing:4px; font-size:36px; color:#2de08b;
11
- text-shadow:0 6px 30px rgba(0,0,0,0.7); margin:20px 0; }
12
  .subtitle { color:#d6f3de; margin-bottom:10px; font-size:24px; }
13
- .robot { width:270px; height:270px; background: url('/static/robot.gif') center/contain no-repeat;
14
- margin: 40px auto; border-radius:8px; }
15
  .control { margin-top:20px; }
16
- .record-btn { width:50px; height:50px; border-radius:60px; border:none;
17
- background:linear-gradient(rgb(248, 245, 248), rgb(248, 245, 248));
18
- box-shadow: 0 10px 30px rgba(0,0,0,0.6); color:white; font-size:18px; cursor:pointer; }
19
- .record-btn.recording { background: linear-gradient(#ff6666, #cc2222);
20
- box-shadow: 0 10px 30px rgba(0,0,0,0.7); }
21
- .reset-btn { position: fixed; top: 20px; right: 20px; padding: 10px 20px;
22
- background: linear-gradient(#2de08b, #0a8f5c); border: none; border-radius: 6px;
23
- font-size: 16px; font-weight: bold; color: #062219; cursor: pointer;
24
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); z-index: 1000; transition: background 0.3s ease; }
25
- .reset-btn:hover { background: linear-gradient(#1bc47a, #07734f); }
26
- .text-stream { margin-top:20px; text-align:left; font-size:16px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  </style>
 
28
  </head>
29
  <body>
30
- <h1 class="heading">Summit Dental & Orthopedics</h1>
31
  <div class="container">
 
32
  <div class="subtitle"><b>KAMMI</b></div>
33
 
34
  <div class="robot" id="robotImg"></div>
@@ -42,9 +53,7 @@
42
  <div class="text-stream" id="textStream"></div>
43
 
44
  <!-- Hidden audio player for streamed voice -->
45
- <audio id="player" controls autoplay playsinline hidden></audio>
46
- <!-- Optional fallback button for mobile autoplay -->
47
- <button id="playBtn" style="display:none;">▶️ Play Response</button>
48
  </div>
49
 
50
  <script>
@@ -54,12 +63,11 @@ let recBtn = document.getElementById("recBtn");
54
  let textStream = document.getElementById("textStream");
55
  let recording = false;
56
  let player = document.getElementById("player");
57
- let playBtn = document.getElementById("playBtn");
58
-
59
- // Reset chat
60
  document.getElementById("resetBtn").addEventListener("click", async () => {
61
  try {
62
- const response = await fetch("/reset_chat", { method: "POST" });
 
 
63
  if (response.ok) {
64
  showTempMessage("Please proceed.", "lightgreen");
65
  } else {
@@ -70,23 +78,18 @@ document.getElementById("resetBtn").addEventListener("click", async () => {
70
  showTempMessage("Reset error: " + error.message, "#ffb3b3");
71
  }
72
  });
73
-
74
  // Utility function to show a message for 2 seconds
75
  function showTempMessage(msg, color) {
76
  const msgDiv = document.createElement("div");
77
  msgDiv.style.color = color;
78
  msgDiv.textContent = msg;
79
  textStream.appendChild(msgDiv);
80
- setTimeout(() => { msgDiv.remove(); }, 2000);
 
 
81
  }
82
-
83
- // Record button logic
84
  recBtn.addEventListener("click", async () => {
85
  if (!recording) {
86
- // Prime audio for mobile autoplay
87
- try { await player.play(); player.pause(); }
88
- catch(e) { console.warn("Audio priming failed:", e); }
89
-
90
  await startRecording();
91
  } else {
92
  stopRecordingAndSend();
@@ -95,10 +98,8 @@ recBtn.addEventListener("click", async () => {
95
  recBtn.textContent = recording ? "Stop" : "🎤";
96
  recBtn.classList.toggle("recording", recording);
97
  });
98
-
99
- // Start recording
100
  async function startRecording() {
101
- textStream.innerHTML = "";
102
  audioChunks = [];
103
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
104
  alert("Your browser does not support microphone capture.");
@@ -106,11 +107,11 @@ async function startRecording() {
106
  }
107
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
108
  mediaRecorder = new MediaRecorder(stream);
109
- mediaRecorder.ondataavailable = e => { if (e.data.size > 0) audioChunks.push(e.data); };
 
 
110
  mediaRecorder.start();
111
  }
112
-
113
- // Stop recording & send to server
114
  function stopRecordingAndSend() {
115
  if (!mediaRecorder) return;
116
  mediaRecorder.stop();
@@ -118,21 +119,24 @@ function stopRecordingAndSend() {
118
  const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
119
  const form = new FormData();
120
  form.append("file", audioBlob, "recording.webm");
121
-
122
- const resp = await fetch("/chat_stream", { method: "POST", body: form });
 
 
 
 
123
  if (!resp.ok) {
124
  const txt = await resp.text();
125
  textStream.innerHTML += "<div style='color:#ffb3b3'>Server error: " + txt + "</div>";
126
  return;
127
  }
128
-
129
- // Stream audio using MediaSource
130
  const mediaSource = new MediaSource();
131
  player.src = URL.createObjectURL(mediaSource);
132
  mediaSource.addEventListener('sourceopen', async () => {
133
  const sourceBuffer = mediaSource.addSourceBuffer('audio/mpeg');
134
  const reader = resp.body.getReader();
135
- while(true) {
136
  const { done, value } = await reader.read();
137
  if (done) break;
138
  sourceBuffer.appendBuffer(value);
@@ -140,19 +144,9 @@ function stopRecordingAndSend() {
140
  }
141
  mediaSource.endOfStream();
142
  });
143
-
144
- // Show fallback play button if autoplay blocked
145
- player.play().catch(() => {
146
- playBtn.style.display = "inline-block";
147
- });
148
  };
149
  }
150
-
151
- // Fallback play button
152
- playBtn.addEventListener("click", () => {
153
- player.play();
154
- playBtn.style.display = "none";
155
- });
156
  </script>
157
  </body>
158
- </html>
 
4
  <meta charset="utf-8" />
5
  <title>Ortho Buddy — Voice</title>
6
  <style>
7
+ html,body { height:100%; margin:0; font-family: "Segoe UI", Roboto, Arial; background: radial-gradient(circle at 50% 10%, #144a2b, #062219); color:#bfe6c9; }
 
8
  .container { width:360px; margin:40px auto; text-align:center; }
9
+ h1 { letter-spacing:4px; font-size:36px; color:#2de08b; text-shadow:0 6px 30px rgba(0,0,0,0.7); margin:20px 0; }
 
10
  .subtitle { color:#d6f3de; margin-bottom:10px; font-size:24px; }
11
+ .robot { width:270px; height:270px; background: url('/static/robot.gif') center/contain no-repeat; margin: 40px auto; border-radius:8px; }
 
12
  .control { margin-top:20px; }
13
+ .record-btn { width:50px; height:50px; border-radius:60px; border:none; background:linear-gradient(rgb(248, 245, 248), rgb(248, 245, 248)); box-shadow: 0 10px 30px rgba(0,0,0,0.6); color:white; font-size:18px; cursor:pointer; }
14
+ .record-btn.recording { background: linear-gradient(#ff6666, #cc2222); box-shadow: 0 10px 30px rgba(0,0,0,0.7); }
15
+ .heading {
16
+ text-align: center;
17
+ }
18
+ .reset-btn {
19
+ position: fixed;
20
+ top: 20px;
21
+ right: 20px;
22
+ padding: 10px 20px;
23
+ background: linear-gradient(#2de08b, #0a8f5c);
24
+ border: none;
25
+ border-radius: 6px;
26
+ font-size: 16px;
27
+ font-weight: bold;
28
+ color: #062219;
29
+ cursor: pointer;
30
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
31
+ z-index: 1000;
32
+ transition: background 0.3s ease;
33
+ }
34
+ .reset-btn:hover {
35
+ background: linear-gradient(#1bc47a, #07734f);
36
+ }
37
  </style>
38
+ <h1 class = "heading">Summit Dental & Orthopedics</h1>
39
  </head>
40
  <body>
 
41
  <div class="container">
42
+
43
  <div class="subtitle"><b>KAMMI</b></div>
44
 
45
  <div class="robot" id="robotImg"></div>
 
53
  <div class="text-stream" id="textStream"></div>
54
 
55
  <!-- Hidden audio player for streamed voice -->
56
+ <audio id="player" controls autoplay hidden></audio>
 
 
57
  </div>
58
 
59
  <script>
 
63
  let textStream = document.getElementById("textStream");
64
  let recording = false;
65
  let player = document.getElementById("player");
 
 
 
66
  document.getElementById("resetBtn").addEventListener("click", async () => {
67
  try {
68
+ const response = await fetch("/reset_chat", {
69
+ method: "POST"
70
+ });
71
  if (response.ok) {
72
  showTempMessage("Please proceed.", "lightgreen");
73
  } else {
 
78
  showTempMessage("Reset error: " + error.message, "#ffb3b3");
79
  }
80
  });
 
81
  // Utility function to show a message for 2 seconds
82
  function showTempMessage(msg, color) {
83
  const msgDiv = document.createElement("div");
84
  msgDiv.style.color = color;
85
  msgDiv.textContent = msg;
86
  textStream.appendChild(msgDiv);
87
+ setTimeout(() => {
88
+ msgDiv.remove();
89
+ }, 2000);
90
  }
 
 
91
  recBtn.addEventListener("click", async () => {
92
  if (!recording) {
 
 
 
 
93
  await startRecording();
94
  } else {
95
  stopRecordingAndSend();
 
98
  recBtn.textContent = recording ? "Stop" : "🎤";
99
  recBtn.classList.toggle("recording", recording);
100
  });
 
 
101
  async function startRecording() {
102
+ textStream.innerHTML = ""; // clear previous
103
  audioChunks = [];
104
  if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
105
  alert("Your browser does not support microphone capture.");
 
107
  }
108
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
109
  mediaRecorder = new MediaRecorder(stream);
110
+ mediaRecorder.ondataavailable = e => {
111
+ if (e.data && e.data.size > 0) audioChunks.push(e.data);
112
+ };
113
  mediaRecorder.start();
114
  }
 
 
115
  function stopRecordingAndSend() {
116
  if (!mediaRecorder) return;
117
  mediaRecorder.stop();
 
119
  const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
120
  const form = new FormData();
121
  form.append("file", audioBlob, "recording.webm");
122
+ // fetch streaming audio directly
123
+ console.log("Sending audio to server...");
124
+ const resp = await fetch("/chat_stream", {
125
+ method: "POST",
126
+ body: form,
127
+ });
128
  if (!resp.ok) {
129
  const txt = await resp.text();
130
  textStream.innerHTML += "<div style='color:#ffb3b3'>Server error: " + txt + "</div>";
131
  return;
132
  }
133
+ // create an object URL from streaming response
 
134
  const mediaSource = new MediaSource();
135
  player.src = URL.createObjectURL(mediaSource);
136
  mediaSource.addEventListener('sourceopen', async () => {
137
  const sourceBuffer = mediaSource.addSourceBuffer('audio/mpeg');
138
  const reader = resp.body.getReader();
139
+ while (true) {
140
  const { done, value } = await reader.read();
141
  if (done) break;
142
  sourceBuffer.appendBuffer(value);
 
144
  }
145
  mediaSource.endOfStream();
146
  });
147
+ player.play();
 
 
 
 
148
  };
149
  }
 
 
 
 
 
 
150
  </script>
151
  </body>
152
+ </html>