#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
, если вы хотите другого поведения.