awacke1 commited on
Commit
05a59a4
·
verified ·
1 Parent(s): 7833681

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +231 -1
README.md CHANGED
@@ -10,4 +10,234 @@ pinned: true
10
  license: mit
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  license: mit
11
  ---
12
 
13
+ import streamlit as st
14
+ import datetime
15
+ import os
16
+ import base64
17
+
18
+ # Initialize session state variables
19
+ if 'transcript_history' not in st.session_state:
20
+ st.session_state.transcript_history = []
21
+
22
+ # Function to create a download link for a string
23
+ def get_download_link(text, filename):
24
+ b64 = base64.b64encode(text.encode()).decode()
25
+ return f'<a href="data:text/plain;base64,{b64}" download="{filename}">Download Transcript</a>'
26
+
27
+ # Create the main layout
28
+ st.title("Speech Recognition with Transcript History")
29
+
30
+ col1, col2 = st.columns([2, 1])
31
+
32
+ with col1:
33
+ html = """
34
+ <!DOCTYPE html>
35
+ <html>
36
+ <head>
37
+ <title>Continuous Speech Demo</title>
38
+ <style>
39
+ body {
40
+ font-family: sans-serif;
41
+ padding: 20px;
42
+ max-width: 800px;
43
+ margin: 0 auto;
44
+ }
45
+ button {
46
+ padding: 10px 20px;
47
+ margin: 10px 5px;
48
+ font-size: 16px;
49
+ }
50
+ #status {
51
+ margin: 10px 0;
52
+ padding: 10px;
53
+ background: #e8f5e9;
54
+ border-radius: 4px;
55
+ }
56
+ #output {
57
+ white-space: pre-wrap;
58
+ padding: 15px;
59
+ background: #f5f5f5;
60
+ border-radius: 4px;
61
+ margin: 10px 0;
62
+ min-height: 100px;
63
+ max-height: 400px;
64
+ overflow-y: auto;
65
+ }
66
+ .controls {
67
+ margin: 10px 0;
68
+ }
69
+ </style>
70
+ </head>
71
+ <body>
72
+ <div class="controls">
73
+ <button id="start">Start Listening</button>
74
+ <button id="stop" disabled>Stop Listening</button>
75
+ <button id="clear">Clear Text</button>
76
+ </div>
77
+ <div id="status">Ready</div>
78
+ <div id="output"></div>
79
+
80
+ <script>
81
+ if (!('webkitSpeechRecognition' in window)) {
82
+ alert('Speech recognition not supported');
83
+ } else {
84
+ const recognition = new webkitSpeechRecognition();
85
+ const startButton = document.getElementById('start');
86
+ const stopButton = document.getElementById('stop');
87
+ const clearButton = document.getElementById('clear');
88
+ const status = document.getElementById('status');
89
+ const output = document.getElementById('output');
90
+ let fullTranscript = '';
91
+ let lastUpdateTime = Date.now();
92
+
93
+ // Configure recognition
94
+ recognition.continuous = true;
95
+ recognition.interimResults = true;
96
+
97
+ // Function to start recognition
98
+ const startRecognition = () => {
99
+ try {
100
+ recognition.start();
101
+ status.textContent = 'Listening...';
102
+ startButton.disabled = true;
103
+ stopButton.disabled = false;
104
+ } catch (e) {
105
+ console.error(e);
106
+ status.textContent = 'Error: ' + e.message;
107
+ }
108
+ };
109
+
110
+ // Auto-start on load
111
+ window.addEventListener('load', () => {
112
+ setTimeout(startRecognition, 1000); // Delay start by 1 second to ensure everything is loaded
113
+ });
114
+
115
+ startButton.onclick = startRecognition;
116
+
117
+ stopButton.onclick = () => {
118
+ recognition.stop();
119
+ status.textContent = 'Stopped';
120
+ startButton.disabled = false;
121
+ stopButton.disabled = true;
122
+ };
123
+
124
+ clearButton.onclick = () => {
125
+ fullTranscript = '';
126
+ output.textContent = '';
127
+ // Send clear signal to Streamlit
128
+ window.parent.postMessage({type: 'clear'}, '*');
129
+ };
130
+
131
+ recognition.onresult = (event) => {
132
+ let interimTranscript = '';
133
+ let finalTranscript = '';
134
+
135
+ for (let i = event.resultIndex; i < event.results.length; i++) {
136
+ const transcript = event.results[i][0].transcript;
137
+ if (event.results[i].isFinal) {
138
+ finalTranscript += transcript + '\\n';
139
+ } else {
140
+ interimTranscript += transcript;
141
+ }
142
+ }
143
+
144
+ if (finalTranscript || (Date.now() - lastUpdateTime > 5000)) {
145
+ if (finalTranscript) {
146
+ fullTranscript += finalTranscript;
147
+ // Send to Streamlit
148
+ window.parent.postMessage({
149
+ type: 'transcript',
150
+ text: finalTranscript
151
+ }, '*');
152
+ }
153
+ lastUpdateTime = Date.now();
154
+ }
155
+
156
+ output.textContent = fullTranscript + (interimTranscript ? '... ' + interimTranscript : '');
157
+ output.scrollTop = output.scrollHeight;
158
+ };
159
+
160
+ recognition.onend = () => {
161
+ if (!stopButton.disabled) {
162
+ try {
163
+ recognition.start();
164
+ console.log('Restarted recognition');
165
+ } catch (e) {
166
+ console.error('Failed to restart recognition:', e);
167
+ status.textContent = 'Error restarting: ' + e.message;
168
+ startButton.disabled = false;
169
+ stopButton.disabled = true;
170
+ }
171
+ }
172
+ };
173
+
174
+ recognition.onerror = (event) => {
175
+ console.error('Recognition error:', event.error);
176
+ status.textContent = 'Error: ' + event.error;
177
+
178
+ if (event.error === 'not-allowed' || event.error === 'service-not-allowed') {
179
+ startButton.disabled = false;
180
+ stopButton.disabled = true;
181
+ }
182
+ };
183
+
184
+ // Listen for messages from Streamlit
185
+ window.addEventListener('message', (event) => {
186
+ if (event.data.type === 'clear') {
187
+ fullTranscript = '';
188
+ output.textContent = '';
189
+ }
190
+ });
191
+ }
192
+ </script>
193
+ </body>
194
+ </html>
195
+ """
196
+
197
+ # Display the HTML component
198
+ component = st.components.v1.html(html, height=400)
199
+
200
+ with col2:
201
+ # Display transcript history
202
+ st.subheader("Transcript History")
203
+
204
+ # Function to save transcript
205
+ def save_transcript(text):
206
+ if not os.path.exists('transcripts'):
207
+ os.makedirs('transcripts')
208
+ timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
209
+ filename = f"transcripts/transcript_{timestamp}.md"
210
+ with open(filename, 'w', encoding='utf-8') as f:
211
+ f.write(text)
212
+ return filename
213
+
214
+ # Display transcript
215
+ if st.session_state.transcript_history:
216
+ full_transcript = "\n".join(st.session_state.transcript_history)
217
+ st.text_area("Full Transcript", value=full_transcript, height=300)
218
+
219
+ # Save transcript to file
220
+ timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
221
+ filename = f"transcript_{timestamp}.md"
222
+
223
+ # Create download link
224
+ st.markdown(get_download_link(full_transcript, filename), unsafe_allow_html=True)
225
+
226
+ # Save to file system
227
+ if st.button("Save to File"):
228
+ saved_file = save_transcript(full_transcript)
229
+ st.success(f"Saved to {saved_file}")
230
+
231
+ # Handle transcript updates from JavaScript
232
+ if component:
233
+ try:
234
+ data = component
235
+ if isinstance(data, dict) and data.get('type') == 'transcript':
236
+ st.session_state.transcript_history.append(data['text'])
237
+ st.experimental_rerun()
238
+ elif isinstance(data, dict) and data.get('type') == 'clear':
239
+ st.session_state.transcript_history = []
240
+ st.experimental_rerun()
241
+ except Exception as e:
242
+ st.error(f"Error processing transcript: {e}")
243
+