Displaying progress bar when playing video with OpenCV

Displaying progress bar when playing video with OpenCV

At times when working in OpenCV with Videos, since there is no easy way to tell how long the video is going to be, or if you are planning to post the video on Social media like Instagram that do not show video progress bar, you may want to embed progress bar on the video itself. There is no build in feature on OpenCV, so we shall write a function that will achieve the same.

To get this done I will create a utility class and add this functionality to the same. And then use this functionality in a separate python file. As always let’s dive into the code!.

To follow along closely Download the code here displayProgressBar.zip

#import needed packages
import cv2
import math

We begin with importing the required packages

#This class provides a way to easily access the basic parameters of the video
#Also it adds a utility function to display progress bar on the video when
#displayed with OpenCV imshow function
class utilsVideo:
	#Ctor that takes following arguments
	#capture - video capture class object from OpenCV
	def __init__(self, capture):
		self.capture = capture

We declare the class utilsVideo on line 11 and then create the constructor for the same. It has just one argument, an object of Video capture class.

	def getStats(self):
		#get frames per seconds (fps) from the video
		fps = self.capture.get(cv2.CAP_PROP_FPS)
		#total frame counts
		frame_count = int(self.capture.get(cv2.CAP_PROP_FRAME_COUNT))
		#codec used to capture the video. This is useful when you are saving the
		#video to disc, currently not used anywhere
		#full parameter list at
		#https://docs.opencv.org/3.4/d4/d15/group__videoio__flags__base.html
		codec = self.capture.get(cv2.CAP_PROP_FOURCC)
		#total duraiton of video in milli seconds
		durationSec = frame_count/fps * 1000
		return (fps,frame_count,durationSec)

On line 18 we create a function that would return some basic statistics of the video. These stats include fps, total frame count, and then total duration of the video in milli seconds. Fps and frame count can easily be obtained from get function in Video Capture object. Using these 2 we need to calculate total duration which is simple if you understand what fps and frame count represent. Frame count is the total number of frames in the video and fps is how many frames are being displayed per second. Hence total duration of video (in seconds) is simply dividing frame count by fps. Then in the last line we return a tuple of the values thus obtained.

	def displayProgressBar(self, currentframe):
		#get next frame number out of all the frames for video
		nextFrameNo = self.capture.get(cv2.CAP_PROP_POS_FRAMES)
		#get total number of frames in the video
		totalFrames =self.capture.get(cv2.CAP_PROP_FRAME_COUNT)
		#calculate the percent complete based on the frame currently
		#playing. OpenCV does provide a variable to access this
		#property directly (CAP_PROP_POS_AVI_RATIO), however
		#it seems to not work all the time, hence we calculate internally
		complete = nextFrameNo/totalFrames
		
		#progress bar thickness
		lineThickness = 2
		#progress bar will be displayed 4% from the bottom of the frame
		y = math.ceil(currentframe.shape[1] - currentframe.shape[1]/25)
		#display progress bar across the width of the video
		x = 0
		w = currentframe.shape[0]
		#white line as background for progressbar
		cv2.line(currentframe, (x, y), (w, y), (255,255,255), lineThickness)
		#red line as progress on top of that
		cv2.line(currentframe, (x, y), (math.ceil(w*complete), y), (0,0,255), lineThickness)
		return currentframe

Now coming to the interesting part. A function that will display progress bar on the current video frame. On line 39 we start the function, it takes just one argument
currentframe: the current frame of video to be saved. This frame will be modified by adding progress bar on top of it and returned to the caller

Then on line 41 and 43 we retrieve 2 important properties from the Video Capture object, namely, next frame number and total frame count.
Next frame number is simply “0-based index of the frame to be decoded/captured next”. Total frame count, as already used in getStats function is simply the total number of frames in the video. Then we use these 2 properties to calculate how much video has already been viewed on line number 48. OpenCV does provide a variable to access this property directly (CAP_PROP_POS_AVI_RATIO), however it seems to not work all the time, hence we calculate internally

Then all that remains to be done is display of progress bar on the current frame, which we proceed to do between line number 51 to 60. We first define the x, y location where we shall display the progress bar, in this case we simply decide to display it near the bottom of the video (4% from the bottom most point) and across the horizontal width. Once these coordinates are defined, we display a white line across the frame and then a red line on top of white to display the progress based on completion ratio calculated above.

Then we return the modified frame in the last line. This completes our implementation of display progress bar on video. Now let’s go ahead and see how we can use this class.

Initiate a new file named displayProgressBar.py

#import the required packages including OpenCV
import cv2
from codedeepai import utilsVideo

vid = "./vid/cctv.mp4"

capture = cv2.VideoCapture(vid)

Again we start with importing the required packages. Note that we imported the class that we just created above on line 3. Then on line 5 we give the path of the video that we want to try with this code and create a Video Capture object with the same.

#initialise the basicsVideo object so we can view stats and draw progress bar
uv = utilsVideo(capture)
(fps,frame_count,durationSec) = uv.getStats()
print ("Total time: {}sec FrameRate: {} FrameCount: {}".format(durationSec, fps, frame_count))

On line 9 we create an object of our class by passing the Video Capture object and then invoke getStats function to get basic stats of the video which we print out.

while(True):
	# Capture frame-by-frame
	ret, currentframe = capture.read()
	if currentframe is not None:
		
		#display progress bar after saving video so that it does not ge saved with
		#current frame
		currentframe = uv.displayProgressBar(currentframe)
		#display video stream
		cv2.imshow('frame',currentframe)
	else:
		break
	if cv2.waitKey(1) & 0xFF == ord('q'):
		break
	
cv2.destroyAllWindows()

On line 13 we start an infinite loop to process the video frame by frame. Then on line 20, we invoke the magic function to draw the progress bar on our frame and then display the same on line 22.

See this code in action here

Now if you want to save the modified video to be uploaded on social networks like Instagram you can easily do the same with out writeVideo class as described in this blog post. Read the blog post to be aware of pitfalls of directly using OpenCV Video Writer class.

I am planning to post these classes on github repo. Will do the same and share link here once ready. But for the time being feel free to download code and it as you see fit.

Download the code here displayProgressBar.zip

 
 #requirement python3 and openCv
 Run project with python writeVideo.py

Do let me know if you have any questions and comments.

Leave a Reply

Your email address will not be published. Required fields are marked *