本文小目标:使用 openCV 实现视频公共类
目标分解:
VideoCapture.read
,根据视频的帧率VideoCapture.get(cv2.CAP_PROP_FPS)
,控制两张图片的显示间隔,从而实现视频播放。import cv2
videos = 'https://cdn.theguardian.tv/webM/2015/07/20/150716YesMen_synd_768k_vp8.webm'
vc = cv2.VideoCapture(video_name)
open_status = vc.isOpened()
fps = vc.get(cv2.CAP_PROP_FPS)
while open_status:
# 从视频中读取一帧图片
ret, image = vc.read()
if ret is True:
# 只有获取到图片时,才会显示。imshow() 第一个参数为自定义的窗口名,第二个参数是显示的图片对象
cv2.imshow('videos', image)
# 设置每帧之间的显示间隔
if fps < 200:
# rstp 通过get方法获取到的帧率不是真实帧率时,数值比较大
cv2.waitKey(int(1000 / int(fps)))
VideoCapture.release()
释放资源,否则暂停后播放视频将会从头开始。cv2.destroyWindow
,停止播放并释放资源;如果视频没有播放,只需要关闭窗口,释放资源。cv2.imwrite(save_path, image)
。True
且不会改变,在播放视频时,视频结束后,不会自动停止循环。因此需要增加一个方法,判断视频是否终止。# 退出倒计时, 连续60次获取的帧数据为False 或者 连续两秒时间的帧数据为False,结束播放
def exit_timing(self):
max_false_ret_num = self.fps * 2 if self.fps else 60
if self._exit_timing > max_false_ret_num:
return True
self._exit_timing += 1
return False
class Cv2Player():
def __init__(self, video_url=None):
self.video_url = video_url
self.capture = cv2.VideoCapture(self.video_url)
# 视频信息:
# 帧率
self.fps = self.capture.get(cv2.CAP_PROP_FPS)
# 帧大小
self.width = int(self.capture.get(cv2.CAP_PROP_FRAME_WIDTH))
self.hight = int(self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.size = (self.width, self.hight)
if video_url == None or video_url== '':
self.status = 0 # 当前视频状态。 0 没有视频,1 未播放,2 播放中,3 计算背景
# 窗口名称
self.video_window_name = 'video'
# 结束倒计时
self._exit_timing = 0
def open_media(self):
self.status = 1
self.capture.open(self.video_url)
ret = self.capture.isOpened()
if not ret:
logger.error(f'视频地址不合法:{self.video_url}')
return False
logger.info(f'打开视频播放地址: {self.video_url}')
return True
# 重新打开视频
def reopen(self):
# 打开新的播放窗口
if self.capture.isOpened():
self.capture.release()
self.open_media()
else:
self.open_media()
# 播放
def play(self):
self.status = 2
self.reopen()
logger.debug('播放视频')
open_status = self.capture.isOpened()
while open_status:
self.ret, image = self.capture.read()
if self.ret is True:
self.image = image
cv2.imshow(self.video_window_name, self.image)
self._exit_timing = 0
elif self.exit_timing():
break
if self.fps < 200:
cv2.waitKey(int(1000 / int(self.fps)))
self.exit()
# 截图
def screenshot(self, save_dir=None):
if not isinstance(self.image, bool):
if save_dir:
if not os.path.exists(save_dir):
os.mkdirs(save_dir)
save_path = os.path.join(save_dir, 'screenshot_{:.7f}.png'.format(time.time()))
cv2.imwrite(save_path, self.image)
else:
save_path = 'screenshot_{:.7f}.png'.format(time.time())
cv2.imwrite(save_path, self.image)
logger.info(f'保存截图: {save_path}')
return True
return False
# 暂停
def pause(self):
if self.status > 1:
self.stop()
logger.debug('视频暂停')
return True
else:
logger.debug(f'当前非播放状态:{self.status}')
return False
# 停止播放
def stop(self):
self.status = 1
cv2.destroyAllWindows()
logger.info(f'停止播放 {self.video_url}')