Skip to content

About

将旧 Android 手机变为局域网监控摄像头,具备实时画面查看、运动检测报警、自动录像、后台保活等功能。 特点:完全本地运行,无需第三方云服务,免费且开源。

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

旧手机家用摄像头 —— 最终版需求文档

一、项目概述

将旧 Android 手机变为局域网监控摄像头,具备实时画面查看、运动检测报警、自动录像、连续录像、录像管理、后台保活等功能。特点:完全本地运行,无需第三方云服务,免费且开源。


二、核心功能清单

功能 状态 说明
实时视频流 (MJPEG) ✅ 已启用 通过浏览器查看,仅视频,无音频
摄像头切换(前后置) ✅ 已启用 设置中可选镜头朝向,分辨率列表随镜头动态枚举;无前置摄像头时自动回退后置
本机预览画面 ✅ 已启用 监控运行中主界面出现「预览画面」按钮,手机本机直接查看实时画面(含 HUD 状态信息)
运动检测 ✅ 已启用 画面变化时自动录像;报警由设置中「运动报警」开关统一控制(两种录像模式共享)
运动触发短视频录制 ✅ 已启用 检测到运动时自动录制指定时长 MP4(含音频),时长可配置(10秒~5分钟)
连续录像(按时间分段) ✅ 已启用 持续录制,可按配置的时长分段保存(1分钟~1小时)
录像模式切换 ✅ 已启用 主界面提供三档选择:连续录像 / 运动触发录像 / 仅预览(不录像不检测)
录像存储循环覆盖 ⚠️ 预留接口 连续录像启用后可通过设置自动清理旧文件
后台保活 ✅ 已启用 前台服务、唤醒锁、引导忽略电池优化
开机自启 ✅ 代码支持 部分手机需手动授权
控制界面 ✅ 已启用 主界面可监控状态、控制模式、开关推流
录像管理(文件夹/视频) ✅ 已启用 按日期分文件夹浏览、播放、搜索、多选删除、导出到外部存储
视频元数据显示 ✅ 已启用 列表显示文件名、大小、录制日期时间、视频时长
横屏推流 ✅ 已启用 推流画面强制横屏,与录像方向一致,无旋转虚影
Web 端查看页面 ✅ 已启用 http://手机IP:8080/ 提供 HTML 页面:状态指示、自动重连、画面旋转、缩放平移、全屏
画面旋转(前端) ✅ 已启用 查看页面支持 0°/90°/180°/270° 旋转,旋转时重置缩放和平移
画面缩放与平移 ✅ 已启用 双指捏合缩放(1x~5x)、单指拖动平移、双击切换;电脑端鼠标滚轮+拖动
全屏查看 ✅ 已启用 查看页面支持全屏模式,全屏时浮层按钮控制旋转和退出
连接状态指示 ✅ 已启用 四种状态:连接中(黄)/已连接(绿)/已断开(红)/推流关闭(灰),断线自动重连
存储异常提示 ✅ 已启用 磁盘写满录像失败时:通知栏提示 + 主界面「录像存储」红显并标注(已满),清理空间后自动恢复

三、界面说明与控件作用

1. 主界面 (MainActivity)

