@the-inclusionist/engine 9.0.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -78
- package/app/css/style.css +761 -377
- package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
- package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
- package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
- package/app/public/vendor/fonts.css +36 -84
- package/dist-pkg/boot/create-game.d.ts +499 -219
- package/dist-pkg/boot/create-game.js +3944 -562
- package/dist-pkg/core/a11y-sr.d.ts +25 -3
- package/dist-pkg/core/a11y-sr.js +38 -19
- package/dist-pkg/core/accessible-label.d.ts +17 -0
- package/dist-pkg/core/accessible-label.js +37 -0
- package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
- package/dist-pkg/core/accommodation-subjects.js +32 -0
- package/dist-pkg/core/accommodations.d.ts +125 -0
- package/dist-pkg/core/accommodations.js +195 -0
- package/dist-pkg/core/actions.d.ts +108 -55
- package/dist-pkg/core/actions.js +122 -71
- package/dist-pkg/core/calm-mode.d.ts +31 -0
- package/dist-pkg/core/calm-mode.js +47 -0
- package/dist-pkg/core/camera-cycle.d.ts +15 -0
- package/dist-pkg/core/camera-cycle.js +7 -0
- package/dist-pkg/core/caption-duration.d.ts +15 -0
- package/dist-pkg/core/caption-duration.js +19 -0
- package/dist-pkg/core/cartridge-problems.d.ts +34 -0
- package/dist-pkg/core/cartridge-problems.js +53 -0
- package/dist-pkg/core/constants.d.ts +0 -54
- package/dist-pkg/core/constants.js +9 -76
- package/dist-pkg/core/contract.d.ts +142 -164
- package/dist-pkg/core/contract.js +222 -208
- package/dist-pkg/core/dom-query.d.ts +4 -4
- package/dist-pkg/core/dom-query.js +12 -20
- package/dist-pkg/core/entity.d.ts +62 -77
- package/dist-pkg/core/entity.js +18 -32
- package/dist-pkg/core/escape-html.d.ts +9 -10
- package/dist-pkg/core/escape-html.js +16 -20
- package/dist-pkg/core/flash-threshold.d.ts +17 -0
- package/dist-pkg/core/flash-threshold.js +113 -0
- package/dist-pkg/core/game-speed.d.ts +11 -0
- package/dist-pkg/core/game-speed.js +16 -0
- package/dist-pkg/core/genres.d.ts +20 -0
- package/dist-pkg/core/genres.js +44 -0
- package/dist-pkg/core/i18n.d.ts +71 -60
- package/dist-pkg/core/i18n.js +186 -200
- package/dist-pkg/core/loop.d.ts +17 -6
- package/dist-pkg/core/loop.js +26 -26
- package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
- package/dist-pkg/core/pause-icon-catalogue.js +54 -0
- package/dist-pkg/core/ring.d.ts +17 -0
- package/dist-pkg/core/ring.js +29 -0
- package/dist-pkg/core/rng.d.ts +7 -12
- package/dist-pkg/core/rng.js +23 -53
- package/dist-pkg/core/route.d.ts +26 -26
- package/dist-pkg/core/route.js +126 -121
- package/dist-pkg/core/scenes.d.ts +37 -40
- package/dist-pkg/core/scenes.js +41 -43
- package/dist-pkg/core/screens.d.ts +4 -4
- package/dist-pkg/core/screens.js +11 -16
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/core/setting-defaults.d.ts +61 -0
- package/dist-pkg/core/setting-defaults.js +66 -0
- package/dist-pkg/core/speech-rate.d.ts +29 -0
- package/dist-pkg/core/speech-rate.js +47 -0
- package/dist-pkg/core/state.d.ts +118 -118
- package/dist-pkg/core/state.js +322 -297
- package/dist-pkg/core/visual-cycles.d.ts +30 -0
- package/dist-pkg/core/visual-cycles.js +52 -0
- package/dist-pkg/core/visual-state.d.ts +13 -0
- package/dist-pkg/core/visual-state.js +6 -0
- package/dist-pkg/educational/activities-registry.d.ts +1 -1
- package/dist-pkg/educational/activities-registry.js +9 -8
- package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
- package/dist-pkg/educational/adaptive-engine.js +17 -17
- package/dist-pkg/educational/segment-bar.d.ts +12 -12
- package/dist-pkg/educational/segment-bar.js +9 -9
- package/dist-pkg/i18n/en.js +324 -223
- package/dist-pkg/i18n/es.js +323 -223
- package/dist-pkg/i18n/pt.js +348 -226
- package/dist-pkg/input/default-bindings.d.ts +37 -38
- package/dist-pkg/input/default-bindings.js +127 -144
- package/dist-pkg/input/devices.d.ts +7 -7
- package/dist-pkg/input/devices.js +17 -16
- package/dist-pkg/input/edges.d.ts +23 -32
- package/dist-pkg/input/edges.js +23 -28
- package/dist-pkg/input/empathy-filter.d.ts +22 -0
- package/dist-pkg/input/empathy-filter.js +34 -0
- package/dist-pkg/input/face-map.d.ts +96 -0
- package/dist-pkg/input/face-map.js +255 -0
- package/dist-pkg/input/face-signals.d.ts +40 -0
- package/dist-pkg/input/face-signals.js +48 -0
- package/dist-pkg/input/gamepad.d.ts +195 -145
- package/dist-pkg/input/gamepad.js +383 -556
- package/dist-pkg/input/gaze-cycle.d.ts +64 -0
- package/dist-pkg/input/gaze-cycle.js +133 -0
- package/dist-pkg/input/gaze-relative.d.ts +68 -0
- package/dist-pkg/input/gaze-relative.js +142 -0
- package/dist-pkg/input/hand-map.d.ts +28 -0
- package/dist-pkg/input/hand-map.js +142 -0
- package/dist-pkg/input/input-cooldown.d.ts +17 -0
- package/dist-pkg/input/input-cooldown.js +39 -0
- package/dist-pkg/input/key-default.d.ts +30 -0
- package/dist-pkg/input/key-default.js +60 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
- package/dist-pkg/input/keyboard-runtime.js +23 -27
- package/dist-pkg/input/keyboard.d.ts +68 -63
- package/dist-pkg/input/keyboard.js +83 -105
- package/dist-pkg/input/keydown.d.ts +123 -137
- package/dist-pkg/input/keydown.js +284 -289
- package/dist-pkg/input/latch-edge.d.ts +33 -21
- package/dist-pkg/input/latch-edge.js +34 -35
- package/dist-pkg/input/latch-scope.d.ts +51 -50
- package/dist-pkg/input/latch-scope.js +61 -82
- package/dist-pkg/input/latch-store.d.ts +26 -30
- package/dist-pkg/input/latch-store.js +42 -50
- package/dist-pkg/input/latch-sync.d.ts +29 -29
- package/dist-pkg/input/latch-sync.js +25 -25
- package/dist-pkg/input/latch.d.ts +14 -17
- package/dist-pkg/input/latch.js +29 -37
- package/dist-pkg/input/pad-defaults.d.ts +13 -16
- package/dist-pkg/input/pad-defaults.js +21 -28
- package/dist-pkg/input/pad-reading.d.ts +76 -0
- package/dist-pkg/input/pad-reading.js +169 -0
- package/dist-pkg/input/pad-wizard.d.ts +99 -0
- package/dist-pkg/input/pad-wizard.js +256 -0
- package/dist-pkg/input/pointer-space.d.ts +19 -20
- package/dist-pkg/input/pointer-space.js +27 -32
- package/dist-pkg/input/pointer.d.ts +39 -40
- package/dist-pkg/input/pointer.js +42 -45
- package/dist-pkg/input/state.d.ts +101 -89
- package/dist-pkg/input/state.js +54 -134
- package/dist-pkg/input/switch-scan.d.ts +59 -0
- package/dist-pkg/input/switch-scan.js +67 -0
- package/dist-pkg/input/synthetic-source.d.ts +42 -0
- package/dist-pkg/input/synthetic-source.js +57 -0
- package/dist-pkg/input/touch-bindings.d.ts +127 -116
- package/dist-pkg/input/touch-bindings.js +158 -173
- package/dist-pkg/input/touch.d.ts +147 -72
- package/dist-pkg/input/touch.js +362 -126
- package/dist-pkg/input/transport-in-use.d.ts +107 -0
- package/dist-pkg/input/transport-in-use.js +130 -0
- package/dist-pkg/input/transports.d.ts +90 -117
- package/dist-pkg/input/transports.js +104 -106
- package/dist-pkg/input/virtual-controller.d.ts +82 -0
- package/dist-pkg/input/virtual-controller.js +69 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
- package/dist-pkg/input/vocabulary-migration.js +80 -79
- package/dist-pkg/input/voice-map.d.ts +59 -0
- package/dist-pkg/input/voice-map.js +123 -0
- package/dist-pkg/platform/audio-ambient.d.ts +13 -2
- package/dist-pkg/platform/audio-ambient.js +14 -14
- package/dist-pkg/platform/audio-earcons.d.ts +20 -19
- package/dist-pkg/platform/audio-earcons.js +51 -42
- package/dist-pkg/platform/audio-jingles.js +9 -10
- package/dist-pkg/platform/audio-mixer.d.ts +14 -2
- package/dist-pkg/platform/audio-mixer.js +31 -39
- package/dist-pkg/platform/audio-sonar.d.ts +49 -152
- package/dist-pkg/platform/audio-sonar.js +124 -302
- package/dist-pkg/platform/audio.d.ts +62 -19
- package/dist-pkg/platform/audio.js +193 -168
- package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
- package/dist-pkg/platform/choose-by-voice.js +157 -0
- package/dist-pkg/platform/flash-sampler.d.ts +19 -0
- package/dist-pkg/platform/flash-sampler.js +79 -0
- package/dist-pkg/platform/font-library.d.ts +77 -0
- package/dist-pkg/platform/font-library.js +98 -0
- package/dist-pkg/platform/font-library.json +721 -0
- package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
- package/dist-pkg/platform/heavy-catalogue.js +256 -0
- package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
- package/dist-pkg/platform/heavy-mirror.js +73 -0
- package/dist-pkg/platform/heavy.d.ts +136 -0
- package/dist-pkg/platform/heavy.js +324 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
- package/dist-pkg/platform/interruptible-speech.js +77 -54
- package/dist-pkg/platform/kokoro-port.d.ts +27 -0
- package/dist-pkg/platform/kokoro-port.js +50 -0
- package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
- package/dist-pkg/platform/kokoro-runtime.js +52 -0
- package/dist-pkg/platform/kokoro.d.ts +70 -0
- package/dist-pkg/platform/kokoro.js +133 -0
- package/dist-pkg/platform/listener-scope.d.ts +12 -0
- package/dist-pkg/platform/listener-scope.js +90 -0
- package/dist-pkg/platform/locale-host.d.ts +14 -0
- package/dist-pkg/platform/locale-host.js +45 -0
- package/dist-pkg/platform/microphone.d.ts +51 -0
- package/dist-pkg/platform/microphone.js +118 -0
- package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
- package/dist-pkg/platform/onnx-runtime.js +42 -0
- package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
- package/dist-pkg/platform/reading-in-worker.js +125 -0
- package/dist-pkg/platform/reading-model.d.ts +94 -0
- package/dist-pkg/platform/reading-model.js +272 -0
- package/dist-pkg/platform/reading-runtime.d.ts +24 -0
- package/dist-pkg/platform/reading-runtime.js +164 -0
- package/dist-pkg/platform/reading-worker.d.ts +41 -0
- package/dist-pkg/platform/reading-worker.js +58 -0
- package/dist-pkg/platform/reading.d.ts +80 -0
- package/dist-pkg/platform/reading.js +136 -0
- package/dist-pkg/platform/speech-recognition.d.ts +60 -0
- package/dist-pkg/platform/speech-recognition.js +104 -0
- package/dist-pkg/platform/speech.d.ts +23 -1
- package/dist-pkg/platform/speech.js +29 -18
- package/dist-pkg/platform/storage-keys.d.ts +96 -0
- package/dist-pkg/platform/storage-keys.js +106 -0
- package/dist-pkg/platform/storage.d.ts +46 -111
- package/dist-pkg/platform/storage.js +104 -169
- package/dist-pkg/platform/tts.d.ts +85 -39
- package/dist-pkg/platform/tts.js +447 -127
- package/dist-pkg/platform/vision-loop.d.ts +23 -0
- package/dist-pkg/platform/vision-loop.js +56 -0
- package/dist-pkg/platform/vision.d.ts +132 -0
- package/dist-pkg/platform/vision.js +117 -0
- package/dist-pkg/platform/voice-listener.d.ts +40 -0
- package/dist-pkg/platform/voice-listener.js +88 -0
- package/dist-pkg/platform/voice-plan.d.ts +15 -98
- package/dist-pkg/platform/voice-plan.js +56 -143
- package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
- package/dist-pkg/platform/vosk-runtime.js +151 -0
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/canvas.d.ts +13 -7
- package/dist-pkg/render/canvas.js +13 -13
- package/dist-pkg/render/crt.d.ts +48 -12
- package/dist-pkg/render/crt.js +78 -80
- package/dist-pkg/render/cvd-matrices.d.ts +22 -18
- package/dist-pkg/render/cvd-matrices.js +37 -38
- package/dist-pkg/render/hc-role-data.d.ts +7 -7
- package/dist-pkg/render/hc-role-data.js +14 -14
- package/dist-pkg/render/high-contrast.d.ts +67 -56
- package/dist-pkg/render/high-contrast.js +226 -217
- package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
- package/dist-pkg/render/low-vision-drawing.js +46 -0
- package/dist-pkg/render/lq-filter.d.ts +32 -20
- package/dist-pkg/render/lq-filter.js +59 -65
- package/dist-pkg/render/port.d.ts +86 -88
- package/dist-pkg/render/port.js +17 -23
- package/dist-pkg/render/screen-pipeline.d.ts +42 -42
- package/dist-pkg/render/screen-pipeline.js +80 -87
- package/dist-pkg/render/sprite-fx.d.ts +2 -1
- package/dist-pkg/render/sprite-fx.js +16 -14
- package/dist-pkg/render/viewports.d.ts +20 -15
- package/dist-pkg/render/viewports.js +83 -114
- package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
- package/dist-pkg/render/viz-axes-labels.js +88 -0
- package/dist-pkg/render/viz-axes.d.ts +89 -86
- package/dist-pkg/render/viz-axes.js +128 -116
- package/dist-pkg/render/viz-modes.d.ts +28 -29
- package/dist-pkg/render/viz-modes.js +40 -45
- package/dist-pkg/render/viz-refusal.d.ts +32 -0
- package/dist-pkg/render/viz-refusal.js +57 -0
- package/dist-pkg/render/viz-setters.d.ts +104 -66
- package/dist-pkg/render/viz-setters.js +182 -191
- package/dist-pkg/ui/aac-sets.d.ts +45 -0
- package/dist-pkg/ui/aac-sets.js +41 -0
- package/dist-pkg/ui/audio-choices.d.ts +68 -0
- package/dist-pkg/ui/audio-choices.js +98 -0
- package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
- package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
- package/dist-pkg/ui/camera-control.d.ts +53 -0
- package/dist-pkg/ui/camera-control.js +48 -0
- package/dist-pkg/ui/changed-mark.d.ts +9 -8
- package/dist-pkg/ui/changed-mark.js +22 -53
- package/dist-pkg/ui/control-choices.d.ts +37 -0
- package/dist-pkg/ui/control-choices.js +84 -0
- package/dist-pkg/ui/debug-panel.d.ts +59 -43
- package/dist-pkg/ui/debug-panel.js +68 -69
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/dom.d.ts +10 -14
- package/dist-pkg/ui/dom.js +10 -47
- package/dist-pkg/ui/drawing-problems.d.ts +25 -0
- package/dist-pkg/ui/drawing-problems.js +94 -0
- package/dist-pkg/ui/eye-control.d.ts +36 -0
- package/dist-pkg/ui/eye-control.js +178 -0
- package/dist-pkg/ui/face-control.d.ts +25 -0
- package/dist-pkg/ui/face-control.js +183 -0
- package/dist-pkg/ui/focus-trap.d.ts +39 -49
- package/dist-pkg/ui/focus-trap.js +56 -65
- package/dist-pkg/ui/fonts.d.ts +157 -68
- package/dist-pkg/ui/fonts.js +305 -115
- package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
- package/dist-pkg/ui/footer-scroll-driver.js +201 -0
- package/dist-pkg/ui/footer-scroll.d.ts +38 -0
- package/dist-pkg/ui/footer-scroll.js +55 -0
- package/dist-pkg/ui/game-options.d.ts +47 -0
- package/dist-pkg/ui/game-options.js +158 -0
- package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
- package/dist-pkg/ui/gaze-overlay.js +165 -0
- package/dist-pkg/ui/hand-control.d.ts +25 -0
- package/dist-pkg/ui/hand-control.js +143 -0
- package/dist-pkg/ui/help-panel.d.ts +87 -0
- package/dist-pkg/ui/help-panel.js +242 -0
- package/dist-pkg/ui/hud-bands.d.ts +62 -0
- package/dist-pkg/ui/hud-bands.js +146 -0
- package/dist-pkg/ui/hud-row.d.ts +34 -0
- package/dist-pkg/ui/hud-row.js +80 -0
- package/dist-pkg/ui/hud.d.ts +73 -73
- package/dist-pkg/ui/hud.js +94 -98
- package/dist-pkg/ui/item-announcement.d.ts +13 -12
- package/dist-pkg/ui/item-announcement.js +25 -26
- package/dist-pkg/ui/layout.d.ts +103 -28
- package/dist-pkg/ui/layout.js +117 -99
- package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
- package/dist-pkg/ui/libras-avatar-clip.js +86 -0
- package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
- package/dist-pkg/ui/libras-avatar-load.js +134 -0
- package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
- package/dist-pkg/ui/libras-avatar-plan.js +211 -0
- package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
- package/dist-pkg/ui/libras-avatar-player.js +226 -0
- package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
- package/dist-pkg/ui/libras-avatar-stage.js +208 -0
- package/dist-pkg/ui/libras-glosses.d.ts +28 -0
- package/dist-pkg/ui/libras-glosses.js +161 -0
- package/dist-pkg/ui/locale-flags.d.ts +16 -0
- package/dist-pkg/ui/locale-flags.js +30 -0
- package/dist-pkg/ui/loop-crash.d.ts +17 -17
- package/dist-pkg/ui/loop-crash.js +33 -62
- package/dist-pkg/ui/menu-intent.d.ts +61 -0
- package/dist-pkg/ui/menu-intent.js +88 -0
- package/dist-pkg/ui/menu-items.d.ts +20 -0
- package/dist-pkg/ui/menu-items.js +51 -0
- package/dist-pkg/ui/menu-nav.d.ts +98 -92
- package/dist-pkg/ui/menu-nav.js +398 -286
- package/dist-pkg/ui/mobility-choices.d.ts +26 -0
- package/dist-pkg/ui/mobility-choices.js +41 -0
- package/dist-pkg/ui/motion-choices.d.ts +31 -0
- package/dist-pkg/ui/motion-choices.js +68 -0
- package/dist-pkg/ui/motion-scene.d.ts +24 -19
- package/dist-pkg/ui/motion-scene.js +29 -61
- package/dist-pkg/ui/mount-panel.d.ts +81 -0
- package/dist-pkg/ui/mount-panel.js +61 -0
- package/dist-pkg/ui/panel-shell.d.ts +65 -31
- package/dist-pkg/ui/panel-shell.js +92 -66
- package/dist-pkg/ui/panel-widgets.d.ts +150 -0
- package/dist-pkg/ui/panel-widgets.js +294 -0
- package/dist-pkg/ui/pause-buttons.d.ts +35 -0
- package/dist-pkg/ui/pause-buttons.js +66 -0
- package/dist-pkg/ui/pause-icons.d.ts +261 -347
- package/dist-pkg/ui/pause-icons.js +671 -601
- package/dist-pkg/ui/pause-markup.d.ts +86 -0
- package/dist-pkg/ui/pause-markup.js +125 -0
- package/dist-pkg/ui/reach-notice.d.ts +22 -23
- package/dist-pkg/ui/reach-notice.js +55 -58
- package/dist-pkg/ui/scan-overlay.d.ts +23 -0
- package/dist-pkg/ui/scan-overlay.js +50 -0
- package/dist-pkg/ui/screen-text.d.ts +25 -0
- package/dist-pkg/ui/screen-text.js +152 -0
- package/dist-pkg/ui/session-clock.d.ts +32 -0
- package/dist-pkg/ui/session-clock.js +67 -0
- package/dist-pkg/ui/settings-aac.d.ts +70 -0
- package/dist-pkg/ui/settings-aac.js +208 -0
- package/dist-pkg/ui/settings-audio.d.ts +97 -114
- package/dist-pkg/ui/settings-audio.js +493 -425
- package/dist-pkg/ui/settings-controls.d.ts +53 -96
- package/dist-pkg/ui/settings-controls.js +143 -215
- package/dist-pkg/ui/settings-empathy.d.ts +39 -30
- package/dist-pkg/ui/settings-empathy.js +53 -60
- package/dist-pkg/ui/settings-mobility.d.ts +192 -0
- package/dist-pkg/ui/settings-mobility.js +332 -0
- package/dist-pkg/ui/settings-motion.d.ts +91 -70
- package/dist-pkg/ui/settings-motion.js +287 -198
- package/dist-pkg/ui/settings-panel.d.ts +58 -45
- package/dist-pkg/ui/settings-panel.js +189 -94
- package/dist-pkg/ui/settings-typo.d.ts +29 -78
- package/dist-pkg/ui/settings-typo.js +158 -129
- package/dist-pkg/ui/settings-visual.d.ts +29 -87
- package/dist-pkg/ui/settings-visual.js +240 -193
- package/dist-pkg/ui/shell.d.ts +112 -135
- package/dist-pkg/ui/shell.js +148 -217
- package/dist-pkg/ui/simulation-list.d.ts +27 -0
- package/dist-pkg/ui/simulation-list.js +76 -0
- package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
- package/dist-pkg/ui/simulation-over-the-world.js +131 -0
- package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
- package/dist-pkg/ui/simulation-refusal.js +8 -56
- package/dist-pkg/ui/switchable-control.d.ts +11 -0
- package/dist-pkg/ui/switchable-control.js +19 -0
- package/dist-pkg/ui/title.d.ts +3 -12
- package/dist-pkg/ui/title.js +49 -18
- package/dist-pkg/ui/top-band.d.ts +26 -0
- package/dist-pkg/ui/top-band.js +96 -0
- package/dist-pkg/ui/typo-choices.d.ts +71 -0
- package/dist-pkg/ui/typo-choices.js +85 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
- package/dist-pkg/ui/visual-axes-panel.js +12 -94
- package/dist-pkg/ui/visual-choices.d.ts +77 -0
- package/dist-pkg/ui/visual-choices.js +107 -0
- package/dist-pkg/ui/vlibras.d.ts +77 -10
- package/dist-pkg/ui/vlibras.js +130 -81
- package/dist-pkg/ui/voice-control.d.ts +68 -0
- package/dist-pkg/ui/voice-control.js +276 -0
- package/dist-pkg/ui/voice-settings.d.ts +95 -0
- package/dist-pkg/ui/voice-settings.js +352 -0
- package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
- package/dist-pkg/ui/where-the-child-is.js +70 -0
- package/docs/CREDITS.md +300 -44
- package/docs/LICENSES.md +189 -145
- package/package.json +51 -27
- package/scripts/check-cartridge.mjs +78 -0
- package/scripts/game-build.d.mts +25 -0
- package/scripts/game-build.mjs +144 -0
- package/scripts/heavy-into-the-delivery.mjs +388 -0
- package/scripts/libras-avatar.json +680 -0
- package/scripts/libras-avatar.mjs +246 -0
- package/scripts/libras-glosses/gloss.py +95 -0
- package/scripts/libras-glosses/pyproject.toml +32 -0
- package/scripts/libras-glosses/uv.lock +781 -0
- package/scripts/libras-glosses.mjs +351 -0
- package/scripts/licences/Apache-2.0.txt +176 -0
- package/scripts/licences/GPL-3.0.txt +674 -0
- package/scripts/licences/MIT.txt +17 -0
- package/scripts/licences/OFL-1.1.txt +86 -0
- package/scripts/licences/UFL-1.0.txt +96 -0
- package/scripts/licences/fonts.mjs +389 -0
- package/scripts/licences/third-party.mjs +301 -0
- package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.woff2 +0 -0
- package/app/public/vendor/fonts/lato-400.woff2 +0 -0
- package/app/public/vendor/fonts/lato-700.woff2 +0 -0
- package/app/public/vendor/fonts/literata-400.woff2 +0 -0
- package/app/public/vendor/fonts/literata-700.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
- package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
- package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
- package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/dist-pkg/core/anel.d.ts +0 -17
- package/dist-pkg/core/anel.js +0 -31
- package/dist-pkg/core/collision.d.ts +0 -21
- package/dist-pkg/core/collision.js +0 -62
- package/dist-pkg/core/layers.d.ts +0 -63
- package/dist-pkg/core/layers.js +0 -95
- package/dist-pkg/core/letter-grid.d.ts +0 -55
- package/dist-pkg/core/letter-grid.js +0 -116
- package/dist-pkg/core/password.d.ts +0 -34
- package/dist-pkg/core/password.js +0 -205
- package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
- package/dist-pkg/core/rotulo-acessivel.js +0 -41
- package/dist-pkg/core/run-state.d.ts +0 -115
- package/dist-pkg/core/run-state.js +0 -40
- package/dist-pkg/core/tiles.d.ts +0 -12
- package/dist-pkg/core/tiles.js +0 -61
- package/dist-pkg/core/world.d.ts +0 -4
- package/dist-pkg/core/world.js +0 -58
- package/dist-pkg/input/origem-sintetica.d.ts +0 -44
- package/dist-pkg/input/origem-sintetica.js +0 -60
- package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
- package/dist-pkg/input/transporte-em-uso.js +0 -130
- package/dist-pkg/platform/audio-nav.d.ts +0 -51
- package/dist-pkg/platform/audio-nav.js +0 -99
- package/dist-pkg/platform/guide-intensity.d.ts +0 -40
- package/dist-pkg/platform/guide-intensity.js +0 -73
- package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
- package/dist-pkg/platform/pesados-catalogo.js +0 -177
- package/dist-pkg/platform/pesados.d.ts +0 -31
- package/dist-pkg/platform/pesados.js +0 -75
- package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
- package/dist-pkg/platform/vozes-prontas.js +0 -61
- package/dist-pkg/render/camera.d.ts +0 -58
- package/dist-pkg/render/camera.js +0 -105
- package/dist-pkg/render/cenario-data.d.ts +0 -127
- package/dist-pkg/render/cenario-data.js +0 -145
- package/dist-pkg/render/city-tex.d.ts +0 -63
- package/dist-pkg/render/city-tex.js +0 -228
- package/dist-pkg/render/city-tiles.d.ts +0 -11
- package/dist-pkg/render/city-tiles.js +0 -140
- package/dist-pkg/render/draw.d.ts +0 -149
- package/dist-pkg/render/draw.js +0 -231
- package/dist-pkg/render/fx.d.ts +0 -63
- package/dist-pkg/render/fx.js +0 -123
- package/dist-pkg/render/minimap.d.ts +0 -11
- package/dist-pkg/render/minimap.js +0 -94
- package/dist-pkg/render/parallax.d.ts +0 -85
- package/dist-pkg/render/parallax.js +0 -158
- package/dist-pkg/render/player-anim.d.ts +0 -71
- package/dist-pkg/render/player-anim.js +0 -152
- package/dist-pkg/render/recycling-tex.d.ts +0 -48
- package/dist-pkg/render/recycling-tex.js +0 -164
- package/dist-pkg/render/scene-city.d.ts +0 -77
- package/dist-pkg/render/scene-city.js +0 -181
- package/dist-pkg/render/scene-parallax.d.ts +0 -72
- package/dist-pkg/render/scene-parallax.js +0 -426
- package/dist-pkg/render/scene-sky.d.ts +0 -126
- package/dist-pkg/render/scene-sky.js +0 -295
- package/dist-pkg/render/set-cenario.d.ts +0 -54
- package/dist-pkg/render/set-cenario.js +0 -103
- package/dist-pkg/render/textures.d.ts +0 -75
- package/dist-pkg/render/textures.js +0 -240
- package/dist-pkg/render/title-scene.d.ts +0 -46
- package/dist-pkg/render/title-scene.js +0 -75
- package/dist-pkg/render/weather.d.ts +0 -96
- package/dist-pkg/render/weather.js +0 -171
- package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
- package/dist-pkg/render/wheelchair-sprites.js +0 -69
- package/dist-pkg/render/world-tex.d.ts +0 -18
- package/dist-pkg/render/world-tex.js +0 -87
- package/dist-pkg/ui/activities-menu.d.ts +0 -258
- package/dist-pkg/ui/activities-menu.js +0 -648
- package/dist-pkg/ui/caa-sets.d.ts +0 -39
- package/dist-pkg/ui/caa-sets.js +0 -65
- package/dist-pkg/ui/latch-refusal.d.ts +0 -32
- package/dist-pkg/ui/latch-refusal.js +0 -60
- package/dist-pkg/ui/map-hub.d.ts +0 -56
- package/dist-pkg/ui/map-hub.js +0 -138
- package/dist-pkg/ui/settings-caa.d.ts +0 -45
- package/dist-pkg/ui/settings-caa.js +0 -137
- package/dist-pkg/ui/settings-motor.d.ts +0 -175
- package/dist-pkg/ui/settings-motor.js +0 -342
- package/dist-pkg/ui/webcam.d.ts +0 -7
- package/dist-pkg/ui/webcam.js +0 -93
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
export type LoopHealth = 'ok' | 'slow' | 'stalled';
|
|
3
|
+
export interface VisionLoopDeps {
|
|
4
|
+
readonly requestFrame: (cb: (ms: number) => void) => number;
|
|
5
|
+
readonly cancelFrame: (handle: number) => void;
|
|
6
|
+
readonly now: () => number;
|
|
7
|
+
readonly every: (cb: () => void, ms: number) => number;
|
|
8
|
+
readonly stopEvery: (handle: number) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface VisionLoopOptions {
|
|
11
|
+
readonly onFrame: (ms: number) => void;
|
|
12
|
+
readonly onError?: (error: unknown) => void;
|
|
13
|
+
readonly onHealth?: (health: LoopHealth, framesPerSecond: number) => void;
|
|
14
|
+
readonly floorFps?: number;
|
|
15
|
+
readonly stallMs?: number;
|
|
16
|
+
readonly watchMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface VisionLoop {
|
|
19
|
+
start(): void;
|
|
20
|
+
stop(): void;
|
|
21
|
+
health(): LoopHealth;
|
|
22
|
+
}
|
|
23
|
+
export declare function createVisionLoop(deps: VisionLoopDeps, { onFrame, onError, onHealth, floorFps, stallMs, watchMs }: VisionLoopOptions): VisionLoop;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// platform/vision-loop — THE CAMERA'S FRAME LOOP, WHICH CANNOT STOP IN SILENCE (ADR-0213; issue #196).
|
|
3
|
+
//
|
|
4
|
+
// · The next frame is booked BEFORE anything that could throw. The lab's loop booked it at the end, one item threw on every frame, and the
|
|
5
|
+
// eye control stopped on its first frame with nothing on screen saying so — every measurement taken after that was of a stopped page.
|
|
6
|
+
// · A frame that throws is handed to `onError` and the loop goes on.
|
|
7
|
+
// · A watchdog on its OWN clock (a stopped loop cannot report itself) says whether frames are arriving: `stalled` when none came for
|
|
8
|
+
// `stallMs`, `slow` under `floorFps` in the last second, `ok` otherwise. A reading taken while it is not `ok` is not a reading, and the
|
|
9
|
+
// child must be told, not left gazing at a control that no longer listens. It reports on change only.
|
|
10
|
+
export function createVisionLoop(deps, { onFrame, onError = () => { }, onHealth = () => { }, floorFps = 8, stallMs = 1000, watchMs = 500 }) {
|
|
11
|
+
let frame = null, watch = null, health = 'ok', startedAt = 0;
|
|
12
|
+
const times = [];
|
|
13
|
+
const tick = (ms) => {
|
|
14
|
+
frame = deps.requestFrame(tick);
|
|
15
|
+
times.push(deps.now());
|
|
16
|
+
try {
|
|
17
|
+
onFrame(ms);
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
onError(e);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const check = () => {
|
|
24
|
+
const now = deps.now();
|
|
25
|
+
while (times.length && now - times[0] > 1000)
|
|
26
|
+
times.shift();
|
|
27
|
+
const last = times.at(-1) ?? startedAt;
|
|
28
|
+
if (health === 'stalled' && now - last < stallMs)
|
|
29
|
+
startedAt = now; // back from a stall: judge the rate on a full second of the new frames
|
|
30
|
+
const next = now - last >= stallMs ? 'stalled' : now - startedAt >= 1000 && times.length < floorFps ? 'slow' : 'ok';
|
|
31
|
+
if (next !== health) {
|
|
32
|
+
health = next;
|
|
33
|
+
onHealth(health, times.length);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
start() {
|
|
38
|
+
if (frame !== null)
|
|
39
|
+
return;
|
|
40
|
+
startedAt = deps.now();
|
|
41
|
+
health = 'ok';
|
|
42
|
+
times.length = 0;
|
|
43
|
+
frame = deps.requestFrame(tick);
|
|
44
|
+
watch = deps.every(check, watchMs);
|
|
45
|
+
},
|
|
46
|
+
stop() {
|
|
47
|
+
if (frame !== null)
|
|
48
|
+
deps.cancelFrame(frame);
|
|
49
|
+
if (watch !== null)
|
|
50
|
+
deps.stopEvery(watch);
|
|
51
|
+
frame = null;
|
|
52
|
+
watch = null;
|
|
53
|
+
},
|
|
54
|
+
health: () => health,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/** The files the face reader needs, by catalogue id. */
|
|
3
|
+
export declare const FACE_VISION_FILES: readonly ["visao:runtime", "visao:runtime:cola", "visao:runtime:wasm", "visao:modelo:rosto"];
|
|
4
|
+
/** The files the hand reader needs (ADR-0210 hands map: the Gesture Recognizer gives the canned gestures and the landmarks). */
|
|
5
|
+
export declare const HAND_VISION_FILES: readonly ["visao:runtime", "visao:runtime:cola", "visao:runtime:wasm", "visao:modelo:gestos"];
|
|
6
|
+
/** The part of one detection the eye control reads. */
|
|
7
|
+
export interface FaceDetection {
|
|
8
|
+
readonly faceBlendshapes?: ReadonlyArray<{
|
|
9
|
+
readonly categories: ReadonlyArray<{
|
|
10
|
+
readonly categoryName: string;
|
|
11
|
+
readonly score: number;
|
|
12
|
+
}>;
|
|
13
|
+
}>;
|
|
14
|
+
readonly facialTransformationMatrixes?: ReadonlyArray<{
|
|
15
|
+
readonly data: ArrayLike<number>;
|
|
16
|
+
}>;
|
|
17
|
+
readonly faceLandmarks?: ReadonlyArray<ReadonlyArray<{
|
|
18
|
+
readonly x: number;
|
|
19
|
+
readonly y: number;
|
|
20
|
+
readonly z: number;
|
|
21
|
+
}>>;
|
|
22
|
+
}
|
|
23
|
+
interface Landmarker {
|
|
24
|
+
detectForVideo(frame: unknown, ms: number): FaceDetection;
|
|
25
|
+
close(): void;
|
|
26
|
+
}
|
|
27
|
+
/** The part of one Gesture Recognizer result the hands map reads: each hand's categories, best first, and its landmarks. */
|
|
28
|
+
export interface HandDetection {
|
|
29
|
+
readonly gestures?: ReadonlyArray<ReadonlyArray<{
|
|
30
|
+
readonly categoryName: string;
|
|
31
|
+
readonly score: number;
|
|
32
|
+
}>>;
|
|
33
|
+
readonly landmarks?: ReadonlyArray<ReadonlyArray<{
|
|
34
|
+
readonly x: number;
|
|
35
|
+
readonly y: number;
|
|
36
|
+
readonly z: number;
|
|
37
|
+
}>>;
|
|
38
|
+
}
|
|
39
|
+
interface Recognizer {
|
|
40
|
+
recognizeForVideo(frame: unknown, ms: number): HandDetection;
|
|
41
|
+
close(): void;
|
|
42
|
+
}
|
|
43
|
+
export type Connections = ReadonlyArray<{
|
|
44
|
+
readonly start: number;
|
|
45
|
+
readonly end: number;
|
|
46
|
+
}>;
|
|
47
|
+
/** The shape of the `tasks-vision` bundle this module uses. */
|
|
48
|
+
export interface TasksVision {
|
|
49
|
+
readonly FilesetResolver: {
|
|
50
|
+
forVisionTasks(wasmBase: string): Promise<unknown>;
|
|
51
|
+
};
|
|
52
|
+
readonly FaceLandmarker: {
|
|
53
|
+
createFromOptions(fileset: unknown, options: object): Promise<Landmarker>;
|
|
54
|
+
readonly FACE_LANDMARKS_LEFT_EYE: Connections;
|
|
55
|
+
readonly FACE_LANDMARKS_RIGHT_EYE: Connections;
|
|
56
|
+
readonly FACE_LANDMARKS_LEFT_IRIS: Connections;
|
|
57
|
+
readonly FACE_LANDMARKS_RIGHT_IRIS: Connections;
|
|
58
|
+
readonly FACE_LANDMARKS_LEFT_EYEBROW: Connections;
|
|
59
|
+
readonly FACE_LANDMARKS_RIGHT_EYEBROW: Connections;
|
|
60
|
+
readonly FACE_LANDMARKS_LIPS: Connections;
|
|
61
|
+
};
|
|
62
|
+
readonly GestureRecognizer: {
|
|
63
|
+
createFromOptions(fileset: unknown, options: object): Promise<Recognizer>;
|
|
64
|
+
readonly HAND_CONNECTIONS: Connections;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** The lines the eye control highlights (ADR-0213): the eyes with their irises, and the brows — never the camera's picture (ADR-0212). */
|
|
68
|
+
export interface EyeLines {
|
|
69
|
+
readonly eyes: Connections;
|
|
70
|
+
readonly brows: Connections;
|
|
71
|
+
}
|
|
72
|
+
/** The face mode also draws the lips (ADR-0212 §3). */
|
|
73
|
+
export interface FaceLines extends EyeLines {
|
|
74
|
+
readonly lips: Connections;
|
|
75
|
+
}
|
|
76
|
+
export interface VisionDeps {
|
|
77
|
+
/** The page's address, to make the delivery paths absolute. */
|
|
78
|
+
readonly base: string;
|
|
79
|
+
/**
|
|
80
|
+
* Whether a catalogue file (by its upstream address) is in the checked cache — `platform/heavy`'s `checkedCacheHas`, over
|
|
81
|
+
* the host's `caches`. REQUIRED (ADR-0232 D4): the root lends the cache; this module reaches none.
|
|
82
|
+
*/
|
|
83
|
+
readonly hasFile: (upstreamUrl: string) => Promise<boolean>;
|
|
84
|
+
readonly importBundle?: (absoluteUrl: string) => Promise<TasksVision>;
|
|
85
|
+
}
|
|
86
|
+
export type Delegate = 'GPU' | 'CPU';
|
|
87
|
+
export interface FaceTracker {
|
|
88
|
+
/** One frame; null while it has nothing to say (no face, or the CPU landmarker still being built after a GPU failure). */
|
|
89
|
+
detect(frame: unknown, ms: number): FaceDetection | null;
|
|
90
|
+
delegate(): Delegate;
|
|
91
|
+
/** The connection sets the bundle ships for the eyes, irises and brows, to draw over the game. */
|
|
92
|
+
readonly eyeLines: EyeLines;
|
|
93
|
+
/** The same lines and the lips, for the face mode. */
|
|
94
|
+
readonly faceLines: FaceLines;
|
|
95
|
+
close(): void;
|
|
96
|
+
}
|
|
97
|
+
export type FaceTrackerLoad = {
|
|
98
|
+
readonly ok: true;
|
|
99
|
+
readonly tracker: FaceTracker;
|
|
100
|
+
} | {
|
|
101
|
+
readonly ok: false;
|
|
102
|
+
readonly missing: readonly string[];
|
|
103
|
+
};
|
|
104
|
+
export interface HandTracker {
|
|
105
|
+
/** The hand's bones, as the bundle ships them, to draw over the game (ADR-0215). */
|
|
106
|
+
readonly handLines: Connections;
|
|
107
|
+
/** One frame; null while it has nothing to say. */
|
|
108
|
+
detect(frame: unknown, ms: number): HandDetection | null;
|
|
109
|
+
delegate(): Delegate;
|
|
110
|
+
close(): void;
|
|
111
|
+
}
|
|
112
|
+
export type HandTrackerLoad = {
|
|
113
|
+
readonly ok: true;
|
|
114
|
+
readonly tracker: HandTracker;
|
|
115
|
+
} | {
|
|
116
|
+
readonly ok: false;
|
|
117
|
+
readonly missing: readonly string[];
|
|
118
|
+
};
|
|
119
|
+
export declare function loadFaceTracker(deps: VisionDeps): Promise<FaceTrackerLoad>;
|
|
120
|
+
/** The Gesture Recognizer, one hand, in video mode — as the lab's map rounds ran it. */
|
|
121
|
+
export declare function loadHandTracker(deps: VisionDeps): Promise<HandTrackerLoad>;
|
|
122
|
+
/** The camera, video only, at the size the readings were measured. */
|
|
123
|
+
export declare function openCamera(media: {
|
|
124
|
+
getUserMedia(c: MediaStreamConstraints): Promise<MediaStream>;
|
|
125
|
+
}): Promise<MediaStream>;
|
|
126
|
+
/** Let the camera go: every track stops, so the device's light goes off. */
|
|
127
|
+
export declare function closeCamera(stream: {
|
|
128
|
+
getTracks(): ReadonlyArray<{
|
|
129
|
+
stop(): void;
|
|
130
|
+
}>;
|
|
131
|
+
} | null | undefined): void;
|
|
132
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// platform/vision — THE FACE LANDMARKER AND THE CAMERA, FROM THE GAME'S OWN ORIGIN (ADR-0213, ADR-0177; issue #196).
|
|
3
|
+
//
|
|
4
|
+
// · MediaPipe `tasks-vision` and the face model are the files the install already fetched and checked by sha256 (`platform/heavy`).
|
|
5
|
+
// They are asked for at `heavy/<host><path>` beside the page, so no third-party host is contacted, and a file that is not in the
|
|
6
|
+
// checked cache is never loaded: the reader says which ones are missing instead, so the child hears why the eyes do not work.
|
|
7
|
+
// · The bundle is imported by an ABSOLUTE address: a relative one resolves against this module, not against the page.
|
|
8
|
+
// · GPU first; a GPU that fails to create the landmarker, or fails on a frame, gives way to the CPU once. The frame that failed reads
|
|
9
|
+
// nothing while the CPU landmarker is being built.
|
|
10
|
+
// · `tasks-vision` tries to send usage logs to `odml.pa.googleapis.com`; the page's CSP refuses it (measured in the lab) and that is
|
|
11
|
+
// kept on purpose — nothing about the child's camera leaves the device.
|
|
12
|
+
// · The camera is video only, 640×480: the lab's readings were measured at that size, and a larger capture changed them.
|
|
13
|
+
import { HEAVY_FILES, deliveryPath } from './heavy.js';
|
|
14
|
+
/** The files the face reader needs, by catalogue id. */
|
|
15
|
+
export const FACE_VISION_FILES = ['visao:runtime', 'visao:runtime:cola', 'visao:runtime:wasm', 'visao:modelo:rosto'];
|
|
16
|
+
/** The files the hand reader needs (ADR-0210 hands map: the Gesture Recognizer gives the canned gestures and the landmarks). */
|
|
17
|
+
export const HAND_VISION_FILES = ['visao:runtime', 'visao:runtime:cola', 'visao:runtime:wasm', 'visao:modelo:gestos'];
|
|
18
|
+
const urlOf = (id) => HEAVY_FILES.find((x) => x.id === id).url; // the vision entries are in the catalogue, with addresses
|
|
19
|
+
const OPTIONS = (modelAssetPath, delegate) => ({
|
|
20
|
+
baseOptions: { modelAssetPath, delegate }, runningMode: 'VIDEO', numFaces: 1,
|
|
21
|
+
outputFaceBlendshapes: true, outputFacialTransformationMatrixes: true,
|
|
22
|
+
});
|
|
23
|
+
/** Checks the files in the checked cache and opens the bundle; the missing ids when any file is not there. */
|
|
24
|
+
async function open(deps, files) {
|
|
25
|
+
const { hasFile } = deps;
|
|
26
|
+
const importBundle = deps.importBundle ?? ((u) => import(/* @vite-ignore */ u));
|
|
27
|
+
const missing = [];
|
|
28
|
+
for (const id of files)
|
|
29
|
+
if (!(await hasFile(urlOf(id))))
|
|
30
|
+
missing.push(id);
|
|
31
|
+
if (missing.length)
|
|
32
|
+
return { missing };
|
|
33
|
+
const at = (id) => new URL(deliveryPath(urlOf(id)), deps.base).href;
|
|
34
|
+
const vision = await importBundle(at('visao:runtime'));
|
|
35
|
+
const glue = at('visao:runtime:cola');
|
|
36
|
+
return { vision, fileset: await vision.FilesetResolver.forVisionTasks(glue.slice(0, glue.lastIndexOf('/'))), at };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* GPU first; a GPU that fails to create, or fails on a frame, gives way to the CPU once; the frame that failed reads nothing while the CPU
|
|
40
|
+
* one is built; a CPU that cannot be built makes the next frame throw. Shared by the face and the hands.
|
|
41
|
+
*/
|
|
42
|
+
async function withFallback(create, read) {
|
|
43
|
+
let delegate = 'GPU', closed = false, failure = null;
|
|
44
|
+
let current;
|
|
45
|
+
try {
|
|
46
|
+
current = await create('GPU');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
delegate = 'CPU';
|
|
50
|
+
current = await create('CPU');
|
|
51
|
+
}
|
|
52
|
+
const toCpu = () => {
|
|
53
|
+
current?.close();
|
|
54
|
+
current = null;
|
|
55
|
+
delegate = 'CPU';
|
|
56
|
+
create('CPU').then((l) => { if (closed)
|
|
57
|
+
l.close();
|
|
58
|
+
else
|
|
59
|
+
current = l; }, (e) => { failure = e; });
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
detect(frame, ms) {
|
|
63
|
+
if (failure)
|
|
64
|
+
throw failure; // the CPU could not be built either: the frame loop says so on screen
|
|
65
|
+
if (!current)
|
|
66
|
+
return null;
|
|
67
|
+
try {
|
|
68
|
+
return read(current, frame, ms);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
if (delegate === 'CPU')
|
|
72
|
+
throw e;
|
|
73
|
+
toCpu();
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
delegate: () => delegate,
|
|
78
|
+
close() { closed = true; current?.close(); current = null; },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export async function loadFaceTracker(deps) {
|
|
82
|
+
const o = await open(deps, FACE_VISION_FILES);
|
|
83
|
+
if ('missing' in o)
|
|
84
|
+
return { ok: false, missing: o.missing };
|
|
85
|
+
const F = o.vision.FaceLandmarker;
|
|
86
|
+
const eyeLines = {
|
|
87
|
+
eyes: [...F.FACE_LANDMARKS_LEFT_EYE, ...F.FACE_LANDMARKS_RIGHT_EYE, ...F.FACE_LANDMARKS_LEFT_IRIS, ...F.FACE_LANDMARKS_RIGHT_IRIS],
|
|
88
|
+
brows: [...F.FACE_LANDMARKS_LEFT_EYEBROW, ...F.FACE_LANDMARKS_RIGHT_EYEBROW],
|
|
89
|
+
};
|
|
90
|
+
const shell = await withFallback((d) => F.createFromOptions(o.fileset, OPTIONS(o.at('visao:modelo:rosto'), d)), (l, frame, ms) => l.detectForVideo(frame, ms));
|
|
91
|
+
return {
|
|
92
|
+
ok: true,
|
|
93
|
+
tracker: {
|
|
94
|
+
...shell,
|
|
95
|
+
eyeLines,
|
|
96
|
+
faceLines: { ...eyeLines, lips: F.FACE_LANDMARKS_LIPS },
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** The Gesture Recognizer, one hand, in video mode — as the lab's map rounds ran it. */
|
|
101
|
+
export async function loadHandTracker(deps) {
|
|
102
|
+
const o = await open(deps, HAND_VISION_FILES);
|
|
103
|
+
if ('missing' in o)
|
|
104
|
+
return { ok: false, missing: o.missing };
|
|
105
|
+
const options = (d) => ({ baseOptions: { modelAssetPath: o.at('visao:modelo:gestos'), delegate: d }, runningMode: 'VIDEO', numHands: 1 });
|
|
106
|
+
const shell = await withFallback((d) => o.vision.GestureRecognizer.createFromOptions(o.fileset, options(d)), (g, frame, ms) => g.recognizeForVideo(frame, ms));
|
|
107
|
+
return { ok: true, tracker: { ...shell, handLines: o.vision.GestureRecognizer.HAND_CONNECTIONS } };
|
|
108
|
+
}
|
|
109
|
+
/** The camera, video only, at the size the readings were measured. */
|
|
110
|
+
export function openCamera(media) {
|
|
111
|
+
return media.getUserMedia({ video: { width: 640, height: 480 }, audio: false });
|
|
112
|
+
}
|
|
113
|
+
/** Let the camera go: every track stops, so the device's light goes off. */
|
|
114
|
+
export function closeCamera(stream) {
|
|
115
|
+
for (const t of stream?.getTracks() ?? [])
|
|
116
|
+
t.stop();
|
|
117
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { AudioContextLike, StreamLike } from './microphone.js';
|
|
3
|
+
import type { VoskModel } from './vosk-runtime.js';
|
|
4
|
+
/** How much sound is handed over at a time. The lab's number; smaller starves the recogniser, larger delays a command. */
|
|
5
|
+
export declare const VOICE_BLOCK = 4096;
|
|
6
|
+
export interface VoiceListenerDeps {
|
|
7
|
+
readonly model: VoskModel;
|
|
8
|
+
/** Every phrase the recogniser may answer with: the language's words, plus what the open menu is showing (ADR-0194). */
|
|
9
|
+
readonly grammar: readonly string[];
|
|
10
|
+
/**
|
|
11
|
+
* The host's `navigator.mediaDevices.getUserMedia`, lent by the root (ADR-0232 D4). REQUIRED, and `undefined` is a device
|
|
12
|
+
* with no microphone: REFUSED and said, never hidden.
|
|
13
|
+
*/
|
|
14
|
+
readonly getUserMedia: ((constraints: {
|
|
15
|
+
audio: object | boolean;
|
|
16
|
+
}) => Promise<StreamLike>) | undefined;
|
|
17
|
+
/** A new audio context from the host's `AudioContext`, lent by the root. REQUIRED. */
|
|
18
|
+
readonly createContext: () => AudioContextLike;
|
|
19
|
+
/** What the recogniser has heard so far in this utterance. */
|
|
20
|
+
readonly onPartial: (text: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* The utterance ended, with the recogniser's last word on it: a name the partials held back because another item's name
|
|
23
|
+
* continued it («voltar» while «voltar ao jogo» could follow) is decided HERE (ADR-0194 §3), and whoever counts what was
|
|
24
|
+
* already answered for starts a new sentence. `''` when the recogniser heard nothing it knows.
|
|
25
|
+
*/
|
|
26
|
+
readonly onFinal?: (text: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface VoiceListener {
|
|
29
|
+
/** The words the recogniser may answer with, from now on. A new grammar is a new recogniser; the microphone stays open. */
|
|
30
|
+
setGrammar(grammar: readonly string[]): void;
|
|
31
|
+
/** Gives the microphone back and closes everything. Safe to call twice. */
|
|
32
|
+
stop(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Opens the microphone and feeds the recogniser until `stop()`.
|
|
36
|
+
*
|
|
37
|
+
* ⚠️ THE MICROPHONE IS ASKED FOR WITH ECHO CANCELLATION AND NOISE SUPPRESSION, which is what a classroom needs: twenty children
|
|
38
|
+
* in one room is the case, not the exception. Mono, because the recogniser hears one channel.
|
|
39
|
+
*/
|
|
40
|
+
export declare function startVoiceListening(d: VoiceListenerDeps): Promise<VoiceListener>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// platform/voice-listener — THE MICROPHONE THAT HEARS COMMANDS, AND LETS GO (ADR-0189, ADR-0193; issue #184).
|
|
3
|
+
//
|
|
4
|
+
// The reading opens a microphone for one sentence and closes it (`platform/microphone`); this one stays open while the child
|
|
5
|
+
// plays by voice, because a command may come at any moment. Everything else is the same promise: the sound is handed to a
|
|
6
|
+
// recogniser ON THIS MACHINE, nothing is kept, and letting go is part of the job — a page that is still listening after the
|
|
7
|
+
// child turned voice off is the promise broken, however good the reason.
|
|
8
|
+
//
|
|
9
|
+
// 📌 THE GRAMMAR CARRIES `[unk]`, and it is what lets the recogniser answer «that was not one of these». Without it a closed
|
|
10
|
+
// grammar pushes whatever it hears to the NEAREST word — the lab measured «configurações de inclusão» coming back as «quatro»,
|
|
11
|
+
// which in a game is a button the child never pressed.
|
|
12
|
+
//
|
|
13
|
+
// ⚠️ `ScriptProcessorNode`, deprecated, for the reason already written in `platform/microphone`: the AudioWorklet replacement
|
|
14
|
+
// needs its code served as a module and the engine's policy has no `blob:` in `script-src` (ADR-0214). It is also what
|
|
15
|
+
// `acceptWaveform` takes directly. Written here so the next person does not «fix» it without that decision.
|
|
16
|
+
/** How much sound is handed over at a time. The lab's number; smaller starves the recogniser, larger delays a command. */
|
|
17
|
+
export const VOICE_BLOCK = 4096;
|
|
18
|
+
const withUnknown = (grammar) => JSON.stringify([...grammar, '[unk]']);
|
|
19
|
+
/**
|
|
20
|
+
* Opens the microphone and feeds the recogniser until `stop()`.
|
|
21
|
+
*
|
|
22
|
+
* ⚠️ THE MICROPHONE IS ASKED FOR WITH ECHO CANCELLATION AND NOISE SUPPRESSION, which is what a classroom needs: twenty children
|
|
23
|
+
* in one room is the case, not the exception. Mono, because the recogniser hears one channel.
|
|
24
|
+
*/
|
|
25
|
+
export async function startVoiceListening(d) {
|
|
26
|
+
const { getUserMedia } = d;
|
|
27
|
+
if (!getUserMedia)
|
|
28
|
+
throw new Error('voice-listener: this device cannot open a microphone');
|
|
29
|
+
const context = d.createContext();
|
|
30
|
+
let recognizer = new d.model.KaldiRecognizer(context.sampleRate, withUnknown(d.grammar));
|
|
31
|
+
const listen = (r) => {
|
|
32
|
+
r.on('partialresult', (heard) => { const t = heard.result.partial; if (t)
|
|
33
|
+
d.onPartial(t); });
|
|
34
|
+
r.on('result', (heard) => { d.onFinal?.(heard.result.text ?? ''); });
|
|
35
|
+
};
|
|
36
|
+
listen(recognizer);
|
|
37
|
+
const stream = await getUserMedia({ audio: { echoCancellation: true, noiseSuppression: true, channelCount: 1 } });
|
|
38
|
+
const node = context.createScriptProcessor(VOICE_BLOCK, 1, 1);
|
|
39
|
+
let stopped = false;
|
|
40
|
+
node.onaudioprocess = (e) => {
|
|
41
|
+
if (stopped)
|
|
42
|
+
return;
|
|
43
|
+
// ⚠️ A recogniser that throws on one block must not take the microphone down with it: the next block is a new chance, and
|
|
44
|
+
// a child mid-sentence would otherwise lose the rest of it.
|
|
45
|
+
try {
|
|
46
|
+
recognizer.acceptWaveform(e.inputBuffer);
|
|
47
|
+
}
|
|
48
|
+
catch { /* this block is lost, the next is not */ }
|
|
49
|
+
};
|
|
50
|
+
context.createMediaStreamSource(stream).connect(node);
|
|
51
|
+
// 📌 The graph has to REACH the destination or nothing is pulled through it — and it must be silent, or the classroom hears
|
|
52
|
+
// itself. That is what the muted gain is for; it is not decoration.
|
|
53
|
+
node.connect(context.destination);
|
|
54
|
+
return {
|
|
55
|
+
setGrammar(grammar) {
|
|
56
|
+
if (stopped)
|
|
57
|
+
return;
|
|
58
|
+
const previous = recognizer;
|
|
59
|
+
recognizer = new d.model.KaldiRecognizer(context.sampleRate, withUnknown(grammar));
|
|
60
|
+
listen(recognizer);
|
|
61
|
+
try {
|
|
62
|
+
previous.remove();
|
|
63
|
+
}
|
|
64
|
+
catch { /* an old recogniser that is already gone is not a failure */ }
|
|
65
|
+
},
|
|
66
|
+
async stop() {
|
|
67
|
+
if (stopped)
|
|
68
|
+
return;
|
|
69
|
+
stopped = true;
|
|
70
|
+
node.onaudioprocess = null;
|
|
71
|
+
try {
|
|
72
|
+
node.disconnect();
|
|
73
|
+
}
|
|
74
|
+
catch { /* a node already detached is not a failure */ }
|
|
75
|
+
for (const t of stream.getTracks())
|
|
76
|
+
t.stop();
|
|
77
|
+
try {
|
|
78
|
+
recognizer.remove();
|
|
79
|
+
}
|
|
80
|
+
catch { /* idem */ }
|
|
81
|
+
try {
|
|
82
|
+
d.model.terminate?.();
|
|
83
|
+
}
|
|
84
|
+
catch { /* idem */ }
|
|
85
|
+
await context.close();
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -1,109 +1,26 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
/**
|
|
3
|
-
export interface
|
|
2
|
+
/** A voice a child may pick. `voice` is its identifier in its engine; `engine` is the engine that reads it. */
|
|
3
|
+
export interface NeuralVoice {
|
|
4
4
|
readonly locale: string;
|
|
5
5
|
readonly engine: string;
|
|
6
6
|
readonly voice: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* modelos `.param`/`.bin` e não `.onnx` — e este projeto corre sherpa-onnx. Dois dos links que chegaram em
|
|
13
|
-
* 2026-09-08 apontavam para os espelhos `ncnn`, e é por isso que a proibição tem gate e não só um comentário.
|
|
14
|
-
* ⚠️ E NENHUMA `int8`, pela razão MEDIDA do mesmo §5: no backend WASM o int8 corre ~3× MAIS LENTO que o fp32
|
|
15
|
-
* (RTF 5,6 contra 2,5, do log do próprio Dev) e produz saída incorrecta ou muda. Quantizar não encurta a
|
|
16
|
-
* espera aqui — alonga-a.
|
|
9
|
+
* The voices a child may pick for a language (ADR-0185): matched on the LANGUAGE of the tag, not the region — a Mexican
|
|
10
|
+
* voice reads Spanish from Spain, and a Brazilian game tagged `pt` is still Portuguese. A voice reading another language
|
|
11
|
+
* is not offered: Portuguese text through English phonemes is noise.
|
|
17
12
|
*/
|
|
18
|
-
export declare
|
|
13
|
+
export declare function voicesForLocale(tag: string, catalogue: readonly NeuralVoice[]): readonly NeuralVoice[];
|
|
19
14
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* 📏 MEDIDO EM 2026-09-08, e não escolhido: o `piper.ttstool.com` — que o Dev nomeou ao perguntar — serve o
|
|
23
|
-
* próprio runtime da própria origem e busca os modelos aqui. As quatro vozes deste catálogo respondem 200
|
|
24
|
-
* neste endereço, com `Access-Control-Allow-Origin: *`, logo um PWA pode buscá-las de outra origem.
|
|
25
|
-
*
|
|
26
|
-
* ⚠️ UM SÍTIO SÓ É A METADE QUE O REGISTO PEDE. Um endereço repetido no ponto de uso é como o CDN do
|
|
27
|
-
* WebGazer chegou ao `ui/webcam` — escrito à mão, sem política, e sem ninguém a poder mudá-lo de uma vez.
|
|
28
|
-
*
|
|
29
|
-
* ========================= 🔴 MUDOU DE ESPELHO EM 2026-09-09, E A REGRA É «BUSCAR DE ONDE O LEITOR LÊ» ====
|
|
30
|
-
* Era `rhasspy/piper-voices`, medido a 08/09 como o espelho que o `piper.ttstool.com` usa. Depois de o
|
|
31
|
-
* `platform/pesados` passar a descer os modelos no primeiro carregamento, mediu-se o outro lado — o
|
|
32
|
-
* `@mintplex-labs/piper-tts-web@1.0.4` INSTALADO, lido do bundle e não do README — e ele busca em
|
|
33
|
-
* `diffusionstudio/piper-voices`, com uma guarda que recusa qualquer URL fora de `huggingface.co`.
|
|
34
|
-
*
|
|
35
|
-
* 🎯 ENDEREÇOS DIFERENTES SIGNIFICAM CACHE DIFERENTE: a Cache Storage é indexada pela URL do pedido, logo os
|
|
36
|
-
* 241 MB que desciam no primeiro dia NÃO ERAM LIDOS POR NINGUÉM, e a biblioteca descarregava tudo outra vez
|
|
37
|
-
* no dia em que a voz fosse pedida. Até 482 MB num link de escola para uma voz.
|
|
38
|
-
*
|
|
39
|
-
* 📏 E OS DOIS ESPELHOS SERVEM OS MESMOS BYTES — 63 201 294 para o `pt_BR-faber-medium`, caminhos idênticos,
|
|
40
|
-
* `Access-Control-Allow-Origin: *` nos dois. Medido nos dois no mesmo minuto, o que torna esta troca uma
|
|
41
|
-
* correcção de facto e não uma preferência entre fornecedores.
|
|
42
|
-
*
|
|
43
|
-
* ⚠️ A CLÁUSULA DO ADR-0114 NÃO SE MEXE: o host continua nomeado num ponto só. O que mudou foi QUAL, e a
|
|
44
|
-
* regra que decide isso passa a estar escrita para não voltar a divergir — **busca-se de onde o LEITOR lê**.
|
|
45
|
-
* No dia em que a engine for dona do runtime (ADR-0124 cláusula 2), o leitor passa a ser ela e é ela que
|
|
46
|
-
* escolhe; até lá, o único leitor é a porta do cartucho.
|
|
15
|
+
* A language's name, written in another language: `languageName('en-GB', 'pt-BR')` is «inglês» — the primary language, because a
|
|
16
|
+
* voice of the same language would have read the part (ADR-0243 §3). Where the platform cannot name it, the tag's language code.
|
|
47
17
|
*/
|
|
48
|
-
export declare
|
|
18
|
+
export declare function languageName(tag: string, inLanguage: string): string;
|
|
19
|
+
/** Does a voice tagged `locale` speak the language of `tag`? By the primary language, as `voicesForLocale` matches. */
|
|
20
|
+
export declare function speaksLanguageOf(locale: string, tag: string): boolean;
|
|
49
21
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* `
|
|
53
|
-
* 🎯 DERIVAR EM VEZ DE TABELAR é a decisão inteira desta função: uma tabela de caminhos ao lado da tabela
|
|
54
|
-
* de vozes seria o mesmo facto escrito duas vezes, e este repositório já pagou isso três vezes — o
|
|
55
|
-
* `DomQuery`, os rótulos de movimento reduzido, as chaves de armazenamento. Duas listas divergem, e
|
|
56
|
-
* divergem uma entrada de cada vez.
|
|
57
|
-
*
|
|
58
|
-
* ⚠️ Devolve `null` para um identificador que não tenha a forma esperada, em vez de montar um caminho
|
|
59
|
-
* torto: uma URL inventada dá 404 na escola, e um `null` dá para reportar antes de sair de casa.
|
|
22
|
+
* THE VOICE OF A LANGUAGE (ADR-0243 §2): the child's chosen voice when it speaks that language; else the first voice `VOICE_ORDER`
|
|
23
|
+
* reaches — the exact tag before the region, a browser voice before a neural one. `chosen` comes in order of precedence.
|
|
24
|
+
* 🔴 No voice of another language is ever returned: `null` means the list has none for it, and the part is not spoken (§3).
|
|
60
25
|
*/
|
|
61
|
-
export declare function
|
|
62
|
-
/** O endereço completo do modelo. `null` quando o identificador não se deixa ler. */
|
|
63
|
-
export declare function urlDoModelo(v: VozNeural): string | null;
|
|
64
|
-
/**
|
|
65
|
-
* A CONFIGURAÇÃO da voz, que o motor lê junto com o modelo.
|
|
66
|
-
*
|
|
67
|
-
* 📌 `.onnx.json` e não um segundo caminho: é o mesmo ficheiro com outro sufixo, medido a responder 200 no
|
|
68
|
-
* mesmo sítio. Escrevê-lo como derivação mantém a regra de que o identificador é a única fonte.
|
|
69
|
-
*/
|
|
70
|
-
export declare function urlDaConfig(v: VozNeural): string | null;
|
|
71
|
-
/** Em que pé está cada voz. `falhou` é um estado e não uma excepção — ver `vozEmUso`. */
|
|
72
|
-
export type EstadoDaVoz = 'ausente' | 'a-buscar' | 'pronta' | 'falhou';
|
|
73
|
-
/** O que se sabe de cada voz, por identificador. Uma voz ausente do mapa é `ausente`. */
|
|
74
|
-
export type EstadosDasVozes = Readonly<Record<string, EstadoDaVoz | undefined>>;
|
|
75
|
-
export declare const estadoDe: (estados: EstadosDasVozes, v: VozNeural) => EstadoDaVoz;
|
|
76
|
-
/**
|
|
77
|
-
* A ORDEM POR QUE SE BUSCAM: primeiro as do idioma corrente, depois as outras, cada grupo na ordem do
|
|
78
|
-
* catálogo. Só entram as que ainda não estão prontas nem em curso.
|
|
79
|
-
*
|
|
80
|
-
* ⚠️ O IDIOMA CORRENTE PRIMEIRO É A REGRA INTEIRA, e ela é sobre uma criança e não sobre eficiência: as
|
|
81
|
-
* outras são para «conforme interesse do jogador», mas a dela é a que ela precisa AGORA. Buscar em ordem de
|
|
82
|
-
* catálogo faria uma criança brasileira esperar por duas vozes inglesas na rede de uma escola.
|
|
83
|
-
*
|
|
84
|
-
* 📌 `falhou` VOLTA À FILA. Uma escola perde a rede a meio da manhã e recupera-a; uma voz marcada como
|
|
85
|
-
* falhada para sempre seria uma criança sem voz até alguém recarregar a página. Quem chama decide QUANDO
|
|
86
|
-
* tentar de novo — este módulo só diz que ainda há o que buscar.
|
|
87
|
-
*/
|
|
88
|
-
export declare function ordemDeBusca(estados: EstadosDasVozes, localeCorrente: string, catalogo?: readonly VozNeural[]): VozNeural[];
|
|
89
|
-
/** O que a criança ouve agora. `recuo` é a voz do sistema — eSpeak ou Web Speech. */
|
|
90
|
-
export type VozEmUso = {
|
|
91
|
-
readonly tipo: 'neural';
|
|
92
|
-
readonly voice: string;
|
|
93
|
-
} | {
|
|
94
|
-
readonly tipo: 'recuo';
|
|
95
|
-
readonly porque: 'a-buscar' | 'sem-voz-para-o-idioma' | 'falhou' | 'ausente';
|
|
96
|
-
};
|
|
97
|
-
/**
|
|
98
|
-
* QUEM ESTÁ A FALAR, E POR QUE — e esta função é o gate 3 do ADR-0110 em forma de código.
|
|
99
|
-
*
|
|
100
|
-
* ⚠️ O DEFEITO QUE ELA IMPEDE TEM NOME NESTE REPOSITÓRIO: «um recuo que se apresenta como a coisa real é a
|
|
101
|
-
* família do `reflectTTS`». Uma engine que dissesse «voz neural» enquanto o modelo ainda desce faria um adulto
|
|
102
|
-
* concluir que a qualidade que ouve É a qualidade final — e desistir de esperar por uma coisa que já vinha a
|
|
103
|
-
* caminho. Dizer `recuo` e dizer PORQUÊ custa uma linha e é a diferença entre informar e enganar.
|
|
104
|
-
*
|
|
105
|
-
* 📌 A PRIMEIRA VOZ PRONTA DO IDIOMA, e nada mais: onde há duas prontas, esta função NÃO escolhe entre elas —
|
|
106
|
-
* devolve a primeira do catálogo porque tem de devolver alguma, e qual delas a criança prefere é a pergunta
|
|
107
|
-
* que o ADR-0110 deixou em aberto. Ver o cabeçalho.
|
|
108
|
-
*/
|
|
109
|
-
export declare function vozEmUso(estados: EstadosDasVozes, localeCorrente: string, catalogo?: readonly VozNeural[]): VozEmUso;
|
|
26
|
+
export declare function voiceOfLanguage(tag: string, voices: readonly NeuralVoice[], chosen?: readonly (string | null | undefined)[]): NeuralVoice | null;
|