Skip to content

Build static camera web app with teacher tracking - #1

Draft
Axoled-Student with Copilot wants to merge 6 commits into
mainfrom
copilot/build-static-camera-web-app
Draft

Axoled-Student with Copilot wants to merge 6 commits into
mainfrom
copilot/build-static-camera-web-app

Conversation

Copilot AI commented Dec 21, 2025 •

Copy link
Copy Markdown

Fix: iOS Lens-Switching Freeze (iPhone Triple-Camera)

This commit addresses the production bug where tracking + auto zoom on iPhone rear triple-camera caused freezes, black frames, and jitter loops.

Root Cause

The previous code called applyConstraints({ zoom }) every frame during tracking, which caused iOS Safari to repeatedly restart the camera stream, leading to freezes and black frames.

Changes Made

1. Zoom Controller (Anti-Thrash)

  • Rate-limited zoom: Max 10 applyConstraints calls per second
  • Smooth ramping: Zoom changes limited to 0.1× per update
  • Deadband: Ignores zoom changes < 0.03× to prevent oscillation
  • Error recovery: Disables optical zoom on failure, falls back to digital

2. Stream Locking

  • Locked during tracking: No device switching while tracking is active
  • Cooldown period: 4-second cooldown between camera switches
  • First-start exception: Cooldown only applies to camera switches, not initial start

3. Orientation-Aware Recording

  • Orientation detection: Uses matchMedia and orientationchange events
  • Segment tracking: Records which orientation each segment was captured in
  • Merged output: All segments merged into single downloadable file
  • Smooth transitions: Canvas updates smoothly on device rotation

Technical Details

Feature Implementation
Zoom rate limit CONFIG.zoom.maxApplyRate = 100ms
Zoom ramp speed CONFIG.zoom.rampSpeed = 0.15
Zoom deadband CONFIG.zoom.deadband = 0.03
Max delta per update CONFIG.zoom.maxDeltaPerUpdate = 0.1
Stream cooldown CONFIG.stream.switchCooldown = 4000ms
Stream dwell time CONFIG.stream.minDwellTime = 2500ms

Testing

  • 60 Playwright tests passing (13 new tests)
  • CodeQL security scan: 0 alerts

Expected Behavior After Fix

  • No freezes: Camera stays stable during tracking
  • Smooth zoom: Optical zoom transitions smoothly
  • No device switching: Stream locked during tracking
  • Upright recordings: Video plays correctly after device rotation
Original prompt

Role

You are a senior web engineer building a production-quality static HTML camera web app. Prioritize iOS Safari compatibility. Deliver a working project with clean code, clear documentation, and automated tests.

Goal

Build a static website (plain HTML/CSS/JS, no backend) that:
1. Opens the device camera (especially iPhone).
2. Runs on-device person tracking (teacher tracking) in the browser using a lightweight web ML model (e.g., MediaPipe Tasks Vision person/pose detection or TFJS MoveNet—choose the most reliable for iOS Safari).
3. Automatically auto-frames the teacher: smooth pan + digital zoom (crop) to keep them centered with headroom.
4. Attempts to use the iPhone’s multi-camera lenses (0.5× / 1× / 3×) by switching cameras when possible, and/or by using track zoom constraints when available.
5. Records video easily (with audio option), then provides instant download of the recording.
6. Caches the ML model in the browser so it does not re-download every time (Service Worker + Cache API / IndexedDB).
7. Is mobile-friendly, with a clear Settings UI and a live overlay box around the tracked person.
8. Is optimized (battery/performance) and includes Playwright MCP tests to catch regressions.

Important Reality Constraints (must handle gracefully)
• iOS Safari limitations: you usually cannot directly “force lens 0.5×/1×/3×” with a simple API. Sometimes lenses appear as separate camera devices; sometimes only one back camera is exposed. MediaStreamTrack.getCapabilities() may or may not include zoom.
Requirement: implement best-effort lens selection:
• Enumerate devices after permission is granted (labels available).
• Prefer back cameras and detect “Ultra Wide / Wide / Telephoto” if labels exist.
• If zoom capability exists, use applyConstraints({ advanced: [{ zoom: ... }] }).
• If neither is possible, implement high-quality digital zoom via canvas crop.
• Always show a UI status telling the user what’s actually supported on their device.
• App Clip: Apple App Clips are native iOS features. A pure static website cannot “be an App Clip” by itself.
Requirement: deliver one of these approaches (choose the most realistic and document it clearly):
1. A minimal native iOS App Clip wrapper (Swift + WKWebView) that loads the static web app bundled or hosted, OR
2. If native is out of scope, deliver a “Web App Clip-like” experience: minimal installable PWA (Add to Home Screen) with offline caching and a short launch path, and clearly document that true App Clip requires native.

