先给结论:每一个按键、每一次窗口切换、每一段屏幕画面,在“Everything You Do Is Being Recorded”这类项目里都会被完整保留。它的核心思路很简单——在本地把用户操作过程记录成一条可回放的行为时间线:屏幕帧、活跃窗口标题、事件发生时间、操作顺序,全部落盘。这类能力在录屏教程、Bug 复现、自动化测试验证、自有产品行为分析里非常实用,也是很多 RPA 和测试框架的底层基础。
这类项目通常不是一个单独的大仓库,而是“录制内核 + 事件监听 + 存储回放”的组合实现。门槛比大部分人想象的低:不需要独立显卡,CPU 编码就能跑;磁盘占用取决于分辨率、帧率和压缩参数;启动方式以命令行为主,也可以包一层 Web 服务提供 API。本文会从环境准备、部署启动、功能验证、接口封装、批量任务、性能观察和排错几个方向,把一套可落地的本地活动记录系统完整讲清楚。
先说一个务实的建议:第一次验证,先跑通屏幕录制,再加事件日志,最后再考虑 API 化和批量导出。不要一上来就把全部功能堆在一起,否则出了问题很难定位是录制模块、事件模块还是接口模块的锅。
1. 核心能力速览
由于标题指向的是一个技术方向,而不是某个固定仓库,下面按这类项目的常见实现形态来梳理能力。
| 能力项 | 说明 |
|---|---|
| 项目类型 | 本地计算机活动记录 / 屏幕录制 + 事件追踪工具 |
| 主要功能 | 屏幕画面录制、活跃窗口追踪、事件时间线记录、回放与导出 |
| 硬件要求 | CPU 编码即可,不需要独立显卡;内存建议 8GB 以上 |
| 显存占用 | 无 GPU 推理需求,显存占用可以视为 0 |
| 支持平台 | Windows / Linux / macOS,取决于录制后端 |
| 启动方式 | 命令行启动,可封装为 Web 服务 |
| 是否支持 API | 可通过 FastAPI / Flask 自行封装 |
| 是否支持批量任务 | 支持,适合批量回放、批量压缩导出 |
| 存储格式 | 视频(MP4/WebM)+ 事件日志(JSONL) |
| 适合场景 | 教程录制、Bug 复现、测试验证、行为分析、数字证据留存 |
一个常见的误解是:记录一切 = 无脑截屏。实际工程实现里,通常要把“画面录制”和“事件记录”分开处理。画面录制解决“看到了什么”,事件记录解决“用户当时在做什么”,两者通过时间戳对齐,才能支撑后面的时间轴回放。
2. 适用场景与使用边界
先讲清楚适合谁用。这类工具最适合的人群是软件测试工程师、自动化脚本开发者、技术写作者和产品经理。测试工程师可以用它复现偶发 Bug,把失败路径录下来交给开发;技术写作者可以用它录制操作演示,省去临时架摄像头的麻烦;产品经理可以在自己参与设计的测试环境里观察用户操作路径,优化交互流程。
不适合什么场景?未经授权的监控、账号密码记录、敏感聊天内容采集、以及任何针对他人设备的隐蔽记录。这些场景不只是道德问题,在绝大多数国家和地区都涉及违法违规,这里不做任何操作层面的建议。
使用边界必须提前划好,特别是当项目涉及人脸、声音、键盘输入记录时:
- 设备边界:只录制自己拥有或已获得明确授权的设备。
- 数据边界:采集范围最小化,密码输入框、支付页面、聊天窗口最好直接排除。
- 时间边界:设定自动清理周期,默认不长期保存。
- 告知边界:如果录制内容会涉及他人,必须提前获得知情同意。
从工程角度看,最稳妥的设计不是“先录下来再说”,而是“录制前就把敏感区域和敏感应用过滤掉”。比如在录屏时只截取指定窗口或裁剪掉输入法区域,事件记录里过滤掉已知的密码输入窗口标题。这样即使文件泄露,风险也可控。
3. 环境准备与前置条件
以一套通用的本地活动记录系统为例,推荐环境如下:
3.1 操作系统与运行环境
- Windows 10/11,或者 Ubuntu 20.04 以上的 Linux 发行版。
- Python 3.9 以上,用于运行事件监听和 Web API 服务。
- FFmpeg 4.x 以上,用于屏幕录制和视频转码。
- 无头服务器需要额外准备虚拟显示方案,比如 Xvfb。
3.2 磁盘空间评估
磁盘占用是最容易被低估的变量。按经验估算:
- 1080p、30fps、H.264 中等码率,每小时约 1-2GB。
- 同样的分辨率,如果使用无损或高码率设置,每小时可能到 5GB 以上。
- 事件日志 JSONL 文件很小,每小时通常只有几 MB 到几十 MB,取决于事件密度。
所以存储规划不要太乐观。建议录制输出目录和数据目录分开,方便做容量配额和自动清理。
3.3 显卡与显存
这类项目不需要 GPU 推理。屏幕录制走的是 FFmpeg 的 CPU 编码或硬件编码,事件监听走的是系统 API,显存占用可以视为 0。如果你的机器有 NVIDIA 显卡,可以按需使用 NVENC 硬件编码降低 CPU 占用,但没有也不影响基础功能。
5. 安装部署与启动方式
下面给出一套可复用的参考实现,包含 Python 虚拟环境、FFmpeg 录制、事件监听脚本和 Web API 服务。实际操作时,请把命令里的路径、分辨率和窗口标题替换成你自己的值。
4.1 创建 Python 环境并安装依赖
# 创建虚拟环境,按实际项目目录调整路径 python -m venv venv source venv/bin/activate # Windows 使用 venv\Scripts\activate # 安装事件监听和图像处理依赖 pip install pynput pillow opencv-python fastapi uvicorn requests4.2 检查 FFmpeg
ffmpeg -version如果系统没有安装 FFmpeg,Linux 可以用 apt 安装:
sudo apt update sudo apt install ffmpegWindows 用户建议直接下载官方 release 包,把 bin 目录加入系统 PATH。
4.3 启动屏幕录制
Linux 下使用 x11grab 录制整个桌面:
# 录制 1920x1080,30 帧,声音使用 PulseAudio 默认输入源 # 如果不需要声音,去掉 -f pulse 部分 ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :0.0 \ -f pulse -i default \ -c:v libx264 -preset ultrafast -crf 28 \ -c:a aac -b:a 128k \ output.mp4Windows 下使用 gdigrab 录制桌面:
ffmpeg -f gdigrab -framerate 30 -video_size 1920x1080 -i desktop \ -c:v libx264 -preset ultrafast -crf 28 \ output.mp4参数解释:
-preset ultrafast:牺牲一点压缩率,换取更低的 CPU 占用。-crf 28:画质折中参数,数值越大文件越小、画质越低。-framerate 30:录屏时建议不低于 15,否则回放会明显掉帧。
录制过程中,FFmpeg 会持续输出帧统计信息。按q键可以正常结束录制,避免生成损坏的 MP4 文件。
4.4 启动事件监听脚本
屏幕画面只能证明“屏幕上有内容”,配合事件记录才能知道用户当时在操作什么。下面是一个最小参考实现,重点记录窗口切换和鼠标点击事件。
# event_logger.py # 参考实现:按目标平台调整窗口标题读取方式 import json import time from pynput import mouse, keyboard from datetime import datetime LOG_FILE = "events.jsonl" def write_event(event_type, detail): with open(LOG_FILE, "a", encoding="utf-8") as f: f.write(json.dumps({ "event": event_type, "detail": detail, "ts": time.time(), "time": datetime.now().isoformat() }) + "\n") def on_click(x, y, button, pressed): if pressed: write_event("mouse_click", {"x": x, "y": y, "button": str(button)}) def on_press(key): # 避免记录密码等敏感输入,这里只记录按键名称,不记录组合内容 if key == keyboard.Key.esc: write_event("keyboard_esc", {}) return False # 启动监听 with mouse.Listener(on_click=on_click) as ml: with keyboard.Listener(on_press=on_press) as kl: ml.join() kl.join()这个脚本故意做了两件事来规避风险:一是只记录鼠标点击坐标,不记录按键文本;二是收到 Esc 键就结束监听,方便紧急停止。实际项目中如果确实需要记录键盘输入,务必在采集层过滤掉密码框和敏感输入法区域。
运行方式:
python event_logger.py4.5 整合为带 Web 服务的完整启动
事件监听和 FFmpeg 是两条独立的进程,如果希望用 API 控制录制启动和停止,可以用一个 FastAPI 服务统一管理。
# app.py # 参考实现:需要根据实际项目改造 import subprocess import json import time from pathlib import Path from fastapi import FastAPI app = FastAPI() OUTPUT_DIR = Path("./sessions") OUTPUT_DIR.mkdir(exist_ok=True) ffmpeg_proc = None @app.get("/health") def health(): return {"status": "ok", "time": time.time()} @app.post("/api/record/start") def start_record(rate: int = 30, size: str = "1920x1080"): global ffmpeg_proc if ffmpeg_proc is not None: return {"error": "recording already running"} out_file = OUTPUT_DIR / f"session_{int(time.time())}.mp4" cmd = [ "ffmpeg", "-y", "-f", "x11grab", "-framerate", str(rate), "-video_size", size, "-i", ":0.0", "-c:v", "libx264", "-preset", "ultrafast", "-crf", "28", str(out_file) ] ffmpeg_proc = subprocess.Popen(cmd) return {"status": "started", "file": str(out_file)} @app.post("/api/record/stop") def stop_record(): global ffmpeg_proc if ffmpeg_proc is None: return {"error": "no recording running"} ffmpeg_proc.stdin.close() ffmpeg_proc.terminate() ffmpeg_proc = None return {"status": "stopped"}启动服务:
uvicorn app:app --host 127.0.0.1 --port 80805. 功能测试与效果验证
部署完之后,按下面的顺序做功能验证,确保每个环节都能独立判断成败。
5.1 屏幕录制测试
测试目的:确认 FFmpeg 能正常录制、正常收尾、输出文件可播放。
操作步骤:
- 在终端启动 FFmpeg 录制命令。
- 打开浏览器,切换几个页面,滚动几次。
- 按
q结束录制。 - 用播放器打开输出的 MP4。
预期结果:视频长度接近实际录制时长,画面没有大面积花屏,切换窗口的过程是连续的。
判断标准:视频能正常拖动进度条,最后 3 秒内容完整,文件没有损坏。
常见失败原因:Linux 下DISPLAY环境变量不对导致黑屏;Windows 下 gdigrab 对高 DPI 屏适配不佳,画面可能被裁剪。
5.2 事件日志测试
测试目的:确认鼠标点击和窗口切换事件能被记录,且时间戳和视频时间轴能对得上。
操作步骤:
- 启动 event_logger.py。
- 做三次固定的鼠标点击操作,例如点击浏览器地址栏。
- 停止脚本,查看 events.jsonl。
预期结果:events.jsonl 里出现 6 条记录(按下和抬起各算一次),每次点击位置和屏幕录制中的实际位置一致。
判断标准:事件时间戳与视频时间轴差值在 1 秒以内,说明对齐可用。
5.3 接口服务测试
测试目的:确认 Web API 能控制录制的启停。
# 检查服务状态 curl http://127.0.0.1:8080/health # 启动录制 curl -X POST "http://127.0.0.1:8080/api/record/start?rate=30&size=1920x1080" # 停止录制 curl -X POST http://127.0.0.1:8080/api/record/stop预期结果:三个请求都能返回 JSON,sessions 目录下生成新的 MP4 文件。
判断标准:停止请求返回后,目标 MP4 文件大小不再变化,播放正常。
6. 接口 API 与批量任务
API 化的价值在于,把“录制”从人工操作变成可编程的任务。有了/api/record/start和/api/record/stop,你就能在自己的脚本里按需录制。
6.1 Python 调用录制接口
import requests import time base_url = "http://127.0.0.1:8080" # 启动录制 resp = requests.post( f"{base_url}/api/record/start", params={"rate": 30, "size": "1920x1080"} ) print(resp.json()) # 模拟录制 10 秒 time.sleep(10) # 停止录制 resp = requests.post(f"{base_url}/api/record/stop") print(resp.json())启动后,这个脚本可以集成到自动化测试的用例里,遇到断言失败时自动录制前后 30 秒,帮助定位问题。
6.2 批量压缩导出
录制时间长了,磁盘上会积累大量原始视频。批量转码是这类项目最常用的批量任务。
# batch_compress.py # 将 sessions 目录下的所有 MP4 转为低码率 H.264 文件并归档 import subprocess from pathlib import Path input_dir = Path("./sessions") output_dir = Path("./archive") output_dir.mkdir(exist_ok=True) for video in input_dir.glob("*.mp4"): out_file = output_dir / f"{video.stem}_compressed.mp4" cmd = [ "ffmpeg", "-y", "-i", str(video), "-c:v", "libx264", "-preset", "medium", "-crf", "32", "-an", str(out_file) ] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: print(f"[OK] {video.name} -> {out_file.name}") else: print(f"[FAIL] {video.name}: {result.stderr[-200:]}")批量任务建议遵循三个原则:
- 每次处理都要记录日志,便于定位哪条任务挂了。
- 任务失败不要直接中断整个队列,收集错误后统一重试。
- 输出目录和输入目录严格分离,避免覆盖原始文件。
7. 资源占用与性能观察
这类项目的资源占用主要集中在三个地方:FFmpeg 编码进程、事件监听进程和磁盘写入。
7.1 如何观察 CPU 与内存占用
Linux 下直接用htop或top,找到 FFmpeg 进程和 python 进程:
top -b -n 1 | grep -E "ffmpeg|python|PID"Windows 下打开任务管理器,按 CPU 排序即可。如果 FFmpeg 进程 CPU 占用长期高于 80%,说明编码参数需要调低,比如把-preset ultrafast改成ultrafast配合-crf 30,或者降低录制的分辨率。
7.2 显存占用观察
这类项目没有 GPU 推理需求。如果使用 NVENC 硬件编码,可以用nvidia-smi观察 GPU 编码器占用,但显存占用基本为 0。这一点和跑大模型完全不同,对只有集显或老显卡的机器非常友好。
7.3 影响性能的关键变量
- 分辨率:从 4K 降到 1080p,CPU 占用通常能下降一半以上。
- 帧率:30fps 降到 15fps,文件体积接近减半,对操作类教程影响不大。
- 录制区域:只录单个窗口或裁剪掉固定区域,比全屏录制省很多资源。
- 音频:不需要声音时关掉音频,能明显降低编码压力。
7.4 降低磁盘占用的手段
# 手动清理超过 7 天的录制文件 find ./sessions -name "*.mp4" -mtime +7 -delete也可以让 FFmpeg 按固定时长分段录制,方便后续自动清理和检索:
ffmpeg -f x11grab -framerate 30 -video_size 1920x1080 -i :0.0 \ -c:v libx264 -preset ultrafast -crf 28 \ -f segment -segment_time 300 -reset_timestamps 1 \ session_%04d.mp4每 5 分钟生成一个文件,单个文件损坏不会影响整个录制。
8. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 录制后视频是黑屏 | DISPLAY 环境变量错误或无头环境 | 执行echo $DISPLAY | Linux 下设置export DISPLAY=:0,无头服务器用 Xvfb |
| MP4 文件无法播放 | 未正常结束录制,编码头缺失 | 查看 FFmpeg 日志是否有中断 | 下次用q正常退出;给停止接口加终止信号处理 |
| CPU 占用过高 | 编码参数太激进 | 用 top 观察 FFmpeg 进程 | 调低分辨率、降低帧率、改用 NVENC |
| 事件日志为空 | 事件监听脚本未启动或权限不足 | 检查 python 进程是否存在 | 以当前桌面用户运行脚本,不要用 sudo 启动 |
| 接口启动失败 | 端口被占用 | netstat -tlnp或lsof -i:8080 | 更换端口:uvicorn app:app --port 8081 |
| 磁盘快速写满 | 码率和 CRF 设置太高 | du -sh ./sessions查看目录大小 | 使用分段录制并配置清理策略 |
| 事件时间戳和视频对不上 | 两个进程启动时间不同步 | 对比日志首条时间戳 | 启动录制后,先写一条同步事件再开始操作 |
| 高 DPI 屏幕画面被裁剪 | gdigrab 对缩放适配不佳 | 检查录出的分辨率与桌面实际分辨率 | 改用 Windows Graphics Capture 或调整 DPI 缩放 |
9. 最佳实践与使用建议
第一,先小参数测试再上生产。第一次录制用 1280x720、15fps、10 秒,确认整个链路能跑通,再逐步提高分辨率。不要一上来就录 4K 一小时,否则即使功能正常,后续排查问题也会很痛苦。
第二,目录结构要清晰。建议把原始视频、事件日志、回放归档三个目录分开:
project/ ├── sessions/ # 原始录制文件 ├── events/ # JSONL 事件日志 └── archive/ # 压缩后归档第三,事件日志用 JSONL 而不是单独的 JSON 文件。JSONL 是追加写入,进程崩溃最多丢最后一条,不会把整个文件写坏,后续也方便用jq或 Python 流式处理。
第四,接口服务一定要限制访问范围。如果只是本机使用,监听地址写127.0.0.1,不要写0.0.0.0。如果确实需要远程访问,前面加一层带认证的反向代理。
第五,涉及人脸、声音、键盘输入记录时,必须确认授权范围。建议在采集层做敏感信息过滤:密码框不记录、支付页面不录制、聊天内容不落入日志。这是技术问题,也是合规红线。对录制的内容设定保留周期,测试用途的数据用完后及时删除。
第六,批量任务必须加日志和失败重试。批量转码、批量导出看起来简单,数据量一上来就会出现各种单点失败。每处理一个文件打一条日志,失败文件单独放一个列表,处理完统一查看。
10. 总结与下一步
“Everything You Do Is Being Recorded”这类项目最值得尝试的地方,不是“记录一切”这个概念本身,而是它把画面、事件、时间戳、接口和批量任务串成了一条完整的数据链路。你先验证屏幕录制能不能稳定出片,再确认事件日志能不能准确落盘,然后把录制启停封装成 API,最后接批量压缩和清理策略。这条链路跑通,你就拥有了一套可以复用在自己自动化测试和教程制作里的基础能力。
最容易踩的坑有两个:一是磁盘规划不够,录了一小时把系统盘写满;二是事件记录和视频时间轴对不齐,导致回放时定位不到操作点。这两个问题在前期设计阶段就要解决,不要等数据量上来再改。
后续可以扩展的方向不少:给录制帧加 OCR 提取屏幕文字,实现基于内容的检索;把事件日志接到自己的后端,做操作路径分析;或者用自动化剪辑规则,把录制的空闲时间段自动裁剪掉。这篇文章提到的方案适合先跑起来,再根据业务需要逐步完善。建议收藏备用,下次需要做本地行为记录时直接按这个流程操作。