amirjamali commited on
Commit
55dbd8d
·
unverified ·
1 Parent(s): 77cd9f4

Enhance Dockerfile and Streamlit configuration; add upload directory, max upload size, and XSRF protection; update README with troubleshooting tips for file uploads

Browse files
Files changed (4) hide show
  1. .streamlit/config.toml +2 -0
  2. Dockerfile +4 -1
  3. README.md +16 -1
  4. src/streamlit_app.py +115 -23
.streamlit/config.toml CHANGED
@@ -3,6 +3,8 @@ port = 8501
3
  address = "0.0.0.0"
4
  headless = true
5
  enableCORS = false
 
 
6
 
7
  [browser]
8
  gatherUsageStats = false
 
3
  address = "0.0.0.0"
4
  headless = true
5
  enableCORS = false
6
+ maxUploadSize = 200
7
+ enableXsrfProtection = false
8
 
9
  [browser]
10
  gatherUsageStats = false
Dockerfile CHANGED
@@ -19,7 +19,8 @@ RUN apt-get update && \
19
  && rm -rf /var/lib/apt/lists/*
20
 
21
  # Create necessary directories
22
- RUN mkdir -p /app/tmp_model /tmp/matplotlib
 
23
 
24
  # Copy requirements first (for better caching)
25
  COPY requirements.txt .
@@ -39,6 +40,8 @@ RUN echo "[server]" > ./.streamlit/config.toml && \
39
  echo "port = 8501" >> ./.streamlit/config.toml && \
40
  echo "address = \"0.0.0.0\"" >> ./.streamlit/config.toml && \
41
  echo "headless = true" >> ./.streamlit/config.toml && \
 
 
42
  echo "" >> ./.streamlit/config.toml && \
43
  echo "[browser]" >> ./.streamlit/config.toml && \
44
  echo "gatherUsageStats = false" >> ./.streamlit/config.toml && \
 
19
  && rm -rf /var/lib/apt/lists/*
20
 
21
  # Create necessary directories
22
+ RUN mkdir -p /app/tmp_model /tmp/matplotlib /app/uploads
23
+ RUN chmod -R 777 /app/uploads /app/tmp_model /tmp/matplotlib
24
 
25
  # Copy requirements first (for better caching)
26
  COPY requirements.txt .
 
40
  echo "port = 8501" >> ./.streamlit/config.toml && \
41
  echo "address = \"0.0.0.0\"" >> ./.streamlit/config.toml && \
42
  echo "headless = true" >> ./.streamlit/config.toml && \
43
+ echo "maxUploadSize = 200" >> ./.streamlit/config.toml && \
44
+ echo "enableXsrfProtection = false" >> ./.streamlit/config.toml && \
45
  echo "" >> ./.streamlit/config.toml && \
46
  echo "[browser]" >> ./.streamlit/config.toml && \
47
  echo "gatherUsageStats = false" >> ./.streamlit/config.toml && \
README.md CHANGED
@@ -73,10 +73,25 @@ If you encounter errors like `Sign in to confirm you're not a bot` when using Yo
73
  The app is containerized with Docker for easy deployment. Use the included Dockerfile to build and run:
74
 
75
  ```bash
 
76
  docker build -t accent-detector .
77
- docker run -p 8501:8501 accent-detector
 
 
 
 
 
78
  ```
79
 
 
 
 
 
 
 
 
 
 
80
  ## Powered By
81
  - [SpeechBrain](https://huggingface.co/speechbrain/lang-id-commonlanguage_ecapa)
82
  - [Hugging Face Transformers](https://huggingface.co/speechbrain/lang-id-voxlingua107-ecapa)
 
73
  The app is containerized with Docker for easy deployment. Use the included Dockerfile to build and run:
74
 
75
  ```bash
76
+ # Build the Docker image
77
  docker build -t accent-detector .
78
+
79
+ # Run the container with volume mounting for better file handling
80
+ docker run -p 8501:8501 --volume /tmp/accent-detector:/app/uploads accent-detector
81
+
82
+ # For Windows users:
83
+ docker run -p 8501:8501 --volume C:\temp\accent-detector:/app/uploads accent-detector
84
  ```
85
 
86
+ ### Troubleshooting Upload Issues
87
+
88
+ If you encounter 403 Forbidden errors when uploading files:
89
+
90
+ 1. Make sure your audio file is under 200MB
91
+ 2. Try converting your audio to a WAV or MP3 format
92
+ 3. For longer files, consider extracting just the speech segment
93
+ 4. If uploading an MP4 video, ensure it's not encrypted or DRM-protected
94
+
95
  ## Powered By
96
  - [SpeechBrain](https://huggingface.co/speechbrain/lang-id-commonlanguage_ecapa)
97
  - [Hugging Face Transformers](https://huggingface.co/speechbrain/lang-id-voxlingua107-ecapa)
src/streamlit_app.py CHANGED
@@ -43,17 +43,23 @@ import matplotlib.pyplot as plt
43
  import tempfile
44
  import time
45
 
46
- # Comment for deployment instructions:
47
  # To deploy this app:
48
  # 1. Make sure Docker is installed
49
  # 2. Build the Docker image: docker build -t accent-detector .
50
- # 3. Run the container: docker run -p 8501:8501 accent-detector
 
51
  # 4. Access the app at http://localhost:8501
52
  #
53
  # For cloud deployment:
54
  # - Streamlit Cloud: Connect your GitHub repository to Streamlit Cloud
55
- # - Hugging Face Spaces: Use the Docker deployment option
56
- # - Azure/AWS/GCP: Deploy the container using their container services
 
 
 
 
 
57
 
58
  # Load environment variables (if .env file exists)
59
  try:
@@ -323,15 +329,52 @@ class AccentDetector:
323
 
324
  def process_uploaded_audio(uploaded_file):
325
  """Process uploaded audio file"""
326
- with tempfile.NamedTemporaryFile(delete=False, suffix='.wav') as temp_file:
327
- temp_file.write(uploaded_file.getvalue())
328
- audio_path = temp_file.name
329
-
330
- detector = AccentDetector()
331
- results = detector.analyze_audio(audio_path)
332
-
333
- # Clean up
334
- os.unlink(audio_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  return results
336
 
337
  # --- Streamlit App ---
@@ -479,9 +522,16 @@ with tab2:
479
  st.markdown("### 🎵 Upload Audio File")
480
  st.caption("**Recommended option!** Direct audio upload is more reliable than video URLs.")
481
 
 
 
 
 
 
 
482
  uploaded_file = st.file_uploader("Upload an audio file",
483
- type=["wav", "mp3", "m4a", "ogg", "flac"],
484
- help="Support for WAV, MP3, M4A, OGG and FLAC formats")
 
485
 
486
  if uploaded_file is not None:
487
  # Show a preview of the audio
@@ -494,14 +544,25 @@ with tab2:
494
  analyze_button = st.button("Analyze Audio", type="primary", use_container_width=True)
495
  with col2:
496
  st.caption("Tip: 15-30 seconds of clear speech works best for accent detection")
497
-
498
  if analyze_button:
499
  with st.spinner("Analyzing audio... (this may take 15-30 seconds)"):
500
  try:
501
- results = process_uploaded_audio(uploaded_file)
502
-
503
- # Display results
504
- st.success(" Analysis Complete!")
 
 
 
 
 
 
 
 
 
 
 
 
505
 
506
  # Create columns for results
507
  col1, col2 = st.columns([2, 1])
@@ -511,8 +572,7 @@ with tab2:
511
  st.markdown(f"**Detected Accent:** {results['accent']}")
512
  st.markdown(f"**English Proficiency:** {results['english_confidence']:.1f}%")
513
  st.markdown(f"**Accent Confidence:** {results['accent_confidence']:.1f}%")
514
-
515
- # Show explanation in a box
516
  st.markdown("### Expert Analysis")
517
  st.info(results['explanation'])
518
 
@@ -520,8 +580,40 @@ with tab2:
520
  if results['audio_viz']:
521
  st.pyplot(results['audio_viz'])
522
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  except Exception as e:
524
- st.error(f"Error during analysis: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
525
 
526
  # Add footer with deployment info
527
  st.markdown("---")
 
43
  import tempfile
44
  import time
45
 
46
+ # Deployment instructions:
47
  # To deploy this app:
48
  # 1. Make sure Docker is installed
49
  # 2. Build the Docker image: docker build -t accent-detector .
50
+ # 3. Run the container: docker run -p 8501:8501 --volume /tmp/accent-detector:/app/uploads accent-detector
51
+ # For Windows: docker run -p 8501:8501 --volume C:\temp\accent-detector:/app/uploads accent-detector
52
  # 4. Access the app at http://localhost:8501
53
  #
54
  # For cloud deployment:
55
  # - Streamlit Cloud: Connect your GitHub repository to Streamlit Cloud
56
+ # - Hugging Face Spaces: Use the Docker deployment option with proper volume mounts
57
+ # - Azure/AWS/GCP: Deploy the container using their container services with persistent storage
58
+ #
59
+ # Troubleshooting file uploads:
60
+ # - Set maxUploadSize in .streamlit/config.toml
61
+ # - Ensure write permissions on upload directories
62
+ # - For 403 errors, check file size and format compatibility
63
 
64
  # Load environment variables (if .env file exists)
65
  try:
 
329
 
330
  def process_uploaded_audio(uploaded_file):
331
  """Process uploaded audio file"""
332
+ try:
333
+ # Create a unique filename based on timestamp
334
+ timestamp = str(int(time.time()))
335
+ file_extension = os.path.splitext(uploaded_file.name)[1].lower()
336
+
337
+ # Write the uploaded file to disk with proper extension
338
+ temp_input_path = f"uploaded_audio_{timestamp}{file_extension}"
339
+ with open(temp_input_path, "wb") as f:
340
+ f.write(uploaded_file.getbuffer())
341
+
342
+ # For MP4 files, extract the audio using ffmpeg
343
+ if file_extension == ".mp4":
344
+ st.info("Extracting audio from video file...")
345
+ audio_path = f"extracted_audio_{timestamp}.wav"
346
+ try:
347
+ subprocess.run(
348
+ ['ffmpeg', '-i', temp_input_path, '-vn', '-acodec', 'pcm_s16le', '-ar', '16000', '-ac', '1', audio_path],
349
+ check=True,
350
+ capture_output=True
351
+ )
352
+ # Remove the original video file
353
+ os.remove(temp_input_path)
354
+ except subprocess.CalledProcessError as e:
355
+ st.error(f"Error extracting audio: {e}")
356
+ st.error(f"ffmpeg output: {e.stderr.decode('utf-8')}")
357
+ raise
358
+ else:
359
+ # For audio files, use them directly
360
+ audio_path = temp_input_path
361
+
362
+ detector = AccentDetector()
363
+ results = detector.analyze_audio(audio_path)
364
+
365
+ # Clean up
366
+ if os.path.exists(audio_path):
367
+ os.remove(audio_path)
368
+
369
+ return results
370
+
371
+ except Exception as e:
372
+ st.error(f"Error processing audio: {str(e)}")
373
+ if 'temp_input_path' in locals() and os.path.exists(temp_input_path):
374
+ os.remove(temp_input_path)
375
+ if 'audio_path' in locals() and os.path.exists(audio_path):
376
+ os.remove(audio_path)
377
+ raise
378
  return results
379
 
380
  # --- Streamlit App ---
 
522
  st.markdown("### 🎵 Upload Audio File")
523
  st.caption("**Recommended option!** Direct audio upload is more reliable than video URLs.")
524
 
525
+ # Add some information about file size limits
526
+ st.info("📝 **File Requirements**: \n"
527
+ "• Maximum file size: 200MB \n"
528
+ "• Supported formats: WAV, MP3, M4A, OGG, FLAC, MP4 \n"
529
+ "• Recommended length: 15-60 seconds of clear speech")
530
+
531
  uploaded_file = st.file_uploader("Upload an audio file",
532
+ type=["wav", "mp3", "m4a", "ogg", "flac", "mp4"],
533
+ help="Support for WAV, MP3, M4A, OGG, FLAC and MP4 formats",
534
+ accept_multiple_files=False)
535
 
536
  if uploaded_file is not None:
537
  # Show a preview of the audio
 
544
  analyze_button = st.button("Analyze Audio", type="primary", use_container_width=True)
545
  with col2:
546
  st.caption("Tip: 15-30 seconds of clear speech works best for accent detection")
 
547
  if analyze_button:
548
  with st.spinner("Analyzing audio... (this may take 15-30 seconds)"):
549
  try:
550
+ # Check file size before processing
551
+ file_size_mb = len(uploaded_file.getvalue()) / (1024 * 1024)
552
+ if file_size_mb > 190: # Stay below the 200MB limit with some buffer
553
+ st.error(f"File size ({file_size_mb:.1f}MB) is too large. Maximum allowed is 190MB.")
554
+ st.info("Tip: Try trimming your audio to just the speech segment for better results.")
555
+ else:
556
+ # Check the file type and inform user about processing steps
557
+ file_extension = os.path.splitext(uploaded_file.name)[1].lower()
558
+ if file_extension == '.mp4':
559
+ st.info("Processing video file - extracting audio track...")
560
+
561
+ # Process the file
562
+ results = process_uploaded_audio(uploaded_file)
563
+
564
+ # Display results
565
+ st.success("✅ Analysis Complete!")
566
 
567
  # Create columns for results
568
  col1, col2 = st.columns([2, 1])
 
572
  st.markdown(f"**Detected Accent:** {results['accent']}")
573
  st.markdown(f"**English Proficiency:** {results['english_confidence']:.1f}%")
574
  st.markdown(f"**Accent Confidence:** {results['accent_confidence']:.1f}%")
575
+ # Show explanation in a box
 
576
  st.markdown("### Expert Analysis")
577
  st.info(results['explanation'])
578
 
 
580
  if results['audio_viz']:
581
  st.pyplot(results['audio_viz'])
582
 
583
+ except subprocess.CalledProcessError as e:
584
+ st.error("Error processing audio file")
585
+ st.error(f"FFmpeg error: {e.stderr.decode('utf-8') if e.stderr else str(e)}")
586
+ st.info("Troubleshooting tips:\n"
587
+ "• Try a different audio file format (WAV or MP3 recommended)\n"
588
+ "• Make sure the file is not corrupted\n"
589
+ "• Try a shorter audio clip")
590
+
591
+ except PermissionError as e:
592
+ st.error(f"Permission error: {str(e)}")
593
+ st.info("The app doesn't have permission to access or create temporary files. "
594
+ "This could be due to Docker container permissions. "
595
+ "Contact the administrator or try using a different file.")
596
+
597
+ except OSError as e:
598
+ st.error(f"System error: {str(e)}")
599
+ st.info("Check that the file isn't corrupted and try with a smaller audio clip.")
600
+
601
  except Exception as e:
602
+ error_msg = str(e)
603
+ st.error(f"Error during analysis: {error_msg}")
604
+
605
+ if "403" in error_msg:
606
+ st.warning("Received a 403 Forbidden error. This may be due to: \n"
607
+ "• File size exceeding limits\n"
608
+ "• Temporary file permission issues\n"
609
+ "• Network restrictions")
610
+ st.info("Try a smaller audio file (less than 50MB) or a different format.")
611
+ elif "timeout" in error_msg.lower():
612
+ st.warning("The request timed out. Try a shorter audio clip or check your internet connection.")
613
+ elif "memory" in error_msg.lower():
614
+ st.warning("Out of memory error. Try a shorter audio clip.")
615
+ else:
616
+ st.info("If the problem persists, try a different audio file format such as MP3 or WAV.")
617
 
618
  # Add footer with deployment info
619
  st.markdown("---")