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 ?
Hi @Shrenav_Dhakal,
Thanks for sharing this question!
At the moment, we do not support this natively.
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.
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!