启动 App 后直接显示的界面,用于控制摄像头服务和查看运行状态。

  • IP 地址 (tvIpAddress)
    显示手机当前 Wi‑Fi 局域网的 IPv4 地址,例如 192.168.1.5。浏览器观看视频流时将使用此 IP 地址 + 端口 8080:访问 http://手机IP:8080/ 获取带状态指示和旋转/缩放/全屏功能的 HTML 查看页面(推荐手机端使用),或访问 http://手机IP:8080/video 直接获取 MJPEG 流(适合电脑端)。支持 HTTP 基本认证(用户名/密码在设置中配置)。

  • 服务状态 (tvStatus)
    显示当前监控服务是否在运行,颜色区分:

    • 绿色 “服务运行中”:摄像头正在工作,可推流和检测运动。此时状态文字右侧出现 「预览画面」按钮(需同时开启 MJPEG 推流),点击进入本机预览页面。

    • 红色 “服务已停止”:服务未启动,无法访问视频流。

  • 预览画面 (btnPreview)
    本机查看摄像头实时画面,仅服务运行中且 MJPEG 推流开启时显示(推流关闭时该按钮不出现)。点击进入 PreviewActivity,详见下文。

  • 当前摄像头 (tvCameraFacing)
    显示服务实际绑定的镜头朝向(“前置”或“后置”)。注意此处反映真实使用的摄像头:若配置了前置但设备没有前置摄像头,会自动回退并显示“后置”。服务停止时显示 当前摄像头: --。

  • 当前分辨率 (tvResolution)
    显示相机绑定后实际生效的推流分辨率(如 640x480)。该值来自 CameraX 绑定结果,经分辨率回退策略后可能与设置值不同(例如所选尺寸不被当前镜头支持时)。服务停止时显示 当前分辨率: --。

  • MJPEG 推流开关 (switchMjpeg)
    打开时:相机画面实时编码为 MJPEG 流,可在浏览器访问。关闭时:视频流停止,但相机仍在后台(运动检测和录像仍可能工作)。实时生效。

  • 录像模式选择(两个互斥 SwitchCompat)

    • 连续录像:开启后持续录制,并按设置的分段时长自动分割文件(默认 10 分钟一段)。

    • 运动触发录像:开启后仅当检测到运动时录制短视频,时长可在设置中调整(默认 10 秒)。

    • 两个开关不能同时打开,均不选时表示“仅预览”(不录像、不运动检测)。实时生效。

  • 录像存储 (tvStorage)
    显示当前所有录像文件占用的总磁盘空间(单位:MB),递归计算所有日期子文件夹内的 MP4 文件。每次回到主界面自动刷新。
    磁盘写满提示:录像因存储空间不足失败时,数值与单位变红并追加红色「(已满)」字样,同时通知栏提示「录像出错已停止」;此时推流与运动检测不受影响。清理空间(如删除录像)回到主界面后红显自动解除。

  • 实际帧率 (tvFps)
    与「录像存储」同一行显示在右侧,实时显示当前实际推流帧率(每秒更新一次)。服务停止时显示 帧率: -- fps。可用于判断设置的帧率与实际运行情况的差距。

  • 启动监控 (btnStart)
    点击后依次检查相机权限、录音权限、引导忽略电池优化,然后启动 CameraService 前台服务,通知栏显示“监控运行中”。

  • 停止监控 (btnStop)
    停止 CameraService,释放摄像头,推流和检测全部停止。

  • 查看录像 (btnViewRecordings)
    跳转到录像列表界面,按日期文件夹展示录像。

  • 设置按钮(右上角齿轮图标)
    跳转到 SettingsActivity,配置详细参数(分辨率、帧率、灵敏度、报警 URL、录像时长等)。


1.5 本机预览页面 (PreviewActivity)

监控手机本机查看摄像头实时画面,无需浏览器、无需认证。入口:主界面「预览画面」按钮。

  • 实现方式:进程内直接订阅服务编码循环产出的 JPEG 帧(与推流共用编码结果),不新增相机用例、不影响推流帧率与录像。解码限速 10fps("看一眼画面"足够),页面关闭即停止解码。

  • 顶部 HUD 信息栏(半透明黑底):

    • ● REC(红色):录像进行中才显示

    • 模式标签:连续录像 / 运动触发 / 仅预览

    • 实际接收帧率:预览页自行统计,每秒刷新

    • 存储剩余:每 10 秒刷新一次

    • 时间码(右上):每秒走秒,用于对照报警时间

  • 提示横幅(画面上方,琥珀色):

    • 当前为非监控时段(画面可能暂停)

    • 无画面(超 2.5 秒无帧:监控停止或推流关闭)

  • 查看期间屏幕保持常亮;底部居中显示「预览画面」装饰文字。


2. 录像列表界面 (RecordingsActivity)

