bug2context

io.github.emanueld92由 GitHub 帳號 emanueld92 發布v0.1.1更新於 Oct 27, 2026

Turn bug screen recordings into chronological context for AI agents: frames, OCR, logcat, voice.

概覽

AI 產生的概覽

把 Bug 螢幕錄影轉成依時間排序的 Markdown 報告,包含關鍵影格、畫面上的文字、裝置日誌與語音旁白,供 AI 代理閱讀。

可以做什麼
  • 分析影片,產出帶時間戳的關鍵影格、OCR 文字、logcat 日誌與語音旁白的時序報告,並以文字回傳
  • 依需求取回某一影格影像,讓助理直接查看畫面
  • 列出先前處理過的結果包,最新的在前
  • 可選:同時錄製 Android 裝置畫面與 logcat,或把既有日誌檔合併進影片
適用情境
當 Bug 只呈現在螢幕錄影中、希望助理據此分析時適用,例如重現當機、Android 日誌加螢幕錄製,或他人傳來的影片。適合重視隱私、希望錄影留在本機的除錯情境。
執行需求
以本機程序方式執行(uvx 或原始碼檢出),需要 ffmpeg 位於 PATH。OCR 需安裝 ocr 附加元件(macOS 使用 Apple Vision,其他平台使用 tesseract);語音轉錄為選用附加元件,首次使用會下載模型。Android 錄製需要 adb 與已連線裝置。不需帳號、API 金鑰或雲端服務。
安裝前請注意
處理結果會寫入 ~/.bug2context/,OCR 結果快取於 ~/.cache/bug2context/,錄影與擷取的文字會留在磁碟上。Android 錄製會蒐集裝置日誌,可能含敏感應用程式資料。語音轉錄會下載模型。超過 10 分鐘的影片預設會被拒絕,除非明確覆寫。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 bug2context,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

bug2context

Turns a screen recording of a bug into structured, chronological context an AI agent can actually read.

Screenshots lose the story: bugs happen fast, a still frame has no timeline, and the logs and the narration live somewhere else entirely. LLMs don't take video. This distills a recording into one markdown chronology — key frames, the text on screen, device logs and spoken narration, all on the same clock.

  • No SDK. Works on any video, including one someone sent you over WhatsApp.
  • Local-first. Nothing leaves your machine. No account, no API key, no cloud.
  • MCP-native. Claude Code calls it as a tool; you just point at the file.
bash
uvx bug2context               # guided menuuvx bug2context process bug.mp4 --out bundle/

Running it with no arguments opens a menu — record an Android device, process a video you already have, or list previous bundles — and writes to ~/.bug2context/, which is where the MCP server looks. Everything it does is reachable through the flags below; it just stops you having to remember them.

What comes out

- `[00:00]` 🖼 `frames/frame_001_00-00.png` — start of recording      OCR: Cart 2 items- `[00:04]` 🖼 `frames/frame_002_00-04.png` — screen changed      OCR: Applying discount..- `[00:04]` 📋 W/DiscountEngine: rate field missing- `[00:06]` 🖼 `frames/frame_003_00-06.png` — screen changed      OCR: TypeError: cannot read 'rate'- `[00:06]` 📋 E/RideService: NullPointerException at RideRequest.kt:142- `[00:06]` 📋 F/AndroidRuntime: FATAL EXCEPTION: main- `[00:06]` 🎙 "ahí está, explota al aplicar el descuento"

A full run is in examples/report.md.

bundle/├── report.md    the chronology above├── frames/      the key frames, named by timestamp└── meta.json    the same data, structured, for programmatic use

Install

Requires ffmpeg on PATH (brew install ffmpeg).

bash
uvx --from 'bug2context[ocr]' bug2context          # OCR: Apple Vision on macOS, tesseract elsewhereuvx --from 'bug2context[ocr,audio]' bug2context    # plus spoken narration

Or from source:

bash
git clone https://github.com/emanueld92/bug2contextcd bug2contextuv sync --extra ocr --extra audio

Every stage is optional and degrades quietly: no OCR backend still gives you frames, no audio track still gives you the visual timeline.

Use it from Claude Code

bash
claude mcp add bug2context -- uvx --from 'bug2context[ocr]' bug2context-mcp

Working from a local clone instead: uvx --from /path/to/bug2context bug2context-mcp.

Then just ask: "analiza este video del bug: ~/Desktop/crash.mp4".

ToolPurpose
analyze_bug_videoVideo → chronological report (returns the text itself)
get_frameFetch one frame as an image so the agent can look at it
list_bundlesPreviously processed bundles, newest first

Bundles default to ~/.bug2context/<video>-<timestamp>/.

Android: screen + logcat in one command

bash
uv run bug2context record --seconds 60 --package com.example.app --out bundle/

Reproduce the bug while it records. Both streams start from a single host timestamp — that anchor is what makes a stack trace land next to the frame showing the crash.

