Voici un exemple assez simple de lecture d'une webcam en utilisant les liaisons python d'OpenCV:
'''capture.py'''
import cv, sys
cap = cv.CaptureFromCAM(0) # 0 is for /dev/video0
while True :
if not cv.GrabFrame(cap) : break
frame = cv.RetrieveFrame(cap)
sys.stdout.write( frame.tostring() )
Maintenant, je veux diriger la sortie vers ffmpeg comme suit:
$ python capture.py | ffmpeg -f image2pipe -pix_fmt bgr8 -i - -s 640x480 foo.avi
Malheureusement, je ne peux pas obtenir l'incantation magique ffmpeg tout à fait juste et ça échoue avec
libavutil 50.15. 1/50.15. 1 Libavcodec 52.72. 2/52,72. 2 Libavformat 52.64. 2/52.64. 2 Libavdevice 52. 2. 0/52. 2. 0 Libavfilter 1.19. 0/1.19. 0 Libswscale 0.11. 0/0,11. 0 Libpostproc 51. 2. 0/51. 2. 0 Sortie # 0, avi, vers 'out.avi': Flux # 0.0: Vidéo: flv, yuv420p , 640x480, q = 2-31, 19660 kb/s, 90 ktbn, 30 tbc [Image2pipe @ 0x1508640] max_analyze_duration atteint [Image2pipe @ 0x1508640] Estimation de la durée à partir du débit, cela peut être inexact Entrée # 0, image2pipe, à partir de 'pipe:': Durée: N/A, débit binaire: N/A Flux # 0.0: Vidéo: 0x0000, bgr8, 25 fps , 25 tbr, 25 tbn, 25 tbc SwScaler: 0x0 -> 640x480 est une dimension d'échelle non valide
Je ne suis pas un gourou ffmpeg. Quelqu'un at-il fait cela avec succès?
J'ai pris un peu de violon, mais je l'ai compris en utilisant le démultiplexeur FFmpeg rawvideo :
python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi
Comme il n'y a pas d'en-tête dans la vidéo brute spécifiant les paramètres vidéo supposés, l'utilisateur doit les spécifier pour pouvoir décoder les données correctement:
-framerate
Définissez la fréquence d'images vidéo d'entrée. La valeur par défaut est 25.-pixel_format
Définit le format de pixel de la vidéo d'entrée. La valeur par défaut est yuv420p.-video_size
Définissez la taille de la vidéo d'entrée. Il n'y a pas de valeur par défaut, cette valeur doit donc être spécifiée explicitement.Et voici un petit quelque chose en plus pour les utilisateurs avec pouvoir. Même chose mais en utilisant VLC pour diffuser la sortie en direct sur le Web, au format Flash:
python capture.py | cvlc --demux=rawvideo --rawvid-fps=30 --rawvid-width=320 --rawvid-height=240 --rawvid-chroma=RV24 - --sout "#transcode{vcodec=h264,vb=200,fps=30,width=320,height=240}:std{access=http{mime=video/x-flv},mux=ffmpeg{mux=flv},dst=:8081/stream.flv}"
Edit: Créer un flux webm en utilisant ffmpeg et ffserver
python capture.py | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 640x480 -framerate 25 -i - http://localhost:8090/feed1.ffm
Je suis un peu en retard, mais mon puissant VidGear
Python Bibliothèque automatise le processus de traitement en pipeline des trames OpenCV dans FFmpeg sur n’importe quelle plate-forme . Voici un exemple de base de python:
# import libraries
from vidgear.gears import WriteGear
import cv2
output_params = {"-vcodec":"libx264", "-crf": 0, "-preset": "fast"} #define (Codec,CRF,preset) FFmpeg Tweak parameters for writer
stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device
writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4'
# infinite loop
while True:
(grabbed, frame) = stream.read()
# read frames
# check if frame empty
if not is grabbed:
#if True break the infinite loop
break
# {do something with frame here}
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# write a modified frame to writer
writer.write(gray)
# Show output window
cv2.imshow("Output Frame", frame)
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
stream.release()
# safely close video stream
writer.close()
# safely close writer
Vous pouvez consulter VidGear Docs pour des applications et des fonctionnalités plus avancées.
J'espère que cela pourra aider!
Il m'a fallu une heure pour comprendre que, par défaut, les pipes Windows ne sont pas binaires. Cela entraîne la modification/l’omission de certains octets (en particulier les nouvelles lignes) et la vidéo résultante se déplace lentement car la taille de l’image n’est pas constante.
Pour résoudre ce problème, le fichier python modifié:
"""
videoCapture.py
"""
import cv2, sys
import time
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
cap = cv2.VideoCapture(0) # 0 is for /dev/video0
while True :
ret, frm = cap.read()
sys.stdout.write( frm.tostring() )
Pour vérifier si le traitement de la vidéo brute est réussi, utilisez ffplay. Assurez-vous de spécifier un débit d'image plus élevé que ce qui provient du canal, sinon la vidéo commencera à prendre du retard.
python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -
Je ne sais pas si c'est spécifique à Mac OS ou à python3, mais je devais convertir le cadre en chaîne pour que cela fonctionne pour moi, comme ceci:
sys.stdout.write(str(frame.tostring()))