4. 车载视频循环覆盖存储策略

任务目标

实现一个车载视频循环覆盖存储管理器:当新片段写入导致总占用超过容量上限时,按录制时间从旧到新删除已有片段,直到腾出足够空间,保证录像持续写入不中断。

核心设计

  • 每个片段记录:文件名、大小(字节)、录制起始时间戳。
  • 写入前先检查剩余空间;不足则循环删除最旧片段,直到空间足够。
  • 若单个新片段大于总容量,直接拒绝写入并返回失败,避免死循环。
  • 删除顺序严格按时间戳升序(最旧优先),与文件名无关。
循环覆盖写入流程 请求写入新片段 剩余空间是否足够? used + size ≤ capacity 删除最旧片段 按时间戳升序 写入成功 否 是 删除后重新检查 空间足够

完整实现(Python)

import os
import time
from dataclasses import dataclass, field

@dataclass
class Clip:
    name: str
    size: int          # 字节
    start_ts: float    # 录制起始时间戳

class CircularStorage:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.clips: list[Clip] = []

    @property
    def used(self) -> int:
        return sum(c.size for c in self.clips)

    def _oldest(self) -> Clip:
        return min(self.clips, key=lambda c: c.start_ts)

    def write(self, name: str, size: int, start_ts: float | None = None) -> bool:
        if size > self.capacity:
            print(f"[拒绝] {name} 大小 {size} 超过总容量 {self.capacity}")
            return False
        start_ts = time.time() if start_ts is None else start_ts
        while self.used + size > self.capacity:
            victim = self._oldest()
            self.clips.remove(victim)
            print(f"[覆盖] 删除最旧片段 {victim.name} ({victim.size} 字节)")
        self.clips.append(Clip(name, size, start_ts))
        print(f"[写入] {name} 成功,当前占用 {self.used}/{self.capacity}")
        return True

    def status(self) -> str:
        order = sorted(self.clips, key=lambda c: c.start_ts)
        return " | ".join(f"{c.name}({c.size})" for c in order) or "(空)"

if __name__ == "__main__":
    store = CircularStorage(capacity=1000)
    store.write("clip_01.mp4", 400, start_ts=1)
    store.write("clip_02.mp4", 400, start_ts=2)
    store.write("clip_03.mp4", 400, start_ts=3)   # 触发覆盖,删除 clip_01
    store.write("clip_04.mp4", 900, start_ts=4)   # 触发覆盖,删除 clip_02、clip_03
    store.write("clip_05.mp4", 1200, start_ts=5)  # 超过总容量,拒绝
    print("最终片段顺序:", store.status())

运行与验证

python circular_storage.py

观察输出并核对以下判定条件:

  • 写入 clip_03 时,因 400+400+400 > 1000,应删除最旧的 clip_01,剩余 clip_02、clip_03。
  • 写入 clip_04(900 字节)时,需连续删除 clip_02、clip_03 才能腾出空间,最终只剩 clip_04。
  • 写入 clip_05(1200 字节)时,因单片段超过总容量 1000,应返回 False 并打印拒绝信息,不删除任何已有片段。
  • 最终 status() 输出应为 clip_04.mp4(900),且写入过程从未因空间不足而中断。

落地要点

  • 真实车载场景中,size 与 start_ts 由录像模块在片段封口时提供,删除动作需同步调用文件系统 os.remove,本示例聚焦策略逻辑,未接入真实文件 IO。
  • 若需持久化,可在每次写入/删除后把 clips 序列化到索引文件,重启时恢复,避免重新扫描目录。
  • 容量上限建议预留少量余量(如 95%),防止文件系统元数据或索引占用导致写入失败。