Pass --package. Level filtering alone is not enough on a real phone: a 2 min capture held 7,634 W/E/F lines and none came from the app under test — they were all AppOpsControllerImpl, GNSSMGT and friends. Scoping to the app's process left 35. Crash tags (AndroidRuntime, DEBUG) are kept regardless of process, since a crash report is the whole point.

Logs are captured unfiltered and scoped afterwards, so an app that crashes and restarts still has its death recorded. Consecutive identical entries fold into one with a (×N) count — framework chatter arrives in bursts of fifteen.

Already have a log file? Merge it into any video:

bash
uv run bug2context process bug.mp4 --logcat logcat.txt --log-tag RideService

Reads both -v time and -v threadtime. --log-levels defaults to WEF and --log-max-lines to 80, ranked by severity so a cap never trades the crash for boot chatter. --log-pid scopes to a process when you already know it. If the device clock and the recorder disagree, --log-offset shifts everything by N seconds; with no --video-started-at, the first log entry becomes the anchor.

screenrecord caps at 3 minutes, so record refuses longer rather than handing back a silently truncated video. Ctrl-C cuts a recording short safely — the file is finalised on the device first, because killing the local adb leaves one ffprobe cannot open.

Videos over 10 minutes are refused with the ffmpeg command to trim them (--max-duration 0 overrides). Nothing scales badly with length except time, but it scales linearly: decoding alone runs at about a third of real time.

Narration

bash
uv run bug2context process bug.mp4 --transcribe --language es

Off by default: it downloads a model on first use and is the slowest stage, while most recordings have no voice-over. Skipped automatically when there is no audio track, or the track is quieter than −50 dB — whisper invents confident sentences out of silence, so that guard is about output quality, not just speed.

How frames get picked

ffmpeg over-produces candidates (scene cuts and a fixed interval, so slowly changing screens are not skipped), then perceptual hashing collapses the near-duplicates. --max-frames caps the result, always keeping the opening frame and then whichever changed most.

FlagDefaultNotes
--scene-threshold0.08ffmpeg scene score for a cut
--interval-seconds1.0forced sample when no cut fires
--max-framesautoone frame per 2 s, between 20 and 40
--phash-distance4below this, frames count as duplicates
--ocr-upscale2enlarge before OCR; skipped above 1600 px wide

Measured end to end, OCR on:

SourceResultTime
synthetic 3 min, 1080×192019 frames8.5 s
Android capture, 2 min, 720×1612 @ ~12 fps118 candidates → 20 frames16 s
macOS capture, 90 s, 2880×1864 @ 60 fps97 candidates → 18 frames86 s

Recognised text is cached by frame content in ~/.cache/bug2context/, so re-running a video with different settings only pays for what actually changed — measured 9.0 s cold against 3.3 s warm on a 44 s clip, identical output. Extracting the same video twice yields byte-identical frames, which is what makes the cache safe. Delete the directory to reset it.

Retina desktop recordings are the slow case and there is no trick to remove: the cost is decoding 60 fps at 5.4 megapixels (26 s) plus OCR, which Vision charges at ~1.6 s per frame regardless of size. Budget roughly real time for those; phone captures stay far under it.

On --ocr-upscale: a stack trace on a recompressed 1080×1920 frame read as Null PointerSxception Ride Requestkt14 at 1× and correctly as NullPointerException Ride Request kt 142 at 3×. Raise it for badly recompressed sources — ask for the video as a file, not as a WhatsApp video. It is skipped on frames already 1600 px or wider, where it changed nothing measurable while building a 5760×3728 image per frame.

OCR also drops lines that are debris rather than text — », .lll (100 4, a misread status-bar clock. On a real capture that removed 41 of 210 report lines and no real text. A line that looks like a failure is never dropped.

Known limitation

Perceptual hashing compares visual structure. It sees navigation, dialogs and error banners, but it cannot detect a small text-only change on an otherwise identical layout — measured on 1080×1920 those differences fall inside the noise floor at every hash size, so no --phash-distance value separates them.

OCR does not rescue this: it runs on frames that survive deduplication, so a screen already collapsed is never read. Reading every candidate instead measured 48–59 s for a 3 min video, over the entire time budget. If your bug is a small text change on an identical screen, record cropped or at lower resolution so the text occupies more of the frame.

Development

bash
uv sync --extra ocruv run pytest -q

183 tests. Device recording is mocked on purpose — a test suite should not record anyone's phone. Whisper is opt-in via BUG2CONTEXT_TEST_WHISPER=1 so the suite stays offline.

License

MIT — see LICENSE.

來源:README.md,提交 c938170

工具

0
SourceWeft 曾在隔離沙箱中以無憑證方式啟動該軟體包一次,以列出其工具,但未能完成:軟體包安裝失敗。

版本歷史

1
  1. v0.1.1最新Oct 21, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分