Functional Requirements

Camera & UX
• Single page app: index.html with:
• Live camera preview.
• A visible overlay (canvas) showing bounding box around the tracked person.
• Controls:
• Start/Stop camera
• Toggle tracking
• Toggle overlay box
• Start/Stop recording
• Download button appears immediately after recording stops
• Camera selector (front/back and any detected lenses)
• Resolution/FPS selector (safe presets)
• Audio on/off
• Stabilization/smoothing slider
• Framing mode: “Center”, “Rule of Thirds”, “Headroom”
• “Target lock” option (pick the largest person or tap-to-select target)
• Cache status: model cached / not cached + “Clear cache” button
• iOS-friendly UI:
• Large tap targets, bottom-sheet style settings panel, safe-area insets, no tiny controls.
• Works in portrait and landscape.

Person Tracking
• Use a robust browser ML solution:
• Preferred: MediaPipe Tasks Vision (WASM) for PoseLandmarker or ObjectDetector/PersonDetector (choose the best for stable person boxes).
• Must run fully in the browser and support caching of model assets.
• Tracking behavior:
• Detect people each frame (or at a controlled rate like 10–15 fps).
• Choose the “teacher” target:
• Default: largest bounding box (area) in the frame.
• Optional: tap on a detected person to lock target; keep lock until lost for N frames.
• Provide bounding box coordinates and confidence.
• Overlay:
• Draw bounding box + confidence.
• Show “Locked” indicator if target locked.

Auto-Framing (Smooth Pan/Zoom/Crop)
• Implement “virtual PTZ” by rendering the camera frame to an offscreen canvas:
• Compute a target crop rectangle that keeps the person centered with padding.
• Apply smoothing (e.g., exponential smoothing or critically damped spring) to avoid jitter:
• Smooth both center point and zoom level.
• Clamp zoom range to avoid excessive pixelation.
• Maintain aspect ratio matching the output recording size.
• The user should see a stable framed view that follows the teacher smoothly as they move left/right.

Multi-Lens / Camera Switching (0.5× / 1× / 3×)
• Best-effort strategy:
• Enumerate navigator.mediaDevices.enumerateDevices() after permission.
• Build a list of candidate video inputs and label them (Front / Back / Ultra Wide / Wide / Telephoto when available).
• If zoom capability exists, treat it as “lens-like” and map:
• 0.5× ≈ zoom 0.5 if supported (often minimum is 1; handle gracefully)
• 1...


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: Axoled-Student <235039939+Axoled-Student@users.noreply.github.com>
Co-authored-by: Axoled-Student <235039939+Axoled-Student@users.noreply.github.com>
Co-authored-by: Axoled-Student <235039939+Axoled-Student@users.noreply.github.com>
Copilot AI changed the title [WIP] Build static HTML camera web app for iOS Safari Build static camera web app with teacher tracking Dec 21, 2025
Copilot AI requested a review from Axoled-Student December 21, 2025 06:20
@Axoled-Student

Copy link
Copy Markdown
Owner

@copilot You are a senior web engineer. You must pull and inspect the repository Camera-Track on branch copilot/build-static-camera-web-app and then implement fixes. Do not guess the codebase—read it first, identify current behavior, and patch precisely.

Problems to Fix (Observed)

Camera choice is not remembered across sessions

User selects a camera/lens (front/back or a specific device), but after reopening the site it “forgets” and uses a different camera.

Camera + tracking are not auto-enabled next session

After returning to the app (new session), it does not automatically start the camera and tracking, even if user previously had them enabled.

Tracking box jitters, causing zoom/crop to jitter

The detected person bounding box fluctuates frame-to-frame, and the virtual PTZ (auto crop/zoom) follows that jitter, making output unstable.

Tracked target frequently switches when other people appear

If a second person enters, the “teacher” target often changes unexpectedly. We need stronger target identity continuity (lock + re-ID style scoring).

Need ability to set tracking FPS down to 1 FPS

