Autoplay multiple audios in a streamlit app one after another

I have list of audios that i need to play automatically one after another in a streamlit application. Is there any way i can do that ?

1 Like

Hi @Shrenav_Dhakal,

Thanks for sharing this question!

At the moment, we do not support this natively.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.

It seems there will be some support for autoplay in the future:


You could add some JS code to make each audio element start playing right after the previous one is finished.

audioplay

Code:
app.py
import streamlit as st

def main():
    ...
    cols = st.columns(3)

    with cols[0]:
        ...
        st.audio(audio_en)

    with cols[1]:
        ...
        st.audio(audio_fr)

    with cols[2]:
        ...
        st.audio(audio_es)

    ## Add a custom button to handle play
    with open("play_control.js") as js:  
        st.html('<button id="play_all">πŸ”Š Play all</button>')
        st.components.v1.html(f"<script>{js.read()}</script>", height=0)

if __name__ == "__main__":
    main()
play_control.js
const audios = [...window.parent.document.getElementsByTagName('audio')];
const button = window.parent.document.getElementById("play_all");
var current = 0;

function play_next(){
    
    if (current < audios.length) {
        var audio = audios[current];
        audio.currentTime = 0;
        audio.play();
        audio.onended = function(){
            current++;
            play_next();
        }
    }
}

button.addEventListener("click", function(){
    current = 0;
    play_next();
});

I made a working code with streamlit_TTS.

Give a shot:

import streamlit as st
import io
from pydub import AudioSegment
from streamlit_TTS import auto_play
def mp3_to_bytes(file_path):
    """Convert an MP3 file to bytes and extract sample rate and width."""
    # Load MP3 file
    audio = AudioSegment.from_mp3(file_path)
    # Export to WAV format in memory
    buffer = io.BytesIO()
    audio.export(buffer, format="wav")
    buffer.seek(0)  # Move to start of the buffer
    # Extract sample rate and sample width from AudioSegment
    sample_rate = audio.frame_rate
    sample_width = audio.sample_width
    return {
        'bytes': buffer.getvalue(),  # Get bytes from buffer
        'sample_rate': sample_rate,
        'sample_width': sample_width
    }
def main():
    print("......")
    audio_file = "audio.mp3"
    audio_data = mp3_to_bytes(audio_file)
    # st.write(f"Audio data:, {audio_data}")
    auto_play(audio_data, wait=True, lag=0.25)
    st.write("Done")
if __name__ == "__main__":
    main()

Important!

Your browser probably will disable the JavaScript which is responsible for the autoplay.

From the streamlti_TTS package:

def auto_play(audio,wait=True,lag=0.25,key=None):
    height_hack = """
<script>
    var hide_me_list = window.parent.document.querySelectorAll('iframe');
    for (let i = 0; i < hide_me_list.length; i++) { 
        if (hide_me_list[i].height == 0) {
            hide_me_list[i].parentNode.style.height = 0;
            hide_me_list[i].parentNode.style.marginBottom = '-1rem';
        };
    };
</script>
"""

I would recommend to test it from Firefox (which offer you to allow the script). By the way I have implemented in my site (Ubuntu server) which is certificated, and it runs there without any problems.

Good luck!