zoukankan      html  css  js  c++  java
  • python实时视频流播放

    @action(methods=['GET'], detail=True)
        def video(self, request, pk=None):
            """
            获取设备实时视频流
            :param request:
            :param pk:
            :return:
            """
            device_obj = self.get_object()
    
            # if device_obj.status == 0:
            #     return Response({'error': '设备离线'})
    
            if not device_obj.rtsp_address:
                return Response({'error': '缺少rtsp地址'})
    
            cache_id = '_video_stream_{}'.format(device_obj.hash)
            cache_status = cache.get(cache_id, None)
            if cache_status is None:  # 任务初始化,设置初始时间
                cache.set(cache_id, time.time(), timeout=60)
    
            elif isinstance(cache_status, float) and time.time() - cache_status > 30:  # 任务已超时, 返回错误信息, 一段时间内不再入队
                return Response({'error': '连接数目超过限制, 请稍后再试'})
    
            ret = job_queue.enqueue_video(rtsp_address=device_obj.rtsp_address, device_hash=device_obj.hash)
    
            logger.info('fetch device %s video job status: %s', pk, ret._status)
    
            if ret._status == b'started' or 'started':  # 视频流正常推送中, 刷新播放时间, 返回视频ID
                cache.set(cache_id, 'continue', timeout=30)
                return Response({'video': ''.join([settings.FFMPEG_VIDEO, device_obj.hash])})
    
            elif ret._status == b'queued' or 'queued':  # 视频任务等待中
                return Response({'status': '等待建立视频连接'})
    
            else:  # 建立视频任务失败
                return Response({'error': '打开视频失败'})
    class JobQueue:
        """实时视频播放"""
        def __init__(self):
            self.video_queue = django_rq.get_queue('video')  # 视频推流消息队列
    
        def enqueue_video(self, rtsp_address, device_hash):
            """视频流队列"""
            job_id = 'video_{}'.format(device_hash)
            job = self.video_queue.fetch_job(job_id)
    
            if not job:
                job = self.video_queue.enqueue_call(
                    func='utils.ffmpeg.ffmpeg_play',
                    args=(rtsp_address, device_hash),
                    timeout=-1,
                    ttl=30,  # 最多等待30秒
                    result_ttl=0,
                    job_id=job_id
                )
    
            return job
    # -*- coding: utf-8 -*-
    
    import subprocess
    import threading
    import time
    import logging
    
    from django.core.cache import cache
    
    
    logger = logging.getLogger('server.default')
    
    
    def ffmpeg_play(stream, name):
    
        play = True
        cache_id = '_video_stream_{}'.format(name)
        cache.set(cache_id, 'continue', timeout=30)
        process = None
    
        def upstream():
            cmd = "ffmpeg -i '{}' -c:v h264 -f flv -r 25 -an 'rtmp://127.0.0.1:1935/live/{}'".format(stream, name)
            process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stderr=subprocess.DEVNULL)
            try:
                logger.info('device: {} stream thread start: {}'.format(name, stream))
                while play:
                    time.sleep(1)
    
            except Exception as e:
                logger.info('device: {} stream thread error {}'.format(name, e))
    
            finally:
                logger.info('device: {} stream thread stop'.format(name))
                process.communicate(b'q')
    
        thr = threading.Thread(target=upstream)
        thr.start()
    
        try:
            while True:
                play = cache.get(cache_id, '')
                if play != 'continue':
                    logger.info('stop device {} video stream'.format(name))
                    play = False
                    break
                time.sleep(1)
    
        except Exception as e:
            logger.info('device: {} play stream error {}'.format(name, e))
            process.communicate(b'q')
    
        logger.info('wait device {} video thread stop'.format(name))
        thr.join()
        logger.info('device {} video job stop'.format(name))
    # 实时视频流播放
    RQ_QUEUES = {
        'video': {
            'USE_REDIS_CACHE': 'video',
        }
    }

     # 还可以通过cv2实现。但是弹出框是自带的,可能出现问题;还可以转成websocket格式返回给前端··

  • 相关阅读:
    国外高手又一力作,CAML Builder
    用word2007发布blog!!
    SharePoint Server 2007 trial 年末大餐细细品尝 (第八口)
    SharePoint Server 2007 trial 年末大餐细细品尝 (再来一口)
    SharePoint Server 2007 trial 年末大餐细细品尝 (第三口)
    SharePoint Server 2007 trial 年末大餐细细品尝 (第十口)
    卡壳了~~~
    SharePoint Server 2007 trial 年末大餐细细品尝 (第九口)
    moss 与 ad 用户信息不同步的问题。
    SharePoint Server 2007 trial 年末大餐细细品尝 (第六口)
  • 原文地址:https://www.cnblogs.com/52-qq/p/11812430.html
Copyright © 2011-2022 走看看