相关文章推荐
严肃的西装  ·  java - ...·  1 年前    · 
沉稳的杨桃  ·  Corrupted file and ...·  1 年前    · 

用OpenCV VideoWriter和Python BytesIO在内存中串流视频

8 人关注

我想知道是否有可能在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:
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 类来写编码视频,如果可以的话,是怎么写的?

在这一点上,我没有什么想法,所以任何帮助都是非常受欢迎的 :-)

1 个评论
你是想对视频进行编码而不写入磁盘吗?这在OpenCV中是不可能的。
python
opencv
video-streaming
cv2
in-memory
Liam Deacon
Liam Deacon
发布于 2018-06-27
3 个回答
Farhan
Farhan
发布于 2021-11-01
已采纳
0 人赞同

不幸的是,OpenCV并不支持向内存编码(或从内存解码)。你必须写到磁盘上(或从磁盘上读出),VideoWriter(或VideoCapture)才能工作。

我担心是这种情况。我想在通过网络传输之前对视频进行编码,以减少发送的数据量,但我试图绕过必须将数据写入磁盘的问题......。我想我将退回到通过网络发送单个图像。
是的,不幸的是OpenCV不支持这个功能,因为我确信它将被大量使用。
VocoJax
VocoJax
发布于 2021-11-01
0 人赞同

如果你想要一些方便来加载一个已经在内存中的视频,可以使用一个临时文件 :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 。现在,不确定其他操作系统的情况,但我的机器没有将/tmptmpfs 。它被安装在主分区上。

但是,像这样创建你自己的 "内存文件系统 "是超级容易的。sudo mount -t tmpfs -o size=1G tmpfs my_folder

如果我们检查df my_folder -h 的输出,我看到这个。

Filesystem      Size  Used Avail Use% Mounted on
tmpfs           1.0G     0  1.0G   0% my_folder

糟糕透顶!!!所以现在如果我在Python中这样做的话,我就可以看到这个文件系统。

所以现在如果我在Python中这样做。

with tempfile.NamedTemporaryFile(dir="my_folder") as temp:

我刚刚在linux中用mkstemp ,在一个完全在内存中的文件系统中创建了一个临时文件。当然,我确实需要把数据从我的Python的内存中复制到另一个内存位置。但是,嘿,在大文件上,这可能比写到磁盘上更便宜。