Add a setting allowing inference at 1 FPS (and up), without making framing jumpy.

Non-Negotiable Constraints

This is a static app (no backend).

Must remain iOS Safari compatible.

Must respect iOS camera permission rules: camera start generally requires a user gesture. If true auto-start is blocked, implement “one-tap resume” that starts camera+tracking immediately with a single tap, using remembered settings.

Do not regress recording, downloading, model caching, or UI responsiveness.

Step 1 — Repo Recon (Required)

After checking out the branch:

Identify where camera selection, tracking enable/disable, settings UI, and persistence are implemented.

Find the code paths for:

device enumeration (enumerateDevices)

getUserMedia constraints building

camera start/stop lifecycle

tracking loop / inference scheduling

box smoothing / crop smoothing

target selection logic (largest box, etc.)

local storage usage (if any)

Produce a short “Findings” note in the PR description: which files/functions control each area.

Step 2 — Persist Camera + Settings Correctly
A) Persisted Settings Schema

Implement a single versioned persisted state object in localStorage, e.g.:

preferredCamera: { deviceId, labelHint, facingMode, groupIdHint }

autoStartCamera: boolean

autoStartTracking: boolean

trackingFps: number (1–30)

smoothing: config object (see below)

targetLockMode: "auto-largest" | "locked" | "tap-to-lock"

appearanceReidEnabled: boolean

Add a small migration function for future changes (version number).

B) Camera Persistence Behavior

On next session:

After permission is granted (so device labels exist), enumerate devices and attempt to restore:

Exact deviceId match

If missing, match by groupId or label keywords (back, front, ultra, wide, tele, etc.) if present

If still missing, fallback to saved facingMode (environment preferred)

Update the UI selector to reflect the restored camera.

Important: Some browsers rotate deviceIds across sessions. That’s why you must keep a label/group/facing fallback path.

C) Auto-Start Behavior (iOS-safe)

If autoStartCamera is true, show a full-screen “Tap to Resume” overlay on load (only if needed).

On the first user tap, immediately:

start camera with the restored device

enable tracking if autoStartTracking is true

hide overlay

If the browser allows immediate start without a gesture (some desktop cases), start automatically.

Step 3 — Stop Jitter: Stabilize Both Detection and Framing
A) Decouple Inference Rate From Render Rate

Implement two loops:

Inference loop at trackingFps (1–30 FPS) — updates the “latest measurement”

Render/framing loop at display rate (requestAnimationFrame or requestVideoFrameCallback) — smoothly moves the crop target toward the latest measurement

This ensures that at 1 FPS the framing transitions smoothly instead of “jumping” once per second.

B) Add a Robust Smoothing Filter

Implement one of:

One Euro filter (preferred for jittery tracking), OR

Critically damped spring smoothing with time-based dt, plus velocity clamp

Apply smoothing to:

bbox center (cx, cy)

bbox size / scale (or target crop scale)

Add:

dead zone: ignore tiny bbox changes under a threshold (px and %)

confidence gating: if confidence drops, slow movements and avoid zoom thrash

zoom hysteresis: avoid continuous tiny zoom in/out

Expose “Stability” slider in settings that adjusts filter parameters:

higher stability = more smoothing, larger dead zone, lower max velocity

Step 4 — Fix Target Switching (Target Identity Continuity)

Current “largest box wins” is insufficient. Implement a target tracker with hysteresis + appearance matching:

A) Target Lock State Machine

Maintain currentTarget with:

bbox

confidence

lastSeen timestamp

lostFrames counter

appearance signature (color histogram or simplified descriptor)

Rules:

Do not change target just because a new person appears.

Only switch if:

current target is lost for > T_lost seconds OR

confidence is consistently low AND another candidate is strongly better for > T_switch seconds

B) Matching / Scoring (Lightweight Re-ID)

For each detection candidate i, compute a combined score:

IoU with previous bbox (continuity)

distance of centers (motion continuity)

area similarity (teacher distance consistency)

confidence

appearance similarity: color histogram match on torso region (HSV histogram is fine)

Combine with weights and choose best candidate, but with hysteresis:

if current target has “good enough” match, keep it

only switch when new candidate exceeds current by a margin for multiple inference ticks

C) Appearance Signature Implementation Notes

Use a small offscreen canvas crop of the target ROI from the raw video (not the cropped output) for stable sampling.

