Pipe raw OpenCV images to FFmpeg
voici un exemple assez simple de lecture d'une webcam utilisant les fixations 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 rediriger la sortie vers ffmpeg comme dans:
$ 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 correcte et il é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 Output #0, avi, to 'out.avi': Stream #0.0: Video: flv, yuv420p, 640x480, q=2-31, 19660 kb/s, 90k tbn, 30 tbc [image2pipe @ 0x1508640]max_analyze_duration reached [image2pipe @ 0x1508640]Estimating duration from bitrate, this may be inaccurate Input #0, image2pipe, from 'pipe:': Duration: N/A, bitrate: N/A Stream #0.0: Video: 0x0000, bgr8, 25 fps, 25 tbr, 25 tbn, 25 tbc swScaler: 0x0 -> 640x480 is invalid scaling dimension
- les cadres capturés sont certainement 640x480.
- je suis assez sûr que l'ordre des pixels pour le type D'image OpenCV (IplImage) est GBR, un octet par canal. Moins, c'est ce que semble provenir de l'appareil.
Je ne suis pas un gourou ffmpeg. Quelqu'un a fait cela avec succès?
3 réponses
a pris un tas de violon mais j'ai compris en utilisant le FFmpeg rawvideo demuxer:
python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi
Puisqu'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 afin de pouvoir décoder les données correctement:
-framerate
définir le taux de trame vidéo d'entrée. La valeur par défaut est de 25.-pixel_format
définir le format de pixel vidéo d'entrée. La valeur par défaut est yuv420p.-video_size
régler le d'entrée de taille de la vidéo. Il n'y a pas de valeur par défaut, cette valeur doit être spécifiée explicitement.
Et voici un petit quelque chose supplémentaire pour les utilisateurs d'alimentation. Même chose, mais en utilisant VLC pour diffuser la sortie en direct sur le web, 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}"
Modifier: 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
m'a pris une heure pour comprendre que par défaut, les pipes windows ne sont pas binaires. Cela fait que certains octets (en particulier les lignes) sont modifiés / omis, et la vidéo résultante se déplace lentement parce que la taille du cadre n'est pas constante.
À ce travail autour de, la modification de fichier python:
"""
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 tester si piping la vidéo brute est réussie, utilisez ffplay. Assurez-vous que vous spécifiez un framerate plus élevé que ce qui vient de la pipe, sinon la vidéo va démarrer à la traîne
python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -
Je ne suis pas sûr que ce soit spécifique à Mac OS, ou à python3, mais j'avais besoin de lancer le cadre sur une chaîne pour que cela fonctionne pour moi, comme ça:
sys.stdout.write(str(frame.tostring()))