Skip to content

feat: Add support for uploading audio files to generate quizzes#673

Open
AbiramiR-27 wants to merge 3 commits into
AOSSIE-Org:mainfrom
AbiramiR-27:feat/audio-upload-support
Open

feat: Add support for uploading audio files to generate quizzes#673
AbiramiR-27 wants to merge 3 commits into
AOSSIE-Org:mainfrom
AbiramiR-27:feat/audio-upload-support

Conversation

@AbiramiR-27

@AbiramiR-27 AbiramiR-27 commented Jun 29, 2026

Copy link
Copy Markdown

Addressed Issues:

Fixes #378

Screenshots/Recordings:

N/A (This is a backend functionality addition implementing .mp3 and .wav transcription, with accompanying text prompt updates on the frontend pages).

Additional Notes:

This PR implements audio upload support (.wav and .mp3) for quiz generation:

  • Audio Conversion: Leverages pydub to convert .mp3 uploads into .wav audio.
  • 60-Second Chunking: Splits the audio track into 60-second segments to bypass the length and size constraints of the free Google Web Speech API interface (SpeechRecognition.recognize_google).
  • Concurrency Safety: Temporary chunks are generated inside the upload folder with a request-unique UUID (uuid.uuid4().hex) prefix, preventing filename collisions across concurrent uploads.
  • Cleanup Guarantee: Utilizes a try...finally block to ensure all temporary chunk files and converted WAV intermediates are immediately deleted from disk after processing.
  • Error Handling: Gracefully handles UnknownValueError by appending [Unintelligible] to the transcription, and chains connection errors (RequestError) into a standard RuntimeError.
  • UI Labels: Updated upload descriptions from PDF, MP3 supported to PDF, Audio supported in both the React Web client and the Chrome extension.
  • Documentation: Added note under README.md highlighting the system requirement for ffmpeg/libav on the system's PATH.

AI Usage Disclosure:

Check one of the checkboxes below:

  • This PR does not contain AI-generated code at all.
  • This PR contains AI-generated code. I have read the AI Usage Policy and this PR complies with this policy. I have tested the code locally and I am responsible for it.

I have used the following AI models and tools: Pair programming with the Antigravity AI coding assistant to design the concurrency safety mechanisms, draft clean-up logic, and build/run isolated mock unit tests.

Checklist

  • My PR addresses a single issue, fixes a single bug or makes a single improvement.
  • My code follows the project's code style and conventions
  • If applicable, I have made corresponding changes or additions to the documentation
  • If applicable, I have made corresponding changes or additions to tests
  • My changes generate no new warnings or errors
  • I have joined the Discord server and I will share a link to this PR with the project maintainers there
  • I have read the Contribution Guidelines
  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.
  • I have filled this PR template completely and carefully, and I understand that my PR may be closed without review otherwise.

Summary by CodeRabbit

  • New Features
    • Added audio-file text extraction (supports common audio formats), including chunked transcription for improved handling of longer files.
  • Documentation
    • Added a “System Requirements” section detailing required system audio tools (ffmpeg/libav on PATH) and required Python packages.
  • UI Updates
    • Updated file upload prompts and accepted file types to reflect broader “Audio supported” support (not just MP3).
  • Bug Fixes
    • Improved error handling for unsupported formats and transcription/runtime failures, returning clear 400 responses instead of propagating errors.
  • Chores
    • Pinned/added required dependencies for transcription audio processing.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@AbiramiR-27, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d14703be-701e-470f-abc7-9aaab8d75bed

📥 Commits

Reviewing files that changed from the base of the PR and between 211f246 and 4f5f448.

📒 Files selected for processing (4)
  • backend/Generator/main.py
  • backend/server.py
  • eduaid_web/src/pages/Text_Input.jsx
  • extension/src/pages/text_input/TextInput.jsx
📝 Walkthrough

Walkthrough

Adds audio upload transcription in the backend, routes WAV/MP3 files through chunked speech recognition, and returns upload errors as HTTP 400. It also adds the required Python dependencies, documents system prerequisites, and updates frontend upload labels and file filters.

Changes

Audio Upload and Transcription

Layer / File(s) Summary
Dependencies, requirements, and UI copy
requirements.txt, README.md, eduaid_web/src/pages/Text_Input.jsx, extension/src/pages/text_input/TextInput.jsx
Pins textblob==0.19.0, adds SpeechRecognition and pydub, documents ffmpeg/libav and Python package requirements, and updates upload prompts and accepted file types for audio support.
Audio transcription helper
backend/Generator/main.py
Adds audio transcription imports and implements extract_text_from_audio with MP3-to-WAV conversion, 60-second chunking, Google speech recognition, placeholder text for unintelligible audio, request-error conversion, and temp-file cleanup.
Upload dispatch and error handling
backend/Generator/main.py, backend/server.py
Updates process_file to validate audio extensions, use UUID-based temp filenames, route .wav/.mp3 into transcription, clean up uploaded files, and return 400 JSON errors from /upload on ValueError or RuntimeError.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nibbled the bytes and the sounds took flight,
Into tidy little chunks for the transcript light.
With WAVs and MP3s, the quizzes now sing,
And ffmpeg hums in the background wing.
Hop hop hooray, the audio trail's clear,
A bunny-built quiz path is finally այստեղ here!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning requirements.txt also pins textblob to 0.19.0, which is unrelated to audio upload support. Remove the textblob version pin unless it is required for this feature, or document it as part of the issue scope.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding audio file upload support for quiz generation.
Linked Issues check ✅ Passed The changes implement the requested audio upload and transcription flow for .mp3/.wav, matching issue #378.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
eduaid_web/src/pages/Text_Input.jsx (1)

190-190: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding an accept attribute to the file input for better UX.

The file input currently has no accept attribute to guide users toward supported formats. Since the backend now handles PDF and audio files (.pdf, .mp3, .wav), consider adding:

