SreekarB commited on
Commit
9c403ff
·
verified ·
1 Parent(s): 8e70044

Upload simple_app.py

Browse files
Files changed (1) hide show
  1. simple_app.py +367 -54
simple_app.py CHANGED
@@ -6,6 +6,8 @@ import logging
6
  import os
7
  import tempfile
8
  import shutil
 
 
9
  from datetime import datetime
10
 
11
  # Try to import ReportLab (needed for PDF generation)
@@ -28,10 +30,14 @@ AWS_ACCESS_KEY = os.getenv("AWS_ACCESS_KEY", "")
28
  AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY", "")
29
  AWS_REGION = os.getenv("AWS_REGION", "us-east-1")
30
 
31
- # Initialize Bedrock client if credentials are available
32
  bedrock_client = None
 
 
 
33
  if AWS_ACCESS_KEY and AWS_SECRET_KEY:
34
  try:
 
35
  bedrock_client = boto3.client(
36
  'bedrock-runtime',
37
  aws_access_key_id=AWS_ACCESS_KEY,
@@ -39,26 +45,52 @@ if AWS_ACCESS_KEY and AWS_SECRET_KEY:
39
  region_name=AWS_REGION
40
  )
41
  logger.info("Bedrock client initialized successfully")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  except Exception as e:
43
- logger.error(f"Failed to initialize Bedrock client: {str(e)}")
 
 
 
 
44
 
45
  # Create data directories if they don't exist
46
  DATA_DIR = os.environ.get("DATA_DIR", "patient_data")
47
  DOWNLOADS_DIR = os.path.join(DATA_DIR, "downloads")
 
48
 
49
  def ensure_data_dirs():
50
  """Ensure data directories exist"""
 
51
  try:
52
  os.makedirs(DATA_DIR, exist_ok=True)
53
  os.makedirs(DOWNLOADS_DIR, exist_ok=True)
54
- logger.info(f"Data directories created: {DATA_DIR}, {DOWNLOADS_DIR}")
 
55
  except Exception as e:
56
  logger.warning(f"Could not create data directories: {str(e)}")
57
  # Fallback to tmp directory on HF Spaces
58
- global DOWNLOADS_DIR
59
  DOWNLOADS_DIR = os.path.join(tempfile.gettempdir(), "casl_downloads")
 
60
  os.makedirs(DOWNLOADS_DIR, exist_ok=True)
61
- logger.info(f"Using fallback directory: {DOWNLOADS_DIR}")
 
62
 
63
  # Initialize data directories
64
  ensure_data_dirs()
@@ -148,11 +180,216 @@ def call_bedrock(prompt, max_tokens=4096):
148
  logger.error(f"Error in call_bedrock: {str(e)}")
