streamlit icon indicating copy to clipboard operation
streamlit copied to clipboard

Autoplay option for audio files

Open mesmith027 opened this issue 5 years ago • 13 comments

Request

When a user uploads an audio file via st.audio(), they then have to hit the play button to hear the audio. While this works in most cases, for interesting applications, like writing an app that takes text-to-speech, it would be reasonable to have the audio file play once automatically.

Solution

MVP: What's the smallest possible solution that would get 80% of the problem out of the way?

To have a parameter like auto_play that can be passed to the function such as st.audio(file.mp4,auto_play=True) (default is auto_play=False), that triggers the audio file to play one time after the file is finished loading.

Additional context

The conversation that sparked this Feature Request from the streamlit community

mesmith027 avatar Dec 09 '20 18:12 mesmith027

Request

When a user uploads an audio file via st.audio(), they then have to hit the play button to hear the audio. While this works in most cases, for interesting applications, like writing an app that takes text-to-speech, it would be reasonable to have the audio file play once automatically.

Solution

MVP: What's the smallest possible solution that would get 80% of the problem out of the way?

To have a parameter like auto_play that can be passed to the function such as st.audio(file.mp4,auto_play=True) (default is auto_play=False), that triggers the audio file to play one time after the file is finished loading.

Additional context

The conversation that sparked this Feature Request from the streamlit community

nikhilnarasimha avatar Dec 20 '20 14:12 nikhilnarasimha

Hi, i am trying to use autoplay but i have this problem, audio() got an unexpected keyword argument 'auto_play', I uninstalled and reinstalled streamlit in the last version (0.78) but it didnt work, appreciate all your advices. thanks.

oscar13ud avatar Mar 06 '21 19:03 oscar13ud

Hi @oscar13ud,

This is a feature request for an autoplay function, and the MVP is demoed as a simple parameter called auto_play.

This is not in Streamlit's core functionality

mesmith027 avatar Mar 08 '21 15:03 mesmith027

It would be great to add audoplay to video file too. Could streamlit add autoplay atttribute when generating the html tag video? see also https://www.w3schools.com/tags/att_video_autoplay.asp

hubutui avatar Dec 20 '21 03:12 hubutui

Hi all, it would be great to have this functionality - an auto_play parameter, default is false. There have been numerous requests for it, and it seems trivial to implement. In my application, a tts model generates audio, and it would be great to have autoplay for the generated audio.

vblagoje avatar Jan 14 '22 18:01 vblagoje

This would be such a useful feature!

Bomme avatar Jan 25 '22 17:01 Bomme

Hi, are there any updates on the autoplay feature? I am creating a Google maps like navigation app using streamlit. I want to autoplay messages like "In 200 meters turn right". Is there a possible workaround to make the autoplay work? Thank you.

durraniu avatar Mar 17 '22 03:03 durraniu

Has anyone figured out a hack around autoplay feature without showing the controls?

Aakashagr avatar Apr 30 '22 20:04 Aakashagr

I tried to add just some notification sound to my app using either:

  • playsound package works locally, but on streamlit cloud the sound does not get propagated, nothing is played but no error displays neither
  • print('\007') Which makes a sound as explained here

But all methods work fine locally but not on Streamlit cloud 👎

tdekelver avatar Jun 01 '22 17:06 tdekelver

I found a workaround. You can use html code to do exactly this:

import streamlit as st
import time

html_string = """
            <audio controls autoplay>
              <source src="https://www.orangefreesounds.com/wp-content/uploads/2022/04/Small-bell-ringing-short-sound-effect.mp3" type="audio/mp3">
            </audio>
            """

sound = st.empty()
sound.markdown(html_string, unsafe_allow_html=True)  # will display a st.audio with the sound you specified in the "src" of the html_string and autoplay it
time.sleep(2)  # wait for 2 seconds to finish the playing of the audio
sound.empty()  # optionally delete the element afterwards

This will display the same widget as st.audio but will autoplay the sound once it is created. You can also afterwards remove it again by using the .empty(), but you need to time.sleep(2) to make sure it has enough time to finish autoplaying.

This works both locally as on streamlit cloud!

tdekelver avatar Jun 01 '22 17:06 tdekelver

Hi @tdekelver ,

Thanks for the code! That's really helpful. May I kindly ask do you know if it is possible to hide the audio button to make it a background music?

Best, Jun

xihajun avatar Jun 30 '22 20:06 xihajun

Hi @tdekelver ,

Thanks for the code! That's really helpful. May I kindly ask do you know if it is possible to hide the audio button to make it a background music?

Best, Jun

No did not find anything...

tdekelver avatar Jul 01 '22 07:07 tdekelver

I found a workaround. You can use html code to do exactly this:

import streamlit as st
import time

html_string = """
            <audio controls autoplay>
              <source src="https://www.orangefreesounds.com/wp-content/uploads/2022/04/Small-bell-ringing-short-sound-effect.mp3" type="audio/mp3">
            </audio>
            """

sound = st.empty()
sound.markdown(html_string, unsafe_allow_html=True)  # will display a st.audio with the sound you specified in the "src" of the html_string and autoplay it
time.sleep(2)  # wait for 2 seconds to finish the playing of the audio
sound.empty()  # optionally delete the element afterwards

