python+openCV 播放器的实现(兼容rstp)(一)

  • 本文小目标:使用 openCV 实现视频公共类

  • 目标分解:

    1. 视频播放
    2. 视频暂停
    3. 视频停止
    4. 视频截图
  1. 视频播放。使用循环语句,读取视频的每一帧图片 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)))
    
  2. 视频暂停。给视频播放程序发送停止信号,退出循环。这里只需要在视频播放的循环语句中增加一个变量,判断是否需要终止循环。注意,这里不能调用VideoCapture.release()释放资源,否则暂停后播放视频将会从头开始。
  3. 视频停止。如果视频正在播放,只需要关闭窗口cv2.destroyWindow,停止播放并释放资源;如果视频没有播放,只需要关闭窗口,释放资源。
  4. 视频截图。因为视频是一帧一帧的图片,视频截图本质是将当前读取的一帧图片进行保存cv2.imwrite(save_path, image)
  5. 视频结束。因为在播放的方法中,循环条件一直为 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
    
  6. 将功能写到一个类中
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}')

你可能感兴趣的:(opencv,opencv,python)