DEV Community

Cover image for Saturday Sessions: Elizabeth Cook performs "Girls of Atomic City"
Ashish
Ashish

Posted on

Saturday Sessions: Elizabeth Cook performs "Girls of Atomic City"

Elizabeth Cooks CBS-Auftritt als Lens für VR HealthTech Implementation: Amblyotube unter der Haube

CBS Saturday Sessions: Elizabeth Cook, „Girls of Atomic City“, 400+ Opry-Shows, Letterman-Film-Referenz. Für Entwickler:innen interessant ist, wie dieselbe Video-Streaming-Infrastruktur therapeutisch repurposed wird. Amblyotube (Seven Sportz, Meta Quest/Unity URP) nimmt Standard-Video-Streams (YouTube API), projiziert sie in VR und splittet im Rendering-Pipeline pro Auge separate Texturen. Kern: dynamische Kontrolle der Stimulation pro Auge (Kontrast, Luminanz, Unterdrückung des dominanten Auges) zur Amblyopie-Behandlung – alles zur Laufzeit, bei konstanter Framerate.

Technische Architektur: Dichoptisches Rendering in Unity URP

Herzstück ist ein Dual-Camera-Setup mit separaten RenderTextures – eine pro Auge. Zwei Camera-Instanzen blicken auf dieselbe Scene, aber mit unterschiedlichen targetTexture-Assignments. Der Video-Stream (YouTube API → VideoPlayer-Texture) wird nicht gespiegelt, sondern pro Auge unterschiedlich modifiziert bevor er ins Headset geht.

Camera_Left  → RenderTexture_Left  → Left Eye Display
Camera_Right → RenderTexture_Right → Right Eye Display
Enter fullscreen mode Exit fullscreen mode

Beide Cameras rendern denselben Video-Quad, aber ein Custom URP Render Feature (nach Opaque, vor Final Blit) wendet augen-spezifische Parameter an – minimaler Overhead, deterministische Frame-Zeit.

Dominant Eye Shader: Digitale Okklusion als Parameter

Ein Fullscreen-Post-Process mit vier uniforms:

float4 frag(Varyings input) : SV_Target {
    float4 col = SAMPLE_TEXTURE2D(_VideoTex, sampler_VideoTex, input.uv);
    col.rgb = lerp(col.rgb, 0, _Opacity);   // Digital Patching (0-1)
    col.rgb *= _Contrast;                    // Kontrast-Abschwächung
    col.rgb += _Brightness;                  // Luminanz-Offset
    col.rgb = Blur(col, _BlurRadius);        // Gauss-Blur (separable)
    return col;
}
Enter fullscreen mode Exit fullscreen mode

_Opacity = 1 → vollständiges digitales Patchen. Klinisch relevanter: partielle Werte (0.3–0.7) – beide Augen bleiben aktiv, dominantes wird gedämpft. Das ist MFBF (Monocular Fixation in Binocular Field): binokulare Fusion erzwingen, nicht monokulare Isolation.

Lazy Eye Sharpener: AI-gesteuerte ROI-Schärfung

Human Figure Detection läuft on-device (Quest 2/3/Pro – Snapdragon XR2). MediaPipe Pose / Custom TFLite liefert Bounding Boxes + Keypoints. ROI-Daten wandern per ComputeBuffer in den Sharpener-Shader:

// ROI Mask Generation (Compute Shader)
[numthreads(8,8,1)]
void CSMain(uint3 id : SV_DispatchThreadID) {
    if (id.x >= width || id.y >= height) return;
    float2 uv = id.xy / float2(width, height);
    float mask = 0;
    for (uint i = 0; i < _PersonCount; i++) {
        float2 center = _PersonCenters[i];
        float2 scale  = _PersonScales[i];
        float d = length((uv - center) / scale);
        mask = max(mask, smoothstep(1.0, 0.8, d));
    }
    _ROIMask[id.xy] = mask;
}
Enter fullscreen mode Exit fullscreen mode

Der Sharpener wendet nur im ROI Unsharp-Mask / High-Boost an – exklusiv für das faule Auge. Hintergrund, UI bleiben unberührt. Reduziert kognitive Last, fokussiert Plastizität auf sozial relevante Reize.

Flicker & Magenta Focus Cue: Temporale & Chromatische Treiber

Flicker (0.5–4 Hz) als modulierte Alpha-Überlagerung auf ROI:

float flicker = 0.5 + 0.5 * sin(_Time.y * _FlickerFreq * 6.283);
col.a *= lerp(1.0, _FlickerDepth, flicker * _ROIMask);
Enter fullscreen mode Exit fullscreen mode

Reizt ipRGCs und M-Zellen – evolutionärer Aufmerksamkeitsmechanismus – gezielt im schwächeren Auge.

