Files
L'électron rare 39457dde41 docs: iPhone capture plan (2 of 3)
Plan for HEVC video capture (VideoToolbox) over the USB
transport and removal of the legacy OSC sender. Skeleton
USB path already exists; this adds the video half.
2026-05-18 17:23:38 +02:00

95 lines
4.6 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
iPhone-only app that streams ARKit `ARBodyAnchor` joints (91 per body) to
the AV-Live stack on a tethered Mac. Part of the parent `AV-Live/`
monorepo — read `../CLAUDE.md` for global conventions (commit style,
French/English split, no emoji, etc.).
## Two build forms, one source tree
Both flavours compile the same files under
`ARBodyTracker.swiftpm/Sources/ARBodyTracker/`:
| Form | When to use | How |
|------|-------------|-----|
| `ARBodyTracker.swiftpm/` (Swift Package) | Quick local iteration; previews | open `Package.swift` in Xcode |
| `ARBodyTracker.xcodeproj` (generated) | Device deploy with reproducible signing | `xcodegen generate` from `project.yml` |
The `.xcodeproj` is **gitignored** — regenerate after every change to
`project.yml` or after adding sources. `Config/Local.xcconfig` (also
gitignored) carries `DEVELOPMENT_TEAM`; copy from
`Config/Local.xcconfig.example` on a fresh clone.
## Common commands
```bash
brew install xcodegen # one-time
cp Config/Local.xcconfig.example Config/Local.xcconfig # set DEVELOPMENT_TEAM
xcodegen generate # writes ARBodyTracker.xcodeproj
open ARBodyTracker.xcodeproj # then ⌘R on a connected iPhone
# AVLiveWire — shared wire-format package (consumed by both the iOS
# app and launcher/AV-Live-Body on macOS). Tests live with it.
cd ../shared/AVLiveWire && swift test
cd ../shared/AVLiveWire && swift test --filter LoopbackTests
```
`xcodegen generate` is the one command to remember: any time `project.yml`
or the dep on `../shared/AVLiveWire` changes, the generated project must
be rebuilt before opening Xcode.
## Architecture
```
ARBodyTrackerApp ── ContentView ── ARViewContainer (ARView)
│ │
│ └─ ARBodySession (ARSessionDelegate)
│ ├─ OSC fanout (UDP) ─► host:57128 (Python data_only_viz)
│ │ host:57129 (Swift AV-Live-Body)
│ ├─ USBServer (TCP :7000, AVLiveWire frames)
│ └─ @Published skeleton2D ──┐
└─ SkeletonOverlay (SwiftUI Canvas) ◄─────────┘
```
- **`ARBodySession`** owns the `ARSession` configured with
`ARBodyTrackingConfiguration` (RGB-only; LiDAR `sceneDepth` is not
available on this config, do not re-add it — it crashes the session).
Throttles to 30 fps. Projects joints to 2D via
`ARCamera.projectPoint(_:orientation:viewportSize:)`; the viewport
size is fed back from the SwiftUI `GeometryReader`.
- **Transport** is dual: legacy OSC/UDP (still default), and a new
USB/TCP path using `AVLiveWire` framed messages. The Mac side bridges
via `usbmuxd`; the iOS side just listens on a fixed local port. No
WiFi involved on the USB path.
- **`AVLiveWire`** (in `../shared/AVLiveWire`) defines a fixed 19-byte
big-endian header (`AVL1` magic + tag + pid + timestamp + length) and
an incremental `StreamDemuxer`. Both the iOS `USBServer` and the
macOS consumer link against it so the wire format lives in exactly
one place.
- **`SkeletonOverlay`** draws joints and bones from a published
`SkeletonSnapshot`; bone parent indices come from
`ARSkeletonDefinition.defaultBody3D.parentIndices` at runtime. For
Xcode previews the snapshot/parents are replaced by a 16-joint
stick-figure mock (ARKit's `neutralBodySkeleton3D` returns nil off
device).
## Gotchas
- **Frame semantics:** `ARBodyTrackingConfiguration` rejects
`.sceneDepth` (world-tracking only) and spams `ABPKPersonIDTracker:
Portrait image is not supported` per-frame if
`.personSegmentationWithDepth` is added. Keep `feats` empty unless a
newly-needed semantic is verified against
`ARBodyTrackingConfiguration.supportsFrameSemantics(_:)`.
- **Signing without an Apple ID logged into Xcode:** with
`CODE_SIGN_STYLE = Automatic`, Xcode needs the account in
Settings → Accounts to download a profile. If only the keychain
cert is present, the build fails with "No Account for Team …".
Reconnect the account, or fall back to a manually installed profile
via `CODE_SIGN_STYLE = Manual` + `PROVISIONING_PROFILE_SPECIFIER`.
- **`UIDeviceFamily` warning:** `Info.plist` and `TARGETED_DEVICE_FAMILY`
duplicate the device family. The build setting wins; the Info.plist
key only generates a warning and can be removed if desired.