
screenpipe 健康检查与故障诊断实战从进程探测到视觉/音频流水线的完整排查手册【免费下载链接】screenpipeYC (S26) | Open Computer History | Record your screen continuously locally and provide context to your agents (Claude, Codex, Openclaw, Hermes, Runner...)项目地址: https://gitcode.com/GitHub_Trending/sc/screenpipescreenpipe 是一款持续在本地录制屏幕画面与音频、并把它们转化为可检索上下文供 Claude、Codex 等 Agent 使用的开源工具。本文基于仓库内的screenpipe-health技能文档系统讲解如何用一套可复制的命令检查 screenpipe 的进程状态、API 健康度、磁盘占用、数据库完整性与音频/视觉流水线指标并结合仓库源码Rust 实现与测试说明每个健康信号背后的判定逻辑。读完本文你将掌握从进程是否存活到音频为什么没有转写的端到端排查能力。快速健康检查五步确认核心运行状态1. 检查 screenpipe 是否在运行# 列出所有 screenpipe 相关进程 pgrep -fl screenpipe # 探测本地 HTTP API 是否响应默认端口 3030 curl -s http://localhost:3030/health | head -100pgrep -fl会同时输出进程 PID 与完整命令行curl /health是判断服务是否可用的黄金标准。端口 3030 是 screenpipe 服务端的默认监听端口从源码看健康检查端点同时提供了 HTTP 与 WebSocket 两种形态/health与/ws/health见 crates/screenpipe-engine/src/server.rs 中的路由注册。2. 检查录制状态# 提取健康响应中的视觉与音频状态字段 curl -s http://localhost:3030/health | jq .frame_status, .audio_status 2/dev/null || curl -s http://localhost:3030/health如果系统没有安装jq命令会自动回退到直接打印完整 JSON。frame_status描述屏幕录制流水线状态audio_status描述音频流水线状态。3. 检查磁盘占用# screenpipe 数据目录总大小 du -sh ~/.screenpipe/ # 数据库文件大小 ls -lh ~/.screenpipe/db.sqlite* 2/dev/null # 视频/音频缓存目录大小 du -sh ~/.screenpipe/data/ 2/dev/nullscreenpipe 默认把所有数据存放在~/.screenpipe/db.sqlite以及 WAL 模式下的db.sqlite-wal、db.sqlite-shm是核心 SQLite 数据库data/目录存放录制的媒体缓存。db.sqlite*通配符可以一并看到 WAL 与 SHM 文件的大小。4. 检查今日错误日志# 今日日志中最后 10 条 error 记录 grep -i error ~/.screenpipe/screenpipe.$(date %Y-%m-%d).log 2/dev/null | tail -10screenpipe 的日志按日期滚动命名screenpipe.YYYY-MM-DD.log$(date %Y-%m-%d)让命令始终命中今天的日志文件。5. 综合状态报告CLI 方式除了直接 curlscreenpipe 还内置了screenpipe status命令它会在不干扰运行中录制器的情况下探测/health、汇总数据库统计与存储占用输出一行式的总览● recording normally/▲ needs attention/○ not running其实现位于 crates/screenpipe-engine/src/cli/status.rs。该命令特别注意到当守护进程正在运行时不会用第二个进程去打开 SQLite 数据库macOS 上使用 unix-excl VFS 的 WAL 索引冲突可能毒化写入端而是直接从健康响应中读取新鲜度字段——这正是值得学习的设计取舍。详细诊断深入到进程、API、流水线与数据库进程信息与内存占用# 详细进程信息 ps aux | grep -i screenpipe | grep -v grep # 内存占用汇总单位 MB ps aux | grep -i screenpipe | grep -v grep | awk {sum$6} END {print Total Memory: sum/1024 MB} # 区分是桌面应用还是 CLI pgrep -fl screenpipe-app echo Desktop app running pgrep -fl screenpipe$ echo CLI running桌面应用进程名是screenpipe-app纯 CLI 录制进程则精确匹配screenpipe$防止误匹配到其他带 screenpipe 前缀的进程。API 端点总览健康诊断工具箱以下是健康排查最常用的一组端点全部注册在 crates/screenpipe-engine/src/server.rs 中# 健康端点含视觉 音频流水线统计 curl -s http://localhost:3030/health # 搜索端点测试查询 curl -s http://localhost:3030/search?limit1 | head -50 # 列出音频设备 curl -s http://localhost:3030/audio/list # 列出显示器 curl -s http://localhost:3030/vision/list # 视觉流水线原始计数器 curl -s http://localhost:3030/vision/metrics # 音频流水线原始计数器 curl -s http://localhost:3030/audio/metrics/audio/list返回设备名列表并标记默认输入/输出设备见 crates/screenpipe-engine/src/routes/audio.rs。/vision/list返回显示器列表id、stable_id、名称、分辨率、是否主屏见 crates/screenpipe-engine/src/routes/health.rs 中的api_list_monitors。/vision/metrics与/audio/metrics返回流水线各阶段的原始计数器快照源码注释明确说明其用途是监控仪表盘与本地开发基准测试见 crates/screenpipe-engine/src/routes/health.rs。音频流水线诊断转写是否真的在工作/audio/metrics的字段与音频流水线的四个阶段一一对应采集capture、VAD语音活动检测、转写transcription、数据库写入DB完整定义见 crates/screenpipe-audio/src/metrics.rs。下面这段 Python 脚本会把原始计数器翻译成人类可读的诊断结论# 快速音频流水线健康检查 —— 转写真的在工作吗 curl -s http://localhost:3030/audio/metrics | python3 -c import sys,json m json.load(sys.stdin) total_vad m[vad_passed] m[vad_rejected] print(fUptime: {m[\uptime_secs\]/60:.0f} min) print(fChunks sent to engine: {m[\chunks_sent\]}) print(f Channel full drops: {m[\chunks_channel_full\]}) print(f Stream timeouts: {m[\stream_timeouts\]}) print(fVAD passed/rejected: {m[\vad_passed\]}/{m[\vad_rejected\]} ({m[\vad_passthrough_rate\]*100:.0f}% passthrough)) print(f Avg speech ratio: {m[\avg_speech_ratio\]:.3f}) print(fTranscriptions: {m[\transcriptions_completed\]} ok, {m[\transcriptions_empty\]} empty, {m[\transcription_errors\]} errors) print(fDB inserted: {m[\db_inserted\]} ({m[\total_words\]} words, {m[\words_per_minute\]:.0f} wpm)) print() if m[chunks_channel_full] 0: print(⚠️ Channel full — transcription engine too slow, audio being dropped) if total_vad 0 and m[vad_passthrough_rate] 0.1: print(⚠️ Very low VAD passthrough — may be dropping real speech) if m[transcription_errors] 0: print(⚠️ Transcription errors detected) if m[chunks_sent] 0 and m[db_inserted] 0: print( Chunks sent but nothing stored — pipeline is broken) if m[chunks_sent] 0 and m[uptime_secs] 120: print( No chunks sent after 2min — audio capture not working) 各计数器在源码中的真实语义crates/screenpipe-audio/src/metrics.rs字段含义阶段chunks_sent发送到转写通道的音频块数采集chunks_channel_full因转写通道已满而被丢弃的块数采集stream_timeouts设备流超时次数30 秒无音频数据采集chunks_lagged因消费者落后于广播通道而跳过的缓冲CPU 争用下的静默丢失采集vad_passed/vad_rejected通过 / 被 VAD 拒绝的块数阈值基于 speech_ratioVADvad_passthrough_ratevad_passed / (vad_passed vad_rejected)0.0 表示全被拒绝VAD派生transcriptions_completed/transcriptions_empty/transcription_errors引擎成功返回 / 返回空串 / 出错转写db_inserted/total_words/words_per_minute成功入库数 / 累计词数 / 每分钟词数数据库一个关键细节last_db_write_ts只在真正插入去重后的转写时更新而last_transcription_attempt_ts在每次转写尝试时都会推进——哪怕 VAD 把全部音频判为静音。这两个时间戳的差异正是/health区分无话可说与流水线卡死的依据。从/health读取的音频流水线汇总视图# 从 /health 读取音频流水线摘要 curl -s http://localhost:3030/health | python3 -c import sys,json h json.load(sys.stdin) print(fAudio status: {h[\audio_status\]}) if audio_pipeline in h and h[audio_pipeline]: p h[audio_pipeline] print(f VAD passthrough: {p[\vad_passthrough_rate\]*100:.0f}%) print(f Words/min: {p[\words_per_minute\]:.0f}) print(f DB inserted: {p[\db_inserted\]}) 数据库健康检查# 数据库完整性检查 sqlite3 ~/.screenpipe/db.sqlite PRAGMA integrity_check; 2/dev/null # 数据库大小与各表行数 sqlite3 ~/.screenpipe/db.sqlite SELECT name, (SELECT COUNT(*) FROM main WHERE namet.name) FROM sqlite_master t WHERE typetable; 2/dev/null # 最近 24 小时的帧数 sqlite3 ~/.screenpipe/db.sqlite SELECT COUNT(*) as frames_today FROM frames WHERE timestamp datetime(now, -1 day); 2/dev/nullPRAGMA integrity_check是 SQLite 官方推荐的完整性校验手段正常输出为ok。注意当 screenpipe 正在运行WAL 模式下时从外部用 sqlite3 打开数据库可能遇到锁或读到不一致的视图此时更稳妥的方式是改用screenpipe status命令或/health接口获取新鲜度信息。macOS 权限检查屏幕录制与麦克风权限是 macOS 上最常出问题的环节。TCCTransparency, Consent, and Control数据库记录了应用的权限授权情况# 检查屏幕录制权限 sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db SELECT client,allowed FROM access WHERE servicekTCCServiceScreenCapture; 2/dev/null | grep -i screenpipe # 检查麦克风权限 sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db SELECT client,allowed FROM access WHERE servicekTCCServiceMicrophone; 2/dev/null | grep -i screenpipe # 或通过系统设置确认 echo Check System Preferences Privacy Security Screen Recording and Microphone for screenpipe permissions直接读取 TCC.db 需要本机相应权限且依赖系统版本命令末尾的2/dev/null用于在无权限时静默失败。日常更推荐走系统设置界面确认。常见问题与修复问题screenpipe 没有运行# 启动 CLI 录制 screenpipe # 或启动桌面应用 open /Applications/screenpipe.app问题没有捕获到屏幕帧在系统设置中检查屏幕录制权限macOS。检查日志中的权限相关错误grep -i permission\|denied\|cg\|capture ~/.screenpipe/screenpipe.$(date %Y-%m-%d).log | tail -20问题没有音频转写检查麦克风权限。检查音频流水线指标用脚本定位卡点# 音频到底有没有被捕获 curl -s http://localhost:3030/audio/metrics | python3 -c import sys,json; mjson.load(sys.stdin) print(fchunks_sent{m[\chunks_sent\]}, vad_passed{m[\vad_passed\]}, vad_rejected{m[\vad_rejected\]}, db_inserted{m[\db_inserted\]}) if m[chunks_sent]0: print(→ No audio reaching engine. Check device/permissions.) elif m[vad_passed]0: print(→ VAD rejecting everything. Check mic input level or lower vad_sensitivity.) elif m[db_inserted]0: print(→ Transcription failing. Check engine config or logs.) 这条脚本的三段式判断与音频流水线的阶段划分完全对应chunks_sent0说明采集层就没拿到数据设备/权限问题vad_passed0说明 VAD 把所有音频都判为静音输入电平过低或vad_sensitivity阈值不合适只有到达db_inserted0这一步才指向转写引擎本身。检查音频设备选择与转写引擎日志curl -s http://localhost:3030/audio/list grep -i audio\|device\|whisper ~/.screenpipe/screenpipe.$(date %Y-%m-%d).log | tail -20问题CPU / 内存占用过高# 查看当前占用 top -l 1 -s 0 | grep -i screenpipe # 在日志中查找内存泄漏或 OOM 痕迹 grep -i memory\|oom ~/.screenpipe/screenpipe.$(date %Y-%m-%d).log问题数据库被锁定# 查看哪些进程持有数据库文件 fuser ~/.screenpipe/db.sqlite 2/dev/null # 检查是否启动了多个 screenpipe 进程 pgrep -c screenpipe数据库被锁通常意味着存在多个 screenpipe 实例同时打开数据库或某个异常进程未释放句柄。fuser能列出持有该文件的进程 PIDpgrep -c统计 screenpipe 进程数确认是否存在重复实例。源码级解读/health如何判定健康状态了解命令之后再深入一层/health返回的每个字段背后都有完整的判定逻辑实现于 crates/screenpipe-engine/src/routes/health.rs。响应结构一次调用拿到全部诊断信息HealthCheckResponse结构体同文件定义包含约 30 个字段核心字段如下字段说明status/status_code总健康状态healthy200/degraded503/unhealthyframe_status视觉流水线状态ok/disabled/stale/not_started等vision_reason视觉状态的机器可读原因见下节audio_status音频状态ok/disabled/stale/active_no_data/no_input_device/waiting_for_meeting等audio_capture_mode实际生效的采集模式always/meetings-only/disabledcapture_status结构化音频捕获状态status severity reason供会议/实时笔记 UI 使用last_frame_timestamp/last_audio_timestamp最近一次写入时间戳pipeline/audio_pipeline视觉与音频流水线的详细计数快照recording_coverage录制覆盖率近期活跃输入期间健康屏幕捕获的占比pool_statsSQLite 读写连接池的 size / idle 数write_queue_degraded等写队列降级、连续致命批次数、连接池重开次数等可靠性信号vision_db_write_stalled/audio_db_write_stalled捕获循环存活但数据库写入停止连接池耗尽或锁争用drm_content_paused/schedule_pausedDRM 内容暂停 / 工作时间表暂停值得注意的两个工程设计细节1 秒缓存 2 秒预算多个 WebSocket 客户端和 HTTP 轮询可能每秒调用/health数十次而响应内容只有约 1 秒才发生有意义变化因此端点实现了 1 秒 TTL 缓存和 single-flight 门控HEALTH_CACHE_TTL_SECS 1同时整个计算被限制在 2 秒预算内HEALTH_RESPONSE_BUDGET超时则返回上次缓存的快照避免健康检查拖垮调用方包括 launchd 看门狗。写队列健康信号write_queue_consecutive_fatal连续致命写入批次数与write_pool_reopens进程内重开连接池清除毒化连接的次数等字段让运维人员能直接看到数据库写入路径的可靠性状况。frame_status与vision_reason从出问题到为什么出问题frame_status的历史教训是它会把screenpipe 自己关掉了像素录制和操作系统拒绝了屏幕捕获折叠成同一个值导致应用曾把已经授权过的用户引导去系统设置重新授权源码注释引用了 issue #5808 的修复背景。为此引入了vision_reason用稳定的机器可读枚举区分九种状态ok— 正常录制disabled_by_setting— 设置中关闭了视觉--disable-vision/disableVisionno_displays_expected— 所有选中显示器都被暂停、休眠或不活跃screenshots_disabled_by_config— 关闭了截图仅捕获屏幕上的无障碍文本screenshots_disabled_by_power_profile— 低电量 / 低功耗模式暂停截图恢复后自动继续permission_denied— 操作系统拒绝屏幕捕获唯一应该给出权限指导的原因capture_stalled— 有权限且预期录制但帧停止到达not_started— 尚未产生第一帧ocr_unavailable— Linux 上找不到 Tesseract OCR 二进制截图被存储但没有可搜索的文本判定顺序是经过刻意设计的先检查所有故意关闭的状态用户自己关了像素就不是故障绝不该收到权限指导最后才轮到真正的故障permission_denied/capture_stalled/not_started/ocr_unavailable。对应逻辑见classify_vision_reason_with_ocr函数。视觉停滞分类不靠猜靠计数器当视觉流水线停滞时/health会依据计数器把原因分为三类VisionStallCause枚举见 crates/screenpipe-engine/src/routes/health.rsSilentLoss静默丢失捕获仍在尝试但帧没有到达写入端——capture_attempts在增长、frames_db_written与dedup_skips都平坦说明帧在尝试与写入之间蒸发。CapturePaused捕获暂停捕获尝试完全停止——TCC 权限被撤销、显示器休眠或 ScreenCaptureKit 守护进程卡死。如果捕获后端最近发生过回退如 ScreenCaptureKit 回退到 CoreGraphics/health会直接点名主后端卡死而非屏幕静止。DbWritesNotLanding数据库写入未落地捕获到达了写入端但写入端是问题所在——表现为丢帧数增长、平均 DB 延迟超过阈值或写连接池完全饱和。这个分类的触发前提也很讲究只有当last_db_write_ts真正过期超过 60 秒新鲜度阈值时才会触发而record_dedup_skip与record_corrupt_skip都会推进该时间戳因此静态屏幕空闲用户不会误报为停滞——源码注释直言旧版本idle user, not a pipeline stall的措辞每一次打印出来都是错的。音频状态机为什么没有麦克风不是故障classify_audio_status函数展示了音频健康判定的完整状态机disabled→屏幕锁定时视为ok→meeting_detector_unavailable→waiting_for_meeting→no_input_device音频开启但没有可捕获的麦克风预期空闲而非失败且不会让桌面端误触发停滞通知→not_started→active_no_data看门狗最近触发过且同一设备未恢复→ok→stale。特别地macOS 合盖clamshell模式下内置麦克风仍会被枚举但只能输出全零缓冲健康判定会将其视为不可用input_device_is_available函数而外接麦克风仍然照常判定。报告输出格式健康检查完成后一份合格的状态报告应遵循以下结构原文档规定的输出规范先给出总体状态healthy / unhealthy列出发现的所有问题给出具体的错误信息尽量引用/health中的message、vision_reason、capture_status.reason等结构化字段而非笼统描述针对每个问题给出修复建议权限、设备、阈值或重启等可操作步骤。这套总体状态 → 问题清单 → 证据 → 修复建议的格式与/health响应本身的设计哲学一脉相承先给结论再给原因最后给可执行的动作。无论你是通过脚本定期巡检、接入监控仪表盘还是为 Agent 提供健康上下文都可以直接复用它。小结screenpipe 的健康排查可以总结为一条清晰的链路进程 → API → 磁盘 → 日志 → 流水线指标 → 数据库 → 权限。本文提供的命令覆盖了前五层而/health端点及其背后的 health.rs 实现则把最后几层压缩成了可机器消费的结构化信号——vision_reason区分故意关闭与真故障VisionStallCause用计数器而非猜测定位停滞环节音频状态机把没有麦克风和流水线卡死分开处理。下次遇到 screenpipe 不工作从pgrep -fl screenpipe和curl -s localhost:3030/health开始沿着本文的步骤逐层深入即可。【免费下载链接】screenpipeYC (S26) | Open Computer History | Record your screen continuously locally and provide context to your agents (Claude, Codex, Openclaw, Hermes, Runner...)项目地址: https://gitcode.com/GitHub_Trending/sc/screenpipe创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考