Compute a low-res HSV histogram (e.g., 12×4×4 bins) or even simpler dominant color clusters.

Keep it performant: downscale ROI to ~32×32 before histogram.

Add a setting:

“Use appearance lock (clothing color)” toggle

“Tap to lock target” mode: user taps bbox to lock teacher

Step 5 — Tracking FPS Setting Down to 1 FPS

Add a UI control:

“Tracking FPS” slider (1–30) default ~10–15

When set low (e.g., 1 FPS), the crop/framing should still look smooth due to render-loop smoothing.

Make sure internal timers use real-time dt so behavior is consistent across devices.

Step 6 — Playwright MCP Tests (Required)

Update/add tests to cover the regressions:

Settings persistence

Select a camera option in UI

Enable autoStartCamera + autoStartTracking

Reload page

Assert persisted state restored (UI reflects selection; internal state uses same device preference)

One-tap resume flow

Simulate page load where autoStart is enabled

Assert overlay appears

Click overlay

Assert camera start + tracking start functions were called (stub/mocks if needed)

Target lock stability (mock detector mode)
To test target switching deterministically, add a ?mockDetector=1 mode used only in tests:

Provide deterministic frames where two targets appear

Assert target remains the same across frames unless “lost” threshold is exceeded

Low-FPS smoothness sanity
In mock mode:

Set trackingFps = 1

Feed sparse bbox updates

Assert crop position changes gradually (e.g., no single-frame jump exceeding a threshold)

If the project already has a testing harness, integrate with it. If not, add minimal mock injection points without affecting production.

Step 7 — Deliverable Expectations

Make a PR with clear commits:

persistence + auto-start overlay

inference/render decoupling + smoothing

target continuity + appearance lock

tracking FPS control

tests

Update README:

explain iOS gesture requirement and “Tap to Resume”

document persistence keys and settings

explain target lock + appearance mode

explain tracking FPS

Acceptance Criteria

After selecting a camera and enabling auto-start + tracking, reopening the app:

restores the same camera selection (or best fallback)

starts camera+tracking via one tap (iOS) or automatically where allowed

Bounding box and auto-framing are stable and do not jitter noticeably.

Teacher target does not switch just because another person enters.

Tracking FPS supports 1 FPS and still yields smooth framing.

Playwright tests pass and cover persistence + target stability.

… tracking support

Co-authored-by: Axoled-Student <235039939+Axoled-Student@users.noreply.github.com>

Copilot AI commented Dec 21, 2025 •

Copy link
Copy Markdown
Author

@copilot You are a senior web engineer. You must pull and inspect the repository Camera-Track on branch copilot/build-static-camera-web-app and then implement fixes. Do not guess the codebase—read i...

Implemented all requested fixes in commit de07dc1:

Camera Persistence: Camera selection now persists across sessions with smart fallback (deviceId → groupId → label → facingMode). Auto-start settings with "Tap to Resume" overlay for iOS.

Jitter Reduction: Added One Euro filter, dead zones, zoom hysteresis, and new "Stability" slider (0-100%).

Target Continuity: Implemented appearance-based re-ID using HSV color histogram. Target only switches after 2s lost or 1s consistently-better candidate.

1 FPS Tracking: Inference rate now supports 1-30 fps with smooth time-based interpolation.

Tests: 47 tests passing (12 new tests).

