我想知道是否可以使用 Python 中的 OpenCV
VideoWriter
类“流式传输”数据?
通常,为了处理内存中本来会写入磁盘的数据,我使用 BytesIO(或 StringIO)。
我尝试使用 BytesIO 但失败了:
import cv2
from io import BytesIO
stream = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc('x264')
data = BytesIO()
# added these to try to make data appear more like a string
data.name = 'stream.{}'.format('av1')
data.__str__ = lambda x: x.name
try:
video = cv2.VideoWriter(data, fourcc=fourcc, fps=30., frameSize=(640, 480))
start = data.tell()
# Check if camera opened successfully
if (stream.isOpened() == False):
print("Unable to read camera feed", file=sys.stderr)
exit(1)
# record loop
while True:
_, frame = stream.read()
video.write(frame)
data.seek(start)
# do stuff with frame bytes
# ...
data.seek(start)
finally:
try:
video.release()
except:
pass
finally:
stream.release()
但是,我最终没有编写
BytesIO
对象,而是收到以下消息:
Traceback (most recent call last):
File "video_server.py", line 54, in talk_to_client
video = cv2.VideoWriter(data, fourcc=fourcc, fps=fps, frameSize=(width, height))
TypeError: Required argument 'apiPreference' (pos 2) not found
...因此,当我将 VideoWriter 调用修改为
cv2.VideoWriter(data, apiPreference=0, fourcc=fourcc, fps=30., frameSize=(640, 480))
(我读到 0 表示自动,但我也尝试过 cv2.CAP_FFMPEG
)时,我反而收到以下错误:
Traceback (most recent call last):
File "video_server.py", line 54, in talk_to_client
video = cv2.VideoWriter(data, apiPreference=0, fourcc=fourcc, fps=fps, frameSize=(width, height))
TypeError: bad argument type for built-in operation
所以我的问题是,是否可以使用内存中的
cv2.VideoWriter
类编写编码视频,如果可以的话,是如何完成的?
此时我还没有什么想法,所以非常欢迎任何帮助:-)
不幸的是,OpenCV 不支持对内存进行编码(或解码)。您必须写入(或读取)磁盘,VideoWriter(或 VideoCapture)才能工作。
如果您想方便地加载内存中已存在的视频,请使用临时文件:https://docs.python.org/3/library/tempfile.html#tempfile.NamedTemporaryFile
import tempfile
import cv2
my_video_bytes = download_video_in_memory()
with tempfile.NamedTemporaryFile() as temp:
temp.write(my_video_bytes)
video_stream = cv2.VideoCapture(temp.name)
# do your stuff.
不幸的是,这仍然会在磁盘上创建一个文件。但是,嘿,至少你不必自己管理。有一个 SpooledTemporaryFile()
实现将保留在内存中,但不幸的是,它不会创建 OpenCV 可以引用的文件系统名称。
编辑更新:进一步探索 Linux 界面,看起来您可以通过使用
tmpfs
在 Ubuntu 机器上测试,未指定
dir
的 NamedTemporaryFile() 对象将遵循 TMPDIR(它恰好指向我机器上的 /tmp
。现在,不确定其他操作系统,但我的机器没有
/tmp
安装在主分区上。
但是,创建自己的“内存文件系统”非常简单,如下所示:
tmpfs
如果我们检查 sudo mount -t tmpfs -o size=1G tmpfs my_folder
的输出,我会看到:
df my_folder -h
真他妈邪恶!!现在如果我在 Python 中执行此操作:
Filesystem Size Used Avail Use% Mounted on
tmpfs 1.0G 0 1.0G 0% my_folder
我刚刚在 Linux 中使用
with tempfile.NamedTemporaryFile(dir="my_folder") as temp:
mkstemp
无论如何都会利用交换空间将文件放在磁盘上。编辑更新
Kubernetes 还允许您直接在 Pod 或 Deployment 上执行此操作。因此,您可以直接在容器的文件系统上创建一个 TMPFS 目录,然后就可以开始了!
tmpfs
编辑完整更新
使用
volumes:
- name: data
emptyDir:
medium: Memory
sizeLimit: 64Mi
volumeMounts:
- mountPath: /tmp/data
name: data
或 cv2.VideoWriter
cv2.VideoCapture
和
shmsrc
在内存中流式传输视频。https://gstreamer.freedesktop.org/documentation/shm/shmsink.html?gi-language=c
整个教程系列必须涵盖 GStreamer,但只需搜索 Gstreamer+Opencv 示例,您就会明白。如果您使用Linux,您可以创建一个ramdisk并对其进行写入。
shmsink