将滑块与视频短划线图的当前时间同步

Synchronize Slider with CurrentTime of Video Dash Plotly

我正在构建一个 Dash 应用程序,它将播放视频并由 play/pause 按钮控制。在视频上方,我有一个滑块,允许用户跳到视频中的任何部分(10 秒长)。我希望能够让滑块随着视频播放而移动。

这是我到目前为止尝试过的方法:

import os
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_player as player
from flask import Flask, Response
from dash.dependencies import Input, Output, State

server = Flask(__name__)
app = dash.Dash(__name__, server=server)


app.layout = html.Div(
    children=[
        html.Div(
            children=[
                html.Div([
                    html.Button('Play/Pause', id='play-button', n_clicks=0),
                ],style={
                    'width':'10%',
                    'display':'inline-block'
                }),
                html.Div([
                    dcc.Slider(id='slider',
                               min=0,
                               max=10,
                               step=1,
                               value=0,
                               marks={0: {'label': '0s', 'style': {'color': 'black'}},
                                      2: {'label': '2s', 'style': {'color': 'black'}},
                                      4: {'label': '4s', 'style': {'color': 'black'}},
                                      6: {'label': '6s', 'style': {'color': 'black'}},
                                      8: {'label': '8s', 'style': {'color': 'black'}},
                                      10: {'label': '10s', 'style': {'color': 'black'}}
                                }
                    ),
                ],style={
                    'width':'90%',
                    'display':'inline-block'
                })
               
             ]
        ),
    
        html.Div(
            children=[
                player.DashPlayer(
                    id='video-player',
                    url='https://www.w3schools.com/html/mov_bbb.mp4',
                    controls=False,
                    width='100%'
                )
            ]
        )    
    ]
)

#Use slider to skip to or "seekTo" different spots in video
@app.callback(Output('video-player', 'seekTo'),
              Input('slider', 'value'))
def set_seekTo(value):
    return value

#Press button to play/pause video 1
@app.callback(
    Output("video-player", "playing"),
    Output("slider","value"),
    Input("play-button", "n_clicks"), 
    State("video-player", "playing"),
    State('slider','value'),
    State("video-player","currentTime")
)
def play_video(n_clicks, playing, value, currentTime):
    value = currentTime
    if n_clicks:
        return not playing, value
    return playing, value




if __name__ == "__main__":
    app.run_server(debug=True, port=8050)

play/pause按钮工作正常,但忽略了将滑块条同步到视频当前时间的功能。没有错误信息。我在这里错过了什么?任何帮助将不胜感激!

Note: I initially wanted to make this a comment as I wasn't able to get the seekTo functionality to work in conjunction with synchronizing the time and the slider, but the explanation of my implementation was too long for a comment. Below is listed a way you could update the slider value based on the currentTime of the dash player component, but doesn't implement seekTo.


实施

import os
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_player as player
from flask import Flask, Response
from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)


app.layout = html.Div(
    children=[
        html.Div(
            children=[
                html.Div(
                    [
                        html.Button("Play/Pause", id="play-button", n_clicks=0),
                    ],
                    style={"width": "10%", "display": "inline-block"},
                ),
                html.Div(
                    [
                        dcc.Slider(
                            id="slider",
                            min=0,
                            max=10,
                            step=1,
                            value=0,
                            marks={
                                0: {"label": "0s", "style": {"color": "black"}},
                                2: {"label": "2s", "style": {"color": "black"}},
                                4: {"label": "4s", "style": {"color": "black"}},
                                6: {"label": "6s", "style": {"color": "black"}},
                                8: {"label": "8s", "style": {"color": "black"}},
                                10: {"label": "10s", "style": {"color": "black"}},
                            },
                        ),
                    ],
                    style={"width": "90%", "display": "inline-block"},
                ),
            ]
        ),
        html.Div(
            children=[
                player.DashPlayer(
                    id="video-player",
                    url="https://www.w3schools.com/html/mov_bbb.mp4",
                    controls=False,
                    width="100%",
                )
            ]
        ),
    ]
)


@app.callback(Output("slider", "value"), Input("video-player", "currentTime"))
def update_slider(current_time):
    return current_time


@app.callback(
    Output("video-player", "playing"),
    Input("play-button", "n_clicks"),
    State("video-player", "playing"),
)
def play_video(n_clicks, playing):
    if n_clicks:
        return not playing
    return playing


if __name__ == "__main__":
    app.run_server(debug=True, port=8050)

说明

上述实现的想法是创建一个回调,用于在每次 currentTime 间隔更改时更新滑块值,并创建一个回调来在按下 play-button 时处理播放和暂停视频.

请记住,我使用 currentTime 作为输入,因此每次此值更改时都会调用回调。 It seems to change every 40 ms by default。您可以通过在 DashPlayer.

上设置 intervalCurrentTime 属性来更改此间隔

还要记住,这里的滑块值只会每秒变化一次,因为 step 设置为 1。因此,如果您想要不同的行为,请结合 intervalCurrentTime 更改 step 值。