Spaces:
Running on Zero
Running on Zero
docs(01-10): record the mobile row as emulated, with the real-device row left open
Browse filesNo phone was available, so the row is Playwright device emulation and says so:
the Pixel 7 descriptor on Chromium renders the avatar and completes a typed
turn on both the direct URL and inside the Hub page's iframe (one three.js
instance, arms posed, 7-8 fps under SwiftShader, speech-start 8.0-8.8 s after
Enter); the iPhone 14 descriptor cannot be exercised because Playwright's
Windows WebKit has no Web Audio API and the boot aborts before the stage
mounts. AVTR-01 is deliberately not marked on this evidence; the section ends
with what a real-device check must record to close it.
docs/LATENCY.md
CHANGED
|
@@ -54,11 +54,21 @@ What this is and is not: a **pause/restart reuses the built image**, which is wh
|
|
| 54 |
|
| 55 |
## Mobile
|
| 56 |
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
-
|
| 62 |
|
| 63 |
## Lip-sync verification (AVTR-02)
|
| 64 |
|
|
|
|
| 54 |
|
| 55 |
## Mobile
|
| 56 |
|
| 57 |
+
**EMULATED — real-device verification still open.** No real phone was available; these rows are Playwright device descriptors driven by the execution agent on the owner's instruction, and they say nothing about a real mobile GPU, thermals or the mobile microphone-permission flow. AVTR-01's manual row therefore stays **open** and the requirement is **not** marked on this evidence. Space revision `b4d182ba9d4ccf77c9910375c9842ddf29496a22`, 2026-09-06T12:32:52Z; raw record `docs/evidence/2026-09-06-mobile-emulation.json`; screenshots `docs/evidence/2026-09-06-mobile-emulated-*.png`.
|
| 58 |
+
|
| 59 |
+
| Device (EMULATED) | OS | Browser | URL | Renders? | Observed smoothness | Push-to-talk | Turn latency | Page -> ready / first frame |
|
| 60 |
+
|---|---|---|---|---|---|---|---|---|
|
| 61 |
+
| Playwright `Pixel 7` descriptor (412x839 CSS px, DPR 2.625, touch, mobile UA) | Android 14 UA string | Chromium 151.0.7922.34 headless, WebGL 2 via **SwiftShader** (no GPU) | direct `hf.space` | **yes** — `ready`, first frame, `threeInstanceCount` 1, `mountCount` 1, `armDown` -0.932 / -0.932, canvas 324x480 CSS (648x960 buffer) | **7.7 fps** over 5 s (rAF = getDebug samples) — a slideshow, but that is the software rasteriser on this laptop, not a phone GPU | **not tested** (mobile mic permission needs a device) | typed こんにちは -> speech-start **8.0 s** after Enter; `lastTurnMs` 6612, `synthesis_ms` 5694; mouth peaks aa/ih/oh 1.0; audio 1.056 s | 4.5 s / 6.0 s |
|
| 62 |
+
| same `Pixel 7` descriptor | Android 14 UA | same Chromium | **huggingface.co Space page** (inside the Hub's `iframe.space-iframe`, `?__theme=system`) | **yes** — same numbers read inside the iframe: 1 instance, mount 1, arms posed, "Running on ZERO" badge above the avatar | **7.3 fps** (SwiftShader) | not tested | speech-start **8.8 s** after Enter; `lastTurnMs` 7354, `synthesis_ms` 6012; turn completed | 5.7 s / 8.0 s |
|
| 63 |
+
| Playwright `iPhone 14` descriptor (390x664, DPR 3, touch, iOS UA) | iOS UA string | **WebKit 26.5, Playwright's Windows build** — WebGL 2 present ("Apple GPU"), **no Web Audio API** (`AudioContext` and `webkitAudioContext` both `undefined`) | direct and Hub page | **NO — not a device result.** Boot aborts before the stage mounts: `avatar boot failed: TypeError: undefined is not a constructor (evaluating 'new AudioCtor()')`, status "the avatar failed to load - see the browser console", blank canvas (`…iphone14-webkit-bootfail.png`) | — | — | — | — |
|
| 64 |
+
|
| 65 |
+
What the emulation does and does not establish:
|
| 66 |
+
|
| 67 |
+
- **Established on the Android/Chromium profile:** the responsive layout stacks the canvas above the controls at a phone width; the VRM, the idle life and a full typed turn (server round trip, decode, lip-synced playback) work at mobile viewport, DPR and user agent, both on the direct URL and embedded in the Hub page. The Hub page swaps its iframe once while resolving the Space (a frame found too early detaches), and the Hub's own script logs one `getBoundingClientRect` error at that moment — neither is the app's.
|
| 68 |
+
- **Not established:** frame rate on a phone (SwiftShader's 7–8 fps is this laptop's CPU rasterising a 648x960 buffer; a real Adreno/Mali/Apple GPU is a different measurement), warmth, battery, the mobile mic-permission and push-to-talk flow, and anything about Safari: **the iPhone rows are a host limitation, not an iOS result.** Real iOS Safari 14.5+ ships `AudioContext`, so the boot is expected to succeed there — but it is expected, not observed.
|
| 69 |
+
- **Finding for the product (deferred, `deferred-items.md`):** the boot constructs the `AudioContext` before the stage mounts (`avatar/avatar.js:58-59`), so a browser without Web Audio gets a blank canvas even though rendering needs no audio. Constructing it lazily on the first turn or mic press would let the avatar render everywhere and only degrade sound.
|
| 70 |
|
| 71 |
+
**To close the row:** open `https://huggingface.co/spaces/WolfDavid/japanese-learning-avatar` on a real phone; record device, OS version, browser version, renders / smooth-or-slideshow, warmth, whether the mic permission and push-to-talk worked, and a rough turn time; then mark AVTR-01.
|
| 72 |
|
| 73 |
## Lip-sync verification (AVTR-02)
|
| 74 |
|
docs/evidence/2026-09-06-mobile-emulated-iphone14-webkit-bootfail.png
ADDED
|
|
Git LFS Details
|
docs/evidence/2026-09-06-mobile-emulated-pixel7-direct.png
ADDED
|
|
Git LFS Details
|
docs/evidence/2026-09-06-mobile-emulated-pixel7-hub.png
ADDED
|
|
Git LFS Details
|
docs/evidence/2026-09-06-mobile-emulation.json
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"started_at": "2026-09-06T12:32:52.511194+00:00",
|
| 3 |
+
"runs": [
|
| 4 |
+
{
|
| 5 |
+
"device": "Pixel 7",
|
| 6 |
+
"engine": "chromium",
|
| 7 |
+
"url": "direct",
|
| 8 |
+
"descriptor": {
|
| 9 |
+
"viewport": {
|
| 10 |
+
"width": 412,
|
| 11 |
+
"height": 839
|
| 12 |
+
},
|
| 13 |
+
"device_scale_factor": 2.625,
|
| 14 |
+
"is_mobile": true,
|
| 15 |
+
"has_touch": true
|
| 16 |
+
},
|
| 17 |
+
"browser_version": "151.0.7922.34",
|
| 18 |
+
"frame_url": "https://wolfdavid-japanese-learning-avatar.hf.space/",
|
| 19 |
+
"ready_s": 4.5,
|
| 20 |
+
"first_frame_s": 6.0,
|
| 21 |
+
"renders": true,
|
| 22 |
+
"threeInstanceCount": 1,
|
| 23 |
+
"armDown": {
|
| 24 |
+
"left": -0.9320020565105094,
|
| 25 |
+
"right": -0.9320044170363805
|
| 26 |
+
},
|
| 27 |
+
"mountCount": 1,
|
| 28 |
+
"transport": "inline",
|
| 29 |
+
"vrmMetaTitle": "VRM1_Constraint_Twist_Sample",
|
| 30 |
+
"webgl": {
|
| 31 |
+
"version": "WebGL 2.0 (OpenGL ES 3.0 Chromium)",
|
| 32 |
+
"renderer": "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)"
|
| 33 |
+
},
|
| 34 |
+
"viewport": {
|
| 35 |
+
"w": 412,
|
| 36 |
+
"h": 839,
|
| 37 |
+
"dpr": 2.625,
|
| 38 |
+
"ua": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.7922.34 Mobile Safari/537.36"
|
| 39 |
+
},
|
| 40 |
+
"canvas": {
|
| 41 |
+
"css": [
|
| 42 |
+
324,
|
| 43 |
+
480
|
| 44 |
+
],
|
| 45 |
+
"buffer": [
|
| 46 |
+
648,
|
| 47 |
+
960
|
| 48 |
+
]
|
| 49 |
+
},
|
| 50 |
+
"fps": {
|
| 51 |
+
"seconds": 5.08,
|
| 52 |
+
"rafPerSecond": 7.677165354330708,
|
| 53 |
+
"debugSamplesPerSecond": 7.677165354330708
|
| 54 |
+
},
|
| 55 |
+
"turn_speech_start_s": 8.0,
|
| 56 |
+
"turn": {
|
| 57 |
+
"completed": true,
|
| 58 |
+
"lastTurnMs": 6612,
|
| 59 |
+
"timings": {
|
| 60 |
+
"audio_query_ms": 1.28,
|
| 61 |
+
"synthesis_ms": 5693.787,
|
| 62 |
+
"timeline_ms": 0.223,
|
| 63 |
+
"encode_ms": 0.105,
|
| 64 |
+
"server_total_ms": 5695.751
|
| 65 |
+
},
|
| 66 |
+
"visemePeaks": {
|
| 67 |
+
"aa": 1,
|
| 68 |
+
"ih": 1,
|
| 69 |
+
"ou": 0,
|
| 70 |
+
"ee": 0,
|
| 71 |
+
"oh": 1
|
| 72 |
+
},
|
| 73 |
+
"turnCount": 1,
|
| 74 |
+
"lastError": null,
|
| 75 |
+
"audioContextState": [
|
| 76 |
+
1.056
|
| 77 |
+
]
|
| 78 |
+
},
|
| 79 |
+
"attempts": [],
|
| 80 |
+
"page_errors": [],
|
| 81 |
+
"console_errors": [
|
| 82 |
+
"error: Failed to load resource: the server responded with a status of 404 ()",
|
| 83 |
+
"warning: [.WebGL-0x26c001c0400]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels",
|
| 84 |
+
"warning: [.WebGL-0x26c001c0400]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels",
|
| 85 |
+
"warning: [.WebGL-0x26c001c0400]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels",
|
| 86 |
+
"warning: [.WebGL-0x26c001c0400]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels (this message will no longer repeat)"
|
| 87 |
+
],
|
| 88 |
+
"status_text": "ready",
|
| 89 |
+
"audio_api": {
|
| 90 |
+
"AudioContext": "function",
|
| 91 |
+
"webkitAudioContext": "undefined"
|
| 92 |
+
}
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"device": "Pixel 7",
|
| 96 |
+
"engine": "chromium",
|
| 97 |
+
"url": "hub",
|
| 98 |
+
"descriptor": {
|
| 99 |
+
"viewport": {
|
| 100 |
+
"width": 412,
|
| 101 |
+
"height": 839
|
| 102 |
+
},
|
| 103 |
+
"device_scale_factor": 2.625,
|
| 104 |
+
"is_mobile": true,
|
| 105 |
+
"has_touch": true
|
| 106 |
+
},
|
| 107 |
+
"browser_version": "151.0.7922.34",
|
| 108 |
+
"frame_url": "https://wolfdavid-japanese-learning-avatar.hf.space/?__theme=system",
|
| 109 |
+
"ready_s": 5.7,
|
| 110 |
+
"first_frame_s": 8.0,
|
| 111 |
+
"renders": true,
|
| 112 |
+
"threeInstanceCount": 1,
|
| 113 |
+
"armDown": {
|
| 114 |
+
"left": -0.9320199291170335,
|
| 115 |
+
"right": -0.9320222848803261
|
| 116 |
+
},
|
| 117 |
+
"mountCount": 1,
|
| 118 |
+
"transport": "inline",
|
| 119 |
+
"vrmMetaTitle": "VRM1_Constraint_Twist_Sample",
|
| 120 |
+
"webgl": {
|
| 121 |
+
"version": "WebGL 2.0 (OpenGL ES 3.0 Chromium)",
|
| 122 |
+
"renderer": "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)"
|
| 123 |
+
},
|
| 124 |
+
"viewport": {
|
| 125 |
+
"w": 412,
|
| 126 |
+
"h": 2055,
|
| 127 |
+
"dpr": 1,
|
| 128 |
+
"ua": "Mozilla/5.0 (Linux; Android 14; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.7922.34 Mobile Safari/537.36"
|
| 129 |
+
},
|
| 130 |
+
"canvas": {
|
| 131 |
+
"css": [
|
| 132 |
+
324,
|
| 133 |
+
480
|
| 134 |
+
],
|
| 135 |
+
"buffer": [
|
| 136 |
+
648,
|
| 137 |
+
960
|
| 138 |
+
]
|
| 139 |
+
},
|
| 140 |
+
"fps": {
|
| 141 |
+
"seconds": 5.096200000047684,
|
| 142 |
+
"rafPerSecond": 7.260311604657156,
|
| 143 |
+
"debugSamplesPerSecond": 7.260311604657156
|
| 144 |
+
},
|
| 145 |
+
"turn_speech_start_s": 8.8,
|
| 146 |
+
"turn": {
|
| 147 |
+
"completed": true,
|
| 148 |
+
"lastTurnMs": 7354,
|
| 149 |
+
"timings": {
|
| 150 |
+
"audio_query_ms": 0.996,
|
| 151 |
+
"synthesis_ms": 6011.549,
|
| 152 |
+
"timeline_ms": 0.181,
|
| 153 |
+
"encode_ms": 0.089,
|
| 154 |
+
"server_total_ms": 6013.038
|
| 155 |
+
},
|
| 156 |
+
"visemePeaks": {
|
| 157 |
+
"aa": 1,
|
| 158 |
+
"ih": 1,
|
| 159 |
+
"ou": 0,
|
| 160 |
+
"ee": 0,
|
| 161 |
+
"oh": 1
|
| 162 |
+
},
|
| 163 |
+
"turnCount": 1,
|
| 164 |
+
"lastError": null,
|
| 165 |
+
"audioContextState": [
|
| 166 |
+
1.056
|
| 167 |
+
]
|
| 168 |
+
},
|
| 169 |
+
"attempts": [
|
| 170 |
+
"Error: Frame.wait_for_selector: Frame was detached\nCall log:\n - waiting for locator(\"#vrm-stage\")\n"
|
| 171 |
+
],
|
| 172 |
+
"page_errors": [
|
| 173 |
+
"Cannot read properties of undefined (reading 'getBoundingClientRect')"
|
| 174 |
+
],
|
| 175 |
+
"console_errors": [
|
| 176 |
+
"warning: Unrecognized feature: 'ambient-light-sensor'.",
|
| 177 |
+
"warning: Unrecognized feature: 'battery'.",
|
| 178 |
+
"warning: Unrecognized feature: 'web-share'.",
|
| 179 |
+
"warning: Unrecognized feature: 'document-domain'.",
|
| 180 |
+
"warning: Unrecognized feature: 'layout-animations'.",
|
| 181 |
+
"warning: Unrecognized feature: 'legacy-image-formats'.",
|
| 182 |
+
"warning: Unrecognized feature: 'oversized-images'.",
|
| 183 |
+
"warning: Unrecognized feature: 'vr'."
|
| 184 |
+
],
|
| 185 |
+
"status_text": "ready",
|
| 186 |
+
"audio_api": {
|
| 187 |
+
"AudioContext": "function",
|
| 188 |
+
"webkitAudioContext": "undefined"
|
| 189 |
+
}
|
| 190 |
+
},
|
| 191 |
+
{
|
| 192 |
+
"device": "iPhone 14",
|
| 193 |
+
"engine": "webkit",
|
| 194 |
+
"url": "direct",
|
| 195 |
+
"descriptor": {
|
| 196 |
+
"viewport": {
|
| 197 |
+
"width": 390,
|
| 198 |
+
"height": 664
|
| 199 |
+
},
|
| 200 |
+
"device_scale_factor": 3,
|
| 201 |
+
"is_mobile": true,
|
| 202 |
+
"has_touch": true
|
| 203 |
+
},
|
| 204 |
+
"browser_version": "26.5",
|
| 205 |
+
"frame_url": "https://wolfdavid-japanese-learning-avatar.hf.space/",
|
| 206 |
+
"error": "TimeoutError: Frame.wait_for_function: Timeout 60000ms exceeded.",
|
| 207 |
+
"attempts": [
|
| 208 |
+
"TimeoutError: Frame.wait_for_function: Timeout 60000ms exceeded."
|
| 209 |
+
],
|
| 210 |
+
"page_errors": [],
|
| 211 |
+
"console_errors": [
|
| 212 |
+
"error: Failed to load resource: the server responded with a status of 404 ()",
|
| 213 |
+
"error: avatar boot failed: TypeError: undefined is not a constructor (evaluating 'new AudioCtor()')"
|
| 214 |
+
],
|
| 215 |
+
"status_text": "the avatar failed to load - see the browser console",
|
| 216 |
+
"audio_api": {
|
| 217 |
+
"AudioContext": "undefined",
|
| 218 |
+
"webkitAudioContext": "undefined"
|
| 219 |
+
}
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
"device": "iPhone 14",
|
| 223 |
+
"engine": "webkit",
|
| 224 |
+
"url": "hub",
|
| 225 |
+
"descriptor": {
|
| 226 |
+
"viewport": {
|
| 227 |
+
"width": 390,
|
| 228 |
+
"height": 664
|
| 229 |
+
},
|
| 230 |
+
"device_scale_factor": 3,
|
| 231 |
+
"is_mobile": true,
|
| 232 |
+
"has_touch": true
|
| 233 |
+
},
|
| 234 |
+
"browser_version": "26.5",
|
| 235 |
+
"frame_url": "https://wolfdavid-japanese-learning-avatar.hf.space/?__theme=system",
|
| 236 |
+
"error": "TimeoutError: Frame.wait_for_function: Timeout 60000ms exceeded.",
|
| 237 |
+
"attempts": [
|
| 238 |
+
"Error: Frame.wait_for_selector: Frame was detached\nCall log:\n - waiting for locator(\"#vrm-stage\")\n",
|
| 239 |
+
"TimeoutError: Frame.wait_for_function: Timeout 60000ms exceeded."
|
| 240 |
+
],
|
| 241 |
+
"page_errors": [],
|
| 242 |
+
"console_errors": [
|
| 243 |
+
"error: avatar boot failed: TypeError: undefined is not a constructor (evaluating 'new AudioCtor()')"
|
| 244 |
+
],
|
| 245 |
+
"status_text": "the avatar failed to load - see the browser console",
|
| 246 |
+
"audio_api": {
|
| 247 |
+
"AudioContext": "undefined",
|
| 248 |
+
"webkitAudioContext": "undefined"
|
| 249 |
+
}
|
| 250 |
+
}
|
| 251 |
+
]
|
| 252 |
+
}
|