python linux opencv ffmpeg pipe

python - Pipetear imágenes OpenCV sin procesar a FFmpeg



linux (3)

Hizo un montón de manipulación, pero lo descubrí usando el demuxer de video sin procesar de FFmpeg:

python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi

Como no hay un encabezado en el video sin formato que especifique los parámetros de video asumidos, el usuario debe especificarlos para poder decodificar los datos correctamente:

  • -framerate Establece la velocidad de cuadro de video de entrada. El valor predeterminado es 25.
  • -pixel_format Establece el formato de píxeles de video de entrada. El valor predeterminado es yuv420p.
  • -video_size Configura el tamaño del video de entrada. No hay un valor predeterminado, por lo que este valor debe especificarse explícitamente.

Y aquí hay algo extra para los usuarios avanzados. Lo mismo pero usando VLC para transmitir la salida en vivo a la web, formato 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}"

Editar: crea una secuencia de webm usando ffmpeg y ffserver

python capture.py | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 640x480 -framerate 25 -i - http://localhost:8090/feed1.ffm

Aquí hay un ejemplo bastante sencillo de lectura de una cámara web utilizando enlaces de python de 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() )

Ahora quiero canalizar la salida a ffmpeg como en:

$ python capture.py | ffmpeg -f image2pipe -pix_fmt bgr8 -i - -s 640x480 foo.avi

Lamentablemente, no puedo obtener el hechizo mágico ffmpeg bastante bien y falla con

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

  • Los cuadros capturados son definitivamente 640x480.
  • Estoy bastante seguro de que el orden de píxeles para el tipo de imagen OpenCV (IplImage) es GBR, un byte por canal. Al menos, eso es lo que parece salir de la cámara.

No soy un gurú de ffmpeg. ¿Alguien ha hecho esto exitosamente?


Me llevó una hora descubrir que, de forma predeterminada, los conductos de Windows no son binarios. Esto ocasiona que algunos bytes (específicamente líneas nuevas) sean modificados / omitidos, y el video resultante se desplaza lentamente porque el tamaño del cuadro no es constante.

Para solucionar esto, el archivo de python modificado:

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

Para probar si la canalización del video en bruto es exitosa, use ffplay. Asegúrese de especificar una tasa de fotogramas mayor que la que proviene de la tubería, de lo contrario, el video comenzará a lag

python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -


No estoy seguro de si esto es específico de Mac OS, o específico de python3, pero necesitaba convertir el marco en una cadena para que esto funcione para mí, así:

sys.stdout.write(str(frame.tostring()))