Dado su enlace, me gustaría capturar un video en línea (por ejemplo, de YouTube) para su posterior procesamiento sin descargarlo en el disco . Lo que quiero decir con esto es que me gustaría cargarlo directamente en la memoria siempre que sea posible. Según estos enlaces:
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/
debería ser factible Mi bash se ve así:
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)
Sin embargo falla con un error
(python:12925): GLib-GObject-CRITICAL **: 14:48:56.168: g_object_set: assertion 'G_IS_OBJECT (object)' failed False
¿Cómo puedo lograr mi objective usando python?
Puedes lograr esto usando youtube-dl
y ffmpeg
:
youtube-dl
. sudo pip install --upgrade youtube_dl
ffmpeg
con soporte HTTPS. Puedes hacerlo activando la opción --enable-gnutls
. Una vez que las instalaciones están completas, es hora de probar el youtube-dl
en la terminal. Usaremos este video de youtube para realizar pruebas.
Primero obtenemos la lista de formatos disponibles para este video:
youtube-dl --list-formats https://www.youtube.com/watch?v=HECa3bAFAYk
Seleccione un format code
de format code
de su elección. Quiero la resolución de 144p así que selecciono 160 .
A continuación obtenemos la url de video para nuestro formato de elección por:
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 y Xtags = tx% 3D9486108 y itag = 160 & MIME = vídeo% 2Fmp4 y mt = 1529091799 & ms = au% 2Conr y ei = XxckW-73GNCogQfqrryQAg y expire = 1529113535 y mm = 31% 2C26 & c = WEB & keepalive = yes & id = o-AJExEG49WtIUkrF7OikaaGBCfKntDl75xCoO5_9cL-eP y ip = 95.91.202.147 y sparams = aitags% 2Cclen% 2Cdur% 2Cei % 2Cgir% 2Cid% 2Cinitcwndbps% 2Cip% 2Cmm% Pág. 1155000 & ipbits = 0 & ratebypass = yes
Finalmente, podemos reproducir este video url en ffplay
o vlc
. Pero en lugar de copiar y pegar, podemos hacer esto en un solo comando:
ffplay -i $(youtube-dl --format 160 --get-url https://www.youtube.com/watch?v=HECa3bAFAYk)
Ahora que hemos confirmado que youtube-dl
y ffmpeg
funcionan, podemos escribir un script de Python para procesar los marcos en OpenCV. Vea este enlace para más opciones de Python.
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()
Usando pafy puedes tener una solución más elegante:
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()