点击主界面“查看录像”后进入,按日期文件夹(格式 yyyy-MM-dd)组织所有录像,每个文件夹显示包含的视频数量和总大小。

  • 普通模式

    • 顶部中央显示文件夹个数。

    • 点击任意文件夹进入该文件夹的视频列表页面 (VideoListActivity)。

    • 长按文件夹进入多选模式。

  • 多选模式

    • 顶部改为:左侧“全选”按钮,中央“已选 X 项”,右侧“取消”按钮。

    • 每个文件夹左侧出现复选框,可勾选多个文件夹。

    • 底部显示“删除选中”和“导出选中”按钮。

    • 点击“删除”会弹窗确认,递归删除文件夹内所有视频。

    • 点击“导出”通过系统文档树选择目标目录,递归复制文件夹及内容。

    • 按返回键退出多选模式。


3. 视频列表界面 (VideoListActivity)

展示单个日期文件夹内的所有 MP4 文件。

  • 顶部工具栏

    • 普通模式:左侧返回按钮,中央显示文件夹名,右侧显示文件总数。

    • 多选模式:左侧“全选”按钮,中央“已选 X 项”,右侧“取消”按钮,同时隐藏返回按钮和文件计数。

  • 搜索栏(始终显示)

    • 输入框 + 清除按钮(X) + 搜索按钮。

    • 输入文字时 X 出现,点击清空输入框并立即恢复全部视频列表(自动搜索空关键词)。

    • 输入框为空时点击 X 则隐藏键盘并失去焦点。

    • 点击搜索按钮或按键盘搜索键执行过滤(文件名包含关键词)。

  • 视频列表
    每一项显示:文件名、文件大小(自适应 KB/MB/GB 单位)、录制日期时间(从文件名解析或取文件修改时间)、视频时长(mm:ss 或 HH:mm:ss)。

    • 普通模式:短按播放视频,长按进入多选模式。

    • 多选模式:每个视频左侧出现复选框,顶部计数实时更新,底部显示“删除选中”和“导出选中”。

    • 删除视频时弹窗确认,支持批量删除。

    • 导出功能:选择外部文件夹后,将选中的视频文件复制到目标位置(支持 MediaStore 刷新)。

    • 按返回键退出多选模式。

  • 元数据异步加载
    首次进入或文件列表变化时,后台线程读取所有视频的时长(MediaMetadataRetriever)和日期时间,加载完成后刷新列表,避免 UI 阻塞。同时使用内存缓存避免重复解析。


