ffmpeg 分段保存 rtsp 视频数据流
本帖最后由 qzhing 于 2022-6-19 11:34 编辑最近买了个某品牌的家用摄像头,但是数据云存储还要额外花钱
作为一个程序员怎能让它赚这个钱,于是乎拿出了吃灰已久的树莓派,挂了个脚本
使用 FFmpeg 按分钟存储文件,并上传到云服务器
以下展示 FFmpeg 相关的指令
> 以 `ffmpeg 5.0.1` 为例
详细文档见官网:(https://ffmpeg.org/ffmpeg-all.html)
> 参数示例
```bash
ffmpeg -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i rtsp://:@: -vcodec copy -acodec copy -f segment -reset_timestamps 1 -segment_atclocktime 1 -segment_time 60 -strftime 1 /outdir/%Y%m%d%H%M.mp4
```
> 参数格式
```
ffmpeg [全局设置] {[输入设置] -i 输入路径} ... {[输出设置] 输出路径} ...
```
> 部分参数介绍
参数 | 可选值 | 说明
--- | --- | ---
-use_wallclock_as_timestamps | 0<br>1 | 如果设置为1,则使用系统时间作为时间戳。<br>默认值为0。
-rtsp_transport | udp<br>tcp<br>udp_multicast<br>http | 设置 `rtsp` 传输协议<br>可以指定多个较低的传输协议,在这种情况下,它们一次尝试一个(如果一个设置失败,则尝试下一个)。<br>默认值为 `udp`
-vcodec || 设置视频编解码, `copy` 代表使用输入源的格式
-acodec || 设置音频编解码, `copy` 代表使用输入源的格式
-f || 强制输入或输出文件格式。 `segment` 代表分段
-reset_timestamps | 0<br>1 | 在每个段的开头重置时间戳,这样每个段将以接近零的时间戳开始。<br>默认为0。
-segment_atclocktime | 0<br>1 | 如果设置为“1”,则按从00:00开始的定时时钟间隔分割。<br>在 `segment_time` 中指定的时间值用于设置每段的长度
-segment_time || 每段时间的时长,单位:秒
-strftime | 0<br>1 | 使用 `strftime` 函数定义要写入的文件的名称。<br>如果选择此选项,输出段名称必须包含一个strftime函数模板。<br>默认值为0。
PS:该文档转载自自己的个人博客,这里就不放个人博客原文链接了 学习下,最近遇到一个问题:ffplay播放大华摄像头报404错误,VLC就可以正常播放,不知道怎么回事?有知道的大佬指教一下,先谢谢啦 不会丢包吗? Cool_Breeze 发表于 2022-6-19 13:24
不会丢包吗?
简单测试下来,偶尔会丢包或卡住
丢包还好,只会有一个一分钟的视频无法播放
卡住就比较尴尬,必须关闭掉进程(摄像头重新开机FFmpeg就会卡住)
所以我在定时任务脚本里面加了判定,没有新文件产生,就断定为卡住,关掉进程重新开 丢包吗? 个人博客发下 zxsbk 发表于 2022-6-19 14:54
个人博客发下
个人博客链接就不放了,根据论坛【编程语言区】总版规第七条规定,不能放
七、 严禁在帖子、源码中私留联系方式,推广链接、网址、广告、二维码等信息或则引导用户私聊和留下联系方式, 这个挺不错的 但是有时候会报错 qzhing 发表于 2022-6-19 14:37
简单测试下来,偶尔会丢包或卡住
丢包还好,只会有一个一分钟的视频无法播放
卡住就比较尴尬,必须关闭 ...
判定没有新文件产生 的脚本可以分享一下吗 本帖最后由 qzhing 于 2022-8-3 17:46 编辑
1e3e 发表于 2022-8-3 17:22
判定没有新文件产生 的脚本可以分享一下吗
注意一下IP和里面用到的工具
#!/bin/bash
# 获取结果
result=$(nmap -p 554 10.0.8.3 | grep 554 | awk '{print $2}')
# 获取进程
pid=$(ps aux | grep ffmpeg | grep -v grep | awk '{print $2}')
# 如果端口是开放的
if [ $result = "open" ]; then
# 获取当前时间
now=$(date "+%Y%m%d%H%M")
# 如果进程存在
if [ $pid ]; then
# 等待5秒
sleep 5
# 获取最新的文件名
filename=$(ls -la /work/camera/video | awk 'END {print}' | awk '{print $9}' | cut -b 1-12)
# 如果当前文件名和当前时间不相同,说明流卡住了
if [ $filename != $now ]; then
# 关闭进程并重新打开
kill -9 $pid
sleep 1
nohup /usr/local/ffmpeg/ffmpeg -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i rtsp://username:password@10.0.8.3:554 -vcodec copy -acodec copy -f segment -reset_timestamps 1 -segment_atclocktime 1 -segment_time 60 -strftime 1 /work/camera/video/%Y%m%d%H%M.mp4 >/work/camera/log/$now.log 2>&1 &
fi
# 否则进程不存在
else
# 开启进程
nohup /usr/local/ffmpeg/ffmpeg -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i rtsp://username:password@10.0.8.3:554 -vcodec copy -acodec copy -f segment -reset_timestamps 1 -segment_atclocktime 1 -segment_time 60 -strftime 1 /work/camera/video/%Y%m%d%H%M.mp4 >/work/camera/log/$now.log 2>&1 &
fi
# 删除旧文件
cd /work/camera/video/
# 获取文件夹大小
size=$(du -s | awk '{print $1}')
# 当文件夹大小超过40G
while [ $size -gt 41943040 ]
do
# 删除最上方的一个文件
rm -rf `ls -t | tail -n 1`
# 重新获取文件夹大小
size=$(du -s | awk '{print $1}')
done
# 如果端口关闭或不存在
else
# 如果进程仍未关闭
if [ $pid ]; then
# 关闭进程
kill -9 $pid
fi
fi
页:
[1]
2