彻底解决RTSP-Simple-Server中recordDeleteAfter参数失效问题
【免费下载链接】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中与录像删除相关的核心配置如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| record | bool | no | 是否开启录像功能 |
| recordDeleteAfter | duration | 0s | 录像保留时间,0s表示不自动删除 |
| recordPath | string | ./recordings/%path/%Y-%m-%d_%H-%M-%S-%f | 录像文件路径模板 |
| recordSegmentDuration | duration | 1h | 单个录像片段时长 |
关键注意事项:
recordDeleteAfter仅在record: yes时生效- 时间格式需符合Go语言的
time.Duration规范(如30m、2h、1d) - 路径模板中的时间变量必须正确设置,否则清理机制无法识别文件创建时间
源码层面深度分析
通过分析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中的清理逻辑:
- 增强错误处理:
err := os.Remove(fpath)
if err != nil {
c.Log(logger.Error, "failed to remove %s: %v", fpath, err)
}
- 添加目录清理逻辑:
// 检查目录是否为空
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 // 没有条目则为空
}
验证与监控
实施解决方案后,可通过以下方式验证效果:
- 日志监控:检查MediaMTX日志是否有删除记录
grep "removing" /path/to/mediamtx.log
- 文件检查:列出超过保留时间的文件
find ./recordings -type f -mmin +1440
- 性能监控:使用Prometheus监控录像文件数量和磁盘使用趋势
最佳实践与注意事项
为避免类似问题再次发生,建议遵循以下最佳实践:
- 路径配置:保持
recordPath简洁,时间变量不超过3级(如年-月-日) - 权限设置:确保MediaMTX进程对录像目录有读写权限
- 定期审计:每周检查一次录像目录结构和文件生命周期
- 版本管理:关注官方仓库更新,main.go中可能包含相关修复
通过以上方法,你应当能够彻底解决recordDeleteAfter参数失效问题。如果问题仍然存在,建议检查internal/record/path.go中的路径解析逻辑,或在官方GitHub仓库提交issue获取帮助。
附录:相关源码文件速查
- 主配置文件:mediamtx.yml
- 清理器实现:internal/record/cleaner.go
- 路径处理逻辑:internal/record/path.go
- 录像格式接口:internal/record/format.go
- 主程序入口:main.go
【免费下载链接】mediamtx 项目地址: https://gitcode.com/gh_mirrors/med/mediamtx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



