victor HF staff commited on
Commit
afde5c9
·
1 Parent(s): e1c3a1a

feat: Implement HTML demo for Mini-Omni chat

Browse files
Files changed (1) hide show
  1. webui/omni_html_demo.html +119 -0
webui/omni_html_demo.html ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Mini-Omni HTML Demo</title>
7
+ <style>
8
+ body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
9
+ #recordButton { width: 100px; height: 100px; border-radius: 50%; background-color: #f0f0f0; border: none; cursor: pointer; }
10
+ #recordButton:active { background-color: #ff4444; }
11
+ #chatHistory { height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 10px; margin-bottom: 20px; }
12
+ .message { margin-bottom: 10px; }
13
+ .user { color: blue; }
14
+ .ai { color: green; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <h1>Mini-Omni Chat Demo</h1>
19
+ <div id="chatHistory"></div>
20
+ <button id="recordButton">Hold to Speak</button>
21
+ <audio id="audioPlayback" controls style="display:none;"></audio>
22
+
23
+ <script>
24
+ const API_URL = 'http://127.0.0.1:60808/chat';
25
+ const recordButton = document.getElementById('recordButton');
26
+ const chatHistory = document.getElementById('chatHistory');
27
+ const audioPlayback = document.getElementById('audioPlayback');
28
+ let mediaRecorder;
29
+ let audioChunks = [];
30
+
31
+ recordButton.addEventListener('mousedown', startRecording);
32
+ recordButton.addEventListener('mouseup', stopRecording);
33
+ recordButton.addEventListener('mouseleave', stopRecording);
34
+
35
+ async function startRecording() {
36
+ try {
37
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
38
+ mediaRecorder = new MediaRecorder(stream);
39
+ mediaRecorder.ondataavailable = event => {
40
+ audioChunks.push(event.data);
41
+ };
42
+ mediaRecorder.start();
43
+ updateChatHistory('User', 'Recording...');
44
+ } catch (error) {
45
+ console.error('Error accessing microphone:', error);
46
+ alert('Error accessing microphone. Please ensure you have given permission.');
47
+ }
48
+ }
49
+
50
+ function stopRecording() {
51
+ if (mediaRecorder && mediaRecorder.state === 'recording') {
52
+ mediaRecorder.stop();
53
+ mediaRecorder.onstop = async () => {
54
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
55
+ audioChunks = [];
56
+ updateChatHistory('User', URL.createObjectURL(audioBlob));
57
+ await sendAudioToAPI(audioBlob);
58
+ };
59
+ }
60
+ }
61
+
62
+ async function sendAudioToAPI(audioBlob) {
63
+ try {
64
+ const reader = new FileReader();
65
+ reader.readAsDataURL(audioBlob);
66
+ reader.onloadend = async function() {
67
+ const base64Audio = reader.result.split(',')[1];
68
+ const response = await fetch(API_URL, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ },
73
+ body: JSON.stringify({ audio: base64Audio })
74
+ });
75
+
76
+ if (response.ok) {
77
+ const reader = response.body.getReader();
78
+ const stream = new ReadableStream({
79
+ async start(controller) {
80
+ while (true) {
81
+ const { done, value } = await reader.read();
82
+ if (done) break;
83
+ controller.enqueue(value);
84
+ }
85
+ controller.close();
86
+ }
87
+ });
88
+
89
+ const audioResponse = new Response(stream);
90
+ const audioBlob = await audioResponse.blob();
91
+ audioPlayback.src = URL.createObjectURL(audioBlob);
92
+ audioPlayback.play();
93
+
94
+ updateChatHistory('AI', URL.createObjectURL(audioBlob));
95
+ } else {
96
+ console.error('API response not ok:', response.status);
97
+ updateChatHistory('AI', 'Error in API response');
98
+ }
99
+ };
100
+ } catch (error) {
101
+ console.error('Error sending audio to API:', error);
102
+ updateChatHistory('AI', 'Error communicating with the server');
103
+ }
104
+ }
105
+
106
+ function updateChatHistory(speaker, content) {
107
+ const messageElement = document.createElement('div');
108
+ messageElement.className = 'message ' + (speaker === 'User' ? 'user' : 'ai');
109
+ if (content.startsWith('blob:') || content.startsWith('data:')) {
110
+ messageElement.innerHTML = `<strong>${speaker}:</strong> <audio src="${content}" controls></audio>`;
111
+ } else {
112
+ messageElement.innerHTML = `<strong>${speaker}:</strong> ${content}`;
113
+ }
114
+ chatHistory.appendChild(messageElement);
115
+ chatHistory.scrollTop = chatHistory.scrollHeight;
116
+ }
117
+ </script>
118
+ </body>
119
+ </html>