【问题标题】:Capture YouTube video for further processing without downloading the video无需下载视频即可捕获 YouTube 视频以进行进一步处理
【发布时间】:2018-11-25 08:11:37
【问题描述】:

鉴于其链接,我想捕获一个在线视频(例如来自 YouTube)以进行进一步处理无需将其下载到磁盘上。我的意思是我想尽可能将它直接加载到内存中。根据这些链接:
http://answers.opencv.org/question/24012/reading-video-stream-from-ip-camera-in-opencv-java/#24013
http://answers.opencv.org/question/24154/how-to-using-opencv-api-get-web-video-stream/#24156
http://answers.opencv.org/question/133/how-do-i-access-an-ip-camera/
https://pypi.org/project/pafy/
它应该是可行的。我的尝试如下所示:

import cv2
import pafy

vid = pafy.new("https://www.youtube.com/watch?v=QuELiw8tbx8")
vid_cap = cv2.VideoCapture()
vid_cap.open(vid.getbest(preftype="webm").url)

但是它失败并出现错误

(python:12925): GLib-GObject-CRITICAL **: 14:48:56.168: g_object_set: assertion 'G_IS_OBJECT (object)' failed
False

如何使用 python 实现我的目标?

【问题讨论】:

    标签: python opencv


    【解决方案1】:

    我想强调我在运行时遇到的问题是 open-cv 版本问题,我使用的是 OpenCV 3.4.x 并且视频提要在被读入 while 循环之前退出,所以,我将我的 open cv 升级到“opencv-contrib-python== 4.2.0.34”。

    【讨论】:

      【解决方案2】:

      首先使用命令pip install -U youtube-dl更新youtube-dl

      然后使用我的VidGear Python 库,然后仅使用其 URL 地址自动流水线化 YouTube 视频。这是一个完整的python示例:

      以下为 VidGear v0.1.9

      # import libraries
      from vidgear.gears import CamGear
      import cv2
      
      stream = CamGear(source='https://youtu.be/dQw4w9WgXcQ', y_tube = True, logging=True).start() # YouTube Video URL as input
      
      # infinite loop
      while True:
          
          frame = stream.read()
          # read frames
      
          # check if frame is None
          if frame is None:
              #if True break the infinite loop
              break
          
          # do something with frame here
          
          cv2.imshow("Output Frame", frame)
          # Show output window
      
          key = cv2.waitKey(1) & 0xFF
          # check for 'q' key-press
          if key == ord("q"):
              #if 'q' key-pressed break out
              break
      
      cv2.destroyAllWindows()
      # close output window
      
      # safely close video stream.
      stream.stop()
      

      对于 VidGear v0.2.0 及以上:y_tube 更改为 stream_mode

      # import libraries
      from vidgear.gears import CamGear
      import cv2
      
      stream = CamGear(source='https://youtu.be/dQw4w9WgXcQ', stream_mode = True, logging=True).start() # YouTube Video URL as input
      
      # infinite loop
      while True:
          
          frame = stream.read()
          # read frames
      
          # check if frame is None
          if frame is None:
              #if True break the infinite loop
              break
          
          # do something with frame here
          
          cv2.imshow("Output Frame", frame)
          # Show output window
      
          key = cv2.waitKey(1) & 0xFF
          # check for 'q' key-press
          if key == ord("q"):
              #if 'q' key-pressed break out
              break
      
      cv2.destroyAllWindows()
      # close output window
      
      # safely close video stream.
      stream.stop()
      

      Code Source

      如果仍然出现错误,请在其 GitHub 存储库中提出 issue here

      【讨论】:

        【解决方案3】:

        使用 pafy,您可以获得更优雅的解决方案:

        import cv2
        import pafy
        
        url = "https://www.youtube.com/watch?v=NKpuX_yzdYs"
        video = pafy.new(url)
        best = video.getbest(preftype="mp4")
        
        capture = cv2.VideoCapture()
        capture.open(best.url)
        
        success,image = capture.read()
        
        while success:
            cv2.imshow('frame', image)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
        
            success,image = capture.read()
        
        cv2.destroyAllWindows()
        capture.release()
        

        【讨论】:

        • 我使用pafy=0.5.4opencv=3.4.0没有得到任何结果
        【解决方案4】:

        您可以通过使用youtube-dlffmpeg 来实现:

        安装完成后,就可以在终端中测试 youtube-dl 了。我们将使用this youtube video 进行测试。

        首先,我们得到此视频可用的格式列表:

        youtube-dl --list-formats https://www.youtube.com/watch?v=HECa3bAFAYk
        

        选择您喜欢的format code。我想要 144p 分辨率,所以我选择 160

        接下来,我们通过以下方式获取我们选择格式的视频网址:

        youtube-dl --format 160 --get-url https://www.youtube.com/watch?v=HECa3bAFAYk
        

        https://r3---sn-4g5e6nz7.googlevideo.com/videoplayback?clen=184077&aitags=133%2C134%2C160%2C242%2C243%2C278&fvip=3&requiressl=yes&signature=5D21FFD906226C7680B26ACEF996B78B6A31F7C9.31B1115DB13F096AA5968DB2838E22A0D6A2EDCB&source=youtube&mn=sn-4g5e6nz7%2Csn-h0jeen7y&xtags=tx%3D9486108&itag=160&mime=video%2Fmp4&mt=1529091799&ms=au%2Conr&ei=XxckW-73GNCogQfqrryQAg&expire=1529113535&mm=31%2C26&c=WEB&keepalive=yes&id=o-AJExEG49WtIUkrF7OikaaGBCfKntDl75xCoO5_9cL-eP&ip=95.91.202.147&sparams=aitags%2Cclen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cxtags%2Cexpire&key=yt6&lmt=1526699176943888&dur=25.375&pl=22&gir=yes&mv=m&initcwndbps=1155000&ipbits=0&ratebypass=yes

        最后,我们可以在ffplayvlc 中播放此视频网址。但是我们可以在一个命令中完成,而不是复制和粘贴:

        ffplay -i $(youtube-dl --format 160 --get-url https://www.youtube.com/watch?v=HECa3bAFAYk)
        

        现在我们已经确认youtube-dlffmpeg 有效,我们可以编写一个Python 脚本来处理OpenCV 中的帧。有关更多 Python 选项,请参阅this link

        import cv2
        import numpy as np
        import youtube_dl
        
        if __name__ == '__main__':
        
            video_url = 'https://www.youtube.com/watch?v=HECa3bAFAYkq'
        
            ydl_opts = {}
        
            # create youtube-dl object
            ydl = youtube_dl.YoutubeDL(ydl_opts)
        
            # set video url, extract video information
            info_dict = ydl.extract_info(video_url, download=False)
        
            # get video formats available
            formats = info_dict.get('formats',None)
        
            for f in formats:
        
                # I want the lowest resolution, so I set resolution as 144p
                if f.get('format_note',None) == '144p':
        
                    #get the video url
                    url = f.get('url',None)
        
                    # open url with opencv
                    cap = cv2.VideoCapture(url)
        
                    # check if url was opened
                    if not cap.isOpened():
                        print('video not opened')
                        exit(-1)
        
                    while True:
                        # read frame
                        ret, frame = cap.read()
        
                        # check if frame is empty
                        if not ret:
                            break
        
                        # display frame
                        cv2.imshow('frame', frame)
        
                        if cv2.waitKey(30)&0xFF == ord('q'):
                            break
        
                    # release VideoCapture
                    cap.release()
        
            cv2.destroyAllWindows()
        

        【讨论】:

        • 我可以确认这是可行的,但这实际上取决于您是否正确安装了 OpenCV。我无法在装有 Anaconda3 的 Linux 机器上运行它,但它在我朋友的装有 Windows 的机器上运行良好
        • @Colonder 我们如何知道它是否安装正确?谢谢
        • 我不知道,坦白说,是OpenCV本身的问题还是机器的问题,我给不了你答案,抱歉
        • 不幸的是,视频只显示了几秒钟,然后程序因错误“无法读取套接字”而关闭,有什么解决方案吗?
        猜你喜欢
        • 1970-01-01
        • 2016-01-16
        • 1970-01-01
        • 1970-01-01
        • 2014-06-16
        • 2011-02-10
        • 2012-12-21
        • 1970-01-01
        相关资源
        最近更新 更多