MATLAB Answers

Using a slider to control a video while it's playing?

37 views (last 30 days)
Safa Bakhshi
Safa Bakhshi on 15 Mar 2017
Answered: Afiq Azaibi on 24 Mar 2017
I have to create a video player with audio playback in MATLAB 2016b that displays video on an axes. I used GUIDE to create a GUI. I have to take the approach where the video plays back through a while loop in the play button callback function. The conditions for this while loop are that the video has frames left to play back and that the UserData in Play button reads 'Play'. Here is the code for playback. vid is the video object.
while hasFrame(vid) && strcmp(get(handles.play_button,'UserData'),'Play')
% starts timing the process it takes to render a frame
tic
% sets the value of the slider to the current time of the time of the code to have it update position as the
% video plays. The min and max of the slider were set prior to this loop
handles.slider1.Value = vid.CurrentTime;
% reads the next frame of the video and stores it to frame
frame = readFrame(vid);
% standard process to correct for audio overrun. If the audio is ahead of the video keep advancing the video by
% a frame
while(((r.CurrentSample/r.SampleRate)- vid.CurrentTime) >= (1/vid.FrameRate))
frame = readFrame(vid);
end
% displays frame on the axes
image(frame,'Parent',handles.axes1);
% stop timing the rendering process and store the time to a variable
delta = toc;
% Process to correct for audio underrun. If the audio is behind the video pause the video by the difference
% let the audio catch up. Otherwise pause for (1/FrameRate - delta) to display the video at the proper framerate
if ((vid.CurrentTime - (r.CurrentSample/r.SampleRate)) >= (1/vid.FrameRate)) && r.isplaying
pause(vid.CurrentTime - (r.CurrentSample/r.SampleRate));
else
pause((1/vid.FrameRate)-delta);
end
end
The playback by itself works very well. It's when I try to change it's position with the slider is where I run into trouble. The slider needs to pause the video and change the position to the time selected. The slider should work whether the video is currently playing or paused.
Here is my callback function for slider movement. r is the audioplayer and vid is the video object.
global r;
vid = handles.vid;
guidata(hObject,handles);
set(handles.slider1,'Min',0);
set(handles.slider1,'Max',vid.Duration);
%Stops the video playback loop and set the button string to play
set(handles.play_button,'UserData','Pause');
set(handles.play_button,'String','Play');
%Pause the audio player
pause(r);
% get the value of the slider
h = get(hObject,'Value');
if h == 0
vid.CurrentTime = 0;
frame = readFrame(vid);
image(frame,'Parent',handles.axes1);
vid.CurrentTime = 0;
elseif h == get(hObject,'Max')
vid.CurrentTime = (vid.Duration-1);
frame = readFrame(vid);
image(frame,'Parent',handles.axes1);
vid.CurrentTime = (vid.Duration-1);
else
vid.CurrentTime = h;
frame = readFrame(vid);
image(frame,'Parent',handles.axes1);
end
This code basically pauses the audio and video and retrieves the position of the slider. It then checks if the video is at the beginning or end. If it is at the beginning it renders the first frame and sets the current time to 0. If it is at the end, it renders the frame a second before and set the current time to second before (I want this behavior).
Otherwise, the current time should be set to the value of the slider and the next frame rendered. This entire process works perfectly fine when moving the slider while the video is paused. However, I have an issue when moving the slider during playback where the slider is not moving to where the user places it and the video is not advancing to where the user sets the slider. Through experimentation I have determined that the code in the play back loop keeps overwriting the current value of the slider with the current time of the video. Therefore I can't get the value of the position the user places the slider. I have tried creating a global variable and an if statement that ignores the slider update command in the playback loop if that variable is set to 1. This did not work. Any advice on approaching this issue?
Thank you for your time.

Answers (1)

Afiq Azaibi
Afiq Azaibi on 24 Mar 2017
It seems that moving the slider while pausing functions fine so what you can do is add two listeners to your slider. The preset will pause the video and the postset will resume its play once the value has been set. You can refer to the following code and documentation for further implementation:
PreCallBack = @(~,~) disp('Pause the video here');
PostCallBack = @(~,~)disp('Play the video here');
F = figure();
H = uicontrol(F,'Style','slider','Position',[81,54,200,23]);
addlistener(H, 'Value', 'PostSet',PostCallBack);
addlistener(H, 'Value', 'PreSet', PreCallBack);
https://www.mathworks.com/help/matlab/ref/handle.addlistener.html

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!