Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture YouTube video for further processing without downloading the video

Tags:

python

opencv

Given its link, I'd like to capture an online video (say from YouTube) for further processing without downloading it on the disk. What I mean by this is that I'd like to load it directly to memory whenever possible. According to these links:
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/
it should be doable. My attempt looks like this:

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)

However it fails with an error

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

How can I achieve my goal using python?

like image 407
Colonder Avatar asked Jun 15 '18 13:06

Colonder


People also ask

How do I download part of a YouTube video?

Click the Video Trim icon, which is the icon of a photo with a pencil at the top-center. Drag the left guide to the place you want your clip to begin, and the right guide to where you want your clip to end. Click Save as at the top. Choose a saving location (and name, if you want) and click Save.


2 Answers

You can achieve this by using youtube-dl and ffmpeg:

  • Install the latest version of youtube-dl.
  • Then do sudo pip install --upgrade youtube_dl
  • Build ffmpeg with HTTPS support. You can do this by turning on the --enable-gnutls option.

Once the installations are complete, it's time to test the youtube-dl in terminal. We'll be using this youtube video for testing.

First we get the list of formats available for this video:

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

Select a format code of your choice. I want the 144p resolution so I select 160.

image

Next we get the video url for our format of choice by:

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

Finally we can play this video url in either ffplay or vlc. But instead of copying and pasting, we can do this in one command:

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

Now that we have confirmed that youtube-dl and ffmpeg works, we can write a Python script to process the frames in OpenCV. See this link for more Python options.

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()
like image 118
zindarod Avatar answered Sep 24 '22 03:09

zindarod


First of all Update youtube-dl using the command pip install -U youtube-dl

Then use my VidGear Python Library, then automates the pipelining of YouTube Video using its URL address only. Here's a complete python example:

For VidGear v0.1.9 below:

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

For VidGear v0.2.0 and above: (y_tube changed to 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

If still get some error, raise an issue here in its GitHub repo.

like image 22
abhiTronix Avatar answered Sep 25 '22 03:09

abhiTronix