Skip to content

st.experimental_audio_input#9404

Merged
sfc-gh-nbellante merged 161 commits intodevelopfrom
nico/audio-input
Sep 25, 2024
Merged

st.experimental_audio_input#9404
sfc-gh-nbellante merged 161 commits intodevelopfrom
nico/audio-input

Conversation

@sfc-gh-nbellante
Copy link
Copy Markdown
Contributor

@sfc-gh-nbellante sfc-gh-nbellante commented Sep 5, 2024

Describe your changes

🔉 This PR introduces the st.experimental_audio_input widget! 🎤

Light Theme Demo

Kapture 2024-09-13 at 11 44 38

Dark Theme Demo

Kapture 2024-09-13 at 11 48 59

Light Theme No Mic Permissions

image

Dark Theme No Mic Permissions

image

Note: this currently does not work on safari and by extension iOS so users on that platform will see a warning with the audio_input disabled
image

GitHub Issue Link (if applicable)

#8899
#903

Testing Plan

  • Unit Tests (JS and/or Python)
    • python unit tests added ✅
  • E2E Tests
    • e2e tests added ✅
    • Note: was unable to reliably add invalid permissions check test that would work locally
  • Any manual testing needed?
    • was also tested manually and will be QA'd

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

@sfc-gh-nbellante sfc-gh-nbellante added security-assessment-completed impact:users PR changes affect end users change:feature PR contains new feature or enhancement implementation labels Sep 5, 2024
const [recordPlugin, setRecordPlugin] = useState<RecordPlugin | null>(null)
// to eventually show the user the available audio devices
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [availableAudioDevices, setAvailableAudioDevices] = useState<

Check notice

Code scanning / CodeQL

Unused variable, import, function or class

Unused variable availableAudioDevices.
@sfc-gh-nbellante sfc-gh-nbellante marked this pull request as ready for review September 5, 2024 19:19
@sfc-gh-nbellante sfc-gh-nbellante requested a review from a team as a code owner September 5, 2024 19:19
Comment thread frontend/lib/src/components/core/Block/ElementNodeRenderer.tsx
Comment thread frontend/lib/src/components/widgets/AudioInput/ActionButton.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/ActionButton.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/NoMicPermissions.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/formatTime.ts
Comment thread frontend/lib/src/components/widgets/AudioInput/uploadFiles.ts Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Fixed
Comment thread e2e_playwright/st_audio_input_test.py
Comment thread e2e_playwright/st_fragment_basics.py
Comment thread frontend/lib/src/components/shared/Toolbar/Toolbar.tsx Outdated
Comment thread frontend/lib/src/components/shared/Toolbar/Toolbar.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/ActionButton.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/uploadFiles.ts
*, # keyword-only arguments:
disabled: bool = False,
label_visibility: LabelVisibility = "visible",
) -> UploadedFile | None:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we unfortunately do not handle this consistently across widgets, but I want to highlight that using a Streamlit-defined type might not be the best UX because the developer sees the type, but has to click on it to get what it really means and we discourage developers to import it from here because we don't give any guarantees about our internal package structure.
I believe we should move all of our type definitions into a module streamlit.types or similar and make that an official part of our API (guarantee the existence) at some point. Until then, it might be nicer to duplicate the definition for the publicly exposed API here and write Union[UploadedFile, DeletedFile, None] (although also here two Streamlit-types are part of, so probably not worth it 😅)

No immediate action item for this PR, but wanted to share one inconsistency in our codebase right now so that we can all think about it 🙂

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@raethlein I definitely agree that types as part of Streamlit API is a great idea!
We need to think carefully about exact types (especially for file-uploader, data-editor like widgets). But on the strategic level, it is something we should do at some point!

Comment thread lib/streamlit/elements/widgets/audio_input.py Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/ActionButton.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread lib/streamlit/elements/widgets/audio_input.py
Comment thread e2e_playwright/st_audio_input.py
Comment thread frontend/lib/src/components/widgets/AudioInput/constants.ts Outdated
Comment thread lib/streamlit/elements/widgets/audio_input.py
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

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

Great implementation & feature 🚀 it looks almost ready for me, I have a couple comments on testing and some observations here:

The responsiveness of the widget seems to be quite good. The case where it doesn't work well is when it is missing the microphone permission (maybe the StyledWaveformContainerDiv needs an overflow: hidden?):

image

Another observation: clicking on start recording - if there is already an old recording - triggers a rerun. This rerun seems to be a bit unnecessary. Is this expected?

Screen.Recording.2024-09-13.at.22.49.03.mov

A strange observation: changing the theme via the menu seems to consistently cause some trouble with the placing of the waves:

