Skip to content

feat(audio): add accept/discard buttons to audio recording#2907

Open
alejandro-workpath wants to merge 6 commits intoChainlit:mainfrom
alejandro-workpath:feat/audio-discard-accept
Open

feat(audio): add accept/discard buttons to audio recording#2907
alejandro-workpath wants to merge 6 commits intoChainlit:mainfrom
alejandro-workpath:feat/audio-discard-accept

Conversation

@alejandro-workpath
Copy link
Copy Markdown

@alejandro-workpath alejandro-workpath commented Apr 24, 2026

Summary

  • When recording audio, the single X button (which always sent the recording) is replaced with two distinct actions: checkmark (accept/send) and X (discard)
  • Adds audio_discard socket event and @cl.on_audio_discard callback so backend apps can clean up resources when audio is discarded (e.g. close streaming transcription sessions)
  • Backward-compatible: apps without on_audio_discard handler work unchanged

Why

Clicking X sends the audio instead of discarding it, which is confusing UX. There is no way to cancel a recording without sending it to the backend.

What was considered

  • Buffer-then-decide: record locally, show accept/discard, only send on accept. Rejected because it breaks the real-time streaming architecture (chunks are sent as they're recorded).
  • Chosen approach: keep real-time streaming, add audio_discard event so the backend knows to discard accumulated chunks and clean up. The frontend stops the recorder/player without emitting audio_end.

Test plan

  • Start recording → click X (discard) → verify no on_audio_end fires, on_audio_discard fires instead
  • Start recording → click checkmark (accept) → verify on_audio_end fires, transcription works
  • Verify tooltips show "Discard recording" and "Send recording"
  • App without on_audio_discard handler works without errors
Recording Discard Send
Idle state Recording state After accept

Summary by cubic

Add accept and discard controls to audio recording so users can cancel without sending. Adds audio_discard and the @cl.on_audio_discard hook so backends can clean up; apps without it keep working.

  • New Features

    • Split actions into check (send) and X (discard) with clear tooltips; P hotkey accepts.
    • Discard emits audio_discard; stops local recorder/player and turns audio off without audio_end.
    • Added i18n keys for “Send recording” and “Discard recording” with native translations across all locales.
  • Bug Fixes

    • Always reset audio state on discard: backend sets connection "off" in a finally block, and frontend always emits audio_discard even if local stop fails.
    • Restored inline comments in the VoiceButton hotkey guard for clarity.

Written for commit ee511a0. Summary will update on new commits.

When recording audio, the single X button (which always sent the audio)
is replaced with two distinct actions: a checkmark to accept and send,
and an X to discard without sending. This adds an `audio_discard` socket
event and `@cl.on_audio_discard` callback so backend apps can clean up
resources (e.g. streaming transcription sessions) when audio is discarded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request frontend Pertains to the frontend. labels Apr 24, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 8 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/chainlit/socket.py">

<violation number="1" location="backend/chainlit/socket.py:474">
P2: `audio_discard` can skip emitting `audio_connection="off"` when `on_audio_discard()` raises, causing stale audio connection state.</violation>
</file>

<file name="libs/react-client/src/useAudio.ts">

<violation number="1" location="libs/react-client/src/useAudio.ts:33">
P2: Discard notification is skipped if local stop fails, so backend audio cleanup may never be triggered.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/chainlit/socket.py
Comment thread libs/react-client/src/useAudio.ts
Adds English fallback strings for "Send recording" and "Discard
recording" to all 22 non-English translation files. Native speakers
can update these in follow-up PRs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

10 issues found across 22 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="backend/chainlit/translations/ko.json">

<violation number="1" location="backend/chainlit/translations/ko.json:86">
P2: Korean locale adds new audio action labels in English, causing mixed-language UI for `ko` users.</violation>
</file>

<file name="backend/chainlit/translations/ja.json">

<violation number="1" location="backend/chainlit/translations/ja.json:72">
P2: Japanese locale adds new speech action labels in English, causing mixed-language UI for `ja` users.</violation>
</file>

<file name="backend/chainlit/translations/it.json">

<violation number="1" location="backend/chainlit/translations/it.json:86">
P2: New Italian speech-action translations were added in English, causing mixed-language UI in the `it` locale.</violation>
</file>

<file name="backend/chainlit/translations/da-DK.json">

<violation number="1" location="backend/chainlit/translations/da-DK.json:85">
P2: Danish locale adds English strings for new audio actions, causing mixed-language UI in `da-DK`.</violation>
</file>

<file name="backend/chainlit/translations/fr-FR.json">

<violation number="1" location="backend/chainlit/translations/fr-FR.json:86">
P2: French locale adds new speech action labels in English, causing mixed-language UI for fr-FR users.</violation>
</file>

<file name="backend/chainlit/translations/pt-PT.json">

<violation number="1" location="backend/chainlit/translations/pt-PT.json:86">
P2: Portuguese locale includes untranslated English strings for new speech actions, causing mixed-language UI.</violation>
</file>

<file name="backend/chainlit/translations/es.json">

<violation number="1" location="backend/chainlit/translations/es.json:86">
P2: Spanish locale adds `chat.speech.accept` and `chat.speech.discard` in English, causing mixed-language UI in `es` translations.</violation>
</file>

<file name="backend/chainlit/translations/hi.json">

<violation number="1" location="backend/chainlit/translations/hi.json:72">
P2: New Hindi locale keys for audio actions are left in English, causing mixed-language UI in `hi` localization.</violation>
</file>

<file name="backend/chainlit/translations/zh-CN.json">

<violation number="1" location="backend/chainlit/translations/zh-CN.json:72">
P2: New zh-CN speech action labels are untranslated English strings, causing mixed-language UI for Chinese users.</violation>
</file>

<file name="backend/chainlit/translations/el-GR.json">

<violation number="1" location="backend/chainlit/translations/el-GR.json:86">
P2: New Greek locale entries for audio actions are untranslated English strings, causing mixed-language UI in `el-GR`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread backend/chainlit/translations/ko.json Outdated
Comment thread backend/chainlit/translations/ja.json Outdated
Comment thread backend/chainlit/translations/it.json Outdated
Comment thread backend/chainlit/translations/da-DK.json Outdated
Comment thread backend/chainlit/translations/fr-FR.json Outdated
Comment thread backend/chainlit/translations/pt-PT.json Outdated
Comment thread backend/chainlit/translations/es.json Outdated
Comment thread backend/chainlit/translations/hi.json Outdated
Comment thread backend/chainlit/translations/zh-CN.json Outdated
Comment thread backend/chainlit/translations/el-GR.json Outdated
alejandro-workpath and others added 4 commits April 24, 2026 12:02
Move update_audio_connection("off") to finally block so backend audio
state resets even if on_audio_discard raises. On frontend, wrap
stopRecording in try/finally so discardAudioStream always fires.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace English fallback strings with proper translations for all 22
non-English locales.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Preserve three comments that were inadvertently stripped during an
earlier refactor: the form-field guard intent, the early-return purpose,
and the preventDefault rationale.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@alejandro-workpath
Copy link
Copy Markdown
Author

Hey guys, I would love to have this in production to improve some clients UX overall since the current setup is confusing for most of them. Can I ask for a review so I can refine if anything needs more work and merge it? @hayescode @asvishnyakov @sandangel Thank you so much!

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

Labels

enhancement New feature or request frontend Pertains to the frontend. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant