스트리밍 레코더¶
이 페이지는 CLAUDE.md의 구현 노트를 미러합니다. 서브시스템 변경 시
양쪽 다 업데이트하세요.
Enable Streaming이 켜지면 Cue는 백그라운드 비디오 캡처 파이프라인을
실행하고 몇 초마다 디지스트 모델에 입력합니다. 레코더는 외부 CLI
(vendor/ocap-{macos,windows} 아래에 vendoring)로 ~10 fps에서
실행되는 서브프로세스입니다. ocap은 GStreamer + 하드웨어 H.265
인코딩(Apple Silicon / NVIDIA에서 거의 zero CPU)을 사용하고 다음을
씁니다:
<스트리밍 루트>/stream/chunk_<ts>.mkv— 비디오.<스트리밍 루트>/stream/chunk_<ts>.mcap— 구조화된 키보드 / 마우스 / 윈도우 / 화면 이벤트.
파이프라인¶
sequenceDiagram
participant Cue as Cue (parent)
participant Rotator
participant Ocap as ocap subprocess
participant Pruner as pruner worker
participant Evictor
participant Digest as digest worker
Cue->>Rotator: start()
loop chunk_secs마다 (기본 30초)
Rotator->>Ocap: spawn (ocap-macos / ocap-windows CLI)
Ocap-->>Rotator: chunk_<ts>.mkv + chunk_<ts>.mcap
Rotator->>Pruner: 닫힌 chunk에 대해 spawn
Pruner->>Pruner: dhash + 이벤트 인지 키프레임 추출
Pruner-->>Cue: keyframe_<ts>.jpg 파일들
end
loop 60초마다
Evictor->>Evictor: window_secs (기본 15분) 밖 chunks/keyframes 제거
end
loop 디지스트 틱(5초)마다
Digest->>Digest: 최근 MCAP 이벤트 + 키프레임 읽기
Digest->>Digest: 최대 10 프레임 선택 + 이벤트 scrub
Digest->>Digest: cue.llm.summarize_digest_with_policy 호출
Digest->>Cue: digest.md 작성 + digests row 삽입
end
ocap 위 Cue 스레드¶
| 스레드 | 역할 |
|---|---|
| rotator | streaming.chunk_secs (기본 30초) 마다 현재 ocap을 멈추고 새 chunk 시작. ocap이 예기치 않게 죽으면도. 회전 후 chunk별 pruner 서브프로세스 spawn. |
| pruner worker | 닫힌 MKV를 owa.gstreamer.gst.mkv_reader로 읽고, 각 프레임 dhash. 이전 키프레임과 큰 차이 또는 실제 입력 이벤트(키 / 클릭 / 윈도우 변경)에 후행하는 프레임만 보존. 키프레임 디렉토리에 작은 JPEG 작성. GStreamer env가 부모로 누설되지 않도록 자체 서브프로세스 spawn. |
| evictor | 60초마다 종료 시간이 streaming.window_secs (기본 15분)보다 오래된 chunk 파일 삭제. 같은 cutoff가 키프레임 JPEG에도 적용. |
| digest | 최근 MCAP 메시지 읽기, 텍스트 PII scrub, 설정된 백엔드로 전송, digest.md 작성. 디지스트 파이프라인 참고. |
ocap이 서브프로세스인 이유¶
GStreamer + 하드웨어 H.265 인코딩은 Cue 자체 Python과 in-process로 공존하기 어려움 — PyGObject가 GLib, GStreamer.framework dylib들을 끌어와 Cue 프로세스 상태와 충돌. 서브프로세스로 ocap을 띄우면 이를 회피하고 프라이버시 일시정지의 SIGKILL을 위한 깔끔한 프로세스 경계 제공.
서브프로세스는 ocap CLI (owa.ocap_macos.cli 또는
owa.ocap_windows.cli)로 실행 — Cue 자체는 GStreamer 레코더 모듈을
import하지 않음.
스냅샷 컨텍스트¶
핫키 경로는 recorder.snapshot_context(recent_secs, max_events)로
digest.md + 가장 최근 MCAP 이벤트 + 최대 3개 pruner 키프레임을
읽음. Opus는 핫키 경로에서 핫키 시점 캡처 지연 없이 "누적된 지식"을
받음.
스트리밍 루트 경로 (macOS)¶
스트림 + 키프레임 디렉토리는 ~/Library/Application Support/Cue/가
아니라 ~/Library/Caches/Cue/ 아래에 있음 — GStreamer
filesink location=...이 공백을 견디지 못해서. Windows는 일반적인
%LOCALAPPDATA%\Cue 사용.
Vendoring¶
레코더는 vendor/ 아래 두 git 서브모듈로 존재:
vendor/ocap-macos—owa.ocap_macos.recorder제공. pyproject가owa-env-desktop==0.6.5에 핀.vendor/ocap-windows—owa.ocap_windows.recorder제공.
둘 다 vendor/open-world-agents-private에 의존하여 owa-core,
owa-msgs, owa-env-desktop, mcap-owa-support, owa-cli 가져옴.
Cue 클론 후 첫 install 전에:
git submodule update --init --recursive
서브모듈 / 벤더링 참고.
프라이버시 상호작용¶
프라이버시 일시정지가 ocap을 즉시 SIGKILL (프라이버시 일시정지 에서 graceful shutdown을 안 쓰는 이유 참고). pruner / evictor / digest 스레드는 계속 실행되지만 새 chunk를 못 찾으니 자연스럽게 파이프라인이 비워짐. 일시정지 해제 시 새 ocap 세션 spawn.
더 보기¶
cue.recorder— 모듈 API.cue.pruner— 키프레임 추출 모듈.- 디지스트 파이프라인 — 키프레임 + MCAP 소비처.
- 크로스 플랫폼 규칙 — 두 플랫폼 동기화.