4. 设置界面 (SettingsActivity)

  • 视频设置

    • 镜头选择(后置/前置;分辨率列表按所选镜头动态枚举;设备无前置摄像头时启动监控会自动回退后置)。

    • 推流分辨率(动态读取摄像头支持的分辨率列表,例如 640x480、1280x720 等)。

    • 推流帧率(1~30 fps,每秒平均策略,实际帧率取决于手机硬件性能)。

  • 运动检测设置

    • 动作识别灵敏度(0~100,数值越低越敏感)。

    • 报警静默期(秒),避免频繁发送报警。仅在报警成功送达(接收方返回 2xx)后才开始计时;发送失败不占用静默期,恢复后下一次运动立即再发。

    • 运动报警开关(默认关闭)。开启后检测到运动时向报警 URL 发送 POST 请求(JSON 数据包含事件类型与时间戳)。两种录像模式共享:连续录像模式下检测到运动只报警不触发录像;运动触发模式下控制是否发送报警。需先配置报警 URL 才能开启,URL 清空时开关自动关闭。

    • 报警接收 URL(须填写接收方实际处理的完整路径,如 http://192.168.1.100:3000/alert,仅到端口会因接收方无根路由而返回 404)。

  • 录像设置

    • 录像模式(连续/运动触发/仅预览)—— 与主界面开关同步。

    • 运动录像时长(10秒、30秒、1分钟、3分钟、5分钟)。

    • 连续录像分段时长(1分钟、5分钟、10分钟、30分钟、1小时)。

    • 注意:修改分段时长不会中断当前正在录制的片段,新设置对下一个片段生效。

  • 系统设置

    • 开机自启开关(保存到 SharedPreferences,由 BootReceiver 实现)。

    • 监控时间限制(可设置每日起止时间,非监控时段相机不分析也不录像)。

  • 安全设置

    • HTTP 认证用户名/密码(基本认证,保护 MJPEG 流)。

所有设置(除镜头朝向、分辨率、帧率需重启监控外)均实时生效,通过 RELOAD_CONFIG 广播通知 CameraService 更新行为。


5. Web 端查看页面

在手机启动监控服务后,同一 Wi‑Fi 下的任意设备(电脑、手机、平板)打开浏览器,访问 http://手机IP:8080/ 即可打开 HTML 查看页面。该页面提供以下功能:

  • 实时画面:通过 fetch Streaming API 直接读取 MJPEG 流并解析 JPEG 帧,帧率接近推流原生帧率(非低帧率快照轮询)。

  • 连接状态指示:顶部状态栏实时显示四种状态:

    • 🟡 连接中(黄色闪烁):页面刚打开或正在重连

    • 🟢 已连接(绿色):正常接收画面,同时显示实时 FPS

    • 🔴 已断开(红色闪烁):服务器不可达,自动尝试重连

    • ⚪ 推流已关闭(灰色):App 端已关闭 MJPEG 推流

  • 画面旋转:点击「旋转」按钮循环切换 0° → 90° → 180° → 270°,旋转时自动重置缩放和平移。适用于手机竖放但需要横屏观看的场景。

  • 画面缩放与平移:

    • 手机端:双指捏合/张开缩放(1x~5x),单指拖动平移(缩放大于 1x 时生效),双击切换 1x ↔ 2x

    • 电脑端:鼠标滚轮缩放,按住拖动平移,双击切换 1x ↔ 2x

    • 缩放回 1x 时自动重置平移位置

  • 全屏模式:点击「全屏」按钮进入全屏,顶部/底部栏隐藏,右上角浮层提供旋转和退出按钮。全屏和非全屏均可使用缩放平移。

  • 自动重连:流连接断开后自动重连,无需手动刷新页面。

  • 状态栏始终可见:放大画面被裁切在画面区域内,不会溢出遮挡状态栏。

也可直接访问 http://手机IP:8080/video 获取裸 MJPEG 流(适合电脑浏览器原生渲染,但不具备上述交互功能)。


四、技术实现要点

  • 最低 Android 版本:8.0 (API 26)

  • 开发语言:Kotlin

  • 核心依赖:

    • CameraX(相机控制、图像分析、视频录制)

    • NanoHTTPD(HTTP 服务器,提供 MJPEG 流)

    • OkHttp(报警 HTTP 请求)

    • AndroidX Core(ContextCompat.registerReceiver 标准广播,服务与界面通信)

  • 视频推流:

    • CameraX ImageAnalysis 获取 YUV 帧,转为 NV21,在 NV21 字节层面直接旋转(纯内存操作,避免 JPEG 二次编解码),再压缩为 JPEG,通过 NanoHTTPD 以 MJPEG 格式输出。

    • 编码链路采用「最新帧槽位 + 单线程编码循环」:分析线程只做覆盖式投递,编码积压时旧帧在编码前即被丢弃(省 CPU、观看延迟恒定),单线程天然保序(避免多线程并发编码导致的画面乱序回跳)。

    • 每个客户端独立线程推送,新帧自动覆盖未发送的旧帧(慢帧丢弃),帧到达通过 wait/notify 事件唤醒推送线程(无固定轮询空转)。多客户端互不阻塞。

    • 帧率限制采用「每秒平均」策略:每秒内最多处理 N 帧(N 为用户设置的帧率),比单帧硬间隔更准确、更接近设置值。

    • 根据 ImageProxy 的旋转角度(imageInfo.rotationDegrees)动态旋转,保证输出画面与录像方向一致。

  • 本机预览:
    PreviewActivity 通过进程内帧监听接口直接订阅编码循环产出的 JPEG 帧,不新增相机用例(零额外相机成本、不影响推流帧率与录像)。解码限速 10fps 并覆盖式丢帧,页面不可见即注销监听。

  • 镜头选择:
    相机选择器(CameraSelector)按设置构造(后置/前置),绑定前通过 hasCamera() 检查所选镜头是否存在,不可用时自动回退后置摄像头并记录日志。画面方向由每帧的传感器朝向(rotationDegrees)自动校正,前后置无需额外处理。

  • 运动检测:
    相邻帧亮度差异算法,支持灵敏度调节。

  • 录像存储:

    • 录像文件按日期存放到 Recordings/yyyy-MM-dd/ 子文件夹。

    • 连续录像:在 CameraService 中维护一个 Recording 会话,通过 Handler 定时停止当前分段并自动开始下一段。

    • 运动触发录像:单次录制指定时长(从设置读取)。

    • 文件命名规则:motion_<时间戳>.mp4(运动触发)或 video_<时间戳>.mp4(连续录像),其中时间戳为毫秒级 Unix 时间戳。

    • 用例动态绑定:仅预览模式下只绑定 ImageAnalysis(独占相机输出,推流帧率最高);录像模式(连续/运动触发)同时绑定 ImageAnalysis + VideoCapture(相机输出共享,推流帧率略降但录像正常)。模式切换时自动重新绑定。

  • 录像管理:

    • RecordingsActivity 扫描 Recordings 下所有日期文件夹,统计视频数量和总大小。

    • VideoListActivity 递归计算文件夹内 MP4 文件,异步加载时长和日期,支持搜索、多选、删除、导出。

    • 导出使用 DocumentsContract / MediaStore API,兼容 Android 10+ 分区存储。

  • 后台保活:
    前台服务 + PARTIAL_WAKE_LOCK,引导用户关闭电池优化。

  • 横屏统一:
    强制 ImageAnalysis 和 VideoCapture 的 targetRotation = Surface.ROTATION_0,确保输出画面宽>高,与录像方向一致。

  • Web 端查看页面:
    StreamServer 在根路径 / 返回内嵌 HTML/CSS/JS 的查看页面,无需额外静态资源。页面用 fetch Streaming API 读取 /video 的 MJPEG 流,在 JS 中扫描 JPEG 帧标记(SOI 0xFF 0xD8 / EOI 0xFF 0xD9)提取完整帧并渲染,帧率接近推流原生帧率。帧渲染优先使用 createImageBitmap + <canvas>(JPEG 解码移出主线程,绘制经串行 Promise 链保序),不支持的浏览器自动回退 <img>(decoding="async")。通过 streamGen 代际计数器防止重连竞态,buffer 超 500KB 自动截断防止内存溢出。同时提供 /status(JSON 状态)和 /snapshot(最新 JPEG 帧)端点供心跳检测和备用访问。画面旋转/缩放/平移通过 CSS transform 合并实现(translate → rotate → scale),GPU 加速,不影响帧渲染性能。


五、已知局限与后续优化方向

项目 现状 建议
远程音频监听 浏览器 MJPEG 不支持音频 可升级为 WebRTC 或 RTMP 推流
开机自启可靠性 部分厂商需手动授权;Android 14+ 系统限制开机自启动相机类前台服务(旧手机 Android 8-13 不受影响) 增加引导说明
通知权限 Android 13+ 需用户授予通知权限,未授予时前台服务通知不显示(App 启动时会请求,拒绝不阻断监控功能) 引导用户授予
多路观看 支持多浏览器同时观看 MJPEG,每个客户端独立线程推送 可增加观看人数统计
录像循环覆盖 代码已预留,未启用 后续可根据总容量自动删除最早文件
帧率硬件上限 不同手机 CameraX 输出帧率上限不同(约 15-30fps),好手机上限更高 可在启动时动态探测硬件上限并反馈给用户
启动预热误报 相机启动初期自动曝光收敛可能触发一次假运动报警 检测器启动时跳过前几帧(待实现)

About

将旧 Android 手机变为局域网监控摄像头,具备实时画面查看、运动检测报警、自动录像、后台保活等功能。 特点:完全本地运行,无需第三方云服务,免费且开源。

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages