能否使用OpenCV从https://(例如YouTube)流式传输视频到Python?

19

这个链接展示了如何使用Python的OpenCV库cv2将相机数据流传输到Python shell中,非常简洁明了。我想进行一些实验,并想使用以下YouTube视频源:https://www.youtube.com/watch?v=oCUqsPLvYBQ

我尝试根据以下方式调整该示例:

import numpy as np
import cv2

cap = cv2.VideoCapture('https://www.youtube.com/watch?v=oCUqsPLvYBQ')

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Display the resulting frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

哪个产生了错误:

WARNING: Couldn't read movie file https://www.youtube.com/watch?v=oCUqsPLvYBQ
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /tmp/opencv20160107-29960-t5glvv/opencv-2.4.12/modules/highgui/src/window.cpp, line 261

有没有简单的解决方案,可以让我通过cv2在Python shell中流式传输此视频源?如果有其他库可以完成相同的目的,也不一定要使用cv2


3
我认为不可能这样打开 VideoCapture。在 OpenCV 的文档中,videocapture 写道,参数应该是一个文件。但你可以使用 youtube-dl 中间转换一下。 - Dimitri Podborski
@incBrain:这看起来很有前途,谢谢。我会尽快查看并告诉你。 - aaron
2
@incBrain:youtube-dl 是个好选择。感谢你的建议! - aaron
5个回答

25

你需要安装以下两个软件包:

  1. pafy (pip install pafy)
  2. youtube_dl (sudo pip install --upgrade youtube_dl)

安装完这两个软件后,你可以使用YouTube的URL播放流媒体视频。请参考下面的代码:

url = 'https://youtu.be/W1yKqFZ34y4'
vPafy = pafy.new(url)
play = vPafy.getbest(preftype="webm")

#start the video
cap = cv2.VideoCapture(play.url)
while (True):
    ret,frame = cap.read()
    """
    your code here
    """
    cv2.imshow('frame',frame)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break    

cap.release()
cv2.destroyAllWindows()

1
太好了,谢谢。我已经很久没有问这个问题了。有人可以测试一下并确认它是否有效,这样我就可以选择答案了吗? - aaron
9
无法工作,使用的是OpenCV 3.4.0。 - Arjun Kava
1
IOError: 错误:由于未知原因,“token”参数不在视频信息中;请在 https://yt-dl.org/bug 上报告此问题。确保您使用的是最新版本;请参阅 https://yt-dl.org/update 了解如何更新。请务必使用 --verbose 标志调用 youtube-dl,并包括其完整输出。 - Mustard Tiger
检查您的pafy是否正常工作。它应该返回一个视频流(https://pythonhosted.org/Pafy/)。还要检查首选类型参数,它可以有不同的值,如下所述: preftype(str)-首选类型,设置为mp4、webm、flv、3gp或任何其他类型。 - Vaibhav K
1
@ArjunKava 解决方案是升级你的openCV版本 :-) - Francis Gonzales
显示剩余6条评论

3

使用pafy (https://pypi.python.org/pypi/pafy) 可能实现此功能。

import cv2, pafy

url = "https://www.youtube.com/watch?v=aKX8uaoy9c8"
videoPafy = pafy.new(url)
best = videoPafy.getbest(preftype="webm")

video=cv2.VideoCapture(best.url)

6
这个方法不起作用(至少在OpenCV 3.4.0中是如此)。video.read() 总是会返回 (False, None)。该视频的URL是有效的,例如使用wget可以下载该视频。 - burny
@burny 你找到解决方法了吗? - wownis

2

我在我的VidGear Python库中添加了对Youtube URL源的支持,只需提供其URL即可自动将YouTube视频导入OpenCV。以下是一个完整的Python示例:

适用于VidGear v0.1.9及以下版本:

Original Answer翻译成"最初的回答"

# 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()

原始答案

,涉及到IT技术方面的内容。

我尝试了这个,得到了None帧,就像我用pafy时得到的一样。 - ruckc
2
@ruckc 这是一个与opencv-python库相关的问题,由于其FFmpeg构建中缺乏OpenSSL支持,因此不支持https协议。更多关于此错误的信息可以在这里找到。好消息是,我最近在opencv-python库中提交了一个PR,完全解决了这个问题,并已被作者合并。所以请耐心等待几天,当这些无错误的二进制文件正式可在PyPi上下载时。祝你好运。 - abhiTronix
@ruckc,该 bug 已得到修复。请升级到最新的 opencv-python 版本。 - abhiTronix
你能让这段代码切换到直播状态吗?我的意思是,每当我将其用于已在 YouTube 上播放了 20 分钟的直播流时,该代码总是从 00.00 开始读取。我希望它从 20 分钟开始。 - Mumbaikar007
@Mumbaikar007 请在我们的GitHub仓库上提出这个问题。请点击此处,我们一定会解决它的。 - abhiTronix

2
@incBrain建议的将YouTube视频下载到本地mp4文件是可行的方法。以下是我用来在EC2上设置远程服务器环境并通过X11转发将输出传送到我的本地计算机的步骤:
  • ssh -X -i "<ssh_key.pem>" ubuntu@<IP-address>.compute-1.amazonaws.com (请注意,-X选项在此处是一个重要的添加。这是我们用来将EC2服务器的输出传递给本地X11客户端的方式)
  • sudo pip install --upgrade youtube_dl(我知道,sudo pip是不好的。我怪网站的指示)
  • 将YouTube视频下载到本地文件:youtube-dl https://www.youtube.com/watch?v=VUjF1fRw9sA -o motocross.mp4
  • python demo_cv.py
X11转发可能有些棘手。如果您遇到任何问题,请参考此帖子,也许对您有所帮助。

2
能否以流的方式访问它?而不必等待文件下载。 - Anand C U
此外,我们有法律限制,禁止我们实际下载文件,并要求我们仅使用流式传输。 - burny

0
#pip install pafy
#sudo pip install --upgrade youtube_dl
import cv2, pafy

url   = "https://www.youtube.com/watch?v=qvyTx01ZcQQ"
video = pafy.new(url)
best  = video.getbest(preftype="mp4")
capture = cv2.VideoCapture(best.url)
while True:
    check, frame = capture.read()
    print (check, frame)

    cv2.imshow('frame',frame)
    cv2.waitKey(10)

capture.release()
cv2.destroyAllWindows()

试试这个,对于直播流也很有效


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接