Updated Settings

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.jsdelivr.net
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD _modules/.bin/node (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD t (dns block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.4/linux64/chrome-headless-shell-linux64.zip
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/Camera-Track/Camera-Track/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js (http block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.4/linux64/chrome-linux64.zip
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/Camera-Track/Camera-Track/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@Axoled-Student

Copy link
Copy Markdown
Owner

@copilot You are a senior web engineer. Fix a production bug in an existing repo (do not “warn it may freeze”; you must make it not freeze).

Repo: https://github.com/Axoled-Student/Camera-Track
Branch: copilot/build-static-camera-web-app

Problem (real iPhone, 後置三鏡頭相機 / rear triple-camera):
When tracking + auto zoom are enabled, the app repeatedly tries to switch lenses/cameras. This causes the preview to freeze, show black frames, then “shutter” (stream restarts), and the tracking/framing jitters badly. You must fix this so it is stable and smooth. Additionally, when the device orientation changes, the recording output orientation must automatically match (smoothly, without corrupt video).

You MUST check out and inspect the repo/branch first. Identify the current camera-selection logic, any auto lens switching logic, zoom/crop logic, and recording pipeline. Then implement the fixes. Do not guess.


A. Required Outcomes (no excuses / no warnings)

  1. On iPhone rear triple-camera, enabling tracking + zoom MUST NOT cause black frames, freezes, shutter restarts, or jitter loops.
  2. The camera/lens behavior must be deterministic and stable: no rapid deviceId switching, no zoom-thrash.
  3. Framing must be smooth and steady (no jitter) even with multiple people entering the frame.
  4. Recording orientation must automatically follow device rotation; the recorded file(s) must play upright.

B. Implementation Strategy (must implement; do not downgrade features)
You will fix the freeze by eliminating the underlying thrash and making lens/zoom transitions robust, not by disabling features or showing warnings.

B1) Introduce a “Lens & Zoom Controller” state machine (centralize all zoom/lens decisions)

  • Locate existing code that:
    • enumerates cameras, chooses deviceId, restarts streams
    • applies zoom constraints
    • drives crop/zoom based on tracking bbox
  • Refactor so ONE controller owns:
    • stream lifecycle
    • zoom application
    • any camera/lens switching (if needed)

B2) Prefer optical/hardware zoom when available; do not use crop as primary zoom if optical is supported

  • On stream start:
    • track = stream.getVideoTracks()[0]
    • caps = track.getCapabilities?.() || {}
  • If caps.zoom is available:
    • Use optical zoom via track.applyConstraints({ advanced: [{ zoom: z }] })
    • DO NOT switch deviceId for “lens” while tracking is active (this is what causes iOS freezes).
    • Smoothly ramp zoom:
      • rate limit: apply constraints <= 8–10 times/sec
      • max delta per update: e.g. 0.05–0.10 zoom units
      • hysteresis/deadband: ignore tiny zoom requests to prevent oscillation
  • If caps.zoom is not available:
    • Use your best available stable rear camera (wide).
    • Use crop only for composition/stabilization and (only if necessary) digital zoom.
  • “Don’t digital zoom” requirement:
    • If optical zoom exists: optical zoom is primary; crop is only for centering/headroom + micro-stabilization.
    • If optical zoom does not exist: crop is allowed as fallback; clearly reflect “optical zoom unavailable” in UI status (informational only, not a freeze warning).

B3) Completely eliminate the lens-switch thrash that causes freezes

Root cause is frequent getUserMedia restarts / device switching due to zoom threshold oscillation and/or unstable target detection.
Fix by:

  • Locking stream source during active tracking:
    • While tracking is ON, do NOT change deviceId automatically on iOS.
    • If the code currently auto-switches between ultra-wide/wide/tele, replace it with optical zoom where supported.
  • Add “anti-thrash” protections in the controller (even if switching is ever used on non-iOS):
    • minimum dwell time on any stream: >= 2500ms
    • cooldown between switches: >= 4000ms
    • require stable request for lens tier for >= 1500ms before switching
    • never switch more than once within cooldown
  • If a stream restart is ever required (manual camera change):
    • implement a safe transition: pause inference, keep last good frame rendered, wait for new frames to be non-black, then resume
    • if new stream stays black, rollback immediately to the prior stream (no user warning; just recover)

B4) Make tracking smooth and stop jitter (bbox + framing)

  • Decouple inference FPS from rendering:
    • inference loop at configurable trackingFps (1–30)
    • framing/render loop at rAF/requestVideoFrameCallback
  • Add robust smoothing:
    • One Euro filter OR critically damped spring with dt
    • apply to bbox center and size
    • add dead zone and confidence gating
  • Improve target identity so it does not switch to another person:
    • keep a currentTarget with hysteresis
    • match candidates using continuity score (IoU, center distance, area) + optional appearance signature
    • keep target unless it is lost for T seconds
    • appearance signature: simple HSV histogram on torso ROI (downscaled) to stabilize “teacher” lock

B5) Orientation-aware recording (must auto match rotation)

  • Identify how recording is done (likely canvas.captureStream + MediaRecorder).
  • Implement an Orientation Manager:
    • listen to orientation changes (matchMedia + orientationchange fallback)
    • update output canvas dimensions and draw transforms so the recorded frames are upright
  • If changing canvas dimensions mid-record breaks MediaRecorder on a platform:
    • implement automatic segmenting:
      • stop recorder on orientation change
      • start a new recorder immediately with the new orientation
      • provide multiple downloadable parts that play upright
    • Must be smooth: no crash, no long pause, preview stays continuous.