149
  return f"Error: {str(e)}"
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  def generate_demo_response(prompt):
152
- """Generate a simulated response for demo purposes"""
153
- # This function generates a realistic but fake response for demo purposes
154
- # In a real deployment, you would call an actual LLM API
155
 
 
 
 
 
 
 
 
 
 
 
 
156
  return """<SPEECH_FACTORS_START>
157
  Difficulty producing fluent speech: 8, 65
158
  Examples:
@@ -508,6 +745,8 @@ def analyze_transcript(transcript, age, gender):
508
 
509
  def export_pdf(results, patient_name="", record_id="", age="", gender="", assessment_date="", clinician=""):
510
  """Export analysis results to a PDF report"""
 
 
511
  # Check if ReportLab is available
512
  if not REPORTLAB_AVAILABLE:
513
  return "ERROR: PDF export is not available - ReportLab library is not installed. Please run 'pip install reportlab'."
@@ -525,7 +764,6 @@ def export_pdf(results, patient_name="", record_id="", age="", gender="", assess
525
  except Exception as e:
526
  logger.warning(f"Could not access downloads directory: {str(e)}")
527
  # Fallback to temp directory
528
- global DOWNLOADS_DIR
529
  DOWNLOADS_DIR = os.path.join(tempfile.gettempdir(), "casl_downloads")
530
  os.makedirs(DOWNLOADS_DIR, exist_ok=True)
531
 
@@ -703,51 +941,88 @@ def create_interface():
703
 
704
  with gr.Blocks(title="Simple CASL Analysis Tool", theme=theme) as app:
705
  gr.Markdown("# CASL Analysis Tool")
706
- gr.Markdown("A simplified tool for analyzing speech transcripts using CASL framework")
707
-
708
- with gr.Row():
709
- with gr.Column(scale=1):
710
- # Patient info
711
- gr.Markdown("### Patient Information")
712
- patient_name = gr.Textbox(label="Patient Name", placeholder="Enter patient name")
713
- record_id = gr.Textbox(label="Record ID", placeholder="Enter record ID")
714
-
715
  with gr.Row():
716
- age = gr.Number(label="Age", value=8, minimum=1, maximum=120)
717
- gender = gr.Radio(["male", "female", "other"], label="Gender", value="male")
718
-
719
- assessment_date = gr.Textbox(
720
- label="Assessment Date",
721
- placeholder="MM/DD/YYYY",
722
- value=datetime.now().strftime('%m/%d/%Y')
723
- )
724
- clinician_name = gr.Textbox(label="Clinician", placeholder="Enter clinician name")
725
-
726
- # Transcript input
727
- gr.Markdown("### Transcript")
728
- sample_btn = gr.Button("Load Sample Transcript")
729
- file_upload = gr.File(label="Upload transcript file (.txt or .cha)")
730
- transcript = gr.Textbox(
731
- label="Speech transcript (CHAT format preferred)",
732
- placeholder="Enter transcript text or upload a file...",
733
- lines=10
734
- )
735
-
736
- # Analysis button
737
- analyze_btn = gr.Button("Analyze Transcript", variant="primary")
738
-
739
- with gr.Column(scale=1):
740
- # Results display
741
- gr.Markdown("### Analysis Results")
742
-
743
- analysis_output = gr.Markdown(label="Full Analysis")
744
-
745
- # PDF export (only shown if ReportLab is available)
746
- export_status = gr.Markdown("")
747
- if REPORTLAB_AVAILABLE:
748
- export_btn = gr.Button("Export as PDF", variant="secondary")
749
- else:
750
- gr.Markdown("⚠️ PDF export is disabled - ReportLab library is not installed")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
751
 
752
  # Load sample transcript button
753
  def load_sample():
@@ -865,6 +1140,43 @@ def create_interface():
865
  ],
866
  outputs=[export_status]
867
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
868
 
869
  return app
870
 
@@ -876,7 +1188,8 @@ def create_requirements_file():
876
  "numpy",
877
  "Pillow",
878
  "reportlab>=3.6.0", # Required for PDF exports
879
- "boto3"
 
880
  ]
881
 
882
  with open("requirements.txt", "w") as f:
 
6
  import os
7
  import tempfile
8
  import shutil
9
+ import time
10
+ import uuid
11
  from datetime import datetime
12
 
13
  # Try to import ReportLab (needed for PDF generation)
 
30
  AWS_SECRET_KEY = os.getenv("AWS_SECRET_KEY", "")
31
  AWS_REGION = os.getenv("AWS_REGION", "us-east-1")
32
 
33
+ # Initialize AWS clients if credentials are available
34
  bedrock_client = None
35
+ transcribe_client = None
36
+ s3_client = None
37
+
38
  if AWS_ACCESS_KEY and AWS_SECRET_KEY:
39
  try:
40
+ # Initialize Bedrock client for AI analysis
41
  bedrock_client = boto3.client(
42
  'bedrock-runtime',
43
  aws_access_key_id=AWS_ACCESS_KEY,
 
45
  region_name=AWS_REGION
46
  )
47
  logger.info("Bedrock client initialized successfully")
48
+
49
+ # Initialize Transcribe client for speech-to-text
50
+ transcribe_client = boto3.client(
51
+ 'transcribe',
52
+ aws_access_key_id=AWS_ACCESS_KEY,
53
+ aws_secret_access_key=AWS_SECRET_KEY,
54
+ region_name=AWS_REGION
55
+ )
56
+ logger.info("Transcribe client initialized successfully")
57
+
58
+ # Initialize S3 client for storing audio files
59
+ s3_client = boto3.client(
60
+ 's3',
61
+ aws_access_key_id=AWS_ACCESS_KEY,
62
+ aws_secret_access_key=AWS_SECRET_KEY,
63
+ region_name=AWS_REGION
64
+ )
65
+ logger.info("S3 client initialized successfully")
66
  except Exception as e:
67
+ logger.error(f"Failed to initialize AWS clients: {str(e)}")
68
+
69
+ # S3 bucket for storing audio files
70
+ S3_BUCKET = os.environ.get("S3_BUCKET", "casl-audio-files")
71
+ S3_PREFIX = "transcribe-audio/"
72
 
73
  # Create data directories if they don't exist
74
  DATA_DIR = os.environ.get("DATA_DIR", "patient_data")
75
  DOWNLOADS_DIR = os.path.join(DATA_DIR, "downloads")
76
+ AUDIO_DIR = os.path.join(DATA_DIR, "audio")
77
 
78
  def ensure_data_dirs():
79
  """Ensure data directories exist"""
80
+ global DOWNLOADS_DIR, AUDIO_DIR
81
  try:
82
  os.makedirs(DATA_DIR, exist_ok=True)
83
  os.makedirs(DOWNLOADS_DIR, exist_ok=True)
84
+ os.makedirs(AUDIO_DIR, exist_ok=True)
85
+ logger.info(f"Data directories created: {DATA_DIR}, {DOWNLOADS_DIR}, {AUDIO_DIR}")
86
  except Exception as e:
87
  logger.warning(f"Could not create data directories: {str(e)}")
88
  # Fallback to tmp directory on HF Spaces
 
89
  DOWNLOADS_DIR = os.path.join(tempfile.gettempdir(), "casl_downloads")
90
+ AUDIO_DIR = os.path.join(tempfile.gettempdir(), "casl_audio")
91
  os.makedirs(DOWNLOADS_DIR, exist_ok=True)
92
+ os.makedirs(AUDIO_DIR, exist_ok=True)
93
+ logger.info(f"Using fallback directories: {DOWNLOADS_DIR}, {AUDIO_DIR}")
94
 
95
  # Initialize data directories
96
  ensure_data_dirs()
 
180
  logger.error(f"Error in call_bedrock: {str(e)}")
181
  return f"Error: {str(e)}"
182
 
183
+ def transcribe_audio(audio_path, patient_age=8):
184
+ """Transcribe an audio recording using Amazon Transcribe and format in CHAT format"""
185
+ if not os.path.exists(audio_path):
186
+ logger.error(f"Audio file not found: {audio_path}")
187
+ return "Error: Audio file not found."
188
+
189
+ if not transcribe_client or not s3_client:
190
+ logger.warning("AWS clients not initialized, using demo transcription")
191
+ return generate_demo_transcription()
192
+
193
+ try:
194
+ # Get file info
195
+ file_name = os.path.basename(audio_path)
196
+ file_size = os.path.getsize(audio_path)
197
+ _, file_extension = os.path.splitext(file_name)
198
+
199
+ # Check file format
200
+ supported_formats = ['.mp3', '.mp4', '.wav', '.flac', '.ogg', '.amr', '.webm']
201
+ if file_extension.lower() not in supported_formats:
202
+ logger.error(f"Unsupported audio format: {file_extension}")
203
+ return f"Error: Unsupported audio format. Please use one of: {', '.join(supported_formats)}"
204
+
205
+ # Generate a unique job name
206
+ timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
207
+ job_name = f"casl-transcription-{timestamp}"
208
+ s3_key = f"{S3_PREFIX}{job_name}{file_extension}"
209
+
210
+ # Upload to S3
211
+ logger.info(f"Uploading {file_name} to S3 bucket {S3_BUCKET}")
212
+ try:
213
+ with open(audio_path, 'rb') as audio_file:
214
+ s3_client.upload_fileobj(audio_file, S3_BUCKET, s3_key)
215
+ except Exception as e:
216
+ logger.error(f"Failed to upload to S3: {str(e)}")
217
+
218
+ # If upload fails, try to create the bucket
219
+ try:
220
+ s3_client.create_bucket(Bucket=S3_BUCKET)
221
+ logger.info(f"Created S3 bucket: {S3_BUCKET}")
222
+
223
+ # Try upload again
224
+ with open(audio_path, 'rb') as audio_file:
225
+ s3_client.upload_fileobj(audio_file, S3_BUCKET, s3_key)
226
+ except Exception as bucket_error:
227
+ logger.error(f"Failed to create bucket and upload: {str(bucket_error)}")
228
+ return "Error: Failed to upload audio file. Please check your AWS permissions."
229
+
230
+ # Start transcription job
231
+ logger.info(f"Starting transcription job: {job_name}")
232
+ media_format = file_extension.lower()[1:] # Remove the dot
233
+ if media_format == 'webm':
234
+ media_format = 'webm' # Amazon Transcribe expects this
235
+
236
+ # Determine language settings based on patient age
237
+ if patient_age < 10:
238
+ # For younger children, enabling child language model is helpful
239
+ language_options = {
240
+ 'LanguageCode': 'en-US',
241
+ 'Settings': {
242
+ 'LanguageModelName': 'ChildLanguage'
243
+ }
244
+ }
245
+ else:
246
+ language_options = {
247
+ 'LanguageCode': 'en-US'
248
+ }
249
+
250
+ transcribe_client.start_transcription_job(
251
+ TranscriptionJobName=job_name,
252
+ Media={
253
+ 'MediaFileUri': f"s3://{S3_BUCKET}/{s3_key}"
254
+ },
255
+ MediaFormat=media_format,
256
+ **language_options,
257
+ Settings={
258
+ 'ShowSpeakerLabels': True,
259
+ 'MaxSpeakerLabels': 2 # Typically patient + clinician
260
+ }
261
+ )
262
+
263
+ # Wait for the job to complete (with timeout)
264
+ logger.info("Waiting for transcription to complete...")
265
+ max_tries = 30 # 5 minutes max wait
266
+ tries = 0
267
+
268
+ while tries < max_tries:
269
+ try:
270
+ job = transcribe_client.get_transcription_job(TranscriptionJobName=job_name)
271
+ status = job['TranscriptionJob']['TranscriptionJobStatus']
272
+
273
+ if status == 'COMPLETED':
274
+ # Get the transcript
275
+ transcript_uri = job['TranscriptionJob']['Transcript']['TranscriptFileUri']
276
+
277
+ # Download the transcript
278
+ import urllib.request
279
+ import json
280
+
281
+ with urllib.request.urlopen(transcript_uri) as response:
282
+ transcript_json = json.loads(response.read().decode('utf-8'))
283
+
284
+ # Convert to CHAT format
285
+ chat_transcript = format_as_chat(transcript_json)
286
+ return chat_transcript
287
+
288
+ elif status == 'FAILED':
289
+ reason = job['TranscriptionJob'].get('FailureReason', 'Unknown failure')
290
+ logger.error(f"Transcription job failed: {reason}")
291
+ return f"Error: Transcription failed - {reason}"
292
+
293
+ # Still in progress, wait and try again
294
+ tries += 1
295
+ time.sleep(10) # Check every 10 seconds
296
+
297
+ except Exception as e:
298
+ logger.error(f"Error checking transcription job: {str(e)}")
299
+ return f"Error getting transcription: {str(e)}"
300
+
301
+ # If we got here, we timed out
302
+ return "Error: Transcription timed out. The process is taking longer than expected."
303
+
304
+ except Exception as e:
305
+ logger.exception("Error in audio transcription")
306
+ return f"Error transcribing audio: {str(e)}"
307
+
308
+ def format_as_chat(transcript_json):
309
+ """Format the Amazon Transcribe JSON result as CHAT format"""
310
+ try:
311
+ # Get transcript items
312
+ items = transcript_json['results']['items']
313
+
314
+ # Get speaker labels if available
315
+ speakers = {}
316
+ if 'speaker_labels' in transcript_json['results']:
317
+ speaker_segments = transcript_json['results']['speaker_labels']['segments']
318
+
319
+ # Map each item to its speaker
320
+ for segment in speaker_segments:
321
+ for item in segment['items']:
322
+ start_time = item['start_time']
323
+ speakers[start_time] = segment['speaker_label']
324
+
325
+ # Build transcript by combining words into utterances by speaker
326
+ current_speaker = None
327
+ current_utterance = []
328
+ utterances = []
329
+
330
+ for item in items:
331
+ # Skip non-pronunciation items (like punctuation)
332
+ if item['type'] != 'pronunciation':
333
+ continue
334
+
335
+ word = item['alternatives'][0]['content']
336
+ start_time = item.get('start_time')
337
+
338
+ # Determine speaker if available
339
+ speaker = speakers.get(start_time, 'spk_0')
340
+
341
+ # If speaker changed, start a new utterance
342
+ if speaker != current_speaker and current_utterance:
343
+ utterances.append((current_speaker, ' '.join(current_utterance)))
344
+ current_utterance = []
345
+
346
+ current_speaker = speaker
347
+ current_utterance.append(word)
348
+
349
+ # Add the last utterance
350
+ if current_utterance:
351
+ utterances.append((current_speaker, ' '.join(current_utterance)))
352
+
353
+ # Format as CHAT
354
+ chat_lines = []
355
+ for speaker, text in utterances:
356
+ # Map speakers to CHAT format
357
+ # Assuming spk_0 is the patient (PAR) and spk_1 is the clinician (INV)
358
+ chat_speaker = "*PAR:" if speaker == "spk_0" else "*INV:"
359
+ chat_lines.append(f"{chat_speaker} {text}.")
360
+
361
+ return '\n'.join(chat_lines)
362
+
363
+ except Exception as e:
364
+ logger.exception("Error formatting transcript")
365
+ return "*PAR: (Error formatting transcript)"
366
+
367
+ def generate_demo_transcription():
368
+ """Generate a simulated transcription response"""
369
+ return """*PAR: today I want to tell you about my favorite toy.
370
+ *PAR: it's a &-um teddy bear that I got for my birthday.
371
+ *PAR: he has &-um brown fur and a red bow.
372
+ *PAR: I like to sleep with him every night.
373
+ *PAR: sometimes I take him to school in my backpack.
374
+ *INV: what's your teddy bear's name?
375
+ *PAR: his name is &-um Brownie because he's brown."""
376
+
377
  def generate_demo_response(prompt):