This will display the same widget as st.audio but will autoplay the sound once it is created. You can also afterwards remove it again by using the .empty(), but you need to time.sleep(2) to make sure it has enough time to finish autoplaying.

This works both locally as on streamlit cloud!

sorry, i beg your permission, what if we want to play file from local with autoplay feature?

diahjunaidijr avatar Aug 04 '22 13:08 diahjunaidijr

Hi, any

html_string = """
            <audio controls autoplay>
              <source src="https://www.orangefreesounds.com/wp-content/uploads/2022/04/Small-bell-ringing-short-sound-effect.mp3" type="audio/mp3">
            </audio>
            """

sound = st.empty()
sound.markdown(html_string, unsafe_allow_html=True)  # will display a st.audio with the sound you specified in the "src" of the html_string and autoplay it
time.sleep(2)  # wait for 2 seconds to finish the playing of the audio
sound.empty()  # op

Hey, that's a cool solution! Any idea on how to play a local audio file using the same html code? I'm not that proficient in html so kindly pardon me.

ayanatherate avatar Oct 14 '22 15:10 ayanatherate

@ayanatherate Using local audio is trickier, because normally that src is expecting a url. But, it also works with a base64-encoded file, like this:

import base64

import streamlit as st


def autoplay_audio(file_path: str):
    with open(file_path, "rb") as f:
        data = f.read()
        b64 = base64.b64encode(data).decode()
        md = f"""
            <audio controls autoplay="true">
            <source src="data:audio/mp3;base64,{b64}" type="audio/mp3">
            </audio>
            """
        st.markdown(
            md,
            unsafe_allow_html=True,
        )


st.write("# Auto-playing Audio!")

autoplay_audio("local_audio.mp3")

blackary avatar Nov 11 '22 15:11 blackary

I found a solution to not show the player: <audio autoplay> instead of <audio controls autoplay>

juanblue2022 avatar Dec 02 '22 14:12 juanblue2022

@blackary thank you for that workaround. Is it possible to play the sound without showing the audio player widget at all?

gustavz avatar Jan 02 '23 12:01 gustavz

@gustavz If you use the solution that @juanblue2022 provided (removing controls) it should work

import base64

import streamlit as st


def autoplay_audio(file_path: str):
    with open(file_path, "rb") as f:
        data = f.read()
        b64 = base64.b64encode(data).decode()
        md = f"""
            <audio autoplay="true">
            <source src="data:audio/mp3;base64,{b64}" type="audio/mp3">
            </audio>
            """
        st.markdown(
            md,
            unsafe_allow_html=True,
        )


st.write("# Auto-playing Audio!")

autoplay_audio("local_audio.mp3")

blackary avatar Jan 03 '23 14:01 blackary

I was struggling with this as well. In my case I was producing an audio file from Python and I didn't want to save it to a file. After a lot of banging my head against the wall, this ended up working:

import base64

audio_base64 = base64.b64encode(audio_bytes).decode('utf-8')
audio_tag = f'<audio autoplay="true" src="data:audio/wav;base64,{audio_base64}">'
st.markdown(audio_tag, unsafe_allow_html=True)

RickyEsclapon avatar Mar 11 '23 21:03 RickyEsclapon

@gustavz If you use the solution that @juanblue2022 provided (removing controls) it should work

import base64

import streamlit as st


def autoplay_audio(file_path: str):
    with open(file_path, "rb") as f:
        data = f.read()
        b64 = base64.b64encode(data).decode()
        md = f"""
            <audio autoplay="true">
            <source src="data:audio/mp3;base64,{b64}" type="audio/mp3">
            </audio>
            """
        st.markdown(
            md,
            unsafe_allow_html=True,
        )


st.write("# Auto-playing Audio!")

autoplay_audio("local_audio.mp3")

There still is a problem, when I use this code for TTS audio. First time, It works. But when i type in another text ,I saw the code running, It gen the audio bytes and run this autoplay code, but there is no voice.... But refresh the page, the first time ,it works....It's weird...

hAcKlyc avatar May 01 '23 14:05 hAcKlyc

I think it may have something to do with the way streamlit reruns code. I save the audio content to memory and set auto play on that. I think that because the contents are changing during the reruns it is being picked up

shawngiese avatar Aug 14 '23 10:08 shawngiese

It doesn't work for me. I have the newest streamlit version. should I downgrade it?

dnabanita7 avatar Sep 08 '23 20:09 dnabanita7

Update

Hey all! We didn't work on this in the past since it's unfortunately more complicated than it seems. We can of course only add the HTML autoplay option. But that will be confusing in Streamlit: if you rerun the app without changing it, that will not trigger autoplay again on an existing audio element, which makes sense. But if you add an element above the audio element, Streamlit is removing the audio element from the page and re-adding it, which will trigger autoplay again. That's a very confusing developer experience.

We're currently looking into if there's some workaround to this behavior. Will update here if we have some new ideas!

jrieke avatar Nov 14 '23 21:11 jrieke

above mentioned ways only works on my localhost perfectly, but once deployed, it doesn't play the sound for the deployed app, weird

michelle-w-br avatar Dec 13 '23 03:12 michelle-w-br