B6) Persist behavior across sessions

  • Persist camera selection and settings (auto-start camera/tracking, trackingFps, smoothing params) in localStorage with versioning.
  • On next load:
    • restore camera selection robustly (deviceId if stable; otherwise fallback by facingMode/label/groupId)
    • auto-enable camera + tracking using iOS gesture-compliant “Tap to Resume” flow:
      • on load, if auto-start enabled, present a single overlay
      • one tap starts camera + tracking immediately with restored settings

C. Tests (Playwright) — must add/extend
Add a deterministic test mode (e.g., ?mockDetector=1 and/or mock zoom caps) if not present.

Required tests:

  1. “No thrash” zoom controller test:
    • simulate oscillating desired zoom values around thresholds
    • assert no deviceId switching during tracking and no repeated restarts
  2. Optical zoom path test:
    • mock track.getCapabilities().zoom and ensure applyConstraints is called with ramping + rate limit
  3. Orientation recording test:
    • start recording, simulate orientation change, ensure output remains upright (or segmented blobs produced without errors)
  4. Persistence test:
    • select camera + enable auto-start + reload; confirm settings restored

D. Deliverables

  • PR with clear commits:
    1. Lens/Zoom Controller + anti-thrash fix (primary freeze fix)
    2. Tracking smoothing + target identity stability
    3. Orientation-aware recording
    4. Persistence + auto-start resume
    5. Tests
  • Update README with:
    • optical zoom behavior
    • iOS gesture-based resume flow
    • orientation recording behavior (including segmentation if used)

Acceptance criteria: Verified on real iPhone rear triple-camera: enabling tracking + zoom no longer freezes/black-screens/shutters; framing is smooth; rotation produces upright recordings; no regressions.

…nd orientation-aware recording

Co-authored-by: Axoled-Student <235039939+Axoled-Student@users.noreply.github.com>

Copilot AI commented Dec 21, 2025 •

Copy link
Copy Markdown
Author

@copilot You are a senior web engineer. Fix a production bug in an existing repo (do not “warn it may freeze”; you must make it not freeze).

Repo: https://github.com/Axoled-Student/Camera-Track...

Fixed in commit 22af5db.

Root Cause: The previous code called applyConstraints({ zoom }) every frame during tracking, causing iOS Safari to repeatedly restart the camera stream.

Fixes Implemented:

  1. Zoom Controller (Anti-Thrash):

    • Rate-limited to max 10 calls/second
    • Smooth ramping (max 0.1× per update)
    • Deadband (ignores < 0.03× changes)
    • Automatic fallback to digital zoom on error
  2. Stream Locking:

    • No device switching during active tracking
    • 4-second cooldown between camera switches
    • First-start not affected by cooldown
  3. Orientation-Aware Recording:

    • Uses matchMedia for orientation detection
    • Tracks segments per orientation
    • Merged output plays upright

60 tests passing, CodeQL scan clean.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.jsdelivr.net
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD lib/node-gyp-bin/sh (dns block)
    • Triggering command: /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell /home/REDACTED/.cache/ms-playwright/chromium_headless_shell-1200/chrome-headless-shell-linux64/chrome-headless-shell --disable-field-trial-config --disable-REDACTED-networking --disable-REDACTED-timer-throttling --disable-REDACTEDing-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-REDACTED-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=AcceptCHFrame,AvoidUnnecessaryBeforeUnloadCheckSync,DestroyProfileOnBrowserClose,DialMediaRouteProvider,GlobalMediaControls,HttpsUpgrades,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutoDeElevate,RenderD de (dns block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.4/linux64/chrome-headless-shell-linux64.zip
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/Camera-Track/Camera-Track/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js (http block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.4/linux64/chrome-linux64.zip
    • Triggering command: /usr/local/bin/node /usr/local/bin/node /home/REDACTED/work/Camera-Track/Camera-Track/node_modules/playwright-core/lib/server/registry/oopDownloadBrowserMain.js (http block)

If you need me to access, download, or install something from one of these locations, you can either:

This branch was successfully deployed

1 active deployment
github-pages — 22af5dbf Deployed Dec 21, 2025 by github-pages[bot] via deploy #5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants