Передайте необработанные изображения OpenCV в FFmpeg
Вот довольно простой пример чтения веб-камеры с использованием привязок Python в 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() )
Теперь я хочу передать вывод в ffmpeg как в:
$ python capture.py | ffmpeg -f image2pipe -pix_fmt bgr8 -i - -s 640x480 foo.avi
К сожалению, я не могу понять магическое заклинание ffmpeg совершенно верно, и это не с
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 Выведите #0, avi, в out.avi: Поток № 0.0: Видео: flv, yuv420p, 640x480, q=2-31, 19660 кбит / с, 90 тыс. Тбн, 30 тбк [image2pipe @ 0x1508640]max_analyze_duration достигнут [image2pipe @ 0x1508640] Оценка длительности по битрейту, это может быть неточно Введите #0, image2pipe, из 'pipe:': Продолжительность: N/A, битрейт: N / A Поток № 0.0: Видео: 0x0000, bgr8, 25 кадров в секунду, 25 тбр, 25 тбн, 25 тбк swScaler: 0x0 -> 640x480 - неверное измерение масштабирования
- Захваченные кадры определенно 640x480.
- Я почти уверен, что порядок пикселей для типа изображения OpenCV (IplImage) составляет GBR, один байт на канал. По крайней мере, это то, что, кажется, сходит с камеры.
Я не гуру ффмпег. Кто-нибудь сделал это успешно?
5 ответов
Взял кучу возни, но я понял это с помощью демодулятора rawvideo FFmpeg:
python capture.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - foo.avi
Поскольку в необработанном видео нет заголовка, указывающего предполагаемые параметры видео, пользователь должен указать их, чтобы иметь возможность правильно декодировать данные:
-framerate
Установите входную частоту кадров видео. Значение по умолчанию 25.-pixel_format
Установите формат входного видео в пикселях. Значением по умолчанию является yuv420p.-video_size
Установите размер входного видео. По умолчанию нет, поэтому это значение должно быть указано явно.
И вот что-то лишнее для опытных пользователей. То же самое, но с использованием VLC для потоковой передачи живого вывода в Интернет, формат 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}"
Редактировать: создать веб-поток, используя ffmpeg и ffserver
python capture.py | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 640x480 -framerate 25 -i - http://localhost:8090/feed1.ffm
Я в последнее время, но мой мощный VidGear
Библиотека Python автоматизирует процесс конвейеризации кадров OpenCV в FFmpeg на любой платформе. Вот основной пример 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
Источник: https://github.com/abhiTronix/vidgear/wiki/Compression-Mode:-FFmpeg
Вы можете проверить VidGear Docs для более продвинутых приложений и функций.
Надеюсь, это поможет!
Не уверен, что это зависит от Mac OS или python3, но мне нужно было привести кадр к строке, чтобы это работало для меня, вот так:
sys.stdout.write(str(frame.tostring()))
Мне потребовался час, чтобы понять, что по умолчанию каналы Windows не являются двоичными. Это приводит к тому, что некоторые байты (в частности, новые строки) изменяются / опускаются, и результирующее видео медленно смещается, потому что размер кадра не является постоянным.
Чтобы обойти это, модифицированный файл 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() )
Чтобы проверить успешность передачи необработанного видео, используйте ffplay. Убедитесь, что вы указали более высокую частоту кадров, чем то, что исходит из канала, иначе видео начнет отставать
python videoCapture.py | ffplay -f rawvideo -pix_fmt bgr24 -s 640x480 -framerate 40 -i -
Если вы передаете кадры bgr8 OpenCV, вам все равно нужно установить-pix_fmt bgr24
в канале FFmpeg.