- <input type="file" ref={fileInputRef} onChange={handleFileUpload} style={{ display: "none" }} />
+ <input type="file" accept=".pdf,.mp3,.wav" ref={fileInputRef} onChange={handleFileUpload} style={{ display: "none" }} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@eduaid_web/src/pages/Text_Input.jsx` at line 190, The file picker in
Text_Input.jsx currently allows any file type, so update the hidden input used
by handleFileUpload to include an accept restriction for the supported backend
formats. Add the accept attribute on the same input element referenced by
fileInputRef so users are guided to choose only PDF and audio files such as
.pdf, .mp3, and .wav.
README.md (2)

25-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clarify that WAV is also directly supported.

The current wording only mentions MP3→WAV conversion, but the backend also accepts .wav files directly per the PR objectives. Users with WAV files may incorrectly think they need to convert externally. Consider rephrasing to indicate both formats are accepted, e.g.:

- **ffmpeg** or **libav** installed and available on your system `PATH`. The backend's `extract_text_from_audio()` method (in `backend/Generator/main.py`) uses `pydub` to convert MP3 to WAV, and `pydub` depends on these tools for audio transcoding.
+ **ffmpeg** or **libav** installed and available on your system `PATH`. Required for audio file processing (`.mp3`, `.wav`). The backend's `extract_text_from_audio()` method (in `backend/Generator/main.py`) uses `pydub` to transcode audio when needed, and `pydub` depends on these tools.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 25 - 28, The System Requirements note in README.md
only describes MP3-to-WAV conversion, but it should also state that .wav files
are accepted directly. Update the wording around extract_text_from_audio() in
backend/Generator/main.py so it clearly indicates both MP3 and WAV inputs are
supported, while still mentioning ffmpeg/libav for transcoding support where
needed. Keep the guidance user-facing and make it explicit that WAV users do not
need to convert their files first.

25-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding the Python package dependencies to the documentation.

The system requirements section mentions ffmpeg/libav but doesn't mention the Python packages (pydub, SpeechRecognition) that were added to requirements.txt in a previous layer. Users installing from source may need to know these are required.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 25 - 28, The System Requirements section only
mentions ffmpeg/libav, but it should also call out the Python dependencies added
elsewhere. Update the README near the existing backend/extract_text_from_audio()
guidance to explicitly list pydub and SpeechRecognition as required packages, so
users installing from source know to install them alongside the system audio
tools.
extension/src/pages/text_input/TextInput.jsx (1)

240-245: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding an accept attribute to the file input for better UX.

The file input currently has no accept attribute to guide users toward supported formats. Since the backend now handles PDF and audio files (.pdf, .mp3, .wav), consider adding:

- <input type="file" ref={fileInputRef} onChange={handleFileUpload} style={{ display: 'none' }} />
+ <input type="file" accept=".pdf,.mp3,.wav" ref={fileInputRef} onChange={handleFileUpload} style={{ display: 'none' }} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@extension/src/pages/text_input/TextInput.jsx` around lines 240 - 245, The
file picker in TextInput’s hidden input lacks an accept filter, so users can
choose unsupported files. Update the input element used by handleFileUpload and
fileInputRef to include an accept attribute that matches the backend-supported
formats, limiting selection to PDF and audio files such as .pdf, .mp3, and .wav.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/Generator/main.py`:
- Around line 405-406: The new exceptions from process_file() are escaping the
upload flow and turning user-facing failures into 500s. Update the caller in
backend/server.py around the file_processor.process_file invocation to catch
ValueError and RuntimeError explicitly, and map them to the intended HTTP
responses instead of letting them propagate. Use the existing process_file,
ValueError, and RuntimeError symbols to keep the route’s error contract
consistent for unsupported formats and speech API/request failures.
- Around line 381-401: The transcription flow in the upload path eagerly loads
the entire WAV and materializes all 60-second chunks before making one
recognition call per chunk, which can tie up workers and memory for long inputs.
Update the audio handling in the main transcription routine to enforce a
configured maximum duration/size before starting, and change the chunk
processing loop to stream or iterate chunks lazily instead of building the full
chunks list up front. Use the existing Recognizer/audio chunk logic in the
upload transcription path to place the limit and keep memory usage bounded.
- Around line 416-435: The upload handling in process_file currently trusts
file.filename for saving and deleting, which risks path traversal and filename
collisions. Change process_file to generate its own safe temporary storage name
before file.save and use that same generated path in the cleanup block, while
only carrying forward a validated extension from the original filename. Keep the
extension-based dispatch for .txt, .pdf, .docx, .wav, and .mp3, but do not use
the client-provided name directly anywhere in the filesystem path.
- Around line 376-392: The temporary WAV creation in the audio conversion flow
is happening before the cleanup scope, so it can be left behind if later steps
fail. Move the MP3-to-WAV export in `main.py` into the existing `try/finally`
used by the chunking/transcription path, alongside the `wav_path` handling in
`Generator`’s audio processing logic. Keep `wav_path` creation and any file
cleanup within that same scope so failures in `AudioSegment.from_wav` or chunk
construction still trigger deletion of the temp file.

---

Nitpick comments:
In `@eduaid_web/src/pages/Text_Input.jsx`:
- Line 190: The file picker in Text_Input.jsx currently allows any file type, so
update the hidden input used by handleFileUpload to include an accept
restriction for the supported backend formats. Add the accept attribute on the
same input element referenced by fileInputRef so users are guided to choose only
PDF and audio files such as .pdf, .mp3, and .wav.

In `@extension/src/pages/text_input/TextInput.jsx`:
- Around line 240-245: The file picker in TextInput’s hidden input lacks an
accept filter, so users can choose unsupported files. Update the input element
used by handleFileUpload and fileInputRef to include an accept attribute that
matches the backend-supported formats, limiting selection to PDF and audio files
such as .pdf, .mp3, and .wav.

In `@README.md`:
- Around line 25-28: The System Requirements note in README.md only describes
MP3-to-WAV conversion, but it should also state that .wav files are accepted
directly. Update the wording around extract_text_from_audio() in
backend/Generator/main.py so it clearly indicates both MP3 and WAV inputs are
supported, while still mentioning ffmpeg/libav for transcoding support where
needed. Keep the guidance user-facing and make it explicit that WAV users do not
need to convert their files first.
- Around line 25-28: The System Requirements section only mentions ffmpeg/libav,
but it should also call out the Python dependencies added elsewhere. Update the
README near the existing backend/extract_text_from_audio() guidance to
explicitly list pydub and SpeechRecognition as required packages, so users
installing from source know to install them alongside the system audio tools.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 27137517-77ad-4cb2-9f10-30b72ef57382

📥 Commits

Reviewing files that changed from the base of the PR and between 2038116 and 6d92b1c.

📒 Files selected for processing (5)
  • README.md
  • backend/Generator/main.py
  • eduaid_web/src/pages/Text_Input.jsx
  • extension/src/pages/text_input/TextInput.jsx
  • requirements.txt

Comment thread backend/Generator/main.py Outdated
Comment thread backend/Generator/main.py Outdated
Comment thread backend/Generator/main.py
Comment thread backend/Generator/main.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/Generator/main.py (1)

383-409: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Set a timeout on Recognizer before recognize_google. SpeechRecognition==3.14.5 exposes r.operation_timeout; without it, the /upload worker can block on stalled network requests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/Generator/main.py` around lines 383 - 409, The recognizer in the
audio transcription flow does not have a network timeout, so stalled Google
recognition calls can block the /upload worker. Update the transcription loop in
the code that creates sr.Recognizer and calls recognize_google to set
r.operation_timeout before making requests, using a reasonable timeout value so
each chunk transcription fails fast instead of hanging indefinitely.
♻️ Duplicate comments (2)
backend/server.py (1)

