awacke1 commited on
Commit
f43e9df
·
verified ·
1 Parent(s): 6afba32

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +228 -0
app.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import datetime
3
+ import os
4
+
5
+ # Initialize session state for transcript history if not exists
6
+ if 'transcript_history' not in st.session_state:
7
+ st.session_state.transcript_history = ""
8
+
9
+ # Create a container for the transcript history
10
+ history_container = st.empty()
11
+ text_area = st.empty()
12
+
13
+ html = """
14
+ <!DOCTYPE html>
15
+ <html>
16
+ <head>
17
+ <title>Continuous Speech Demo</title>
18
+ <style>
19
+ body {
20
+ font-family: sans-serif;
21
+ padding: 20px;
22
+ max-width: 800px;
23
+ margin: 0 auto;
24
+ }
25
+ button {
26
+ padding: 10px 20px;
27
+ margin: 10px 5px;
28
+ font-size: 16px;
29
+ }
30
+ #status {
31
+ margin: 10px 0;
32
+ padding: 10px;
33
+ background: #e8f5e9;
34
+ border-radius: 4px;
35
+ }
36
+ #output {
37
+ white-space: pre-wrap;
38
+ padding: 15px;
39
+ background: #f5f5f5;
40
+ border-radius: 4px;
41
+ margin: 10px 0;
42
+ min-height: 100px;
43
+ max-height: 400px;
44
+ overflow-y: auto;
45
+ }
46
+ .controls {
47
+ margin: 10px 0;
48
+ }
49
+ </style>
50
+ </head>
51
+ <body>
52
+ <h1>Continuous Speech Recognition</h1>
53
+ <div class="controls">
54
+ <button id="start">Start Listening</button>
55
+ <button id="stop" disabled>Stop Listening</button>
56
+ <button id="clear">Clear Text</button>
57
+ </div>
58
+ <div id="status">Ready</div>
59
+ <div id="output"></div>
60
+
61
+ <script>
62
+ if (!('webkitSpeechRecognition' in window)) {
63
+ alert('Speech recognition not supported');
64
+ } else {
65
+ const recognition = new webkitSpeechRecognition();
66
+ const startButton = document.getElementById('start');
67
+ const stopButton = document.getElementById('stop');
68
+ const clearButton = document.getElementById('clear');
69
+ const status = document.getElementById('status');
70
+ const output = document.getElementById('output');
71
+ let fullTranscript = '';
72
+ let lastUpdateTime = Date.now();
73
+
74
+ // Function to update Streamlit
75
+ function updateStreamlit(text, isFinal) {
76
+ // Create data object
77
+ const data = {
78
+ text: text,
79
+ isFinal: isFinal,
80
+ timestamp: new Date().toISOString()
81
+ };
82
+
83
+ // Send to Streamlit using the Streamlit component API
84
+ window.parent.postMessage({
85
+ type: 'streamlit:setComponentValue',
86
+ value: data
87
+ }, '*');
88
+ }
89
+
90
+ // Configure recognition
91
+ recognition.continuous = true;
92
+ recognition.interimResults = true;
93
+
94
+ startButton.onclick = () => {
95
+ try {
96
+ recognition.start();
97
+ status.textContent = 'Listening...';
98
+ startButton.disabled = true;
99
+ stopButton.disabled = false;
100
+ } catch (e) {
101
+ console.error(e);
102
+ status.textContent = 'Error: ' + e.message;
103
+ }
104
+ };
105
+
106
+ stopButton.onclick = () => {
107
+ recognition.stop();
108
+ status.textContent = 'Stopped';
109
+ startButton.disabled = false;
110
+ stopButton.disabled = true;
111
+ };
112
+
113
+ clearButton.onclick = () => {
114
+ fullTranscript = '';
115
+ output.textContent = '';
116
+ updateStreamlit('', true); // Clear Streamlit display
117
+ };
118
+
119
+ recognition.onresult = (event) => {
120
+ let interimTranscript = '';
121
+ let finalTranscript = '';
122
+
123
+ // Process results
124
+ for (let i = event.resultIndex; i < event.results.length; i++) {
125
+ const transcript = event.results[i][0].transcript;
126
+ if (event.results[i].isFinal) {
127
+ finalTranscript += transcript + '\\n';
128
+ } else {
129
+ interimTranscript += transcript;
130
+ }
131
+ }
132
+
133
+ // Update if we have final results or it's been 5 seconds
134
+ if (finalTranscript || (Date.now() - lastUpdateTime > 5000)) {
135
+ if (finalTranscript) {
136
+ fullTranscript += finalTranscript;
137
+ updateStreamlit(finalTranscript, true); // Send final transcript to Streamlit
138
+ } else if (interimTranscript) {
139
+ fullTranscript += interimTranscript + '\\n';
140
+ updateStreamlit(interimTranscript, false); // Send interim transcript to Streamlit
141
+ }
142
+ lastUpdateTime = Date.now();
143
+ }
144
+
145
+ // Display results
146
+ output.textContent = fullTranscript + (interimTranscript ? '... ' + interimTranscript : '');
147
+
148
+ // Auto-scroll to bottom
149
+ output.scrollTop = output.scrollHeight;
150
+ };
151
+
152
+ recognition.onend = () => {
153
+ // Automatically restart if not manually stopped
154
+ if (!stopButton.disabled) {
155
+ try {
156
+ recognition.start();
157
+ console.log('Restarted recognition');
158
+ } catch (e) {
159
+ console.error('Failed to restart recognition:', e);
160
+ status.textContent = 'Error restarting: ' + e.message;
161
+ startButton.disabled = false;
162
+ stopButton.disabled = true;
163
+ }
164
+ }
165
+ };
166
+
167
+ recognition.onerror = (event) => {
168
+ console.error('Recognition error:', event.error);
169
+ status.textContent = 'Error: ' + event.error;
170
+
171
+ // Only reset buttons if it's a fatal error
172
+ if (event.error === 'not-allowed' || event.error === 'service-not-allowed') {
173
+ startButton.disabled = false;
174
+ stopButton.disabled = true;
175
+ }
176
+ };
177
+ }
178
+ </script>
179
+ </body>
180
+ </html>
181
+ """
182
+
183
+ # Create custom component
184
+ def speech_recognition():
185
+ component_value = st.components.v1.html(html, height=600)
186
+ return component_value
187
+
188
+ # Function to save transcript to file
189
+ def save_transcript(text):
190
+ if not os.path.exists('transcripts'):
191
+ os.makedirs('transcripts')
192
+
193
+ timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
194
+ filename = f"transcripts/transcript_{timestamp}.md"
195
+
196
+ with open(filename, 'a', encoding='utf-8') as f:
197
+ f.write(text + '\n')
198
+
199
+ # Main app
200
+ st.title("Speech Recognition with Transcript History")
201
+
202
+ # Get the speech recognition component value
203
+ result = speech_recognition()
204
+
205
+ # If we receive a new transcript
206
+ if result:
207
+ transcript_data = result
208
+
209
+ # Update the transcript history
210
+ if transcript_data.get('isFinal', False):
211
+ new_text = transcript_data.get('text', '')
212
+ st.session_state.transcript_history += new_text
213
+
214
+ # Save to file
215
+ save_transcript(new_text)
216
+
217
+ # Update the display
218
+ history_container.markdown(st.session_state.transcript_history)
219
+ text_area.text_area("Full Transcript", st.session_state.transcript_history, height=200)
220
+
221
+ # Add a download button for the full transcript
222
+ if st.session_state.transcript_history:
223
+ st.download_button(
224
+ label="Download Full Transcript",
225
+ data=st.session_state.transcript_history,
226
+ file_name=f"transcript_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.md",
227
+ mime="text/markdown"
228
+ )