Python中如何处理镜像文件流?

背景

最近做毕设需要做用树莓派视频流式处理,copy 了一个 picamera 的[源码]( https://github.com/waveform80/pistreaming)(大致思路是树莓派录制原是视频流 yuv,用 ffmpeg 转成 mpeg1 喂给 jsmpeg)并改造到了 flask 里用,
直接用的效果挺好,前提是不加其他骚操作,但现在需要定时从摄像头提取画面,但这样会造成视频流丢帧
所以我就想到了将视频流复制出来,需要提取的时候就取一帧就好,

问题

现在的问题是被卡在了复制流上
尝试写出了这样的同步代码,但同样会造成丢帧
    将输入流写入多个文件流
class Mirror(object):
    def __init__(self, items):
        self.items = items
def write(self, b):
    for x in self.items:
        x.write(b)

def flush(self):
    for x in self.items:
        x.flush()

不知道还有没有什么好办法,python 基础不牢,请大佬们轻拍
ps:开线程的话会造成频繁删建线程,似乎会造成性能问题,SF 上看到的

Python中如何处理镜像文件流?

5 回复

那就线程池呗,提前开出来
量不大就塞内存里慢慢写


在Python中处理镜像文件流(比如Docker镜像的tar包),通常用tarfile模块来流式读取,避免把整个大文件加载到内存。下面是一个处理从网络下载的镜像文件流的例子:

import tarfile
import io
import requests

def process_image_stream(url):
    # 流式下载
    response = requests.get(url, stream=True)
    response.raise_for_status()
    
    # 创建类文件对象用于tarfile流式处理
    stream = io.BytesIO()
    for chunk in response.iter_content(chunk_size=8192):
        stream.write(chunk)
    stream.seek(0)  # 重置指针到开头
    
    # 流式读取tar文件
    with tarfile.open(fileobj=stream, mode='r|') as tar:
        for member in tar:
            if member.isfile():
                # 提取文件内容流
                file_obj = tar.extractfile(member)
                if file_obj:
                    content = file_obj.read()
                    # 在这里处理文件内容,比如分析镜像层
                    print(f"处理文件: {member.name}, 大小: {len(content)} 字节")
            # 可以跳过目录等非文件成员

# 使用示例(假设有个镜像tar的URL)
# process_image_stream('http://example.com/image.tar')

关键点:

  1. requests.get(stream=True)实现流式下载
  2. io.BytesIO作为内存缓冲区,避免写磁盘
  3. tarfile.open(fileobj=..., mode='r|')中的|模式支持流式解压
  4. 通过tar.extractfile()逐个获取文件内容流

如果是从本地文件流式处理,更简单:

with open('image.tar', 'rb') as f:
    with tarfile.open(fileobj=f, mode='r|') as tar:
        # 同样的处理逻辑

这样处理大镜像时内存占用稳定。用流式方式处理大文件。

picamera 有个从录制视频中提取一帧的方法 ,camera.capture(,这里啥参数我忘了)你查一下

感谢,虽然截取的质量低了一点,但能用就行,就是不知道为什么容易导致关闭不了摄像头,导致第二次启动的时候进程锁死,要重启才行,头疼
参数是use_video_port=True,给后来人

时隔几天回来补充一下
如果捕获图片时用 use_video_port=True 参数并没有什么好处,而且因为会请求视频端口的原因,很容易造成错误退出时不能正常关闭视频端口,下一次启动的时候就锁死进程,重启才能释放.
直接捕获反而不会有这问题,
The general idea here is that the capture (still) port operates on its own, while the video port is always connected to a splitter component, so requests for a video port also have to specify which splitter port they want to use.
源代码里的原话
这坑里有屎

回到顶部