498-501: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not return 400 for speech-service request failures.

RuntimeError comes from sr.RequestError in extract_text_from_audio, so this is an upstream/service failure rather than a bad upload. Return a retryable/server-side status separately from ValueError.

Proposed status split
     try:
         content = file_processor.process_file(file)
-    except (ValueError, RuntimeError) as e:
+    except ValueError as e:
         return jsonify({"error": str(e)}), 400
+    except RuntimeError as e:
+        return jsonify({"error": str(e)}), 503
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/server.py` around lines 498 - 501, The error handling in the file
processing flow currently treats both validation errors and speech-service
failures the same in the try/except around file_processor.process_file. Split
the handling in this block so ValueError still returns a client-side bad
request, but RuntimeError from extract_text_from_audio/sr.RequestError is mapped
to a separate retryable server-side status with an appropriate error payload.
Keep the change localized to the processing endpoint and use the existing
file_processor.process_file path as the reference point.
backend/Generator/main.py (1)

426-432: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Move file.save inside the cleanup scope.

If file.save(file_path) creates a partial file and then raises, the finally block is never entered, leaving temp files in uploads/.

Proposed cleanup-scope fix
         temp_filename = f"{uuid.uuid4().hex}{ext}"
         file_path = os.path.join(self.upload_folder, temp_filename)
-        file.save(file_path)
         content = ""
 
         try:
+            file.save(file_path)
             if ext == '.txt':
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/Generator/main.py` around lines 426 - 432, Move the file write in
Generator.main’s upload handling so `file.save(file_path)` happens inside the
existing try/finally cleanup scope, using the same `temp_filename`/`file_path`
flow. This ensures that if `file.save` raises after creating a partial upload,
the `finally` block still runs and removes the temp file from
`self.upload_folder`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@eduaid_web/src/pages/Text_Input.jsx`:
- Around line 188-190: The upload helper text in Text_Input should match the
actual formats accepted by handleFileUpload and the file input accept list.
Update the label near the file input to mention TXT and DOCX alongside PDF and
audio so users don’t think those options were removed, and keep the wording
consistent with the formats supported by the backend Generator flow.

---

Outside diff comments:
In `@backend/Generator/main.py`:
- Around line 383-409: The recognizer in the audio transcription flow does not
have a network timeout, so stalled Google recognition calls can block the
/upload worker. Update the transcription loop in the code that creates
sr.Recognizer and calls recognize_google to set r.operation_timeout before
making requests, using a reasonable timeout value so each chunk transcription
fails fast instead of hanging indefinitely.

---

Duplicate comments:
In `@backend/Generator/main.py`:
- Around line 426-432: Move the file write in Generator.main’s upload handling
so `file.save(file_path)` happens inside the existing try/finally cleanup scope,
using the same `temp_filename`/`file_path` flow. This ensures that if
`file.save` raises after creating a partial upload, the `finally` block still
runs and removes the temp file from `self.upload_folder`.

In `@backend/server.py`:
- Around line 498-501: The error handling in the file processing flow currently
treats both validation errors and speech-service failures the same in the
try/except around file_processor.process_file. Split the handling in this block
so ValueError still returns a client-side bad request, but RuntimeError from
extract_text_from_audio/sr.RequestError is mapped to a separate retryable
server-side status with an appropriate error payload. Keep the change localized
to the processing endpoint and use the existing file_processor.process_file path
as the reference point.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c86a3286-aa34-423a-b6d5-2dfec7bb2912

📥 Commits

Reviewing files that changed from the base of the PR and between 6d92b1c and 211f246.

📒 Files selected for processing (5)
  • README.md
  • backend/Generator/main.py
  • backend/server.py
  • eduaid_web/src/pages/Text_Input.jsx
  • extension/src/pages/text_input/TextInput.jsx
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • extension/src/pages/text_input/TextInput.jsx

Comment thread eduaid_web/src/pages/Text_Input.jsx Outdated
@AbiramiR-27

Copy link
Copy Markdown
Author

I would really appreciate it if maintainers could review these changes when you have a moment! Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Support for Uploading Audio Files to Generate Quizzes

1 participant