Replaying an audio file with a timecode click

Summary

I want that, in my website, when I click on a timecode (e.g: 1.26), it recall the audio player at this start time and play the audio.

Steps to reproduce

Here is the parse of my code of the current audio playing solution:

strmlt.subheader("Audio file")
audio=strmlt.file_uploader("Download an audio file (format wav)",type="wav")

#getting the audio file 
if(audio is not None):
    strmlt.subheader("Transcription")
    audio_file=audio.read()
    #readable audio
    strmlt.caption("Listen to the call")
    strmlt.audio(audio_file,format='audio/wav', start_time=60)
    #audio player

Screen Capture of what it looks like now

Thanks in advance for the help !

Hi @RAPHCVR

There’s the start_time parameter of st.audio() that you can use for starting the audio at the designated portion of the audio file.

Further details can are described on the Documentation page:

@dataprofessor Hi, indeed, I’ve already saw this, the problem is that I don’t know how to change dynamically the states of the player (from starting to 1min, to starting at 20s for example, by clicking on a text)

Coudl you explore the use of st.experimental_set_query_params or st.experimental_get_query_params that would allow the setting of key:value pairs.

More info:

Example of this in action:
In the 30 days app, we’ve extracted the parameter:value pair (the specific day to display):

https://30days.streamlit.app/?challenge=Day5

Perhaps you can experiment with the above so that clicking on a link would take us to the specific segment of the audio (using the above query parameters with start_time parameter).

@dataprofessor I don’t really know how to implement this on the hyperlink provided by the time code click (highlighted in blue), with the start_time and the query experimental feature

What hyperlink? I can’t see anything highlighted in blue in your screenshot.

Hi @Goyo , indeed, that’s because I don’t have implemented this yet, because I don’t know how to do.

I said Hyperlink cause in french it’s called “hyperlien”, sorry. By this name I mean the link you click and allow you to refresh one element of the website, here the audio player. For example, by clicking on the time code 00:02:800 it will play the audio on the upper player at 2,8s.

You could use an input widget to allow the user to select when to start playing, like this:

import streamlit as st

st.subheader("Audio file")
audio = st.file_uploader("Download an audio file (format wav)", type="wav")

# getting the audio file
if audio is not None:
    st.subheader("Transcription")
    audio_file = audio.read()
    # readable audio
    # st.caption("Listen to the call")
    if st.button("Play from start"):
        st.audio(audio_file, format="audio/wav")
    if st.button("Play from 10 seconds"):
        st.audio(audio_file, format="audio/wav", start_time=10)
    if st.button("Play from 20 seconds"):
        st.audio(audio_file, format="audio/wav", start_time=20)

Oh thank you @blackary . Unfortunately, it’s not really what i’m serching for. Indeed, my goal is to enable a link on the text that refresh the player at the selected timecode.

What about styling buttons to look like links, like this?

import streamlit as st
from streamlit_extras.stylable_container import stylable_container


st.subheader("Audio file")
audio = st.file_uploader("Download an audio file (format wav)", type="wav")

if "start_time" not in st.session_state:
    st.session_state.start_time = 0

# Style buttons as links
with stylable_container(
    key="link_buttons",
    css_styles="""
    button {
        background: none!important;
        border: none;
        padding: 0!important;
        font-family: arial, sans-serif;
        color: #069;
        text-decoration: underline;
        cursor: pointer;
    }
    """,
):
    # getting the audio file
    if audio is not None:
        st.subheader("Transcription")
        audio_file = audio.read()
        for time in range(0, 60, 10):
            start = time
            end = time + 10
            range = f"00:{start:02} - 00:{end}"
            if st.button(range):
                st.session_state["start_time"] = start
                st.experimental_rerun()

        st.audio(audio_file, format="audio/wav", start_time=st.session_state.start_time)

I would try this:

  1. split the transcript into lines
  2. split each line into two columns, e.g.: timestamp | content
  3. create a dataframe to use with st.table(df) with proper styling.
  4. Assuming the table is responsive, write a row_clicked callback, e.g. on row_clicked, retrieve the index, parse the 1st portion of the timestamp, convert to seconds → new start time.
    Hope this helps!

UPDATE
I tried providing an example of my proposed implementation, but I was assuming too much about streamlit.
Streamlit’s “elements” are not (all) widgets. I was assuming that st.dataframe or st.edit_data would have an on_click property (st.edit_data can have a callback but only for the “on change” event!).

I guess this is why I use Panel!

@CatChenal Hi!
The transcript look like this with my raw texts:
"
[0.56s → 1.56s] Oui, allo ?

[1.56s → 4.56s] Oui, bonjour, est-ce que je pourrais parler Ă  M. DestrĂ©, s’il vous plaĂźt ?

[4.56s → 5.56s] C’est moi-mĂȘme, madame.
"
How to apply your proposition with my purpose of clicking on timestamp ?

@blackary Hi ! Thanks for the help ! Is it possible to do your proposition, but instead of creating a new player each time, just change the current ?

@RAPHCVR That’s what my solution does – it just changes the current audio player.

I am confused: In the screenshot of your original post, the timestamps look like

00:00.800 --> 00:01.800 ...

Since they come from a text file, they need to be parsed and converted to decimal seconds to be useable by the audio widget. Now, with your new “raw texts”, it seems you have already converted them (yet they are still not useable as is).

Which is the real raw format?

PS: The proposal from @backary seem viable. Have you tried it? Please let the community knows, thank you.

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