Metadata-Version: 2.4
Name: vcon-laptop
Version: 0.1.0
Summary: Record laptop activity (screenshots, audio, webcam) into spec-compliant vCon objects
Author-email: Thomas Howe <thomas@strolid.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/vcon-dev/vcon-laptop
Project-URL: Repository, https://github.com/vcon-dev/vcon-laptop
Project-URL: Issues, https://github.com/vcon-dev/vcon-laptop/issues
Keywords: vcon,recording,screenshot,transcription,obsidian
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio :: Capture/Recording
Classifier: Topic :: Multimedia :: Video :: Capture
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mss>=9.0
Requires-Dist: Pillow>=10.0
Requires-Dist: sounddevice>=0.4
Requires-Dist: soundfile>=0.12
Requires-Dist: opencv-python>=4.8
Requires-Dist: numpy>=1.24
Requires-Dist: httpx>=0.25
Requires-Dist: python-dotenv>=1.0
Provides-Extra: analysis
Requires-Dist: anthropic>=0.40; extra == "analysis"
Requires-Dist: openai>=1.30; extra == "analysis"
Requires-Dist: mlx-whisper>=0.4; extra == "analysis"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Requires-Dist: ruff>=0.1; extra == "dev"
Provides-Extra: all
Requires-Dist: vcon-laptop[analysis,dev]; extra == "all"
Dynamic: license-file

# vcon-laptop

Record laptop activity — screenshots, microphone audio, and webcam video — into spec-compliant [vCon](https://datatracker.ietf.org/doc/draft-ietf-vcon-vcon-core/) objects. Optionally transcribe audio, describe screenshots with AI, and export session notes to an Obsidian vault.

## Features

- **Screen capture** — periodic screenshots via `mss` (cross-platform) with macOS `screencapture` fallback
- **Audio recording** — continuous microphone capture via `sounddevice`
- **Video recording** — webcam capture via OpenCV at configurable FPS (default 1 fps for activity logging)
- **Capture budget** — stop recording automatically when a size limit is hit (`MAX_CAPTURE_MB`)
- **AI analysis** — fully local by default, no API keys required:
  - Audio transcription: [mlx-whisper](https://github.com/ml-explore/mlx-examples/tree/main/whisper) (Apple Silicon)
  - Screenshot descriptions: [Ollama](https://ollama.com/) with any vision model (default `gemma3:4b`)
  - Session summary: generated from transcription + descriptions
  - Fallback chain: Ollama → OpenAI → Anthropic (when API keys are configured)
- **Obsidian export** — markdown note with YAML frontmatter, `![[wikilink]]` image embeds, transcription, and AI descriptions
- **Conserver posting** — POST vCon JSON to a conserver endpoint with API token auth and ingress routing
- **vCon compliant** — `extensions`, `parties` with `validation`, `sha512-base64url` content hashes, `purpose`-based attachments

## Quick start

```bash
git clone https://github.com/vcon-dev/vcon-laptop.git
cd vcon-laptop
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[analysis]"

# Copy and edit config
cp .env.example .env

# Record for 30 seconds (screenshots only)
vcon-laptop --sources screenshot --duration 30

# Record everything for 2 minutes with a 100 MB cap
vcon-laptop --duration 120 --max-mb 100
```

## Configuration

All settings are loaded from environment variables or a `.env` file. See [`.env.example`](.env.example) for the full reference.

### Capture

| Variable | Default | Description |
|----------|---------|-------------|
| `CAPTURE_SOURCES` | `screenshot,audio,video` | Comma-separated sources to enable |
| `SCREENSHOT_INTERVAL` | `5` | Seconds between screenshots |
| `VIDEO_FPS` | `1` | Webcam frames per second |
| `MAX_CAPTURE_MB` | `0` | Stop recording at this size (0 = unlimited) |
| `MAX_SESSION_DURATION` | `0` | Stop after this many seconds (0 = unlimited) |

### Analysis

| Variable | Default | Description |
|----------|---------|-------------|
| `OLLAMA_URL` | `http://localhost:11434` | Ollama server for vision + summary |
| `OLLAMA_MODEL` | `gemma3:4b` | Ollama model (must support vision) |
| `WHISPER_MODEL` | `mlx-community/whisper-small-mlx` | HuggingFace model for mlx-whisper |
| `ANTHROPIC_API_KEY` | | Fallback for image description + summary |
| `OPENAI_API_KEY` | | Fallback for vision + Whisper transcription |

### Obsidian

| Variable | Default | Description |
|----------|---------|-------------|
| `OBSIDIAN_VAULT_PATH` | | Path to vault root (blank = skip export) |
| `OBSIDIAN_FOLDER` | `Recordings` | Subfolder for recording notes |

## CLI options

```
vcon-laptop [--sources screenshot,audio,video]
            [--duration SECONDS]
            [--max-mb MB]
            [--output DIRECTORY]
            [--env PATH]
            [-v|--verbose]
```

Press `Ctrl+C` to stop recording. The session is saved, analyzed, and exported on stop.

## vCon output

Each session produces a `session.vcon.json` file:

```json
{
  "vcon": "0.0.1",
  "uuid": "...",
  "created_at": "2026-04-12T17:45:29+00:00",
  "parties": [{"name": "anonymous", "validation": "anonymous", "role": "agent"}],
  "dialog": [
    {"type": "recording", "mediatype": "image/png", "filename": "screen_00000.png", ...},
    {"type": "recording", "mediatype": "audio/wav", "duration": 13.36, ...},
    {"type": "recording", "mediatype": "video/mp4", "duration": 8.47, ...}
  ],
  "analysis": [
    {"type": "transcript", "vendor": "mlx-community", "body": "..."},
    {"type": "report", "vendor": "Ollama", "schema": "screenshot-description-v1", "body": "..."},
    {"type": "summary", "vendor": "Ollama", "body": "..."}
  ],
  "attachments": [
    {"purpose": "tags", "body": "{\"source\": \"laptop_adapter\", ...}", "encoding": "json"}
  ]
}
```

## Analysis performance

| Provider | Per screenshot | Summary | Total (2 shots) | Cost |
|----------|---------------|---------|-----------------|------|
| Ollama gemma3:4b | ~60s | ~100s | ~7 min | Free |
| OpenAI gpt-4o-mini | ~4s | ~2s | ~10s | $ |
| Anthropic Sonnet | ~5s | ~3s | ~13s | $$ |

## Tests

```bash
pip install -e ".[dev]"
pytest tests/ -v
```

69 tests covering config, builder, storage, poster, analysis (with mocked APIs), Obsidian export, and session lifecycle.

## Architecture

```
vcon_laptop/
├── main.py          CLI entry point
├── config.py        Env-based configuration
├── session.py       Session lifecycle + size monitoring
├── builder.py       Assembles media into vCon JSON
├── analyze.py       Transcription + image description + summary
├── obsidian.py      Obsidian vault markdown export
├── storage.py       Save vCon to disk
├── poster.py        POST to conserver
└── capture/
    ├── screenshot.py   Periodic screen capture (mss / screencapture)
    ├── audio.py        Mic recording (sounddevice callback)
    └── video.py        Webcam recording (OpenCV)
```

## Related projects

- [vcon-lib](https://github.com/vcon-dev/vcon-lib) — Python vCon library
- [vcon-server](https://github.com/vcon-dev/vcon-server) — vCon processing server
- [vcon-audio-adapter](https://github.com/vcon-dev/vcon-audio-adapter) — Audio file adapter

## License

MIT
