彻底解决RTSP-Simple-Server中recordDeleteAfter参数失效问题

彻底解决RTSP-Simple-Server中recordDeleteAfter参数失效问题

【免费下载链接】mediamtx 【免费下载链接】mediamtx 项目地址: https://gitcode.com/gh_mirrors/med/mediamtx

你是否在使用RTSP-Simple-Server(MediaMTX)时遇到录像文件无法自动删除的问题?设置了recordDeleteAfter: 24h却发现磁盘空间持续增长?本文将从配置解析、源码分析到解决方案,帮你彻底解决这一棘手问题,确保录像文件按时清理,避免磁盘空间耗尽。

问题现象与影响

当在mediamtx.yml中配置录像自动删除参数后:

pathDefaults:
  record: yes
  recordDeleteAfter: 24h  # 期望24小时后自动删除
  recordPath: ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f

实际运行中可能出现以下问题:

  • 超过24小时的录像文件依然存在
  • 磁盘空间持续增长直至满溢
  • 系统日志未显示删除操作记录

这一问题在安防监控、直播回放等长时间运行场景中影响尤为严重,可能导致服务中断和数据丢失风险。

配置参数深度解析

要理解参数失效的原因,首先需要正确配置相关参数。mediamtx.yml中与录像删除相关的核心配置如下:

参数类型默认值说明
recordboolno是否开启录像功能
recordDeleteAfterduration0s录像保留时间,0s表示不自动删除
recordPathstring./recordings/%path/%Y-%m-%d_%H-%M-%S-%f录像文件路径模板
recordSegmentDurationduration1h单个录像片段时长

关键注意事项

  1. recordDeleteAfter仅在record: yes时生效
  2. 时间格式需符合Go语言的time.Duration规范(如30m2h1d
  3. 路径模板中的时间变量必须正确设置,否则清理机制无法识别文件创建时间

源码层面深度分析

通过分析internal/record/cleaner.go中的清理逻辑,我们发现几个可能导致参数失效的关键因素:

1. 路径解析机制

清理器通过CommonPath函数计算文件路径的公共前缀:

// 计算所有录像片段的公共路径
func CommonPath(v string) string {
    common := ""
    remaining := v
    // 代码逻辑见[internal/record/path.go](https://link.gitcode.com/i/0690bb17c2aa2216a9f925f879adb77f)
}

如果recordPath中包含动态变量(如%f微秒级时间戳),可能导致CommonPath计算错误,使清理器无法定位到需要删除的文件。

2. 时间比较逻辑

清理器通过以下代码判断文件是否过期:

now := timeNow()
if now.Sub(pa.Start) > e.DeleteAfter {
    c.Log(logger.Debug, "removing %s", fpath)
    os.Remove(fpath)  // 实际删除操作
}

这段代码存在两个潜在问题:

  • pa.Start是从文件名解析的创建时间,若文件名格式错误则无法正确解析
  • os.Remove调用未检查错误,可能因权限问题导致删除失败但无日志记录

3. 清理调度机制

清理器的运行周期由以下代码决定:

interval := 30 * 60 * time.Second  // 默认30分钟检查一次
for _, e := range c.Entries {
    if interval > (e.DeleteAfter / 2) {
        interval = e.DeleteAfter / 2  // 确保检查间隔小于保留时间的一半
    }
}

recordDeleteAfter设置为24小时时,检查间隔会自动调整为12小时,可能导致文件实际保留时间最长达36小时(24+12)。

解决方案与实施步骤

针对以上分析,我们提供三种解决方案,按实施复杂度递增:

方案一:配置优化(推荐)

通过调整mediamtx.yml配置解决大部分场景问题:

pathDefaults:
  record: yes
  recordDeleteAfter: 24h
  recordPath: ./recordings/%path/%Y-%m-%d_%H-%M  # 简化时间格式
  recordSegmentDuration: 1h  # 保持默认值但需与删除时间匹配

关键优化点

  • 简化recordPath中的时间变量,保留到分钟级别
  • 确保recordSegmentDuration小于recordDeleteAfter
  • 避免在路径中使用特殊字符和过多层级

方案二:外部清理脚本

当配置优化无法解决问题时,可使用外部定时任务:

#!/bin/bash
# 清理超过24小时的录像文件
find ./recordings -type f -mmin +1440 -delete
# 清理空目录
find ./recordings -type d -empty -delete

将此脚本添加到crontab:

0 */6 * * * /path/to/cleanup.sh >> /var/log/cleanup.log 2>&1

方案三:源码修改(高级)

修改internal/record/cleaner.go中的清理逻辑:

  1. 增强错误处理:
err := os.Remove(fpath)
if err != nil {
    c.Log(logger.Error, "failed to remove %s: %v", fpath, err)
}
  1. 添加目录清理逻辑:
// 检查目录是否为空
func isDirEmpty(name string) bool {
    f, err := os.Open(name)
    if err != nil {
        return false
    }
    defer f.Close()
    
    _, err = f.Readdirnames(1) // 读取一个条目
    return err == io.EOF       // 没有条目则为空
}

验证与监控

实施解决方案后,可通过以下方式验证效果:

  1. 日志监控:检查MediaMTX日志是否有删除记录
grep "removing" /path/to/mediamtx.log
  1. 文件检查:列出超过保留时间的文件
find ./recordings -type f -mmin +1440
  1. 性能监控:使用Prometheus监控录像文件数量和磁盘使用趋势

最佳实践与注意事项

为避免类似问题再次发生,建议遵循以下最佳实践:

  1. 路径配置:保持recordPath简洁,时间变量不超过3级(如年-月-日)
  2. 权限设置:确保MediaMTX进程对录像目录有读写权限
  3. 定期审计:每周检查一次录像目录结构和文件生命周期
  4. 版本管理:关注官方仓库更新,main.go中可能包含相关修复

通过以上方法,你应当能够彻底解决recordDeleteAfter参数失效问题。如果问题仍然存在,建议检查internal/record/path.go中的路径解析逻辑,或在官方GitHub仓库提交issue获取帮助。

附录:相关源码文件速查

【免费下载链接】mediamtx 【免费下载链接】mediamtx 项目地址: https://gitcode.com/gh_mirrors/med/mediamtx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值