378
+ """Generate a response using Bedrock if available, otherwise return a demo response"""
379
+ # This function will attempt to call Bedrock, and only fall back to the demo response
380
+ # if Bedrock is not available or fails
381
 
382
+ # Try to call Bedrock first if client is available
383
+ if bedrock_client:
384
+ try:
385
+ return call_bedrock(prompt)
386
+ except Exception as e:
387
+ logger.error(f"Error calling Bedrock: {str(e)}")
388
+ logger.info("Falling back to demo response")
389
+ # Continue to fallback response if Bedrock call fails
390
+
391
+ # Fallback demo response
392
+ logger.warning("Using demo response - Bedrock client not available or call failed")
393
  return """<SPEECH_FACTORS_START>
394
  Difficulty producing fluent speech: 8, 65
395
  Examples:
 
745
 
746
  def export_pdf(results, patient_name="", record_id="", age="", gender="", assessment_date="", clinician=""):
747
  """Export analysis results to a PDF report"""
748
+ global DOWNLOADS_DIR
749
+
750
  # Check if ReportLab is available
751
  if not REPORTLAB_AVAILABLE:
752
  return "ERROR: PDF export is not available - ReportLab library is not installed. Please run 'pip install reportlab'."
 
764
  except Exception as e:
765
  logger.warning(f"Could not access downloads directory: {str(e)}")
766
  # Fallback to temp directory
 
767
  DOWNLOADS_DIR = os.path.join(tempfile.gettempdir(), "casl_downloads")
768
  os.makedirs(DOWNLOADS_DIR, exist_ok=True)
769
 
 
941
 
942
  with gr.Blocks(title="Simple CASL Analysis Tool", theme=theme) as app:
943
  gr.Markdown("# CASL Analysis Tool")
944
+ gr.Markdown("A simplified tool for analyzing speech transcripts and audio using CASL framework")
945
+
946
+ with gr.Tabs() as main_tabs:
947
+ # Analysis Tab
948
+ with gr.TabItem("Analysis", id=0):
 
 
 
 
949
  with gr.Row():
950
+ with gr.Column(scale=1):
951
+ # Patient info
952
+ gr.Markdown("### Patient Information")
953
+ patient_name = gr.Textbox(label="Patient Name", placeholder="Enter patient name")
954
+ record_id = gr.Textbox(label="Record ID", placeholder="Enter record ID")
955
+
956
+ with gr.Row():
957
+ age = gr.Number(label="Age", value=8, minimum=1, maximum=120)
958
+ gender = gr.Radio(["male", "female", "other"], label="Gender", value="male")
959
+
960
+ assessment_date = gr.Textbox(
961
+ label="Assessment Date",
962
+ placeholder="MM/DD/YYYY",
963
+ value=datetime.now().strftime('%m/%d/%Y')
964
+ )
965
+ clinician_name = gr.Textbox(label="Clinician", placeholder="Enter clinician name")
966
+
967
+ # Transcript input
968
+ gr.Markdown("### Transcript")
969
+ sample_btn = gr.Button("Load Sample Transcript")
970
+ file_upload = gr.File(label="Upload transcript file (.txt or .cha)")
971
+ transcript = gr.Textbox(
972
+ label="Speech transcript (CHAT format preferred)",
973
+ placeholder="Enter transcript text or upload a file...",
974
+ lines=10
975
+ )
976
+
977
+ # Analysis button
978
+ analyze_btn = gr.Button("Analyze Transcript", variant="primary")
979
+
980
+ with gr.Column(scale=1):
981
+ # Results display
982
+ gr.Markdown("### Analysis Results")
983
+
984
+ analysis_output = gr.Markdown(label="Full Analysis")
985
+
986
+ # PDF export (only shown if ReportLab is available)
987
+ export_status = gr.Markdown("")
988
+ if REPORTLAB_AVAILABLE:
989
+ export_btn = gr.Button("Export as PDF", variant="secondary")
990
+ else:
991
+ gr.Markdown("⚠️ PDF export is disabled - ReportLab library is not installed")
992
+
993
+ # Transcription Tab
994
+ with gr.TabItem("Transcription", id=1):
995
+ with gr.Row():
996
+ with gr.Column(scale=1):
997
+ gr.Markdown("### Audio Transcription")
998
+ gr.Markdown("Upload an audio recording to automatically transcribe it in CHAT format")
999
+
1000
+ # Patient's age helps with transcription accuracy
1001
+ transcription_age = gr.Number(label="Patient Age", value=8, minimum=1, maximum=120,
1002
+ info="For children under 10, special language models may be used")
1003
+
1004
+ # Audio input
1005
+ audio_input = gr.Audio(type="filepath", label="Upload Audio Recording",
1006
+ format="mp3,wav,ogg,webm",
1007
+ elem_id="audio-input")
1008
+
1009
+ # Transcribe button
1010
+ transcribe_btn = gr.Button("Transcribe Audio", variant="primary")
1011
+
1012
+ with gr.Column(scale=1):
1013
+ # Transcription output
1014
+ transcription_output = gr.Textbox(
1015
+ label="Transcription Result",
1016
+ placeholder="Transcription will appear here...",
1017
+ lines=12
1018
+ )
1019
+
1020
+ with gr.Row():
1021
+ # Button to use transcription in analysis
1022
+ copy_to_analysis_btn = gr.Button("Use for Analysis", variant="secondary")
1023
+
1024
+ # Status/info message
1025
+ transcription_status = gr.Markdown("")
1026
 
1027
  # Load sample transcript button
1028
  def load_sample():
 
1140
  ],
1141
  outputs=[export_status]
1142
  )
1143
+
1144
+ # Transcription button handler
1145
+ def on_transcribe_audio(audio_path, age_val):
1146
+ try:
1147
+ if not audio_path:
1148
+ return "Please upload an audio file to transcribe.", "Error: No audio file provided."
1149
+
1150
+ # Process the audio file with Amazon Transcribe
1151
+ transcription = transcribe_audio(audio_path, age_val)
1152
+
1153
+ # Return status message based on whether it's a demo or real transcription
1154
+ if not transcribe_client:
1155
+ status_msg = "⚠️ Demo mode: Using example transcription (AWS credentials not configured)"
1156
+ else:
1157
+ status_msg = "✅ Transcription completed successfully"
1158
+
1159
+ return transcription, status_msg
1160
+ except Exception as e:
1161
+ logger.exception("Error transcribing audio")
1162
+ return f"Error: {str(e)}", f"❌ Transcription failed: {str(e)}"
1163
+
1164
+ # Connect the transcribe button to its handler
1165
+ transcribe_btn.click(
1166
+ on_transcribe_audio,
1167
+ inputs=[audio_input, transcription_age],
1168
+ outputs=[transcription_output, transcription_status]
1169
+ )
1170
+
1171
+ # Copy transcription to analysis tab
1172
+ def copy_to_analysis(transcription):
1173
+ return transcription, gr.update(selected=0) # Switch to Analysis tab
1174
+
1175
+ copy_to_analysis_btn.click(
1176
+ copy_to_analysis,
1177
+ inputs=[transcription_output],
1178
+ outputs=[transcript, main_tabs]
1179
+ )
1180
 
1181
  return app
1182
 
 
1188
  "numpy",
1189
  "Pillow",
1190
  "reportlab>=3.6.0", # Required for PDF exports
1191
+ "boto3>=1.28.0", # Required for AWS services
1192
+ "botocore>=1.31.0" # Required for AWS services
1193
  ]
1194
 
1195
  with open("requirements.txt", "w") as f: