Синхронизируйте слайдер с текущим временем видео-тире Сюжетно

#python #video #slider #plotly-dash #plotly-python

Вопрос:

Я создаю приложение Dash, которое будет воспроизводить видео и управляться кнопкой воспроизведения/паузы. Над видео у меня есть ползунок, который позволяет пользователю перейти к любой части видео (длиной 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)
 

Кнопка воспроизведения/паузы работает просто отлично, но функция синхронизации ползунка с текущим временем видео игнорируется. Никаких сообщений об ошибках. Что я здесь упускаю? Любая помощь будет очень признательна!

Комментарии:

1. Это потому, что у вас нет текущего времени или другого временного интервала в качестве входных данных для ваших обратных вызовов. Мне удалось синхронизировать время с ползунком, но я не смог заставить его работать в сочетании с seekTo

2. Можете ли вы поделиться тем, как у вас появилось время для синхронизации со слайдером?

Ответ №1:

Примечание: Изначально я хотел сделать это комментарием, так как мне не удалось заставить seekTo функциональность работать в сочетании с синхронизацией времени и слайдера, но объяснение моей реализации было слишком длинным для комментария. Ниже приведен способ, которым вы могли бы обновить значение ползунка на основе currentTime компонента dash player, но он не реализован 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 в качестве входных данных, поэтому обратный вызов будет вызываться каждый раз, когда это значение изменяется. По умолчанию он, похоже, меняется каждые 40 мс. Вы можете изменить этот интервал, установив intervalCurrentTime опору на DashPlayer .

Также имейте в виду, что значение ползунка здесь будет меняться только каждую секунду, потому step что установлено значение 1 . Поэтому измените step значение в сочетании с intervalCurrentTime , если вы хотите другого поведения.