External widgets to control media

First of all, I’d like to say that I really love this project and thank you very much for this space!

Recently I’ve been working with some videos that are the result of a ML detection algorithm.
When the processing is done, I can easily output it to the user with st.video(...) and the user can move the progress bar around to watch it.

But I’d like to bring the user atenttion to certain moments that are important in the detected video.
Let’s suppose my video (60 seconds in total) is composed of three main parts: A, B and C.

A: 0 → 20 seconds
B: 20 → 40 seconds
C: 40 → 60 seconds

It would be nice if I could connect some kind of time stamp or a button to each one of this parts (moments of interest in the video), just like time stamps in a YouTube video, that you click and the progress bar goes to that moment in time.


Is there a functionallity like that available?
Is it possible to have this kind of “external control” over the progress bar?

There is a parameter start_time to st.video().

Hi, @Goyo! Thanks for your reply!

I tried start_time parameter but it only seems to work when the video is first loaded.

For example, look at the snippet below that mimics my situation:

import streamlit as st

data = "video.mp4"

st.write("Click to go to that moment in video.")

time_stamps = [
    (st.button("Part A", "a"), 1),  # bool, moment (seconds)
    (st.button("Part B", "b"), 20),
    (st.button("Part C", "c"), 40),
]

time_chosen = [v for k, v in time_stamps if k == True]  # return [int] associated with a clicked button
if time_chosen:
    st.video(data, start_time=time_chosen[0])

It works the first time I click in one of the buttons and streamlit runs st.video(...), but fails the following interactions with the buttons.

Maybe, maybe st.video is cached and do not accept changes like start_video in the middle of execution.

What do you think?

I don’t quite get how streamlit magic works here. Looks like calling st.video in subsequent reruns has no effect even with a different start_time and I can’t find a way around this. Keep up posted if you make any progress.

Hi again, @Goyo!!

I think I found out how to deal with it.

*But an observation first: I edited my code above to be more clear and
look alike the answer I came up with.

The idea I had was to delete the widget every time a button is clicked and update the widget based on this interaction. You can see a discussion about deleting widgets here.

I created a placeholder with st.empty(), and before any update a placeholder.empty() is performed. This made the use of start_time possible for subsequent reruns.

import streamlit as st

data = "video.mp4"

st.write("Click to go to that moment in video.")

time_stamps = [
    (st.button("Part A", "a"), 1),  # bool, moment (seconds)
    (st.button("Part B", "b"), 20),
    (st.button("Part C", "c"), 40),
]

placeholder = st.empty()

time_chosen = [v for k, v in time_stamps if k == True]  # return [int] associated with a clicked button
if time_chosen:
    placeholder.empty()
    placeholder.video(data, start_time=time_chosen[0])

Great minds think alike. I was playing with the same idea after posting and kind of made it work. There was a minor issue where things didn’t work if I pressed the buttons too fast.

1 Like