Magenta Focus Cue: Kreisförmiges Target (~2° FoV), nur dem fahlen Auge in Magenta (#FF00FF), dominantem Auge neutrales Grau (#808080). Magenta: selten in Naturvideo, hoher Kontrast zu Hauttönen, stimuliert L- und S-Zapfen ohne M-Dominanz. Subtile Perlin-Noise-Drift trainiert vergence-Akkommodation-Kopplung.

Visual Accents (MFBF v2+): Attention Scaffolding

Highlight (gelb-grün, additiv), Outline (rot, Sobel auf ROI-Mask), Pulse (0.1–0.3 Hz). Zweiter Pass nach Sharpener:

float pulse = 0.5 + 0.5 * sin(_Time.y * _PulseFreq * 6.283);
finalCol += _HighlightColor * _ROIMask * pulse * _PulseAmp
          + _OutlineColor   * _EdgeMask   * pulse * _PulseAmp;
Enter fullscreen mode Exit fullscreen mode

„Atmen“ verhindert Habituation – pulsierende Saliency hält exogene Aufmerksamkeit auf Target, während Gehirn lernt, schwaches Auge endogen zu gewichten.

Gaze-Tracking: Closed-Loop Stimulus

Quest Pro / 3 Eye-Tracking: Gaze-Ray → Video-Quad UV → ROI-Attention-Weight. Wenn Nutzer nicht auf Person schaut:

  1. Flicker-Frequenz erhöhen (exogener „Look here“)
  2. Magenta Cue zur Gaze-Position ziehen (okulomotorisches Training)
  3. Sharpener-Intensität im gefixten ROI boosten

Adaptive Stimulation – response-contingent, nicht starr. InputSubsystem → EyeGazeDataProvider → Shader-Properties pro Frame (< 0.5 ms).

Performance Budget: 72/90 Hz stabil

Komponente GPU (Quest 2) Notes
Video Decode (H.264 HW) ~2 ms MediaCodec, zero-copy
Dual Camera Render ~3 ms 2× 1832×1920 @ 72 Hz
AI Pose (MediaPipe) ~4 ms GPU / NNAPI Delegate
Sharpener + Accents ~1.5 ms Fullscreen, ALU-bound
Flicker / Cue / Pulse ~0.3 ms Trivial Math
Total ~11 ms Headroom > 3 ms

Single-Pass Instanced (SPI) nächster Schritt: ein Draw-Call, SV_ViewID → zwei Viewport-Scissor-Rects. Spart ~30% Vertex-Overhead. Aktuell zwei Cameras → zwei Culling-Pässe. Acceptable, aber technical debt.

Safety & Compliance: Hard Constraints im Code

public class SessionController : MonoBehaviour {
    const float MAX_SESSION_MIN = 60f;
    const float TARGET_SESSION_MIN = 35f;
    float _elapsed;
    void Update() {
        _elapsed += Time.unscaledDeltaTime;
        if (_elapsed > MAX_SESSION_MIN * 60f) 
            EndSession("Hard limit – eye strain prevention");
        if (_elapsed > 40f * 60f && !_warned) ShowWarning();
    }
    public void SetLazyEye(Eye lazy) {
        Debug.Assert(lazy != Eye.None, "Lazy eye MUST be set");
        _shader.SetInt("_LazyEyeIndex", (int)lazy);
    }
}
Enter fullscreen mode Exit fullscreen mode

Nicht medizinisch – Disclaimer ist Code: keine Diagnose, keine Dosis, keine Garantie. System liefert Stimulus-Parameter, Clinician definiert Protokoll.

Warum für Devs relevant: Content-Pipes als Therapeutische Vektoren

YouTube API → Unity VideoPlayer → Custom URP Pass → Dichoptische Modulation = generische Pipeline. Austauschbar:

  • Source: YouTube → MP4 → Livestream → 360°
  • Indikation: Amblyopie → Strabismus → Konvergenz-Insuffizienz → Visual Snow
  • Platform: Quest → PICO → Vision Pro (polymorphes IXRDisplaySubsystem)

Kein Gamification-Layer (keine Scores, Levels, Loot). Compliance durch Content-Wahl. Teenager (13+) schauen ihre Creator – Therapie passiert nebenbei. Behavioral Design ohne Dark Patterns.

Nächste Schritte für Contributors / Forks

  1. SPI Migration – Graphics.RenderMeshInstanced + SV_ViewID
  2. ONNX Runtime für Pose – plattformunabhängiger als MediaPipe
  3. Dynamic Foveated Rendering – Eye-Tracking → VRS auf Quest 3
  4. OpenXR Hand/Eye Interaction – Cue via Pinch-Drag, nicht Head-Gaze
  5. FHIR / HL7 Export – Session-Logs (Duration, Params, Gaze-Heatmap) für Clinician Dashboard

Repo (noch) closed, aber Architektur-Patterns offen: Dichoptic URP Pipeline, AI-gated Shader Modulation, Temporal-Chromatic Attention Scaffolding. Wer VR HealthTech baut: Studiert die Shader, nicht nur die Store-Page.

Meta Store: https://www.meta.com/en-gb/experiences/amblyotube/25906906972338493/

Top comments (0)