@hypit/hypit 0.1.3 → 0.1.5
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 +5 -3
- package/dist/public/caption.d.ts +206 -183
- package/dist/public/composition.d.ts +25 -3
- package/dist/public/endpoint-kit.d.ts +24 -2
- package/dist/public/generation.d.ts +5 -1
- package/dist/public/hyperframes.d.ts +19 -1
- package/dist/public/narrative.d.ts +17 -3
- package/dist/public/performance.d.ts +1590 -0
- package/dist/public/program-space.d.ts +179 -32
- package/dist/public/runtime-kit.d.ts +21 -8
- package/dist/public/sound.d.ts +822 -0
- package/dist/public/speech.d.ts +41 -0
- package/dist/public/studio-adapter.d.ts +107 -16
- package/dist/public/temporal-markup.d.ts +9 -44
- package/dist/public/temporal.d.ts +37 -28
- package/dist/public/{semantic-track.d.ts → timeline.d.ts} +62 -49
- package/examples/README.md +18 -10
- package/examples/minimal-author-package/packages/example-component/preview/preview.svml +19 -12
- package/examples/minimal-author-package/packages/example-component/src/component.ts +5 -5
- package/examples/minimal-author-package/packages/example-component/src/fragment.ts +3 -5
- package/examples/minimal-author-package/packages/example-component/src/manifest.ts +8 -10
- package/examples/minimal-author-package/packages/example-component/src/surface.ts +2 -2
- package/examples/provider-package/README.md +78 -0
- package/examples/provider-package/hypit.runtime.json +12 -0
- package/examples/provider-package/packages/provider-images/package.json +11 -0
- package/examples/provider-package/packages/provider-images/src/activation.ts +24 -0
- package/examples/provider-package/packages/provider-images/src/provider.ts +122 -0
- package/examples/provider-package/packages/provider-images/tsconfig.json +9 -0
- package/examples/semantic-composition/README.md +6 -0
- package/examples/semantic-composition/chat.svml +6 -5
- package/examples/semantic-composition/packages/chat-scene/README.md +3 -3
- package/examples/semantic-composition/packages/chat-scene/src/activation.ts +18 -21
- package/examples/semantic-composition/packages/chat-scene/src/render.ts +4 -4
- package/examples/semantic-composition/packages/performance-styles/README.md +42 -0
- package/examples/semantic-composition/packages/performance-styles/package.json +25 -0
- package/examples/semantic-composition/packages/performance-styles/src/activation.ts +57 -0
- package/examples/semantic-composition/packages/performance-styles/src/render.ts +54 -0
- package/examples/semantic-composition/packages/performance-styles/src/studio.ts +28 -0
- package/examples/semantic-composition/packages/performance-styles/tsconfig.json +18 -0
- package/examples/semantic-composition/packages/responsive-explainer/README.md +16 -9
- package/examples/semantic-composition/packages/responsive-explainer/src/activation.ts +12 -12
- package/examples/semantic-composition/packages/responsive-explainer/src/render.ts +5 -5
- package/examples/semantic-composition/packages/sound-styles/README.md +36 -0
- package/examples/semantic-composition/packages/sound-styles/package.json +25 -0
- package/examples/semantic-composition/packages/sound-styles/src/activation.ts +53 -0
- package/examples/semantic-composition/packages/sound-styles/src/render.ts +14 -0
- package/examples/semantic-composition/packages/sound-styles/tsconfig.json +18 -0
- package/package.json +35 -15
- package/packages/audio-track/README.md +20 -13
- package/packages/audio-track/package.json +1 -1
- package/packages/audio-track/src/component.ts +4 -4
- package/packages/audio-track/src/fragment.ts +6 -5
- package/packages/audio-track/src/index.ts +1 -1
- package/packages/audio-track/src/manifest.ts +17 -16
- package/packages/audio-track/src/program.ts +21 -25
- package/packages/audio-track/src/surface.ts +19 -18
- package/packages/audio-track-studio/README.md +23 -0
- package/packages/audio-track-studio/src/index.ts +33 -19
- package/packages/author-kit/README.md +1 -1
- package/packages/background-removal/README.md +4 -7
- package/packages/browser-capture/package.json +1 -1
- package/packages/build-result/README.md +69 -0
- package/packages/build-result/package.json +2 -1
- package/packages/build-result/src/decode.ts +12 -8
- package/packages/build-result/src/execution-log.ts +17 -0
- package/packages/build-result/src/file-reference.ts +42 -0
- package/packages/build-result/src/index.ts +4 -0
- package/packages/build-result/src/replace-file-windows.ts +58 -0
- package/packages/build-result/src/replace-file.ts +11 -0
- package/packages/build-result/src/store.ts +58 -14
- package/packages/build-result/src/types.ts +41 -8
- package/packages/build-result/src/writer.ts +12 -1
- package/packages/build-result-fs/README.md +23 -1
- package/packages/build-result-s3/README.md +5 -0
- package/packages/build-result-s3/src/repository.ts +23 -5
- package/packages/caption/README.md +61 -73
- package/packages/caption/package.json +3 -2
- package/packages/caption/src/activation.ts +2 -2
- package/packages/caption/src/component.ts +20 -5
- package/packages/caption/src/display.ts +3 -18
- package/packages/caption/src/fragment.ts +3 -7
- package/packages/caption/src/index.ts +6 -5
- package/packages/caption/src/manifest.ts +29 -46
- package/packages/caption/src/style.ts +24 -135
- package/packages/caption/src/surface.ts +12 -92
- package/packages/caption/src/temporalize.ts +18 -53
- package/packages/caption/src/types.ts +8 -35
- package/packages/caption/src/visibility.ts +23 -0
- package/packages/caption-fine/README.md +31 -11
- package/packages/caption-fine/package.json +4 -2
- package/packages/caption-fine/src/component.ts +3 -3
- package/packages/caption-fine/src/fragment.ts +7 -19
- package/packages/caption-fine/src/index.ts +2 -0
- package/packages/caption-fine/src/manifest.ts +27 -18
- package/packages/caption-fine/src/recipe.ts +7 -0
- package/packages/caption-fine/src/render.ts +62 -49
- package/packages/caption-fine/src/schedule.ts +39 -35
- package/packages/caption-fine/src/style.ts +10 -9
- package/packages/caption-fine/src/surface.ts +62 -35
- package/packages/caption-fine/src/types.ts +2 -0
- package/packages/caption-fine-studio/README.md +24 -2
- package/packages/caption-fine-studio/package.json +10 -3
- package/packages/caption-fine-studio/src/activation.ts +3 -3
- package/packages/caption-fine-studio/src/index.ts +61 -40
- package/packages/cli/README.md +81 -3
- package/packages/cli/package.json +1 -0
- package/packages/cli/src/arguments.ts +39 -15
- package/packages/cli/src/build-planning.ts +9 -3
- package/packages/cli/src/command.ts +7 -1
- package/packages/cli/src/commands/environment.ts +66 -27
- package/packages/cli/src/commands/execution.ts +81 -26
- package/packages/cli/src/commands/results.ts +7 -11
- package/packages/cli/src/index.ts +2 -2
- package/packages/cli/src/machine-view.ts +15 -5
- package/packages/cli/src/main.ts +38 -42
- package/packages/cli/src/observation.ts +7 -1
- package/packages/cli/src/output.ts +92 -34
- package/packages/cli/src/result-export.ts +22 -13
- package/packages/cli/src/run-file.ts +19 -8
- package/packages/cli/src/view.ts +64 -18
- package/packages/comment-sticker/README.md +3 -3
- package/packages/comment-sticker/package.json +1 -1
- package/packages/comment-sticker/src/component.ts +4 -4
- package/packages/comment-sticker/src/fragment.ts +5 -4
- package/packages/comment-sticker/src/manifest.ts +7 -6
- package/packages/comment-sticker/src/program.ts +9 -9
- package/packages/comment-sticker/src/surface.ts +6 -7
- package/packages/comment-sticker-studio/src/index.ts +2 -1
- package/packages/compiler-node/src/compiler.ts +1 -0
- package/packages/composition/README.md +21 -0
- package/packages/composition/src/audio-presentation.ts +44 -0
- package/packages/composition/src/index.ts +3 -0
- package/packages/composition/src/schema.ts +8 -3
- package/packages/composition/src/track.ts +15 -1
- package/packages/credential-store-env/README.md +1 -1
- package/packages/deck-track/README.md +3 -3
- package/packages/deck-track/package.json +1 -1
- package/packages/deck-track/src/component.ts +5 -5
- package/packages/deck-track/src/fragment.ts +6 -5
- package/packages/deck-track/src/lower.ts +12 -12
- package/packages/deck-track/src/manifest.ts +8 -7
- package/packages/deck-track/src/program.ts +13 -16
- package/packages/deck-track/src/surface.ts +9 -10
- package/packages/driver-node/src/driver.ts +41 -3
- package/packages/elevenlabs-speech/README.md +27 -0
- package/packages/{provider-xiaomi-mimo → elevenlabs-speech}/package.json +5 -8
- package/packages/elevenlabs-speech/src/activation.ts +26 -0
- package/packages/elevenlabs-speech/src/fragment.ts +11 -0
- package/packages/elevenlabs-speech/src/index.ts +111 -0
- package/packages/elevenlabs-speech/src/surface.ts +167 -0
- package/packages/endpoint-kit/README.md +24 -0
- package/packages/endpoint-kit/src/index.ts +7 -1
- package/packages/estimate/README.md +56 -3
- package/packages/estimate/src/program.ts +7 -8
- package/packages/film/README.md +12 -7
- package/packages/film/package.json +1 -1
- package/packages/film/src/component.ts +4 -4
- package/packages/film/src/fragment.ts +6 -5
- package/packages/film/src/manifest.ts +11 -10
- package/packages/film/src/program.ts +5 -5
- package/packages/film/src/recipe.ts +2 -1
- package/packages/film/src/surface.ts +6 -6
- package/packages/film-studio/package.json +1 -1
- package/packages/film-studio/src/index.ts +2 -2
- package/packages/fishaudio-speech/README.md +33 -0
- package/packages/fishaudio-speech/package.json +21 -0
- package/packages/fishaudio-speech/src/activation.ts +32 -0
- package/packages/fishaudio-speech/src/fragment.ts +11 -0
- package/packages/fishaudio-speech/src/index.ts +156 -0
- package/packages/fishaudio-speech/src/surface.ts +192 -0
- package/packages/fonts-open/README.md +5 -0
- package/packages/fonts-open/package.json +5 -1
- package/packages/fonts-open/src/studio.ts +21 -0
- package/packages/generation/README.md +11 -1
- package/packages/generation/src/mapping.ts +28 -30
- package/packages/gpt-image/README.md +1 -2
- package/packages/grok-imagine/README.md +1 -2
- package/packages/hyperframes/README.md +7 -3
- package/packages/hyperframes/src/browser-program.ts +11 -2
- package/packages/hyperframes/src/document.ts +15 -2
- package/packages/interview-emoji-reveal/README.md +4 -4
- package/packages/interview-emoji-reveal/package.json +1 -1
- package/packages/interview-emoji-reveal/src/component.ts +4 -4
- package/packages/interview-emoji-reveal/src/fragment.ts +6 -5
- package/packages/interview-emoji-reveal/src/manifest.ts +9 -8
- package/packages/interview-emoji-reveal/src/program.ts +14 -14
- package/packages/interview-emoji-reveal/src/surface.ts +8 -9
- package/packages/media-execution/README.md +7 -3
- package/packages/media-execution/src/audio-presentation.ts +23 -0
- package/packages/media-execution/src/execute.ts +2 -0
- package/packages/media-pipeline/README.md +7 -3
- package/packages/media-pipeline/src/audio-plan.ts +4 -1
- package/packages/media-pipeline/src/component.ts +16 -2
- package/packages/media-pipeline/src/manifest.ts +3 -1
- package/packages/media-pipeline/src/types.ts +2 -1
- package/packages/media-track/README.md +14 -47
- package/packages/media-track/package.json +1 -1
- package/packages/media-track/preview/preview.svml +5 -5
- package/packages/media-track/src/author.ts +12 -6
- package/packages/media-track/src/component.ts +10 -16
- package/packages/media-track/src/fragment.ts +8 -7
- package/packages/media-track/src/index.ts +3 -1
- package/packages/media-track/src/lower.ts +7 -7
- package/packages/media-track/src/manifest.ts +16 -38
- package/packages/media-track/src/program.ts +62 -67
- package/packages/media-track/src/sampling.ts +6 -6
- package/packages/media-track/src/sequence.ts +8 -8
- package/packages/media-track/src/surface.ts +25 -43
- package/packages/media-track-studio/README.md +9 -0
- package/packages/media-track-studio/src/index.ts +23 -13
- package/packages/mimo-speech/README.md +1 -1
- package/packages/minimax-h3/README.md +1 -1
- package/packages/nano-banana/README.md +1 -1
- package/packages/narrative/README.md +23 -1
- package/packages/narrative/src/identity.ts +11 -0
- package/packages/narrative/src/index.ts +3 -0
- package/packages/narrative/src/schema.ts +28 -27
- package/packages/narrative/src/selection.ts +52 -0
- package/packages/narrative/src/types.ts +2 -0
- package/packages/package-loader-node/README.md +30 -0
- package/packages/package-loader-node/package.json +5 -2
- package/packages/package-loader-node/src/distribution-resolution.ts +10 -3
- package/packages/package-loader-node/src/index.ts +1 -0
- package/packages/package-loader-node/src/loader.ts +12 -15
- package/packages/package-loader-node/src/location.ts +27 -1
- package/packages/package-loader-node/src/module-scope.ts +183 -0
- package/packages/package-loader-node/src/types.ts +4 -0
- package/packages/performance/README.md +83 -0
- package/packages/performance/package.json +30 -0
- package/packages/performance/src/activation.ts +11 -0
- package/packages/performance/src/component.ts +46 -0
- package/packages/performance/src/index.ts +6 -0
- package/packages/performance/src/manifest.ts +53 -0
- package/packages/{media-track/src/performance.ts → performance/src/media.ts} +9 -10
- package/packages/performance/src/program.ts +51 -0
- package/packages/performance/src/style.ts +35 -0
- package/packages/performance/src/surface.ts +99 -0
- package/packages/performance-studio/README.md +25 -0
- package/packages/performance-studio/package.json +21 -0
- package/packages/performance-studio/src/activation.ts +6 -0
- package/packages/performance-studio/src/index.ts +84 -0
- package/packages/program-space/README.md +9 -18
- package/packages/program-space/src/activation.ts +1 -5
- package/packages/program-space/src/index.ts +2 -11
- package/packages/program-space/src/surface.ts +1 -20
- package/packages/project-context-node/README.md +20 -0
- package/packages/project-context-node/package.json +10 -0
- package/packages/project-context-node/src/index.ts +3 -0
- package/packages/{cli → project-context-node}/src/runtime-selection.ts +7 -2
- package/packages/provider-hyperframes-local/README.md +43 -15
- package/packages/provider-hyperframes-local/src/activation.ts +4 -3
- package/packages/provider-hyperframes-local/src/capture-process.ts +26 -4
- package/packages/provider-hyperframes-local/src/capture.ts +96 -26
- package/packages/provider-hyperframes-local/src/concurrency.ts +86 -0
- package/packages/provider-hyperframes-local/src/opaque-capture.ts +92 -0
- package/packages/provider-hyperframes-local/src/options.ts +2 -0
- package/packages/provider-hyperframes-local/src/program.ts +6 -3
- package/packages/provider-hyperframes-local/src/progress.ts +53 -0
- package/packages/provider-hyperframes-local/src/provider.ts +18 -5
- package/packages/provider-hyperframes-local/src/render.ts +48 -7
- package/packages/provider-hypihub/README.md +48 -17
- package/packages/provider-hypihub/package.json +2 -0
- package/packages/provider-hypihub/src/mapping.ts +31 -7
- package/packages/provider-hypihub/src/oauth.ts +6 -0
- package/packages/provider-hypihub/src/provider.ts +25 -13
- package/packages/provider-hypihub/src/routes.ts +1 -2
- package/packages/provider-hypihub/src/upload.ts +2 -0
- package/packages/provider-media-local/README.md +3 -4
- package/packages/provider-whisperx-local/README.md +57 -0
- package/packages/provider-whisperx-local/src/program.ts +1 -0
- package/packages/provider-whisperx-local/src/provider.ts +3 -0
- package/packages/ranking/README.md +8 -6
- package/packages/ranking/package.json +1 -1
- package/packages/ranking/src/component.ts +6 -6
- package/packages/ranking/src/fragment.ts +11 -7
- package/packages/ranking/src/manifest.ts +21 -14
- package/packages/ranking/src/render.ts +33 -35
- package/packages/ranking/src/schedule.ts +16 -19
- package/packages/ranking/src/surface.ts +12 -13
- package/packages/ranking-studio/README.md +29 -0
- package/packages/ranking-studio/package.json +8 -3
- package/packages/ranking-studio/src/index.ts +71 -12
- package/packages/render-hyperframes/README.md +7 -7
- package/packages/render-hyperframes/package.json +1 -1
- package/packages/render-hyperframes/src/component.ts +11 -1
- package/packages/render-hyperframes/src/fragment.ts +7 -4
- package/packages/render-hyperframes/src/manifest.ts +4 -4
- package/packages/render-hyperframes/src/surface.ts +6 -6
- package/packages/runtime/README.md +8 -1
- package/packages/runtime/src/catalog.ts +2 -0
- package/packages/runtime/src/execution.ts +15 -4
- package/packages/runtime/src/index.ts +2 -1
- package/packages/runtime/src/log.ts +51 -0
- package/packages/runtime/src/types.ts +5 -8
- package/packages/runtime-host-node/README.md +30 -0
- package/packages/runtime-host-node/package.json +1 -0
- package/packages/runtime-host-node/src/index.ts +25 -9
- package/packages/runtime-host-node/src/packages.ts +47 -50
- package/packages/runtime-kit/README.md +5 -0
- package/packages/runtime-kit/src/index.ts +3 -1
- package/packages/runtime-local/README.md +111 -4
- package/packages/runtime-local/src/config.ts +202 -56
- package/packages/runtime-local/src/control.ts +9 -1
- package/packages/runtime-local/src/executor.ts +66 -0
- package/packages/runtime-local/src/host.ts +37 -17
- package/packages/runtime-local/src/log.ts +48 -0
- package/packages/runtime-local/src/programs.ts +41 -25
- package/packages/runtime-local/src/result-writer.ts +2 -0
- package/packages/runtime-local/src/runtime.ts +10 -6
- package/packages/runtime-local/src/supervisor.ts +142 -0
- package/packages/runtime-local/src/types.ts +9 -2
- package/packages/runtime-local/src/worker-process.ts +7 -24
- package/packages/runtime-local/src/worker.ts +55 -83
- package/packages/screen-overlay/README.md +3 -3
- package/packages/screen-overlay/package.json +1 -1
- package/packages/screen-overlay/src/component.ts +3 -3
- package/packages/screen-overlay/src/fragment.ts +5 -4
- package/packages/screen-overlay/src/manifest.ts +7 -6
- package/packages/screen-overlay/src/program.ts +9 -9
- package/packages/screen-overlay/src/surface.ts +6 -7
- package/packages/script/README.md +37 -2
- package/packages/script/src/edit.ts +123 -73
- package/packages/script/src/lexical.ts +40 -6
- package/packages/script/src/manifest.ts +2 -2
- package/packages/script/src/narrative.ts +1 -0
- package/packages/script/src/parser.ts +36 -8
- package/packages/script/src/surface.ts +4 -3
- package/packages/script/src/types.ts +5 -1
- package/packages/script-studio/package.json +9 -3
- package/packages/script-studio/src/index.ts +2 -0
- package/packages/script-studio/src/projection.ts +105 -0
- package/packages/seedance/README.md +30 -1
- package/packages/seedance/src/index.ts +18 -7
- package/packages/seedance/src/surface.ts +17 -4
- package/packages/seedance-kits/README.md +10 -2
- package/packages/seedance-kits/kits/speaker-v1.svs +5 -5
- package/packages/seedream/README.md +1 -1
- package/packages/sound/README.md +81 -0
- package/packages/sound/package.json +25 -0
- package/packages/sound/src/activation.ts +11 -0
- package/packages/sound/src/component.ts +28 -0
- package/packages/sound/src/index.ts +5 -0
- package/packages/sound/src/manifest.ts +47 -0
- package/packages/sound/src/program.ts +84 -0
- package/packages/sound/src/style.ts +34 -0
- package/packages/sound/src/surface.ts +90 -0
- package/packages/sound-studio/README.md +22 -0
- package/packages/sound-studio/package.json +20 -0
- package/packages/sound-studio/src/activation.ts +6 -0
- package/packages/sound-studio/src/index.ts +74 -0
- package/packages/speech/README.md +2 -2
- package/packages/speech-alignment/src/align.ts +45 -21
- package/packages/speech-alignment/src/local.ts +8 -0
- package/packages/speech-alignment/src/locate.ts +1 -1
- package/packages/store-sqlite/README.md +7 -0
- package/packages/store-sqlite/src/store.ts +84 -83
- package/packages/studio/INSPECTOR.md +117 -0
- package/packages/studio/README.md +149 -14
- package/packages/studio/package.json +8 -7
- package/packages/studio/src/build-library.ts +99 -84
- package/packages/studio/src/companion-assembly.ts +1 -0
- package/packages/studio/src/domain.ts +1 -1
- package/packages/studio/src/fallback-companions.ts +3 -3
- package/packages/studio/src/feedback-server.ts +51 -0
- package/packages/studio/src/feedback-store.ts +66 -0
- package/packages/studio/src/feedback.ts +60 -0
- package/packages/studio/src/library-media.ts +19 -0
- package/packages/studio/src/parameter-values.ts +83 -1
- package/packages/studio/src/parameters.ts +132 -43
- package/packages/studio/src/preview/render.ts +5 -1
- package/packages/studio/src/preview/runtime-shim.ts +49 -3
- package/packages/studio/src/programme.ts +14 -30
- package/packages/studio/src/server.ts +66 -34
- package/packages/studio/src/shared.ts +24 -8
- package/packages/studio/src/snapshot.ts +21 -132
- package/packages/studio/src/studio-preflight.ts +3 -3
- package/packages/studio/src/studio-registry.ts +72 -6
- package/packages/studio/src/style.css +342 -190
- package/packages/studio/src/temporal-edit.ts +131 -0
- package/packages/studio/src/ui/artifact-name.ts +80 -0
- package/packages/studio/src/ui/artifact-preview.ts +99 -0
- package/packages/studio/src/ui/comments.ts +233 -0
- package/packages/studio/src/ui/icons.ts +10 -1
- package/packages/studio/src/ui/library.ts +373 -192
- package/packages/studio/src/ui/main.ts +291 -110
- package/packages/studio/src/ui/material-preview.ts +1 -1
- package/packages/studio/src/ui/overlay.ts +31 -26
- package/packages/studio/src/ui/scrub-preview.ts +108 -0
- package/packages/studio/src/ui/sidebar-panel.ts +31 -0
- package/packages/studio/src/ui/stage.ts +188 -9
- package/packages/studio/src/ui/timeline.ts +187 -281
- package/packages/studio/start.ts +19 -5
- package/packages/studio-adapter/README.md +151 -11
- package/packages/studio-adapter/src/index.ts +126 -14
- package/packages/temporal/README.md +6 -6
- package/packages/temporal/package.json +1 -1
- package/packages/temporal/src/component.ts +5 -6
- package/packages/temporal/src/index.ts +8 -6
- package/packages/temporal/src/location.ts +11 -11
- package/packages/temporal/src/projection.ts +19 -19
- package/packages/temporal/src/rational.ts +4 -4
- package/packages/temporal-markup/EDITING.md +183 -0
- package/packages/temporal-markup/README.md +31 -11
- package/packages/temporal-markup/package.json +1 -1
- package/packages/temporal-markup/src/index.ts +20 -25
- package/packages/temporal-markup/src/space.ts +10 -41
- package/packages/timeline/README.md +31 -0
- package/packages/{semantic-track → timeline}/package.json +1 -1
- package/packages/timeline/src/activation.ts +8 -0
- package/packages/timeline/src/component.ts +24 -0
- package/packages/timeline/src/identity.ts +60 -0
- package/packages/timeline/src/index.ts +6 -0
- package/packages/{semantic-track → timeline}/src/location.ts +20 -20
- package/packages/timeline/src/manifest.ts +39 -0
- package/packages/{semantic-track → timeline}/src/projection.ts +14 -14
- package/packages/timeline/src/types.ts +24 -0
- package/packages/timeline-author/README.md +68 -0
- package/packages/{speech-track → timeline-author}/package.json +6 -4
- package/packages/timeline-author/src/activation.ts +22 -0
- package/packages/{speech-track → timeline-author}/src/component.ts +15 -13
- package/packages/{speech-track → timeline-author}/src/fragment.ts +14 -23
- package/packages/timeline-author/src/index.ts +7 -0
- package/packages/timeline-author/src/manifest.ts +78 -0
- package/packages/timeline-author/src/program.ts +107 -0
- package/packages/timeline-author/src/surface.ts +46 -0
- package/packages/timeline-author/src/types.ts +6 -0
- package/packages/typography-track/README.md +4 -4
- package/packages/typography-track/package.json +1 -1
- package/packages/typography-track/src/component.ts +4 -4
- package/packages/typography-track/src/fragment.ts +4 -3
- package/packages/typography-track/src/manifest.ts +11 -9
- package/packages/typography-track/src/program.ts +15 -15
- package/packages/typography-track/src/surface.ts +17 -18
- package/packages/typography-track-studio/package.json +8 -3
- package/packages/typography-track-studio/src/index.ts +5 -1
- package/packages/video-cli/README.md +16 -4
- package/packages/video-cli/package.json +2 -1
- package/packages/video-cli/src/creation.ts +25 -9
- package/packages/video-cli/src/index.ts +1 -1
- package/packages/video-cli/src/studio-distribution.ts +2 -1
- package/packages/volcengine-matting/README.md +3 -3
- package/packages/whisperx/README.md +8 -1
- package/packages/workspace/src/index.ts +2 -0
- package/packages/workspace-fs-node/README.md +4 -1
- package/packages/workspace-fs-node/src/workspace.ts +3 -1
- package/services/whisperx/README.md +14 -0
- package/services/whisperx/pyproject.toml +2 -0
- package/services/whisperx/uv.lock +20 -20
- package/packages/provider-hyperframes-aws-lambda/README.md +0 -30
- package/packages/provider-hyperframes-aws-lambda/package.json +0 -30
- package/packages/provider-hyperframes-aws-lambda/src/activation.ts +0 -97
- package/packages/provider-hyperframes-aws-lambda/src/client.ts +0 -114
- package/packages/provider-hyperframes-aws-lambda/src/index.ts +0 -21
- package/packages/provider-hyperframes-aws-lambda/src/provider.ts +0 -522
- package/packages/provider-kie/README.md +0 -134
- package/packages/provider-kie/package.json +0 -43
- package/packages/provider-kie/src/activation.ts +0 -71
- package/packages/provider-kie/src/index.ts +0 -10
- package/packages/provider-kie/src/mapping.ts +0 -182
- package/packages/provider-kie/src/provider.ts +0 -657
- package/packages/provider-kie/src/routes.ts +0 -150
- package/packages/provider-xiaomi-mimo/README.md +0 -32
- package/packages/provider-xiaomi-mimo/src/activation.ts +0 -57
- package/packages/provider-xiaomi-mimo/src/index.ts +0 -5
- package/packages/provider-xiaomi-mimo/src/provider.ts +0 -214
- package/packages/runtime/src/environment.ts +0 -6
- package/packages/semantic-track/README.md +0 -21
- package/packages/semantic-track/src/activation.ts +0 -8
- package/packages/semantic-track/src/component.ts +0 -24
- package/packages/semantic-track/src/identity.ts +0 -58
- package/packages/semantic-track/src/index.ts +0 -6
- package/packages/semantic-track/src/manifest.ts +0 -38
- package/packages/semantic-track/src/types.ts +0 -26
- package/packages/speech-track/README.md +0 -51
- package/packages/speech-track/src/activation.ts +0 -19
- package/packages/speech-track/src/index.ts +0 -7
- package/packages/speech-track/src/manifest.ts +0 -73
- package/packages/speech-track/src/program.ts +0 -64
- package/packages/speech-track/src/surface.ts +0 -35
- package/packages/speech-track/src/types.ts +0 -6
- package/packages/speech-track-studio/README.md +0 -3
- package/packages/speech-track-studio/package.json +0 -14
- package/packages/speech-track-studio/src/activation.ts +0 -7
- package/packages/speech-track-studio/src/index.ts +0 -40
- /package/packages/{cli → project-context-node}/src/project-context.ts +0 -0
- /package/packages/{speech-track → timeline-author}/preview/Track.png +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ExecutionDiagnostic } from "@hypit/runtime";
|
|
1
2
|
import { execFile, spawn } from "node:child_process";
|
|
2
3
|
import { promisify } from "node:util";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -11,7 +12,17 @@ const cleanupMs = 5_000;
|
|
|
11
12
|
/** Chrome starts its own process group, so stopping only the Node child is insufficient. */
|
|
12
13
|
async function killRenderTree(pid: number): Promise<void> {
|
|
13
14
|
if (process.platform === "win32") {
|
|
14
|
-
|
|
15
|
+
try {
|
|
16
|
+
await exec("taskkill", ["/PID", String(pid), "/T", "/F"], { windowsHide: true, timeout: cleanupMs });
|
|
17
|
+
} catch (error) {
|
|
18
|
+
// The worker may exit after reporting completion, before taskkill opens it.
|
|
19
|
+
// Ask the OS whether it is gone; localized taskkill output is not an API.
|
|
20
|
+
try { process.kill(pid, 0); }
|
|
21
|
+
catch (probeError) {
|
|
22
|
+
if ((probeError as NodeJS.ErrnoException).code === "ESRCH") return;
|
|
23
|
+
}
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
15
26
|
return;
|
|
16
27
|
}
|
|
17
28
|
const { stdout } = await exec("ps", ["-A", "-o", "pid=,ppid="], { timeout: cleanupMs });
|
|
@@ -47,6 +58,7 @@ export async function runCaptureProcess(
|
|
|
47
58
|
signal: AbortSignal,
|
|
48
59
|
onProgress: (event: HyperframesRenderProgress) => void,
|
|
49
60
|
entry = new URL("./capture-worker.ts", import.meta.url),
|
|
61
|
+
onDiagnostic?: (diagnostic: ExecutionDiagnostic) => Promise<void>,
|
|
50
62
|
): Promise<void> {
|
|
51
63
|
signal.throwIfAborted();
|
|
52
64
|
await new Promise<void>((resolve, reject) => {
|
|
@@ -58,6 +70,7 @@ export async function runCaptureProcess(
|
|
|
58
70
|
let completed = false;
|
|
59
71
|
let outputBytes = 0;
|
|
60
72
|
let stderr = "";
|
|
73
|
+
let diagnostics = Promise.resolve();
|
|
61
74
|
let grace: ReturnType<typeof setTimeout> | undefined;
|
|
62
75
|
let killing: Promise<void> | undefined;
|
|
63
76
|
const kill = () => {
|
|
@@ -80,8 +93,16 @@ export async function runCaptureProcess(
|
|
|
80
93
|
if (error) stderr = `${stderr}${chunk.toString()}`.slice(-32_000);
|
|
81
94
|
if (outputBytes > input.config.maxProcessOutputBytes) stop(new Error("HyperFrames process output exceeded the configured limit"));
|
|
82
95
|
};
|
|
83
|
-
child.stdout
|
|
84
|
-
|
|
96
|
+
for (const [stream, pipe] of [["stdout", child.stdout], ["stderr", child.stderr]] as const) {
|
|
97
|
+
pipe?.setEncoding("utf8");
|
|
98
|
+
pipe?.on("data", (text: string) => {
|
|
99
|
+
log(Buffer.from(text), stream === "stderr");
|
|
100
|
+
if (onDiagnostic !== undefined && text.trim()) {
|
|
101
|
+
diagnostics = diagnostics.then(() => onDiagnostic({ stream, level: "info", message: text.trimEnd() }))
|
|
102
|
+
.catch((error) => stop(error instanceof Error ? error : new Error(String(error))));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
85
106
|
child.on("message", (value: { type: string; event?: HyperframesRenderProgress; error?: string }) => {
|
|
86
107
|
if (value.type === "progress" && value.event !== undefined) {
|
|
87
108
|
try { onProgress(value.event); } catch (error) { stop(error instanceof Error ? error : new Error(String(error))); }
|
|
@@ -98,7 +119,8 @@ export async function runCaptureProcess(
|
|
|
98
119
|
child.on("close", () => {
|
|
99
120
|
if (grace !== undefined) clearTimeout(grace);
|
|
100
121
|
signal.removeEventListener("abort", abort);
|
|
101
|
-
void (killing ?? Promise.resolve()).then(() => {
|
|
122
|
+
void (killing ?? Promise.resolve()).then(async () => {
|
|
123
|
+
await diagnostics;
|
|
102
124
|
if (failure !== undefined) reject(failure);
|
|
103
125
|
else if (!completed) reject(new Error(`HyperFrames process exited before completion: ${stderr}`));
|
|
104
126
|
else resolve();
|
|
@@ -6,6 +6,9 @@ import type { HyperframesRenderProgress, resolveExecutionOptions } from "./rende
|
|
|
6
6
|
import { assert, runProcess } from "./process.js";
|
|
7
7
|
import { verifyOutput } from "./output.js";
|
|
8
8
|
import { distributeFrameRange, sourceFrameAt, sourceWindows, videoSlots } from "./sampling.js";
|
|
9
|
+
import { renderWorkerLimit } from "./render.js";
|
|
10
|
+
import { CaptureConcurrency } from "./concurrency.js";
|
|
11
|
+
import { createOpaqueFrameCapture } from "./opaque-capture.js";
|
|
9
12
|
|
|
10
13
|
export type CaptureInput = {
|
|
11
14
|
readonly document: HyperframesDocument;
|
|
@@ -22,8 +25,14 @@ export async function captureStagedVisual(input: CaptureInput, controller: Abort
|
|
|
22
25
|
const { document, range, config, directory: work } = input;
|
|
23
26
|
const signal = controller.signal;
|
|
24
27
|
const frameCount = range.endFrameExclusive - range.startFrame;
|
|
25
|
-
const tasks = distributeFrameRange(range, config.workers);
|
|
26
28
|
const fps = { num: document.frameRate.numerator, den: document.frameRate.denominator };
|
|
29
|
+
const limit = renderWorkerLimit(config, frameCount, fps.num / fps.den);
|
|
30
|
+
const concurrency = new CaptureConcurrency(limit, config.workers === "auto");
|
|
31
|
+
// Short contiguous batches retain sequential capture while allowing free browsers
|
|
32
|
+
// to help with expensive passages. This queue exists only inside this render.
|
|
33
|
+
const batchCount = Math.max(limit, Math.ceil(frameCount / Math.max(1, Math.round(fps.num / fps.den))));
|
|
34
|
+
const batches = distributeFrameRange(range, batchCount);
|
|
35
|
+
let nextBatch = 0;
|
|
27
36
|
const started = performance.now();
|
|
28
37
|
const elapsedMs = () => Math.round(performance.now() - started);
|
|
29
38
|
const engine = await import(input.engineModule) as typeof import("@hyperframes/engine");
|
|
@@ -65,7 +74,11 @@ export async function captureStagedVisual(input: CaptureInput, controller: Abort
|
|
|
65
74
|
const sources = new Map<string, { frames: Map<number, string>; width: number; height: number }>();
|
|
66
75
|
let sourceFrames = 0;
|
|
67
76
|
// One source at a time bounds decoder pressure independently of browser concurrency.
|
|
68
|
-
|
|
77
|
+
const windows = sourceWindows(slots, range);
|
|
78
|
+
const sourceTotal = windows.reduce((sum, source) => sum + source.windows.reduce((count, window) =>
|
|
79
|
+
count + window.endFrameExclusive - window.startFrame, 0), 0);
|
|
80
|
+
if (sourceTotal > 0) onProgress({ phase: "decoding", completed: 0, total: sourceTotal, elapsedMs: elapsedMs() });
|
|
81
|
+
for (const source of windows) {
|
|
69
82
|
const path = resolve(work, source.src);
|
|
70
83
|
assert(path.startsWith(`${work}${sep}`), "HyperFrames source is outside the staged project");
|
|
71
84
|
const frames = new Map<number, string>();
|
|
@@ -86,6 +99,7 @@ export async function captureStagedVisual(input: CaptureInput, controller: Abort
|
|
|
86
99
|
width = extracted.metadata.width;
|
|
87
100
|
height = extracted.metadata.height;
|
|
88
101
|
sourceFrames += count;
|
|
102
|
+
onProgress({ phase: "decoding", completed: sourceFrames, total: sourceTotal, elapsedMs: elapsedMs() });
|
|
89
103
|
}
|
|
90
104
|
sources.set(source.src, { frames, width, height });
|
|
91
105
|
}
|
|
@@ -109,9 +123,24 @@ export async function captureStagedVisual(input: CaptureInput, controller: Abort
|
|
|
109
123
|
const serverUrl = server.url;
|
|
110
124
|
const outputFrames = join(work, "frames");
|
|
111
125
|
await mkdir(outputFrames);
|
|
112
|
-
onProgress?.({ phase: "prepared", workers:
|
|
113
|
-
const
|
|
126
|
+
onProgress?.({ phase: "prepared", workers: concurrency.target, sourceFrames, elapsedMs: elapsedMs() });
|
|
127
|
+
const jobs: Promise<void>[] = [];
|
|
128
|
+
let active = 0, open = 0, initializing = 0, capturedFrames = 0;
|
|
129
|
+
let startupMs = 0;
|
|
130
|
+
const launch = (): void => {
|
|
131
|
+
const worker = jobs.length;
|
|
132
|
+
jobs.push(runWorker(worker));
|
|
133
|
+
// Failure stops all jobs promptly; all jobs are still awaited below.
|
|
134
|
+
void jobs[worker]!.catch(() => {});
|
|
135
|
+
};
|
|
136
|
+
const runWorker = async (worker: number): Promise<void> => {
|
|
114
137
|
let session: Session | undefined;
|
|
138
|
+
let ready = false;
|
|
139
|
+
active++;
|
|
140
|
+
open++;
|
|
141
|
+
initializing++;
|
|
142
|
+
const launched = performance.now();
|
|
143
|
+
let setupMs = 0;
|
|
115
144
|
try {
|
|
116
145
|
signal.throwIfAborted();
|
|
117
146
|
const directory = join(work, `worker-${worker}`);
|
|
@@ -120,7 +149,9 @@ export async function captureStagedVisual(input: CaptureInput, controller: Abort
|
|
|
120
149
|
frameSrcResolver: (path) => new URL(relative(work, path).split(sep).map(encodeURIComponent).join("/"), `${serverUrl}/`).href,
|
|
121
150
|
});
|
|
122
151
|
session = await engine.createCaptureSession(serverUrl, directory, {
|
|
123
|
-
|
|
152
|
+
// Engine initialization couples PNG to transparent-export mode. Use
|
|
153
|
+
// its opaque session setup; our capture adapter writes lossless PNG.
|
|
154
|
+
...document.canvas, fps, format: "jpeg",
|
|
124
155
|
compositionDurationSeconds: document.frameCount * fps.den / fps.num,
|
|
125
156
|
skipReadinessVideoIds: slots.map((slot) => slot.id),
|
|
126
157
|
videoMetadataHints: slots.flatMap((slot) => {
|
|
@@ -132,38 +163,77 @@ export async function captureStagedVisual(input: CaptureInput, controller: Abort
|
|
|
132
163
|
signal.throwIfAborted();
|
|
133
164
|
const activeSession = session;
|
|
134
165
|
const browserPid = session.browser.process()?.pid;
|
|
135
|
-
onProgress?.({ phase: "worker-initializing", worker, range
|
|
166
|
+
onProgress?.({ phase: "worker-initializing", worker, range, browserPid, elapsedMs: elapsedMs() });
|
|
136
167
|
await stage(`worker ${worker} initialization`, config.initializationTimeoutMs, () => engine.initializeSession(activeSession));
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
onProgress?.({ phase: "worker-start", worker, range
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
const captureFrame = await createOpaqueFrameCapture(activeSession);
|
|
169
|
+
setupMs = performance.now() - launched;
|
|
170
|
+
startupMs = Math.max(startupMs, setupMs);
|
|
171
|
+
ready = true;
|
|
172
|
+
initializing--;
|
|
173
|
+
if (initializing === 0) concurrency.settled(performance.now());
|
|
174
|
+
onProgress?.({ phase: "worker-start", worker, range, browserPid, elapsedMs: elapsedMs() });
|
|
175
|
+
let completed = 0;
|
|
176
|
+
let lastProgressAt = performance.now();
|
|
177
|
+
const timing = { seekMs: 0, prepareMs: 0, screenshotMs: 0 };
|
|
178
|
+
while (true) {
|
|
179
|
+
// Retire only between complete batches, before claiming more work.
|
|
180
|
+
if (active > concurrency.target) break;
|
|
181
|
+
const batch = batches[nextBatch++];
|
|
182
|
+
if (batch === undefined) break;
|
|
183
|
+
for (let frame = batch.startFrame; frame < batch.endFrameExclusive; frame++) {
|
|
184
|
+
signal.throwIfAborted();
|
|
185
|
+
const captured = await stage(`worker ${worker} frame ${frame}`, config.frameTimeoutMs, () => captureFrame(frame));
|
|
186
|
+
timing.seekMs += captured.seekMs;
|
|
187
|
+
timing.prepareMs += captured.prepareMs;
|
|
188
|
+
timing.screenshotMs += captured.screenshotMs;
|
|
189
|
+
await writeFile(join(outputFrames, `${String(frame - range.startFrame).padStart(9, "0")}.png`), captured.buffer);
|
|
190
|
+
completed++;
|
|
191
|
+
capturedFrames++;
|
|
192
|
+
if (performance.now() - lastProgressAt >= 1_000) {
|
|
193
|
+
onProgress({ phase: "worker-progress", worker, completed, elapsedMs: elapsedMs() });
|
|
194
|
+
lastProgressAt = performance.now();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const decision = concurrency.complete({ now: performance.now(), frames: batch.endFrameExclusive - batch.startFrame,
|
|
198
|
+
remainingFrames: frameCount - capturedFrames, startupMs, active: initializing === 0 ? active : 0 });
|
|
199
|
+
if (decision !== undefined) {
|
|
200
|
+
console.log(`Capture auto: ${active} -> ${decision.workers} browsers; ${decision.fps.toFixed(1)} frames/s; ${decision.reason}`);
|
|
201
|
+
while (active < decision.workers && open < limit && nextBatch < batches.length) launch();
|
|
202
|
+
}
|
|
154
203
|
}
|
|
155
|
-
|
|
204
|
+
console.log(`Capture worker ${worker}: ${completed} frames; startup ${Math.round(setupMs)} ms; `
|
|
205
|
+
+ `seek ${Math.round(timing.seekMs)} ms; prepare ${Math.round(timing.prepareMs)} ms; PNG ${Math.round(timing.screenshotMs)} ms`);
|
|
206
|
+
onProgress({ phase: "worker-complete", worker, completed, browserPid, elapsedMs: elapsedMs() });
|
|
156
207
|
} catch (error) {
|
|
157
208
|
controller.abort(error);
|
|
158
209
|
throw error;
|
|
159
210
|
} finally {
|
|
211
|
+
active--;
|
|
212
|
+
if (!ready) initializing--;
|
|
160
213
|
if (session !== undefined) await close(session);
|
|
214
|
+
open--;
|
|
215
|
+
// A restoring decision can wait for a retiring Chrome to release its
|
|
216
|
+
// slot. Closing processes still count against the reserved ceiling.
|
|
217
|
+
if (!signal.aborted && active < concurrency.target && open < limit && nextBatch < batches.length) launch();
|
|
161
218
|
}
|
|
162
|
-
}
|
|
219
|
+
};
|
|
220
|
+
const initialWorkers = concurrency.target;
|
|
221
|
+
console.log(`Capture: opaque fast PNG; ${config.workers === "auto" ? "auto" : "fixed"} workers ${initialWorkers}, limit ${limit}`);
|
|
222
|
+
for (let i = 0; i < initialWorkers; i++) launch();
|
|
223
|
+
// New workers can join while earlier jobs run; collect every launched job.
|
|
224
|
+
let awaited = 0;
|
|
225
|
+
let failure: unknown;
|
|
226
|
+
while (awaited < jobs.length) {
|
|
227
|
+
const pending = jobs.slice(awaited);
|
|
228
|
+
awaited = jobs.length;
|
|
229
|
+
const results = await Promise.allSettled(pending);
|
|
230
|
+
for (const result of results) if (result.status === "rejected") failure ??= result.reason;
|
|
231
|
+
}
|
|
232
|
+
if (failure !== undefined) throw failure;
|
|
163
233
|
signal.throwIfAborted();
|
|
164
|
-
for (const result of results) if (result.status === "rejected") throw result.reason;
|
|
165
234
|
await Promise.all(closing.values());
|
|
166
235
|
const output = join(work, "visual.mp4");
|
|
236
|
+
onProgress({ phase: "encoding", elapsedMs: elapsedMs() });
|
|
167
237
|
const crf = { draft: 28, standard: 23, high: 18 }[config.quality];
|
|
168
238
|
await runProcess({ executable: config.ffmpegPath,
|
|
169
239
|
argv: ["-v", "error", "-y", "-framerate", `${fps.num}/${fps.den}`, "-i", join(outputFrames, "%09d.png"),
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { availableParallelism, totalmem } from "node:os";
|
|
2
|
+
|
|
3
|
+
function hostMemory(): number {
|
|
4
|
+
const constrained = process.constrainedMemory?.() ?? 0;
|
|
5
|
+
return constrained > 0 ? Math.min(totalmem(), constrained) : totalmem();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Stable reservation ceiling. Actual load tuning happens inside the admitted render. */
|
|
9
|
+
export function autoWorkerLimit(cpu = availableParallelism(), memory = hostMemory()): number {
|
|
10
|
+
// Chrome owns raster surfaces, decoded media and the JS heap in separate
|
|
11
|
+
// processes. Leave half the memory and two CPU slots to the host/other stages.
|
|
12
|
+
const byMemory = Math.floor(memory / 2 / (1.5 * 1024 ** 3));
|
|
13
|
+
return Math.max(1, Math.min(Math.max(1, cpu - 2), byMemory));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Online throughput comparison of useful capture batches. All samples and
|
|
18
|
+
* decisions die with this attempt. A change never invalidates captured frames.
|
|
19
|
+
*/
|
|
20
|
+
export class CaptureConcurrency {
|
|
21
|
+
target: number;
|
|
22
|
+
private since: number | undefined;
|
|
23
|
+
private frames = 0;
|
|
24
|
+
private batches = 0;
|
|
25
|
+
private baseline: { workers: number; rate: number } | undefined;
|
|
26
|
+
private previousRate: number | undefined;
|
|
27
|
+
private growth = true;
|
|
28
|
+
|
|
29
|
+
constructor(readonly limit: number, readonly automatic: boolean) {
|
|
30
|
+
this.target = automatic ? Math.max(1, Math.ceil(limit / 2)) : limit;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
settled(now: number): void {
|
|
34
|
+
this.since = now;
|
|
35
|
+
this.frames = 0;
|
|
36
|
+
this.batches = 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
complete(input: { now: number; frames: number; remainingFrames: number; startupMs: number; active: number }):
|
|
40
|
+
{ workers: number; reason: string; fps: number } | undefined {
|
|
41
|
+
if (!this.automatic) return;
|
|
42
|
+
if (input.active !== this.target) { this.since = undefined; return; }
|
|
43
|
+
if (this.since === undefined) { this.settled(input.now); return; }
|
|
44
|
+
this.frames += input.frames;
|
|
45
|
+
this.batches++;
|
|
46
|
+
const elapsed = input.now - this.since;
|
|
47
|
+
// At least two batches per worker and a browser startup's worth of useful
|
|
48
|
+
// work amortize short fluctuations. No synthetic calibration is rendered.
|
|
49
|
+
if (this.batches < this.target * 2 || elapsed < Math.max(1_000, input.startupMs)) return;
|
|
50
|
+
const rate = this.frames * 1_000 / elapsed;
|
|
51
|
+
let next = this.target;
|
|
52
|
+
let reason = "";
|
|
53
|
+
if (this.baseline !== undefined) {
|
|
54
|
+
const before = this.baseline;
|
|
55
|
+
this.baseline = undefined;
|
|
56
|
+
const added = this.target > before.workers;
|
|
57
|
+
if (rate < before.rate * (added ? 1.05 : 0.95)) {
|
|
58
|
+
next = before.workers;
|
|
59
|
+
reason = added ? "extra browser did not improve throughput" : "fewer browsers reduced throughput";
|
|
60
|
+
this.growth = false;
|
|
61
|
+
}
|
|
62
|
+
} else if (this.previousRate !== undefined && rate < this.previousRate * 0.7 && this.target > 1
|
|
63
|
+
&& input.remainingFrames > this.frames * 2) {
|
|
64
|
+
// A slower passage is not proof of contention. Compare fewer browsers
|
|
65
|
+
// on subsequent useful work and restore the old count if it is worse.
|
|
66
|
+
this.baseline = { workers: this.target, rate };
|
|
67
|
+
next--;
|
|
68
|
+
reason = "compare fewer browsers after throughput changed";
|
|
69
|
+
this.growth = false;
|
|
70
|
+
}
|
|
71
|
+
if (next === this.target && this.growth && next < this.limit
|
|
72
|
+
&& input.remainingFrames / rate * 1_000 > input.startupMs * (next + 1) * 2) {
|
|
73
|
+
// A new browser must have enough remaining work to repay its startup,
|
|
74
|
+
// even if its ideal contribution is only 1/(N+1) of current throughput.
|
|
75
|
+
this.baseline = { workers: this.target, rate };
|
|
76
|
+
next++;
|
|
77
|
+
reason = "remaining capture can amortize another browser";
|
|
78
|
+
}
|
|
79
|
+
this.previousRate = rate;
|
|
80
|
+
this.settled(input.now);
|
|
81
|
+
if (next === this.target) return;
|
|
82
|
+
this.target = next;
|
|
83
|
+
this.since = undefined;
|
|
84
|
+
return { workers: next, reason, fps: rate };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { CaptureSession, HfProtocol } from "@hyperframes/engine";
|
|
2
|
+
import { getCdpSession } from "@hyperframes/engine";
|
|
3
|
+
|
|
4
|
+
/** The optional completion hooks supplied by the pinned Hyperframes page runtime. */
|
|
5
|
+
type RenderWindow = Window & {
|
|
6
|
+
__hf: HfProtocol & { colorGrading?: { waitForActiveLuts?: () => Promise<void> } };
|
|
7
|
+
__hfWaitForSeekCompletion?: () => Promise<void>;
|
|
8
|
+
__hf_page_composite_pending?: boolean;
|
|
9
|
+
__hf_page_composite_prepare?: () => Promise<void>;
|
|
10
|
+
__hf_page_composite_resolve?: () => void;
|
|
11
|
+
__hypitBrowserProgramError?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A screenshot adapter for this Provider's opaque MP4 output. Session lifecycle,
|
|
16
|
+
* the page's seek protocol and the video injector remain engine-owned. Encoding
|
|
17
|
+
* the already-composited frame as a fast PNG does not change source alpha.
|
|
18
|
+
* No engine/session methods are replaced and no installed dependency is patched.
|
|
19
|
+
*/
|
|
20
|
+
export async function createOpaqueFrameCapture(session: CaptureSession) {
|
|
21
|
+
const { page, options } = session;
|
|
22
|
+
const cdp = await getCdpSession(page);
|
|
23
|
+
// MP4 has no alpha channel. The authored Canvas paints over this final matte.
|
|
24
|
+
await cdp.send("Emulation.setDefaultBackgroundColorOverride", { color: { r: 0, g: 0, b: 0, a: 1 } });
|
|
25
|
+
// These decoded image handles belong to this page, just like its DOM. Retain
|
|
26
|
+
// only URLs used by inline background images; changing a style can need a load
|
|
27
|
+
// even after initializeSession has finished its initial resource readiness.
|
|
28
|
+
await page.evaluate(() => {
|
|
29
|
+
const decoded = new Map<string, Promise<void>>();
|
|
30
|
+
(window as unknown as { __hypitPrepareImages: () => Promise<void> }).__hypitPrepareImages = async () => {
|
|
31
|
+
const pending: Promise<unknown>[] = [];
|
|
32
|
+
if (document.fonts.status === "loading") pending.push(document.fonts.ready);
|
|
33
|
+
for (const image of Array.from(document.images)) {
|
|
34
|
+
if (!image.complete) pending.push(image.decode());
|
|
35
|
+
}
|
|
36
|
+
for (const element of Array.from(document.querySelectorAll<HTMLElement>('[style*="background"]'))) {
|
|
37
|
+
const background = element.style.backgroundImage;
|
|
38
|
+
for (const match of background.matchAll(/url\(\s*(?:"((?:\\.|[^"])*)"|'((?:\\.|[^'])*)'|([^)]*))\s*\)/gu)) {
|
|
39
|
+
const url = (match[1] ?? match[2] ?? match[3] ?? "").trim();
|
|
40
|
+
if (!url) continue;
|
|
41
|
+
let ready = decoded.get(url);
|
|
42
|
+
if (ready === undefined) {
|
|
43
|
+
const image = new Image();
|
|
44
|
+
image.src = url;
|
|
45
|
+
ready = image.decode();
|
|
46
|
+
decoded.set(url, ready);
|
|
47
|
+
}
|
|
48
|
+
pending.push(ready);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
await Promise.all(pending);
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
return async (frame: number) => {
|
|
55
|
+
const time = frame * options.fps.den / options.fps.num;
|
|
56
|
+
const start = performance.now();
|
|
57
|
+
await page.evaluate(async t => {
|
|
58
|
+
const w = window as unknown as RenderWindow;
|
|
59
|
+
await w.__hf.seek(t);
|
|
60
|
+
}, time);
|
|
61
|
+
const sought = performance.now();
|
|
62
|
+
await session.onBeforeCapture?.(page, time);
|
|
63
|
+
const composite = await page.evaluate(async () => {
|
|
64
|
+
const w = window as unknown as RenderWindow & { __hypitPrepareImages: () => Promise<void> };
|
|
65
|
+
await w.__hfWaitForSeekCompletion?.();
|
|
66
|
+
await w.__hf.colorGrading?.waitForActiveLuts?.();
|
|
67
|
+
await w.__hypitPrepareImages();
|
|
68
|
+
if (w.__hypitBrowserProgramError !== undefined) throw new Error(w.__hypitBrowserProgramError);
|
|
69
|
+
if (w.__hf_page_composite_pending) {
|
|
70
|
+
await w.__hf_page_composite_prepare?.();
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
});
|
|
75
|
+
if (composite) {
|
|
76
|
+
// The runtime's shader compositor needs a paint between preparing its DOM
|
|
77
|
+
// layers and resolving them. A 1 px capture flushes Chrome's compositor.
|
|
78
|
+
await cdp.send("Page.captureScreenshot", {
|
|
79
|
+
format: "jpeg", quality: 1, clip: { x: 0, y: 0, width: 1, height: 1, scale: 1 },
|
|
80
|
+
});
|
|
81
|
+
await page.evaluate(() => (window as unknown as RenderWindow).__hf_page_composite_resolve?.());
|
|
82
|
+
}
|
|
83
|
+
const prepared = performance.now();
|
|
84
|
+
const result = await cdp.send("Page.captureScreenshot", {
|
|
85
|
+
format: "png", optimizeForSpeed: true, fromSurface: true,
|
|
86
|
+
captureBeyondViewport: options.captureBeyondViewport ?? false,
|
|
87
|
+
clip: { x: 0, y: 0, width: options.width, height: options.height, scale: options.deviceScaleFactor ?? 1 },
|
|
88
|
+
});
|
|
89
|
+
return { buffer: Buffer.from(result.data, "base64"),
|
|
90
|
+
seekMs: sought - start, prepareMs: prepared - sought, screenshotMs: performance.now() - prepared };
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -8,6 +8,8 @@ export type HyperframesExecutionOptions = {
|
|
|
8
8
|
readonly ffmpegPath?: string;
|
|
9
9
|
/** Parallel Chrome workers inside one render. This is separate from Provider request concurrency. */
|
|
10
10
|
readonly workers?: HyperframesWorkers;
|
|
11
|
+
/** Upper bound for auto's browser reservation; explicit workers remain fixed. */
|
|
12
|
+
readonly maxWorkers?: number;
|
|
11
13
|
readonly quality?: HyperframesQuality;
|
|
12
14
|
/** Chrome's rasterizer, default hardware. Use software without a usable GPU. */
|
|
13
15
|
readonly browserGpu?: HyperframesBrowserGpu;
|
|
@@ -22,13 +22,16 @@ export function localHyperframesBrowserProgram(
|
|
|
22
22
|
input: {
|
|
23
23
|
readonly id: string;
|
|
24
24
|
readonly nodePath: string;
|
|
25
|
-
readonly hyperframesCliPath: string;
|
|
25
|
+
readonly hyperframesCliPath: string | (() => string);
|
|
26
26
|
readonly ffprobePath: string;
|
|
27
27
|
readonly ffmpegPath?: string;
|
|
28
28
|
},
|
|
29
29
|
): ManagedProgram {
|
|
30
|
+
const cliPath = () => typeof input.hyperframesCliPath === "string" ? input.hyperframesCliPath : input.hyperframesCliPath();
|
|
30
31
|
const probeBrowser = async (): Promise<ManagedProgramState> => {
|
|
31
|
-
|
|
32
|
+
let executable: string;
|
|
33
|
+
try { executable = cliPath(); } catch (error) { return { state: "down", detail: error instanceof Error ? error.message : String(error) }; }
|
|
34
|
+
const located = await run(input.nodePath, [executable, "browser", "path"]);
|
|
32
35
|
if (!located.ok) return { state: "down", detail: `HyperFrames browser is unavailable: ${located.output}` };
|
|
33
36
|
const path = located.output.trim();
|
|
34
37
|
if (path.length === 0 || path.includes("\n") || path.includes("\r")) {
|
|
@@ -44,7 +47,7 @@ export function localHyperframesBrowserProgram(
|
|
|
44
47
|
id: input.id,
|
|
45
48
|
installation: {
|
|
46
49
|
probe: probeBrowser,
|
|
47
|
-
commands
|
|
50
|
+
get commands() { return [{ command: input.nodePath, args: [cliPath(), "browser", "ensure"] }]; },
|
|
48
51
|
},
|
|
49
52
|
async probe(): Promise<ManagedProgramState> {
|
|
50
53
|
const browser = await probeBrowser();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { OperationProgress } from "@hypit/endpoint-kit";
|
|
2
|
+
import type { HyperframesRenderProgress } from "./render.js";
|
|
3
|
+
|
|
4
|
+
/** Reduce parallel capture events to one readable progress report for this render request. */
|
|
5
|
+
export function renderProgressReporter(
|
|
6
|
+
report: ((progress: OperationProgress) => Promise<void>) | undefined,
|
|
7
|
+
totalFrames: number,
|
|
8
|
+
now: () => number = Date.now,
|
|
9
|
+
) {
|
|
10
|
+
const workers = new Map<number, number>();
|
|
11
|
+
let rendering = false;
|
|
12
|
+
let lastPhase: string | undefined;
|
|
13
|
+
let lastAt = -Infinity;
|
|
14
|
+
let writes = Promise.resolve();
|
|
15
|
+
const frames = () => ({ phase: "rendering frames", completed: [...workers.values()].reduce((a, b) => a + b, 0),
|
|
16
|
+
total: totalFrames, unit: "frames" });
|
|
17
|
+
return {
|
|
18
|
+
onProgress(event: HyperframesRenderProgress): void {
|
|
19
|
+
if (report === undefined) return;
|
|
20
|
+
let progress: OperationProgress;
|
|
21
|
+
switch (event.phase) {
|
|
22
|
+
case "staging": progress = { phase: "preparing resources" }; break;
|
|
23
|
+
case "decoding": progress = { phase: "decoding source frames", completed: event.completed, total: event.total, unit: "frames" }; break;
|
|
24
|
+
case "prepared":
|
|
25
|
+
case "worker-initializing":
|
|
26
|
+
if (rendering) return;
|
|
27
|
+
progress = { phase: "starting browsers" }; break;
|
|
28
|
+
case "worker-start":
|
|
29
|
+
rendering = true;
|
|
30
|
+
workers.set(event.worker, 0);
|
|
31
|
+
progress = frames(); break;
|
|
32
|
+
case "worker-progress":
|
|
33
|
+
workers.set(event.worker, event.completed);
|
|
34
|
+
progress = frames(); break;
|
|
35
|
+
case "worker-complete":
|
|
36
|
+
workers.set(event.worker, event.completed);
|
|
37
|
+
progress = frames(); break;
|
|
38
|
+
case "encoding": progress = { phase: "encoding video" }; break;
|
|
39
|
+
case "storing": progress = { phase: "storing output" }; break;
|
|
40
|
+
case "complete": return;
|
|
41
|
+
}
|
|
42
|
+
const at = now();
|
|
43
|
+
if (progress.phase === lastPhase && at - lastAt < 1_000
|
|
44
|
+
&& (progress.total === undefined || progress.completed !== progress.total)) return;
|
|
45
|
+
lastPhase = progress.phase;
|
|
46
|
+
lastAt = at;
|
|
47
|
+
// Attach rejection handling immediately; flush still propagates storage failure to the caller.
|
|
48
|
+
writes = writes.then(() => report(progress));
|
|
49
|
+
void writes.catch(() => {});
|
|
50
|
+
},
|
|
51
|
+
flush: () => writes,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -3,8 +3,9 @@ import { mediaTypes } from "@hypit/media";
|
|
|
3
3
|
import { renderHyperframesCapabilities, verifyHyperframesVisualRequest } from "@hypit/render-hyperframes";
|
|
4
4
|
import { canonicalize } from "@hypit/protocol";
|
|
5
5
|
import { resolveNodePackageExecutable } from "@hypit/package-loader-node";
|
|
6
|
-
import { renderHyperframesVisual, resolveExecutionOptions } from "./render.js";
|
|
6
|
+
import { renderHyperframesVisual, resolveExecutionOptions, renderWorkerLimit } from "./render.js";
|
|
7
7
|
import type { HyperframesExecutionOptions } from "./options.js";
|
|
8
|
+
import { renderProgressReporter } from "./progress.js";
|
|
8
9
|
|
|
9
10
|
export type * from "./options.js";
|
|
10
11
|
export const localHyperframesProviderModuleRef = { name: "@hypit/provider-hyperframes-local", version: "1" } as const;
|
|
@@ -31,6 +32,8 @@ export function createLocalHyperframesProvider(config: CreateLocalHyperframesPro
|
|
|
31
32
|
if (config.browserCapacity !== undefined && (!Number.isSafeInteger(config.browserCapacity) || config.browserCapacity < 1)) {
|
|
32
33
|
throw new Error("HyperFrames browserCapacity must be a positive integer");
|
|
33
34
|
}
|
|
35
|
+
const maxWorkers = execution.workers === "auto" ? Math.min(execution.maxWorkers, config.browserCapacity ?? Infinity) : execution.maxWorkers;
|
|
36
|
+
const reserved = { ...execution, maxWorkers };
|
|
34
37
|
return defineEndpointPackage({
|
|
35
38
|
module: localHyperframesProviderModuleRef,
|
|
36
39
|
facet: "render",
|
|
@@ -47,15 +50,25 @@ export function createLocalHyperframesProvider(config: CreateLocalHyperframesPro
|
|
|
47
50
|
unitsForRequest: (request: import("@hypit/endpoint-kit").EndpointRequest) => {
|
|
48
51
|
verifyHyperframesVisualRequest(request.constraints);
|
|
49
52
|
const { document, range } = request.constraints;
|
|
50
|
-
return { [browsers]:
|
|
51
|
-
range === undefined ? document.frameCount : range.endFrameExclusive - range.startFrame
|
|
53
|
+
return { [browsers]: renderWorkerLimit(reserved,
|
|
54
|
+
range === undefined ? document.frameCount : range.endFrameExclusive - range.startFrame,
|
|
55
|
+
document.frameRate.numerator / document.frameRate.denominator) };
|
|
52
56
|
},
|
|
53
57
|
}),
|
|
54
58
|
handler: async (context) => {
|
|
55
59
|
const request = context.need.constraints;
|
|
56
60
|
verifyHyperframesVisualRequest(request);
|
|
57
|
-
const
|
|
58
|
-
|
|
61
|
+
const frameCount = request.range === undefined ? request.document.frameCount
|
|
62
|
+
: request.range.endFrameExclusive - request.range.startFrame;
|
|
63
|
+
const progress = renderProgressReporter(context.reportProgress, frameCount);
|
|
64
|
+
try {
|
|
65
|
+
const visual = await renderHyperframesVisual(request, { ...config, workers: execution.workers, maxWorkers,
|
|
66
|
+
resources: context.resources, onProgress: progress.onProgress,
|
|
67
|
+
...(context.reportDiagnostic === undefined ? {} : { onDiagnostic: context.reportDiagnostic }) });
|
|
68
|
+
return { value: { kind: "inline", value: canonicalize(visual) } };
|
|
69
|
+
} finally {
|
|
70
|
+
await progress.flush();
|
|
71
|
+
}
|
|
59
72
|
},
|
|
60
73
|
}],
|
|
61
74
|
});
|