ffmpeg - 如何根据触发器缓冲和捕获 RTSP 流到磁盘?

标签 ffmpeg raspberry-pi gstreamer rtsp live555

我想我要问的问题类似于这篇关于如何捕捉雷击的 ffmpeg 帖子(https://trac.ffmpeg.org/wiki/Capture/Lightning)。
我有一个带有 RTSP 上的 IP 摄像头的 Raspberry Pi,我想知道的是如何保持连续 5 秒的实时视频缓冲区,直到我触发一个“保存”命令,该命令会将 5 秒的缓冲区通过管道传输到磁盘,然后继续将实时视频流式传输到磁盘,直到我将其关闭。
本质上,Pi 启动,这个神奇的黑盒进程开始并将实时视频保存到一个固定大小的 5 秒缓冲区,然后假设一个小时后 - 我单击一个按钮,它会将 5 秒缓冲区刷新到磁盘上的文件并继续将视频传输到磁盘,直到我单击取消。
在我的环境中,我可以使用 ffmpeg、gstreamer 或 openRTSP。对于其中的每一个,我都可以连接到我的 RTSP 流并将其保存到磁盘,但我不确定如何创建这个永远存在的 5 秒缓存。
我觉得 gstreamer 文档在这里暗示它( https://gstreamer.freedesktop.org/documentation/application-development/advanced/buffering.html?gi-language=c ),但我想我只是不明白缓冲如何适应触发保存。从那篇文章中,我得到的印象是视频的结束时间是提前知道的(我想我可以人为地限制我的)。
我无法对文件进行后处理,因此使用 openRTSP 之类的东西,保存一大堆视频片段,然后合并它们并不是一个真正的选择。
注意:成功保存后,我不需要再保存一分钟左右的视频,这样 5 秒的缓存就有足够的时间在下一次之前填满
这是我发现的最接近的类似问题:https://video.stackexchange.com/questions/18514/ffmpeg-buffered-recording

最佳答案

嘿,
我不知道你是否有关于 python 的知识,但是有一个名为 pyav 的库,它是一个用于 ffmpeg 的精美 python 包装器/接口(interface)。
在那里,您可以从 RTSP 源中读取帧并根据需要处理这些帧。
这只是关于你所描述的想法/黑客实现,你需要设计你的帧缓冲区。当您知道您从相机获得 25 FPS 时,您可以将队列大小限制为 125。

import av
import time
import queue
from threading import Thread, Event


class LightingRecorder(Thread):

    def __init__(self, source: str = ""):
        Thread.__init__(self)
        self.source = source
        self.av_instance = None
        self.connected = False
        self.frame_buffer = queue.Queue()
        self.record_event = Event()

    def open_rtsp_stream(self):
        try:
            self.av_instance = av.open(self.source, 'r')
            self.connected = True
            print ("Connected")
        except av.error.HTTPUnauthorizedError:
            print ("aHTTPUnauthorizedError")
        except Exception as Error:
            # Catch other pyav errors if you want, just for example
            print (Error)

    def run(self):
        self.open_rtsp_stream()

        while 1:
            if self.connected:
                for packet in self.av_instance.demux():
                    for frame in packet.decode():
                        if packet.stream.type == 'video':
                            # TODO:
                            # Handle clearing of Framebuffer, remove frames that are older as a specific timestamp
                            # Or calculate FPS per seconds and store that many frames on framebuffer
                            print ("Add Frame to framebuffer", frame)
                            self.frame_buffer.put(frame)

                        if self.record_event.is_set():
                            [frame.to_image().save('frame-%04d.jpg' % frame.index) for frame in self.frame_buffer]
            else:
                time.sleep(10)

LightingRecorder(source='rtsp://root:pass@192.168.1.197/axis-media/media.amp').start()

关于ffmpeg - 如何根据触发器缓冲和捕获 RTSP 流到磁盘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72453124/

相关文章:

c# - 视频文件未在 C# 中使用 FFMpeg 进行修剪和复制

linux - Shell 脚本段错误 - AWS

c++ - GCC 中树莓派的交叉编译。从哪儿开始?

c++ - 将图像插入 gstreamer 管道

c++ - Gstreamer RTSP 解码帧时间戳

audio - FFMPEG 比特率为 16Bit 用于音频转换

非英文字符的 FFMPEG 错误

ffmpeg - ffmpeg 中的 RFC 4175 支持?

linux - 树莓派 Arch Linux 上的 qemu 最新 sd 镜像

Python 类型错误 : 'TagList' object is not iterable