For anyone interested, here is my attempt on a simple interactive video player in Makie:
using GLMakie
using VideoIO
"""
videoplayer(fig, vid; totalframes)
Create videoplayer
providing totalframes makes it start faster
"""
function videoplayer(fig, vid; totalframes = nothing)
playing = Observable(false)
frame = Observable(1)
lastframe = 0
isnothing(totalframes) && (totalframes = counttotalframes(vid))
framerate = round(VideoIO.framerate(vid))
# image
img = read(vid)
gl = GridLayout()
gl[1,1] = vid_ax = Axis(fig, aspect = DataAspect())
hidedecorations!(vid_ax)
videonode = Observable(rotr90(img))
image!(videonode)
# controls
gl[2,1] = controls = GridLayout()
controls[1,1] = playbutton = Button(fig, label=lift(x -> x ? " ▌▌ " : " ▶ ", playing))
controls[1,2] = progressbar = Slider(fig, range = 1:totalframes)
controls[1,3] = timebutton = Button(fig, label=" F:1/$totalframes ")
fig[1,1] = gl
on(playbutton.clicks) do _
(frame[] == totalframes) && set_close_to!(progressbar, 1)
playing[] = !playing[]
end
on(playing) do pl
!pl && return
@async begin
while playing[] && frame[]<totalframes
frame[] = frame[] + 1
sleep(1/framerate)
end
playing[] = false # stop
end
end
on(frame) do fr
set_close_to!(progressbar, frame[])
notify(progressbar.value)
end
on(progressbar.value) do wantedframe
if wantedframe != frame[]
frame[] = wantedframe
end
if wantedframe != lastframe + 1
seek(vid, (wantedframe-1)/framerate)
end
timebutton.label = " F:$(frame[])/$totalframes "
read!(vid, img)
# image modification function may come here
videonode[] = rotr90(img)
lastframe = wantedframe
end
return gl
end
# __Main__
io = VideoIO.testvideo("annie_oakley") # test video
totalframes = nothing
# io = VideoIO.open(videofile)
# totalframes = VideoIO.get_number_frames(videofile)
vid = VideoIO.openvideo(io)
fig = Figure()
display(fig)
vp = videoplayer(fig[1,1], vid; totalframes)