image

Comment thread e2e_playwright/st_audio_input_test.py Outdated
Comment thread e2e_playwright/st_audio_input.py
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/src/components/widgets/AudioInput/uploadFiles.ts
Comment thread e2e_playwright/st_audio_input_test.py Outdated
Comment thread e2e_playwright/st_audio_input_test.py Outdated
Comment thread e2e_playwright/st_audio_input_test.py Outdated
Comment thread e2e_playwright/st_audio_input_test.py
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx
@sfc-gh-nbellante
Copy link
Copy Markdown
Contributor Author

Another observation: clicking on start recording - if there is already an old recording - triggers a rerun. This rerun seems to be a bit unnecessary. Is this expected?

@lukasmasuch the reason the rerun is happening is because its deleting the old file before recording the new. perhaps we should not do that to avoid this rerun?

@lukasmasuch
Copy link
Copy Markdown
Collaborator

the reason the rerun is happening is because its deleting the old file before recording the new. perhaps we should not do that to avoid this rerun?

Hmm, yeah it looks like we don't need to delete the file / rerun up until the point where the new recording is available (on stop recording)? Two potential options:

  • on start recording: delete file but don't call setFileUploaderStateValue
  • or delete the old recording file only on stopRecording before uploading the new data (maybe the safer option)

Clicking the clear button might be the only case where we want to delete the file & setFileUploaderStateValue to empty.

@sfc-gh-nbellante
Copy link
Copy Markdown
Contributor Author

sfc-gh-nbellante commented Sep 16, 2024

or delete the old recording file only on stopRecording before uploading the new data (maybe the safer option)

i've switched it to follow this suggestion

Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx
lukasmasuch
lukasmasuch previously approved these changes Sep 18, 2024
Comment thread frontend/lib/src/components/widgets/AudioInput/AudioInput.tsx Outdated
Comment thread frontend/lib/package.json Outdated
Comment thread e2e_playwright/st_audio_input.py Outdated
@sfc-gh-nbellante sfc-gh-nbellante changed the title st.audio_input st.experimental_audio_input Sep 24, 2024
Copy link
Copy Markdown
Contributor

@sfc-gh-kmcgrady sfc-gh-kmcgrady left a comment

Choose a reason for hiding this comment

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

Protobuf is backwards-compatible

Comment on lines +25 to +31
message AudioInput {
string id = 1;
string label = 2;
string help = 3;
string form_id = 4;
bool disabled = 5;
LabelVisibilityMessage label_visibility = 6;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think this is another aspect we should codify: whether or not to use optional I think we use it pretty inconsistently 😅

@sfc-gh-nbellante sfc-gh-nbellante merged commit 7d70195 into develop Sep 25, 2024
@sfc-gh-nbellante sfc-gh-nbellante deleted the nico/audio-input branch September 25, 2024 19:59
edegp pushed a commit to edegp/streamlit that referenced this pull request Jan 19, 2025
## Describe your changes

🔉 This PR introduces the `st.experimental_audio_input` widget! 🎤 

### Light Theme Demo
![Kapture 2024-09-13 at 11 44
38](https://github.com/user-attachments/assets/56530c43-31f4-498c-b322-df52f6be804a)


### Dark Theme Demo
![Kapture 2024-09-13 at 11 48
59](https://github.com/user-attachments/assets/70069859-bc58-4eb8-ad7c-8aff6bdaf74f)


### Light Theme No Mic Permissions
<img width="755" alt="image"
src="https://github.com/user-attachments/assets/51df40c7-1c75-415b-bc70-59fdb59f1c3b">

### Dark Theme No Mic Permissions
<img width="752" alt="image"
src="https://github.com/user-attachments/assets/8f8d47f6-2195-4dfc-ab41-07231ae3a15b">

Note: this currently does not work on safari and by extension iOS so
users on that platform will see a warning with the audio_input disabled

![image](https://github.com/user-attachments/assets/0b882904-3f66-464e-9a9b-3587805a33a9)



## GitHub Issue Link (if applicable)
streamlit#8899
streamlit#903

## Testing Plan

- Unit Tests (JS and/or Python)
   - python unit tests added ✅ 
- E2E Tests
  - e2e tests added ✅ 
- Note: was unable to reliably add invalid permissions check test that
would work locally
- Any manual testing needed?
  - was also tested manually and will be QA'd

---

**Contribution License Agreement**

By submitting this pull request you agree that all contributions to this
project are made under the Apache 2.0 license.

---------

Co-authored-by: Karen Javadyan <kajarenc@gmail.com>
Co-authored-by: Bob Nisco <bob.nisco@snowflake.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants