如何从ffmpeg管道直播视频帧到PIL?

我需要使用ffmpeg / avconv将jpg帧传输到python PIL(Pillow)图像对象,使用gst作为中介*。 我一直在寻找这个答案,没有多少运气。 我想我很接近 - 但我被卡住了。 使用Python 2.7

我从python启动的理想流水线如下所示:

  • ffmpeg / avconv (如h264视频)
  • 管道 - >
  • gst-streamer (分割成jpg的帧)
  • 管道 - >
  • Pil图像对象
  • 作为一个单一的命令,我可以控制前几个步骤,将硬编码所允许的.jpgs写入磁盘的速度非常快。

    该命令看起来像这样:

    command = [
            "ffmpeg",
            "-f video4linux2",
            "-r 30",
            "-video_size 1280x720",
            "-pixel_format 'uyvy422'",
            "-i /dev/video0",
            "-vf fps=30",
            "-f H264",
            "-vcodec libx264",
            "-preset ultrafast",
            "pipe:1 -",
            "|", # Pipe to GST
            "gst-launch-1.0 fdsrc !",
            "video/x-h264,framerate=30/1,stream-format=byte-stream !",
            "decodebin ! videorate ! video/x-raw,framerate=30/1 !",
            "videoconvert !",
            "jpegenc quality=55 !",
            "multifilesink location=" + Utils.live_sync_path + "live_%04d.jpg"
          ]
    

    如果使用popen或os.system运行,这将成功将帧写入磁盘。

    但是我不想将帧写入磁盘,而是想要捕获子进程管道中的输出,并在写入时读取帧,然后将其读入类似文件的缓冲区,然后由PIL读取。

    像这样的东西:

        import subprocess as sp
        import shlex
        import StringIO
    
        clean_cmd = shlex.split(" ".join(command))
        pipe = sp.Popen(clean_cmd, stdout = sp.PIPE, bufsize=10**8)
    
        while pipe:
    
            raw = pipe.stdout.read()
            buff = StringIO.StringIO()
            buff.write(raw)
            buff.seek(0)
    
            # Open or do something clever...
            im = Image.open(buff)
            im.show()
    
            pipe.flush()
    

    这段代码不起作用 - 我甚至不确定我可以用这种方式使用“管道”。 我很新,以这种方式使用缓冲区和管道。

    我不知道如何知道图像已写入管道或何时读取“下一张”图像。

    在理解如何从管道而不是磁盘读取图像时,任何帮助都将非常感谢。

  • 这最终是一个Raspberry Pi 3管道,为了增加我的帧速率,我不能(A)从磁盘读/写或者(B)使用逐帧捕获方法 - 而不是直接从H246视频运行相机芯片。

  • 我假设最终目标是在Linux上以高帧率处理USB摄像头,下面解决这个问题。

    首先,尽管少数USB摄像头支持H.264,但USB摄像头的Linux驱动程序(UVC驱动程序)目前不支持基于数据流的有效载荷,其中包括H.264,请参见驱动程序主页上的“UVC功能”表。 像ffmpeg这样的用户空间工具使用驱动程序,因此在使用什么视频格式进行USB传输时具有相同的限制。

    好消息是,如果摄像头支持H.264,则几乎可以肯定支持MJPEG,它受UVC驱动程序支持,压缩足够好,可以通过USB 2.0以30 fps的速度支持1280x720。 您可以使用v4l2-ctl -d 0 --list-formats-ext列出相机支持的视频格式。 对于Microsoft Lifecam影院,例如,对于YUV 4:2:2,1280x720仅支持10 fps,对于MJPEG则仅支持30 fps。

    对于从照相机阅读,我有OpenCV的良好经验。 在我的一个项目中,我有24台(!)Lifecams连接到一台Ubuntu 6核i7机器上,该机器能够以每台摄像机7.5 fps的速度使用320x240实时跟踪果蝇(并且还为每台摄像机节省了MJPEG AVI有实验记录)。 由于OpenCV直接使用V4L2 API,因此它应该比使用ffmpeg,gst-streamer和两个管道的解决方案更快。

    使用OpenCV从相机中读取裸露骨骼(无错误检查)代码并创建PIL图像,如下所示:

    import cv2
    from PIL import Image
    
    cap = cv2.VideoCapture(0)   # /dev/video0
    while True:
      ret, frame = cap.read()
      if not ret:
        break
      pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
      ...   # do something with PIL image
    

    最后说明:您可能需要构建V4L版本的OpenCV才能获得压缩(MJPEG),请参阅此答案。

    链接地址: http://www.djcxy.com/p/37931.html

    上一篇: How to pipe live video frames from ffmpeg to PIL?

    下一篇: Matlab sin(pi) and its relation to machine epsilon