人工智能 2026 用程序保存监控摄像头rtsp的图片和视频
当我们安装监控摄像头时,我们可以选择使用厂家提供的录像机作为监控的工具,但如果动一点编程,我们也可以通过rtsp通过我们的计算机直接连接摄像头,把影像或者图片保存到我们的计算机上。如果你还会一点人工智能的编程技能,那通过摄像头的影响来监控你感兴趣的目标对象,那会更加好玩,但我们这篇文章先不讨论人工智能,我们先确保影响能被计算机保存下来。
RTSP简介
Real Time Streaming Protocol,RTSP,中文叫实时流协议,是一种网络应用协议,专为娱乐和通信系统的使用,以控制流媒体服务器。该协议用于创建和控制终端之间的媒体会话。媒体服务器的客户端发布VCR命令,例如播放,录制和暂停,以便于实时控制从服务器到客户端(视频点播)或从客户端到服务器(语音录音)的媒体流。
监控摄像头的RTSP
现在大部分的网络监控摄像头都支持RTSP的推流,你可以通过查看说明书,或者登录到摄像头的后台管理界面,找到摄像头的推流RTSP URL,用户密码并启用它。当然,如果你启用了摄像头推流,记得修改一个密码,以免黑客通过扫描默认端口,获得了你的摄像头的控制权。
常见大厂的摄像头RTSP地址
海康威视
| 说明 | RTSP URL | 类型 | 备注 |
|---|---|---|---|
| 第1个通道的主码流 | rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101 | 摄像头 | 新款 |
| 第1个通道的子码流 | rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/102 | 摄像头 | 新款 |
| 多播取流 | rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101?transportmode=multicast | 摄像头/录像机 | |
| 第1个通道的主码流 | rtsp://{user}:{pwd@{host}:{port}/{videotype}/ch1/main/av_stream | 摄像头 | 旧型号摄像头(2012年之前的设备) |
| 第1个通道的子码流 | rtsp://{user}:{pwd@{host}:{port}/videotype}/ch1/sub/av_stream | 摄像头 | 旧型号摄像头(2012年之前的设备) |
说明 user: 用户名。例如: admin。 pwd: 密码。例如: 888888(默认)。 ip: 为设备IP。例如 10.7.8.122。 port: 端口号默认为554,若为默认可不填写。 channel: 通道号,新款格式是N01,N02,N代表通道,例如901;旧款的chN,N代表通道,例如:ch2 subtype: 码流类型,主码流为101(新款)或 main,子码流为102,或者sub
大华
| 说明 | RTSP URL | 类型 |
|---|---|---|
| 第1个通道的主码流 | rtsp://{user}:{pwd}@{ip}:{port}/cam/realmonitor?channel=1&subtype=0 | 摄像头 |
| 第1个通道的辅码流 | rtsp://{user}:{pwd}@{ip}:{port}/cam/realmonitor?channel=1&subtype=1 | 摄像头 |
说明 user: 用户名。例如: admin。 pwd: 密码。例如: 888888(默认)。 ip: 为设备IP。例如 10.7.8.122。 port: 端口号默认为554,若为默认可不填写。 channel: 通道号,起始为1。例如通道2,则为channel=2。 subtype: 码流类型,主码流为0(即subtype=0),辅码流为1(即subtype=1)。
使用Python程序来保存图片或视频片段
准备
先安装ffmpeg工具
sudo apt install ffmpeg
保存图片
下面程序可以保存一张图片,文件名为img001.jpg,如果需要保存多张图片,可以把cap_count改成大于1。
import os
user = '>>'
pwd = '>'
host = '>>'
port = 554
img_files = 'img%03d.jpg'
cap_count = 1
url = "rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101".format(user=user, pwd=pwd, host=host, port=port)
cmd = "ffmpeg -rtsp_transport tcp -y -i \"{url}\" -vframes {cap_count} {img_files}".format(url=url, cap_count=cap_count, img_files=img_files)
os.system(cmd)
保存视频
下面程序可以保存一段10秒视频,文件名为video.mp4,如果需要修改视频时长,可以把duration改成其他数字。
import os
user = '>>'
pwd = '>>'
host = '>>'
port = 554
duration = 10
video_files = 'video.mp4'
url = "rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101".format(user=user, pwd=pwd, host=host, port=port)
cmd = "ffmpeg -rtsp_transport tcp -y -t {duration} -i \"{url}\" -acodec copy -vcodec copy -hide_banner -loglevel error -an {video_files}".format(url=url, duration=duration, video_files=video_files)
os.system(cmd)
FFmpeg RTSP完整命令参考
下面整理了使用FFmpeg处理RTSP流时最常用的参数和命令格式。
核心参数说明
| 参数 | 说明 | 示例 |
|---|---|---|
-rtsp_transport | 指定传输协议 | tcp(推荐)或udp |
-i | 输入源 | RTSP URL |
-t | 录制时长(秒) | -t 30表示30秒 |
-vframes | 保存的帧数(图片数量) | -vframes 1保存一张图 |
-vcodec | 视频编码器 | copy(直接复制)或libx264 |
-acodec | 音频编码器 | copy或aac |
-an | 去掉音频 | 录像时不需要音频可加此参数 |
-y | 覆盖已有文件 | 不询问直接覆盖 |
-r | 帧率 | -r 1表示每秒1帧 |
-s | 分辨率 | -s 1280x720 |
FFmpeg RTSP常用命令模板
# 基础命令:从RTSP流截取一张图片
ffmpeg -rtsp_transport tcp -y -i "rtsp://user:pwd@ip:554/stream" -vframes 1 snapshot.jpg
# 录制10秒视频
ffmpeg -rtsp_transport tcp -y -t 10 -i "rtsp://user:pwd@ip:554/stream" -c copy output.mp4
# 以H.264重新编码并压缩(文件更小)
ffmpeg -rtsp_transport tcp -y -t 30 -i "rtsp://user:pwd@ip:554/stream" -vcodec libx264 -crf 23 compressed.mp4
# 截图并调整分辨率
ffmpeg -rtsp_transport tcp -y -i "rtsp://user:pwd@ip:554/stream" -vframes 1 -s 640x480 small.jpg
定时截图:使用Cron实现每隔N秒拍照
在实际监控应用中,我们经常需要每隔一段时间拍一张照片保存下来。
方法一:使用Linux Cron定时任务
创建一个截图脚本snapshot.sh:
#!/bin/bash
# snapshot.sh - 从RTSP流截取一张图片
USER='admin'
PWD='password'
HOST='192.168.1.100'
PORT=554
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="/home/user/snapshots"
mkdir -p "$OUTPUT_DIR"
URL="rtsp://${USER}:${PWD}@${HOST}:${PORT}/Streaming/Channels/101"
ffmpeg -rtsp_transport tcp -y -i "$URL" -vframes 1 "${OUTPUT_DIR}/snapshot_${TIMESTAMP}.jpg" 2>/dev/null
给脚本添加执行权限:
chmod +x snapshot.sh
编辑crontab,设置每分钟执行一次:
crontab -e
添加以下行:
# 每分钟从摄像头截取一张图片
* * * * * /home/user/snapshot.sh
如果只想在工作时间(9:00-18:00)截图:
# 周一到周五,9:00到18:00,每分钟截图
* 9-18 * * 1-5 /home/user/snapshot.sh
方法二:Python循环截图(更灵活)
import os
import time
from datetime import datetime
user = 'admin'
pwd = 'password'
host = '192.168.1.100'
port = 554
interval = 60 # 每60秒截图一次
output_dir = '/home/user/snapshots'
os.makedirs(output_dir, exist_ok=True)
url = f"rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101"
while True:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
output_file = f"{output_dir}/snapshot_{timestamp}.jpg"
cmd = f'ffmpeg -rtsp_transport tcp -y -i "{url}" -vframes 1 "{output_file}" 2>/dev/null'
os.system(cmd)
print(f"截图已保存: {output_file}")
time.sleep(interval)
录制指定时长的视频到MP4
上面的保存视频示例已经给出了基本用法,这里补充一些实用选项:
import os
user = 'admin'
pwd = 'password'
host = '192.168.1.100'
port = 554
url = f"rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101"
# 录制60秒视频,直接复制编码流(最快,文件较大)
cmd = f'ffmpeg -rtsp_transport tcp -y -t 60 -i "{url}" -c copy output_copy.mp4'
os.system(cmd)
# 录制60秒视频,使用H.264重新编码(压缩率高,文件较小)
cmd = f'ffmpeg -rtsp_transport tcp -y -t 60 -i "{url}" -vcodec libx264 -crf 23 output_compressed.mp4'
os.system(cmd)
# 录制并包含音频
cmd = f'ffmpeg -rtsp_transport tcp -y -t 60 -i "{url}" -c copy output_with_audio.mp4'
os.system(cmd)
# 分段录制(每小时一个文件,自动命名)
cmd = f'ffmpeg -rtsp_transport tcp -y -i "{url}" -c copy -f segment -segment_time 3600 -strftime 1 "recording_%Y%m%d_%H%M%S.mp4"'
os.system(cmd)
处理连接断开:自动重连
RTSP连接可能因为网络不稳定而中断,以下方法可以实现自动重连:
方法一:使用FFmpeg的-reconnect参数
ffmpeg -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5 \
-rtsp_transport tcp -i "rtsp://user:pwd@ip:554/stream" \
-c copy -f segment -segment_time 3600 output_%03d.mp4
方法二:Python自动重连脚本
import os
import time
import subprocess
user = 'admin'
pwd = 'password'
host = '192.168.1.100'
port = 554
url = f"rtsp://{user}:{pwd}@{host}:{port}/Streaming/Channels/101"
def record_with_reconnect(url, duration=3600, max_retries=5):
"""录制视频,断开后自动重连"""
retry_count = 0
while retry_count < max_retries:
output_file = f"recording_{int(time.time())}.mp4"
cmd = [
'ffmpeg', '-rtsp_transport', 'tcp',
'-y', '-t', str(duration),
'-i', url,
'-c', 'copy', '-an',
'-loglevel', 'error',
output_file
]
print(f"开始录制: {output_file} (尝试 {retry_count + 1}/{max_retries})")
result = subprocess.run(cmd)
if result.returncode == 0:
print("录制完成")
retry_count = 0 # 成功录制,重置重试计数
else:
retry_count += 1
wait_time = min(30, 5 * retry_count) # 递增等待时间
print(f"录制失败,{wait_time}秒后重试...")
time.sleep(wait_time)
print("已达最大重试次数,停止录制")
# 每小时录制一段,断开自动重连
while True:
record_with_reconnect(url, duration=3600)
批量处理多个摄像头
如果你有多个摄像头需要同时录制或截图,可以编写批量处理脚本:
import os
import subprocess
from datetime import datetime
# 摄像头配置列表
cameras = [
{
'name': 'front_door',
'url': 'rtsp://admin:pwd@192.168.1.100:554/Streaming/Channels/101'
},
{
'name': 'backyard',
'url': 'rtsp://admin:pwd@192.168.1.101:554/Streaming/Channels/101'
},
{
'name': 'garage',
'url': 'rtsp://admin:pwd@192.168.1.102:554/Streaming/Channels/101'
}
]
output_dir = '/home/user/multi_camera'
def snapshot_all_cameras():
"""对所有摄像头同时截图"""
os.makedirs(output_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
processes = []
for cam in cameras:
output_file = f"{output_dir}/{cam['name']}_{timestamp}.jpg"
cmd = [
'ffmpeg', '-rtsp_transport', 'tcp',
'-y', '-i', cam['url'],
'-vframes', '1',
'-loglevel', 'error',
output_file
]
# 使用subprocess.Popen实现并行截图
p = subprocess.Popen(cmd)
processes.append((cam['name'], p))
# 等待所有截图完成
for name, p in processes:
p.wait()
print(f"{name} 截图完成")
def record_all_cameras(duration=60):
"""对所有摄像头同时录制"""
os.makedirs(output_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
processes = []
for cam in cameras:
output_file = f"{output_dir}/{cam['name']}_{timestamp}.mp4"
cmd = [
'ffmpeg', '-rtsp_transport', 'tcp',
'-y', '-t', str(duration),
'-i', cam['url'],
'-c', 'copy', '-an',
'-loglevel', 'error',
output_file
]
p = subprocess.Popen(cmd)
processes.append((cam['name'], p))
print(f"开始录制 {name}")
for name, p in processes:
p.wait()
print(f"{name} 录制完成")
# 执行批量截图
snapshot_all_cameras()
常见错误及解决方案
错误1:Connection timed out(连接超时)
原因:网络不通或摄像头未启用RTSP,或者使用了UDP传输模式被防火墙拦截。
解决方案:
# 使用TCP传输代替UDP
ffmpeg -rtsp_transport tcp -i "rtsp://..."
# 增加超时时间
ffmpeg -rtsp_transport tcp -stimeout 10000000 -i "rtsp://..."
错误2:Protocol not found(协议未找到)
原因:FFmpeg编译时未包含RTSP支持。
解决方案:
# 检查FFmpeg是否支持RTSP
ffmpeg -protocols | grep rtsp
# 如果不支持,需要重新编译FFmpeg或安装完整版本
sudo apt install ffmpeg # 使用包管理器安装通常包含RTSP支持
错误3:Invalid data found when processing input(输入数据无效)
原因:摄像头编码格式与FFmpeg不兼容,或者码流类型不对(主码流vs子码流)。
解决方案:
# 先查看摄像头的视频流信息
ffprobe -rtsp_transport tcp -i "rtsp://user:pwd@ip:554/stream"
# 尝试使用子码流(通常兼容性更好)
# 海康:将101改102,大华:将subtype=0改subtype=1
错误4:Output file does not contain any stream(输出文件无内容)
原因:摄像头推流了但FFmpeg未能正确解码。
解决方案:
# 添加-an去掉音频(某些摄像头音频编码不支持)
ffmpeg -rtsp_transport tcp -y -t 10 -i "rtsp://..." -c copy -an output.mp4
# 强制指定输入格式
ffmpeg -rtsp_transport tcp -f rtsp -i "rtsp://..." -c copy output.mp4
错误5:录制文件无法播放
原因:录制过程中程序被强制杀死,MP4文件没有写入moov atom(文件索引信息)。
解决方案:
# 方法一:使用-movflags +faststart或-movflags +frag_keyframe+empty_moov
ffmpeg -rtsp_transport tcp -y -i "rtsp://..." -c copy -movflags +faststart output.mp4
# 方法二:录制为MKV格式(MKV对中断更友好)
ffmpeg -rtsp_transport tcp -y -i "rtsp://..." -c copy output.mkv
# 方法三:使用ts格式(适合流式录制)
ffmpeg -rtsp_transport tcp -y -i "rtsp://..." -c copy output.ts
希望这些补充内容能帮助你更灵活地使用FFmpeg处理RTSP监控摄像头的视频流!