@mevdragon/vidfarm-devcli 0.13.0 → 0.15.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/.agents/skills/embedded-captions/CATALOG.md +93 -0
- package/.agents/skills/embedded-captions/SKILL.md +286 -0
- package/.agents/skills/embedded-captions/assets/brand/CDPR-fankit-terms.txt +35 -0
- package/.agents/skills/embedded-captions/assets/brand/cyberpunk-widths.json +115 -0
- package/.agents/skills/embedded-captions/assets/fonts/char-widths.json +2211 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScript1.svg +242 -0
- package/.agents/skills/embedded-captions/assets/strokefonts/HersheyScriptMed.svg +242 -0
- package/.agents/skills/embedded-captions/dna/README.md +148 -0
- package/.agents/skills/embedded-captions/dna/chrome.json +68 -0
- package/.agents/skills/embedded-captions/dna/cream.json +69 -0
- package/.agents/skills/embedded-captions/dna/documentary.json +62 -0
- package/.agents/skills/embedded-captions/dna/editorial.json +70 -0
- package/.agents/skills/embedded-captions/dna/glitch.json +82 -0
- package/.agents/skills/embedded-captions/dna/ink.json +65 -0
- package/.agents/skills/embedded-captions/dna/keynote.json +62 -0
- package/.agents/skills/embedded-captions/dna/loud.json +75 -0
- package/.agents/skills/embedded-captions/dna/neon.json +58 -0
- package/.agents/skills/embedded-captions/dna/velocity.json +89 -0
- package/.agents/skills/embedded-captions/modes/cinematic/README.md +48 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/spec.md +98 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/champion/template.html +188 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/spec.md +134 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/memory-wall/template.html +179 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/spec.md +81 -0
- package/.agents/skills/embedded-captions/modes/cinematic/_archive/portrait-header/template.html +170 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/spec.md +16 -0
- package/.agents/skills/embedded-captions/modes/cinematic/cinematic-cream/template.html +226 -0
- package/.agents/skills/embedded-captions/modes/cinematic/engine.html +355 -0
- package/.agents/skills/embedded-captions/modes/standard/_anatomy.md +233 -0
- package/.agents/skills/embedded-captions/modes/standard/_motion.md +192 -0
- package/.agents/skills/embedded-captions/modes/standard/fonts/build-fonts-css.cjs +97 -0
- package/.agents/skills/embedded-captions/references/aesthetic-principles.md +168 -0
- package/.agents/skills/embedded-captions/references/anti-patterns.md +188 -0
- package/.agents/skills/embedded-captions/references/bespoke-vs-presets.md +178 -0
- package/.agents/skills/embedded-captions/references/caption-grouping.md +130 -0
- package/.agents/skills/embedded-captions/references/composition-craft.md +522 -0
- package/.agents/skills/embedded-captions/references/direction-catalog.md +138 -0
- package/.agents/skills/embedded-captions/references/example-renders/champion.html +371 -0
- package/.agents/skills/embedded-captions/references/example-renders/memory-wall.html +334 -0
- package/.agents/skills/embedded-captions/references/failure-modes.md +145 -0
- package/.agents/skills/embedded-captions/references/layout-heuristics.md +238 -0
- package/.agents/skills/embedded-captions/references/motion-vocabulary.md +148 -0
- package/.agents/skills/embedded-captions/references/rail.md +68 -0
- package/.agents/skills/embedded-captions/references/reference-bar.md +47 -0
- package/.agents/skills/embedded-captions/references/scene-types.md +94 -0
- package/.agents/skills/embedded-captions/references/test-set.md +66 -0
- package/.agents/skills/embedded-captions/references/typographic-moves.md +266 -0
- package/.agents/skills/embedded-captions/references/typography-presets.md +63 -0
- package/.agents/skills/embedded-captions/scripts/audio-envelope.cjs +95 -0
- package/.agents/skills/embedded-captions/scripts/check-occlusion.cjs +250 -0
- package/.agents/skills/embedded-captions/scripts/check-overflow.cjs +194 -0
- package/.agents/skills/embedded-captions/scripts/check-rail-climax.cjs +233 -0
- package/.agents/skills/embedded-captions/scripts/check-timing.cjs +173 -0
- package/.agents/skills/embedded-captions/scripts/fill-timings.cjs +124 -0
- package/.agents/skills/embedded-captions/scripts/fit-fonts.cjs +158 -0
- package/.agents/skills/embedded-captions/scripts/gen-stroke-path.py +46 -0
- package/.agents/skills/embedded-captions/scripts/inject-fonts.cjs +169 -0
- package/.agents/skills/embedded-captions/scripts/lib-dna.cjs +201 -0
- package/.agents/skills/embedded-captions/scripts/make-cinematic.cjs +1205 -0
- package/.agents/skills/embedded-captions/scripts/make-composition.cjs +404 -0
- package/.agents/skills/embedded-captions/scripts/make-theme.cjs +8781 -0
- package/.agents/skills/embedded-captions/scripts/matte.cjs +294 -0
- package/.agents/skills/embedded-captions/scripts/measure-layout.cjs +293 -0
- package/.agents/skills/embedded-captions/scripts/prepare.sh +39 -0
- package/.agents/skills/embedded-captions/scripts/preview-frames.cjs +268 -0
- package/.agents/skills/embedded-captions/scripts/render-and-composite.sh +509 -0
- package/.agents/skills/embedded-captions/scripts/render-theme.sh +34 -0
- package/.agents/skills/embedded-captions/scripts/safe-zones.cjs +813 -0
- package/.agents/skills/embedded-captions/scripts/transcribe.cjs +349 -0
- package/.agents/skills/embedded-captions/themes/PORTING.md +49 -0
- package/.agents/skills/embedded-captions/themes/README.md +244 -0
- package/.agents/skills/embedded-captions/themes/anchor.json +27 -0
- package/.agents/skills/embedded-captions/themes/arcade.json +51 -0
- package/.agents/skills/embedded-captions/themes/aurora.json +41 -0
- package/.agents/skills/embedded-captions/themes/biolume.json +35 -0
- package/.agents/skills/embedded-captions/themes/brush.json +74 -0
- package/.agents/skills/embedded-captions/themes/chalkboard.json +52 -0
- package/.agents/skills/embedded-captions/themes/dossier.json +56 -0
- package/.agents/skills/embedded-captions/themes/graffiti.json +62 -0
- package/.agents/skills/embedded-captions/themes/hologram.json +41 -0
- package/.agents/skills/embedded-captions/themes/inkwater.json +43 -0
- package/.agents/skills/embedded-captions/themes/laser.json +46 -0
- package/.agents/skills/embedded-captions/themes/lastpage.json +33 -0
- package/.agents/skills/embedded-captions/themes/neonsign.json +53 -0
- package/.agents/skills/embedded-captions/themes/nightcity.json +56 -0
- package/.agents/skills/embedded-captions/themes/ordnance.json +54 -0
- package/.agents/skills/embedded-captions/themes/papercut.json +37 -0
- package/.agents/skills/embedded-captions/themes/popup.json +46 -0
- package/.agents/skills/embedded-captions/themes/ransom.json +62 -0
- package/.agents/skills/embedded-captions/themes/scoreboard.json +54 -0
- package/.agents/skills/embedded-captions/themes/spectrum.json +46 -0
- package/.agents/skills/embedded-captions/themes/stardust.json +29 -0
- package/.agents/skills/embedded-captions/themes/stomp.json +43 -0
- package/.agents/skills/embedded-captions/themes/terminal.json +49 -0
- package/.agents/skills/embedded-captions/themes/thunder.json +44 -0
- package/.agents/skills/embedded-captions/themes/transit.json +44 -0
- package/.agents/skills/embedded-captions/themes/vhs.json +47 -0
- package/.agents/skills/faceless-explainer/SKILL.md +209 -0
- package/.agents/skills/faceless-explainer/references/cut-catalog.md +215 -0
- package/.agents/skills/faceless-explainer/references/motion-language.md +156 -0
- package/.agents/skills/faceless-explainer/references/story-design.md +248 -0
- package/.agents/skills/faceless-explainer/references/visual-design.md +146 -0
- package/.agents/skills/faceless-explainer/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/faceless-explainer/scripts/audio.mjs +260 -0
- package/.agents/skills/faceless-explainer/scripts/build-frame.mjs +536 -0
- package/.agents/skills/faceless-explainer/scripts/captions.mjs +508 -0
- package/.agents/skills/faceless-explainer/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/faceless-explainer/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/faceless-explainer/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/faceless-explainer/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/faceless-explainer/scripts/lib/transitions.json +71 -0
- package/.agents/skills/faceless-explainer/scripts/transitions.mjs +320 -0
- package/.agents/skills/faceless-explainer/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/flockposter/LICENSE +17 -0
- package/.agents/skills/flockposter/README.md +72 -0
- package/.agents/skills/flockposter/SKILL.md +562 -0
- package/.agents/skills/flockposter/examples/cli-instagram-reel.sh +21 -0
- package/.agents/skills/flockposter/examples/cli-multi-platform.json +69 -0
- package/.agents/skills/flockposter/examples/cli-tiktok-upload-only.sh +22 -0
- package/.agents/skills/flockposter/examples/cli-x-thread.sh +17 -0
- package/.agents/skills/flockposter/examples/cli-youtube-short.sh +21 -0
- package/.agents/skills/flockposter/examples/public-api-instagram-reel.json +28 -0
- package/.agents/skills/general-video/SKILL.md +143 -0
- package/.agents/skills/hyperframes/SKILL.md +160 -0
- package/.agents/skills/hyperframes-animation/SKILL.md +84 -0
- package/.agents/skills/hyperframes-animation/adapters/animate-text.md +64 -0
- package/.agents/skills/hyperframes-animation/adapters/animejs.md +114 -0
- package/.agents/skills/hyperframes-animation/adapters/css-animations.md +143 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-easing-and-stagger.md +118 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-timeline-and-labels.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap-transforms-and-perf.md +96 -0
- package/.agents/skills/hyperframes-animation/adapters/gsap.md +105 -0
- package/.agents/skills/hyperframes-animation/adapters/html-in-canvas-patterns.md +507 -0
- package/.agents/skills/hyperframes-animation/adapters/lottie.md +117 -0
- package/.agents/skills/hyperframes-animation/adapters/three.md +131 -0
- package/.agents/skills/hyperframes-animation/adapters/typegpu.md +178 -0
- package/.agents/skills/hyperframes-animation/adapters/waapi.md +101 -0
- package/.agents/skills/hyperframes-animation/blueprints/comparison-split.md +27 -0
- package/.agents/skills/hyperframes-animation/blueprints/constellation-hub.md +44 -0
- package/.agents/skills/hyperframes-animation/blueprints/cta-morph-press.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/cursor-ui-demo.md +57 -0
- package/.agents/skills/hyperframes-animation/blueprints/dataviz-countup.md +46 -0
- package/.agents/skills/hyperframes-animation/blueprints/device-surface-showcase.md +53 -0
- package/.agents/skills/hyperframes-animation/blueprints/grid-card-assemble.md +66 -0
- package/.agents/skills/hyperframes-animation/blueprints/kinetic-type-beats.md +78 -0
- package/.agents/skills/hyperframes-animation/blueprints/logo-assemble-lockup.md +69 -0
- package/.agents/skills/hyperframes-animation/blueprints/overwhelm-surround.md +28 -0
- package/.agents/skills/hyperframes-animation/blueprints/spatial-pan-stations.md +37 -0
- package/.agents/skills/hyperframes-animation/blueprints/ticker-takeover.md +29 -0
- package/.agents/skills/hyperframes-animation/blueprints/titlecard-reveal.md +42 -0
- package/.agents/skills/hyperframes-animation/blueprints/typewriter-reveal.md +51 -0
- package/.agents/skills/hyperframes-animation/blueprints/video-text-pivot.md +30 -0
- package/.agents/skills/hyperframes-animation/blueprints-index.md +146 -0
- package/.agents/skills/hyperframes-animation/examples/assets/avatars/02.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/github.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/nvidia.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/visa.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/assets/brands/zoominfo.avif +0 -0
- package/.agents/skills/hyperframes-animation/examples/brand-reveal-assemble-zoom.html +382 -0
- package/.agents/skills/hyperframes-animation/examples/comparison-split-cards.html +649 -0
- package/.agents/skills/hyperframes-animation/examples/concept-demo-decode-pan.html +520 -0
- package/.agents/skills/hyperframes-animation/examples/cta-morph-press.html +468 -0
- package/.agents/skills/hyperframes-animation/examples/cta-orbit-collapse.html +1298 -0
- package/.agents/skills/hyperframes-animation/examples/demo-page-scroll-spotlight.html +759 -0
- package/.agents/skills/hyperframes-animation/examples/hook-counter-burst.html +729 -0
- package/.agents/skills/hyperframes-animation/examples/messaging-multi-phrase.html +352 -0
- package/.agents/skills/hyperframes-animation/examples/metric-video-text-pivot.html +779 -0
- package/.agents/skills/hyperframes-animation/examples/problem-mockup-overwhelm.html +1374 -0
- package/.agents/skills/hyperframes-animation/examples/proof-logo-chain.html +861 -0
- package/.agents/skills/hyperframes-animation/examples/takeover-ticker-displace.html +347 -0
- package/.agents/skills/hyperframes-animation/examples/workflow-approve-press.html +606 -0
- package/.agents/skills/hyperframes-animation/rules/3d-page-scroll.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/3d-text-depth-layers.md +297 -0
- package/.agents/skills/hyperframes-animation/rules/ai-tracking-box.md +382 -0
- package/.agents/skills/hyperframes-animation/rules/ambient-glow-bloom.md +305 -0
- package/.agents/skills/hyperframes-animation/rules/asr-keyword-glow.md +286 -0
- package/.agents/skills/hyperframes-animation/rules/avatar-cloud-network.md +371 -0
- package/.agents/skills/hyperframes-animation/rules/camera-cursor-tracking.md +246 -0
- package/.agents/skills/hyperframes-animation/rules/card-morph-anchor.md +267 -0
- package/.agents/skills/hyperframes-animation/rules/center-outward-expansion.md +227 -0
- package/.agents/skills/hyperframes-animation/rules/context-sensitive-cursor.md +257 -0
- package/.agents/skills/hyperframes-animation/rules/coordinate-target-zoom.md +332 -0
- package/.agents/skills/hyperframes-animation/rules/counting-dynamic-scale.md +283 -0
- package/.agents/skills/hyperframes-animation/rules/css-marker-patterns.md +373 -0
- package/.agents/skills/hyperframes-animation/rules/cursor-click-ripple.md +262 -0
- package/.agents/skills/hyperframes-animation/rules/depth-of-field-blur.md +313 -0
- package/.agents/skills/hyperframes-animation/rules/depth-scatter-assemble.md +303 -0
- package/.agents/skills/hyperframes-animation/rules/discrete-text-sequence.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/dynamic-content-sequencing.md +307 -0
- package/.agents/skills/hyperframes-animation/rules/gsap-effects.md +299 -0
- package/.agents/skills/hyperframes-animation/rules/hacker-flip-3d.md +223 -0
- package/.agents/skills/hyperframes-animation/rules/kinetic-beat-slam.md +183 -0
- package/.agents/skills/hyperframes-animation/rules/motion-blur-streak.md +328 -0
- package/.agents/skills/hyperframes-animation/rules/multi-phase-camera.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/orbit-3d-entry.md +301 -0
- package/.agents/skills/hyperframes-animation/rules/physics-press-reaction.md +350 -0
- package/.agents/skills/hyperframes-animation/rules/press-release-spring.md +296 -0
- package/.agents/skills/hyperframes-animation/rules/reactive-displacement.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/scale-swap-transition.md +298 -0
- package/.agents/skills/hyperframes-animation/rules/sine-wave-loop.md +278 -0
- package/.agents/skills/hyperframes-animation/rules/split-tilt-cards.md +277 -0
- package/.agents/skills/hyperframes-animation/rules/spring-pop-entrance.md +273 -0
- package/.agents/skills/hyperframes-animation/rules/stat-bars-and-fills.md +156 -0
- package/.agents/skills/hyperframes-animation/rules/svg-icon-enrichment.md +329 -0
- package/.agents/skills/hyperframes-animation/rules/svg-path-draw.md +274 -0
- package/.agents/skills/hyperframes-animation/rules/vertical-spring-ticker.md +239 -0
- package/.agents/skills/hyperframes-animation/rules/viewport-change.md +349 -0
- package/.agents/skills/hyperframes-animation/rules-index.md +86 -0
- package/.agents/skills/hyperframes-animation/scripts/animation-map.mjs +606 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-animation/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-animation/techniques.md +507 -0
- package/.agents/skills/hyperframes-animation/transitions/TRANSITION-REGISTRY.md +167 -0
- package/.agents/skills/hyperframes-animation/transitions/catalog.md +127 -0
- package/.agents/skills/hyperframes-animation/transitions/css-3d.md +12 -0
- package/.agents/skills/hyperframes-animation/transitions/css-blur.md +51 -0
- package/.agents/skills/hyperframes-animation/transitions/css-cover.md +43 -0
- package/.agents/skills/hyperframes-animation/transitions/css-destruction.md +95 -0
- package/.agents/skills/hyperframes-animation/transitions/css-dissolve.md +66 -0
- package/.agents/skills/hyperframes-animation/transitions/css-distortion.md +45 -0
- package/.agents/skills/hyperframes-animation/transitions/css-grid.md +10 -0
- package/.agents/skills/hyperframes-animation/transitions/css-light.md +49 -0
- package/.agents/skills/hyperframes-animation/transitions/css-mechanical.md +30 -0
- package/.agents/skills/hyperframes-animation/transitions/css-other.md +25 -0
- package/.agents/skills/hyperframes-animation/transitions/css-push.md +41 -0
- package/.agents/skills/hyperframes-animation/transitions/css-radial.md +37 -0
- package/.agents/skills/hyperframes-animation/transitions/css-scale.md +24 -0
- package/.agents/skills/hyperframes-animation/transitions/overview.md +153 -0
- package/.agents/skills/hyperframes-cli/SKILL.md +113 -0
- package/.agents/skills/hyperframes-cli/references/doctor-browser.md +45 -0
- package/.agents/skills/hyperframes-cli/references/init-and-scaffold.md +55 -0
- package/.agents/skills/hyperframes-cli/references/lambda.md +132 -0
- package/.agents/skills/hyperframes-cli/references/lint-validate-inspect.md +121 -0
- package/.agents/skills/hyperframes-cli/references/preview-render.md +149 -0
- package/.agents/skills/hyperframes-cli/references/upgrade-info-misc.md +75 -0
- package/.agents/skills/hyperframes-core/SKILL.md +78 -0
- package/.agents/skills/hyperframes-core/references/composition-patterns.md +263 -0
- package/.agents/skills/hyperframes-core/references/data-attributes.md +70 -0
- package/.agents/skills/hyperframes-core/references/determinism-rules.md +68 -0
- package/.agents/skills/hyperframes-core/references/full-screen-motion.md +62 -0
- package/.agents/skills/hyperframes-core/references/minimal-composition.md +66 -0
- package/.agents/skills/hyperframes-core/references/script-format.md +49 -0
- package/.agents/skills/hyperframes-core/references/storyboard-format.md +95 -0
- package/.agents/skills/hyperframes-core/references/sub-compositions.md +237 -0
- package/.agents/skills/hyperframes-core/references/subagent-dispatch.md +41 -0
- package/.agents/skills/hyperframes-core/references/tailwind.md +125 -0
- package/.agents/skills/hyperframes-core/references/tracks-and-clips.md +76 -0
- package/.agents/skills/hyperframes-core/references/variables-and-media.md +90 -0
- package/.agents/skills/hyperframes-creative/SKILL.md +70 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/FRAME.md +289 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/caption-skin.html +221 -0
- package/.agents/skills/hyperframes-creative/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blockframe/frame-showcase.html +1347 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/FRAME.md +307 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/blue-professional/frame-showcase.html +1372 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/FRAME.md +275 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/bold-poster/frame-showcase.html +1140 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/caption-skin.html +225 -0
- package/.agents/skills/hyperframes-creative/frame-presets/broadside/frame-showcase.html +1166 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/FRAME.md +284 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/capsule/frame-showcase.html +1465 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/FRAME.md +278 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/caption-skin.html +222 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cartesian/frame-showcase.html +1263 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/FRAME.md +277 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/caption-skin.html +224 -0
- package/.agents/skills/hyperframes-creative/frame-presets/claude/frame-showcase.html +1439 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/caption-skin.html +238 -0
- package/.agents/skills/hyperframes-creative/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/FRAME.md +314 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/caption-skin.html +226 -0
- package/.agents/skills/hyperframes-creative/frame-presets/coral/frame-showcase.html +1268 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/FRAME.md +333 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/caption-skin.html +227 -0
- package/.agents/skills/hyperframes-creative/frame-presets/creative-mode/frame-showcase.html +1330 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/FRAME.md +274 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/caption-skin.html +230 -0
- package/.agents/skills/hyperframes-creative/frame-presets/daisy-days/frame-showcase.html +1444 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/FRAME.md +265 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/caption-skin.html +223 -0
- package/.agents/skills/hyperframes-creative/frame-presets/editorial-forest/frame-showcase.html +1273 -0
- package/.agents/skills/hyperframes-creative/palettes/bold-energetic.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/clean-corporate.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/dark-premium.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/jewel-rich.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/monochrome.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/nature-earth.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/neon-electric.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/pastel-soft.md +14 -0
- package/.agents/skills/hyperframes-creative/palettes/warm-editorial.md +14 -0
- package/.agents/skills/hyperframes-creative/references/audio-reactive.md +76 -0
- package/.agents/skills/hyperframes-creative/references/beat-direction.md +164 -0
- package/.agents/skills/hyperframes-creative/references/composition-patterns.md +199 -0
- package/.agents/skills/hyperframes-creative/references/data-in-motion.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-adherence.md +19 -0
- package/.agents/skills/hyperframes-creative/references/design-picker.md +123 -0
- package/.agents/skills/hyperframes-creative/references/design-spec.md +55 -0
- package/.agents/skills/hyperframes-creative/references/house-style.md +73 -0
- package/.agents/skills/hyperframes-creative/references/motion-principles.md +150 -0
- package/.agents/skills/hyperframes-creative/references/narration.md +92 -0
- package/.agents/skills/hyperframes-creative/references/prompt-expansion.md +68 -0
- package/.agents/skills/hyperframes-creative/references/typography.md +218 -0
- package/.agents/skills/hyperframes-creative/references/video-composition.md +63 -0
- package/.agents/skills/hyperframes-creative/references/visual-styles.md +457 -0
- package/.agents/skills/hyperframes-creative/scripts/contrast-report.mjs +353 -0
- package/.agents/skills/hyperframes-creative/scripts/extract-audio-data.py +188 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.mjs +288 -0
- package/.agents/skills/hyperframes-creative/scripts/package-loader.test.mjs +62 -0
- package/.agents/skills/hyperframes-creative/templates/design-picker.html +1432 -0
- package/.agents/skills/hyperframes-keyframes/SKILL.md +237 -0
- package/.agents/skills/hyperframes-keyframes/agents/openai.yaml +4 -0
- package/.agents/skills/hyperframes-keyframes/references/keyframe-patterns.md +106 -0
- package/.agents/skills/motion-graphics/SKILL.md +172 -0
- package/.agents/skills/motion-graphics/agents/builder.md +40 -0
- package/.agents/skills/motion-graphics/agents/director.md +53 -0
- package/.agents/skills/motion-graphics/agents/finalize.md +17 -0
- package/.agents/skills/motion-graphics/catalog-map.md +40 -0
- package/.agents/skills/motion-graphics/categories/asset-fusion/module.md +37 -0
- package/.agents/skills/motion-graphics/categories/charts/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/kinetic-type/module.md +19 -0
- package/.agents/skills/motion-graphics/categories/logo-reveal/module.md +17 -0
- package/.agents/skills/motion-graphics/categories/lower-thirds/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/maps/bake-basemap.mjs +273 -0
- package/.agents/skills/motion-graphics/categories/maps/module.md +61 -0
- package/.agents/skills/motion-graphics/categories/news/module.md +56 -0
- package/.agents/skills/motion-graphics/categories/stat/module.md +21 -0
- package/.agents/skills/motion-graphics/categories/tweet/module.md +16 -0
- package/.agents/skills/motion-graphics/categories/webpage/module.md +21 -0
- package/.agents/skills/motion-graphics/grounding/PROTOCOL.md +64 -0
- package/.agents/skills/motion-graphics/grounding/locate.mjs +227 -0
- package/.agents/skills/motion-graphics/phases/source/guide.md +21 -0
- package/.agents/skills/motion-graphics/references/builder-contract.md +38 -0
- package/.agents/skills/motion-graphics/references/motion-vocabulary.md +43 -0
- package/.agents/skills/motion-graphics/references/shot-plan-ir.md +54 -0
- package/.agents/skills/motion-graphics/samples/asset-fusion/_ref-circle-highlight.html +306 -0
- package/.agents/skills/product-launch-video/SKILL.md +208 -0
- package/.agents/skills/product-launch-video/references/cut-catalog.md +220 -0
- package/.agents/skills/product-launch-video/references/motion-language.md +156 -0
- package/.agents/skills/product-launch-video/references/story-design.md +373 -0
- package/.agents/skills/product-launch-video/references/visual-design.md +126 -0
- package/.agents/skills/product-launch-video/scripts/assemble-index.mjs +570 -0
- package/.agents/skills/product-launch-video/scripts/audio.mjs +260 -0
- package/.agents/skills/product-launch-video/scripts/build-frame.mjs +536 -0
- package/.agents/skills/product-launch-video/scripts/captions.mjs +508 -0
- package/.agents/skills/product-launch-video/scripts/lib/assets.mjs +55 -0
- package/.agents/skills/product-launch-video/scripts/lib/dimensions.mjs +45 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.mjs +36 -0
- package/.agents/skills/product-launch-video/scripts/lib/pad-frame-duration.test.mjs +76 -0
- package/.agents/skills/product-launch-video/scripts/lib/storyboard.mjs +249 -0
- package/.agents/skills/product-launch-video/scripts/lib/tokens.mjs +204 -0
- package/.agents/skills/product-launch-video/scripts/lib/transition-registry.mjs +38 -0
- package/.agents/skills/product-launch-video/scripts/lib/transitions.json +71 -0
- package/.agents/skills/product-launch-video/scripts/stage-assets.mjs +39 -0
- package/.agents/skills/product-launch-video/scripts/transitions.mjs +327 -0
- package/.agents/skills/product-launch-video/sub-agents/frame-worker.md +75 -0
- package/.agents/skills/slideshow/SKILL.md +550 -0
- package/.agents/skills/slideshow/references/standalone-harness.md +1020 -0
- package/.agents/skills/talking-head-recut/NOTICE.md +39 -0
- package/.agents/skills/talking-head-recut/SKILL.md +1195 -0
- package/.agents/skills/talking-head-recut/assets/vendor/gsap.min.js +10 -0
- package/.agents/skills/talking-head-recut/references/DESIGN_INDEX.md +145 -0
- package/.agents/skills/talking-head-recut/references/frames/clean.html +92 -0
- package/.agents/skills/talking-head-recut/references/frames/hairline.html +171 -0
- package/.agents/skills/talking-head-recut/references/frames/polaroid.html +131 -0
- package/.agents/skills/talking-head-recut/references/layouts/overlay.html +164 -0
- package/.agents/skills/talking-head-recut/references/layouts/pip.html +143 -0
- package/.agents/skills/talking-head-recut/references/layouts/split.html +121 -0
- package/.agents/skills/talking-head-recut/references/layouts/stack.html +109 -0
- package/.agents/skills/talking-head-recut/references/styles/academic.html +172 -0
- package/.agents/skills/talking-head-recut/references/styles/audit.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/editorial.html +189 -0
- package/.agents/skills/talking-head-recut/references/styles/geom.html +181 -0
- package/.agents/skills/talking-head-recut/references/styles/minimal.html +130 -0
- package/.agents/skills/talking-head-recut/references/styles/spotlight.html +142 -0
- package/.agents/skills/talking-head-recut/references/styles/swiss.html +188 -0
- package/.agents/skills/talking-head-recut/references/styles/terminal.html +196 -0
- package/.agents/skills/talking-head-recut/references/styles/whiteboard.html +170 -0
- package/.agents/skills/talking-head-recut/references/styles/xhs.html +206 -0
- package/.agents/skills/vidfarm-media/SKILL.md +85 -0
- package/.agents/skills/vidfarm-media/references/tts.md +54 -0
- package/.agents/skills/vidfarm-media/scripts/audio.mjs +628 -0
- package/.agents/skills/vidfarm-media/scripts/wait-bgm.mjs +31 -0
- package/.agents/skills/website-to-video/SKILL.md +145 -0
- package/.agents/skills/website-to-video/assets/sfx/CREDITS.md +35 -0
- package/.agents/skills/website-to-video/assets/sfx/manifest.json +97 -0
- package/.agents/skills/website-to-video/references/beat-builder-guide.md +263 -0
- package/.agents/skills/website-to-video/references/capabilities.md +713 -0
- package/.agents/skills/website-to-video/references/step-0-capture.md +55 -0
- package/.agents/skills/website-to-video/references/step-1-design.md +333 -0
- package/.agents/skills/website-to-video/references/step-2-brief.md +178 -0
- package/.agents/skills/website-to-video/references/step-3-storyboard.md +572 -0
- package/.agents/skills/website-to-video/references/step-4-vo.md +225 -0
- package/.agents/skills/website-to-video/references/step-5-build.md +483 -0
- package/.agents/skills/website-to-video/references/step-6-validate.md +341 -0
- package/.agents/skills/website-to-video/scripts/w2h-verify.mjs +759 -0
- package/SKILL.director.md +60 -4
- package/SKILL.platform.md +7 -2
- package/demo/dist/app.css +1 -1
- package/demo/dist/app.js +485 -86
- package/dist/src/account-pages-legacy.js +9 -14
- package/dist/src/app.js +659 -159
- package/dist/src/cli.js +618 -17
- package/dist/src/composition-runtime.js +286 -6
- package/dist/src/devcli/composition-edit.js +176 -8
- package/dist/src/devcli/doctor.js +192 -0
- package/dist/src/devcli/hyperframes-cli.js +118 -0
- package/dist/src/devcli/skills.js +476 -0
- package/dist/src/devcli/stills.js +249 -0
- package/dist/src/devcli/transitions.js +205 -0
- package/dist/src/editor-chat.js +260 -4
- package/dist/src/frontend/template-editor-chat.js +6 -5
- package/dist/src/homepage.js +2 -48
- package/dist/src/hyperframes/composition.js +188 -7
- package/dist/src/services/composition-lint.js +199 -0
- package/dist/src/services/hyperframes.js +127 -28
- package/dist/src/services/serverless-records.js +7 -0
- package/dist/src/template-editor-shell.js +87 -48
- package/package.json +2 -1
- package/public/assets/page-runtime-client-app.js +31 -31
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
9
9
|
(() => {
|
|
10
10
|
const root = document.querySelector("[data-composition-id]");
|
|
11
|
-
|
|
11
|
+
let declaredDuration = Number(root?.getAttribute("data-duration") || 0);
|
|
12
|
+
let duration = declaredDuration;
|
|
12
13
|
let time = 0;
|
|
13
14
|
let playing = false;
|
|
14
15
|
let playbackRate = 1;
|
|
@@ -53,6 +54,11 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
function refreshClips() {
|
|
57
|
+
// The parent editor can live-patch the composition DOM. Re-read the root's
|
|
58
|
+
// declared duration so a patched data-duration followed by refreshClips()
|
|
59
|
+
// never leaves the player clamped to a stale duration.
|
|
60
|
+
declaredDuration = Number(root?.getAttribute("data-duration") || 0);
|
|
61
|
+
duration = declaredDuration;
|
|
56
62
|
clips = Array.from(document.querySelectorAll("[data-start]")).filter((node) => node !== root);
|
|
57
63
|
for (const clip of clips) {
|
|
58
64
|
if (clip instanceof HTMLMediaElement && !initialMuted.has(clip)) {
|
|
@@ -74,6 +80,7 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
74
80
|
activeVideoProxyKey = null;
|
|
75
81
|
activeVideoProxyNode = null;
|
|
76
82
|
hasVideoProxies = clips.some((clip) => clip instanceof Element && clip.getAttribute("data-vf-timeline-proxy") === "video");
|
|
83
|
+
discoverGeneralCssAnimations();
|
|
77
84
|
apply(time, { forceSeek: true });
|
|
78
85
|
}
|
|
79
86
|
|
|
@@ -146,6 +153,130 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
146
153
|
}
|
|
147
154
|
}
|
|
148
155
|
|
|
156
|
+
// Runtime-adapter bridge — mirrors the official @hyperframes/producer
|
|
157
|
+
// deterministic adapters so compositions driven by a registered GSAP
|
|
158
|
+
// timeline (window.__timelines), Anime.js (window.__hfAnime), Lottie
|
|
159
|
+
// (window.__hfLottie), or Three.js/TypeGPU (window.__hfThreeTime/
|
|
160
|
+
// __hfTypegpuTime + the hf-seek CustomEvent) scrub with the player instead
|
|
161
|
+
// of running on the wall clock. Everything is duck-typed and try/caught so
|
|
162
|
+
// a broken composition script never kills the apply loop.
|
|
163
|
+
function compositionTimeline() {
|
|
164
|
+
let registry = null;
|
|
165
|
+
try { registry = window.__timelines; } catch { return null; }
|
|
166
|
+
if (!registry || typeof registry !== "object") return null;
|
|
167
|
+
const compId = root?.getAttribute("data-composition-id") || "";
|
|
168
|
+
let timeline = compId ? registry[compId] : null;
|
|
169
|
+
if (!timeline) {
|
|
170
|
+
const keys = Object.keys(registry);
|
|
171
|
+
if (keys.length === 1) timeline = registry[keys[0]];
|
|
172
|
+
}
|
|
173
|
+
if (!timeline || typeof timeline.pause !== "function") return null;
|
|
174
|
+
if (typeof timeline.totalTime !== "function" && typeof timeline.seek !== "function") return null;
|
|
175
|
+
return timeline;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function timelineDuration(timeline) {
|
|
179
|
+
try {
|
|
180
|
+
const value = typeof timeline.duration === "function" ? Number(timeline.duration()) : Number(timeline.duration);
|
|
181
|
+
if (Number.isFinite(value) && value > 0) return value;
|
|
182
|
+
} catch {}
|
|
183
|
+
return 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function syncTimeline() {
|
|
187
|
+
const timeline = compositionTimeline();
|
|
188
|
+
if (!timeline) return;
|
|
189
|
+
try {
|
|
190
|
+
timeline.pause();
|
|
191
|
+
// Official gsap adapter seek: nudge to time+1ms with suppressed events,
|
|
192
|
+
// then land exactly, so gsap re-renders even when the target equals the
|
|
193
|
+
// timeline's current time.
|
|
194
|
+
if (typeof timeline.totalTime === "function") {
|
|
195
|
+
timeline.totalTime(time + 0.001, true);
|
|
196
|
+
timeline.totalTime(time, false);
|
|
197
|
+
} else {
|
|
198
|
+
timeline.seek(time, false);
|
|
199
|
+
}
|
|
200
|
+
} catch {}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function syncAnimeInstances() {
|
|
204
|
+
let instances = null;
|
|
205
|
+
try { instances = window.__hfAnime; } catch { return; }
|
|
206
|
+
if (!Array.isArray(instances) || instances.length === 0) return;
|
|
207
|
+
const ms = Math.max(0, time) * 1000;
|
|
208
|
+
for (const instance of instances) {
|
|
209
|
+
try {
|
|
210
|
+
if (instance && typeof instance.seek === "function") instance.seek(ms);
|
|
211
|
+
} catch {}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function syncLottiePlayers() {
|
|
216
|
+
let players = null;
|
|
217
|
+
try { players = window.__hfLottie; } catch { return; }
|
|
218
|
+
if (!Array.isArray(players) || players.length === 0) return;
|
|
219
|
+
const safe = Math.max(0, time);
|
|
220
|
+
for (const player of players) {
|
|
221
|
+
try {
|
|
222
|
+
if (!player || typeof player !== "object") continue;
|
|
223
|
+
if (typeof player.goToAndStop === "function") {
|
|
224
|
+
player.goToAndStop(safe * 1000, false);
|
|
225
|
+
} else if (typeof player.pause === "function" && ("totalFrames" in player || "duration" in player)) {
|
|
226
|
+
if (typeof player.setCurrentRawFrameValue === "function") {
|
|
227
|
+
const totalFrames = player.totalFrames ?? 0;
|
|
228
|
+
const frameRate = player.frameRate ?? 30;
|
|
229
|
+
if (totalFrames > 0) player.setCurrentRawFrameValue(Math.min(safe * frameRate, totalFrames - 1));
|
|
230
|
+
} else if (typeof player.seek === "function") {
|
|
231
|
+
player.seek(Math.min(100, (safe / (player.duration ?? 1)) * 100));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
} catch {}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let lastDispatchedSeekTime = -1;
|
|
239
|
+
function syncSeekGlobals() {
|
|
240
|
+
const safe = Math.max(0, time);
|
|
241
|
+
try { window.__hfThreeTime = safe; } catch {}
|
|
242
|
+
try { window.__hfTypegpuTime = safe; } catch {}
|
|
243
|
+
// The official three/typegpu adapters dedupe the hf-seek dispatch on the
|
|
244
|
+
// last dispatched time.
|
|
245
|
+
if (safe === lastDispatchedSeekTime) return;
|
|
246
|
+
lastDispatchedSeekTime = safe;
|
|
247
|
+
try { window.dispatchEvent(new CustomEvent("hf-seek", { detail: { time: safe } })); } catch {}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function syncRuntimeAdapters() {
|
|
251
|
+
syncTimeline();
|
|
252
|
+
syncAnimeInstances();
|
|
253
|
+
syncLottiePlayers();
|
|
254
|
+
syncSeekGlobals();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// data-duration on the root is authoritative when present. Arbitrary
|
|
258
|
+
// compositions may omit it, so infer the duration from clip extents,
|
|
259
|
+
// preferring a registered GSAP timeline that reports a longer duration.
|
|
260
|
+
// Recomputed on every apply so a timeline registered after load still
|
|
261
|
+
// corrects the duration (and seek clamping) lazily.
|
|
262
|
+
function ensureDuration() {
|
|
263
|
+
if (declaredDuration > 0) {
|
|
264
|
+
duration = declaredDuration;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
let inferred = 0;
|
|
268
|
+
for (const clip of clips) {
|
|
269
|
+
const timing = readTiming(clip);
|
|
270
|
+
if (timing.end > inferred) inferred = timing.end;
|
|
271
|
+
}
|
|
272
|
+
const timeline = compositionTimeline();
|
|
273
|
+
if (timeline) {
|
|
274
|
+
const reported = timelineDuration(timeline);
|
|
275
|
+
if (reported > inferred) inferred = reported;
|
|
276
|
+
}
|
|
277
|
+
duration = inferred;
|
|
278
|
+
}
|
|
279
|
+
|
|
149
280
|
// Ken Burns image clips carry a CSS transform animation (vf-kb-* keyframes)
|
|
150
281
|
// directly on the [data-kenburns] <img>. CSS animations run on the wall clock,
|
|
151
282
|
// not player time, so the runtime scrubs them: pause + set currentTime from
|
|
@@ -176,7 +307,10 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
176
307
|
// previous clip on its track — so that previous clip must stay active for
|
|
177
308
|
// the transition window. Publish materializes this overlap into
|
|
178
309
|
// data-duration (normalizePublishHtml); the preview grants it live so
|
|
179
|
-
// butt-cut drafts preview exactly like the render.
|
|
310
|
+
// butt-cut drafts preview exactly like the render. A [data-transition-out]
|
|
311
|
+
// clip additionally animates AWAY (vf-tr-out-* keyframes) over its last
|
|
312
|
+
// data-transition-out-duration seconds — no hold needed, the exit window
|
|
313
|
+
// lives inside the clip's own span.
|
|
180
314
|
function collectTransitionWindows() {
|
|
181
315
|
const windows = [];
|
|
182
316
|
for (const clip of clips) {
|
|
@@ -210,8 +344,26 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
210
344
|
return hold;
|
|
211
345
|
}
|
|
212
346
|
|
|
213
|
-
function syncTransitionClip(clip, timing) {
|
|
347
|
+
function syncTransitionClip(clip, timing, hold) {
|
|
214
348
|
if (typeof clip.getAnimations !== "function") return;
|
|
349
|
+
// Exit animations sit at the clip's tail via the inline --vf-tr-out-delay
|
|
350
|
+
// var. Timeline edits touch data-duration only, so re-derive the delay
|
|
351
|
+
// (duration + any live hold − out duration) before scrubbing; publish
|
|
352
|
+
// materializes the same value for the render producer.
|
|
353
|
+
if (clip.hasAttribute("data-transition-out")) {
|
|
354
|
+
let outDuration = Number(clip.getAttribute("data-transition-out-duration"));
|
|
355
|
+
if (!Number.isFinite(outDuration) || outDuration <= 0) outDuration = 0.5;
|
|
356
|
+
outDuration = Math.min(outDuration, timing.duration);
|
|
357
|
+
const expectedDelay = Math.max(0, timing.duration + (hold || 0) - outDuration);
|
|
358
|
+
try {
|
|
359
|
+
if (Math.abs((parseFloat(clip.style.getPropertyValue("--vf-tr-out-dur")) || 0) - outDuration) > 0.002) {
|
|
360
|
+
clip.style.setProperty("--vf-tr-out-dur", outDuration.toFixed(3) + "s");
|
|
361
|
+
}
|
|
362
|
+
if (Math.abs((parseFloat(clip.style.getPropertyValue("--vf-tr-out-delay")) || 0) - expectedDelay) > 0.002) {
|
|
363
|
+
clip.style.setProperty("--vf-tr-out-delay", expectedDelay.toFixed(3) + "s");
|
|
364
|
+
}
|
|
365
|
+
} catch {}
|
|
366
|
+
}
|
|
215
367
|
const offsetMs = Math.max(0, (time - timing.start)) * 1000;
|
|
216
368
|
let anims = [];
|
|
217
369
|
try { anims = clip.getAnimations({ subtree: true }); } catch { return; }
|
|
@@ -292,25 +444,144 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
292
444
|
}
|
|
293
445
|
}
|
|
294
446
|
|
|
447
|
+
// Generalized CSS keyframe scrub — the preview twin of the official
|
|
448
|
+
// producer CSS adapter: every element whose computed animation-name is set
|
|
449
|
+
// gets its animations paused and scrubbed to the player time relative to
|
|
450
|
+
// the nearest ancestor-or-self [data-start] (0 when none). vf-* animations
|
|
451
|
+
// (Ken Burns, transitions, captions) keep their dedicated machinery above.
|
|
452
|
+
// Discovery is cached per refreshClips like the official adapter's discover
|
|
453
|
+
// pass; elements added by live patches are picked up on the next refresh.
|
|
454
|
+
// Each entry also caches its clip-relative start at discovery so the
|
|
455
|
+
// per-frame sync skips the ancestor walk; a re-parented or retimed element
|
|
456
|
+
// is likewise re-resolved on the next refreshClips discovery.
|
|
457
|
+
let generalCssEntries = [];
|
|
458
|
+
|
|
459
|
+
function discoverGeneralCssAnimations() {
|
|
460
|
+
generalCssEntries = [];
|
|
461
|
+
let nodes = [];
|
|
462
|
+
try { nodes = document.querySelectorAll("*"); } catch { return; }
|
|
463
|
+
for (const node of nodes) {
|
|
464
|
+
if (!(node instanceof HTMLElement) || typeof node.getAnimations !== "function") continue;
|
|
465
|
+
let names = "";
|
|
466
|
+
try { names = getComputedStyle(node).animationName || ""; } catch { continue; }
|
|
467
|
+
if (!names || names === "none") continue;
|
|
468
|
+
const expected = [];
|
|
469
|
+
for (const name of names.split(",")) {
|
|
470
|
+
const trimmed = name.trim();
|
|
471
|
+
if (!trimmed || trimmed === "none" || trimmed.indexOf("vf-") === 0) continue;
|
|
472
|
+
expected.push(trimmed);
|
|
473
|
+
}
|
|
474
|
+
if (expected.length) generalCssEntries.push({ el: node, names: expected, start: generalClipStartFor(node) });
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function hasAnimationNamed(anims, name) {
|
|
479
|
+
for (const anim of anims) {
|
|
480
|
+
if (anim.animationName === name) return true;
|
|
481
|
+
}
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function generalClipStartFor(node) {
|
|
486
|
+
const holder = node.closest("[data-start]");
|
|
487
|
+
return holder ? readNumberAttr(holder, ["data-start"], 0) : 0;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Cycling animation-name through none re-creates dropped CSS animations
|
|
491
|
+
// declaratively (same trick as the caption resurrection above), preserving
|
|
492
|
+
// any authored inline animation-name.
|
|
493
|
+
function resurrectCssAnimations(node) {
|
|
494
|
+
try {
|
|
495
|
+
const inline = node.style.animationName;
|
|
496
|
+
node.style.animationName = "none";
|
|
497
|
+
void node.offsetWidth;
|
|
498
|
+
if (inline && inline !== "none") {
|
|
499
|
+
node.style.animationName = inline;
|
|
500
|
+
} else {
|
|
501
|
+
node.style.removeProperty("animation-name");
|
|
502
|
+
}
|
|
503
|
+
} catch {}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function scrubGeneralAnimation(anim, offsetMs) {
|
|
507
|
+
let target = offsetMs;
|
|
508
|
+
try {
|
|
509
|
+
const computed = anim.effect && typeof anim.effect.getComputedTiming === "function"
|
|
510
|
+
? anim.effect.getComputedTiming()
|
|
511
|
+
: null;
|
|
512
|
+
const endTime = computed && typeof computed.endTime === "number" ? computed.endTime : NaN;
|
|
513
|
+
if (Number.isFinite(endTime) && offsetMs >= endTime) {
|
|
514
|
+
// Same Chrome guard as the caption scrub: paused fill:none/backwards
|
|
515
|
+
// animations pushed past their effect end are destroyed permanently,
|
|
516
|
+
// so park them at 0; fill:forwards/both hold their final keyframe at
|
|
517
|
+
// the clamped end. Infinite-iteration animations (endTime Infinity)
|
|
518
|
+
// take the raw clip-relative offset like the official CSS adapter —
|
|
519
|
+
// the browser resolves the iteration phase.
|
|
520
|
+
target = computed.fill === "forwards" || computed.fill === "both" ? endTime : 0;
|
|
521
|
+
}
|
|
522
|
+
} catch {}
|
|
523
|
+
try {
|
|
524
|
+
anim.pause();
|
|
525
|
+
anim.currentTime = target;
|
|
526
|
+
} catch {}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function syncGeneralCssAnimations() {
|
|
530
|
+
for (const entry of generalCssEntries) {
|
|
531
|
+
const node = entry.el;
|
|
532
|
+
if (!node.isConnected) continue;
|
|
533
|
+
const offsetMs = Math.max(0, time - entry.start) * 1000;
|
|
534
|
+
let anims = [];
|
|
535
|
+
try { anims = node.getAnimations(); } catch { continue; }
|
|
536
|
+
let missing = null;
|
|
537
|
+
for (const name of entry.names) {
|
|
538
|
+
if (!hasAnimationNamed(anims, name)) (missing || (missing = [])).push(name);
|
|
539
|
+
}
|
|
540
|
+
if (missing) {
|
|
541
|
+
resurrectCssAnimations(node);
|
|
542
|
+
try { anims = node.getAnimations(); } catch { anims = []; }
|
|
543
|
+
// Names that still have no live animation (e.g. a display:none
|
|
544
|
+
// subtree) are dropped until the next discovery so a hidden element
|
|
545
|
+
// is not forced through a reflow every frame.
|
|
546
|
+
entry.names = entry.names.filter((name) => missing.indexOf(name) === -1 || hasAnimationNamed(anims, name));
|
|
547
|
+
}
|
|
548
|
+
for (const anim of anims) {
|
|
549
|
+
if (typeof anim.animationName !== "string" || anim.animationName.indexOf("vf-") === 0) continue;
|
|
550
|
+
scrubGeneralAnimation(anim, offsetMs);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
295
555
|
function apply(nextTime, options = {}) {
|
|
296
556
|
const forceSeek = Boolean(options.forceSeek);
|
|
297
557
|
const fromClock = Boolean(options.fromClock);
|
|
558
|
+
ensureDuration();
|
|
298
559
|
time = clampTime(nextTime);
|
|
299
560
|
let activeVideoProxy = null;
|
|
561
|
+
let activeVideoProxyStart = -Infinity;
|
|
300
562
|
const transitionWindows = collectTransitionWindows();
|
|
301
563
|
for (const clip of clips) {
|
|
302
564
|
const timing = readTiming(clip);
|
|
303
565
|
const hold = transitionHoldFor(clip, timing, transitionWindows);
|
|
304
|
-
|
|
566
|
+
// hyperframes-core clip windows are inclusive of both ends — the final
|
|
567
|
+
// frame holds.
|
|
568
|
+
const active = time >= timing.start && time <= timing.end + hold;
|
|
305
569
|
if (clip instanceof HTMLElement && !(clip instanceof HTMLAudioElement)) {
|
|
306
570
|
if (clip.getAttribute("data-vf-timeline-proxy") === "video") {
|
|
307
|
-
|
|
571
|
+
// Clip windows are inclusive of both ends, so at an exact butt-cut
|
|
572
|
+
// the outgoing AND incoming proxies are both active. Prefer the
|
|
573
|
+
// greatest data-start (timeline order — the incoming clip wins);
|
|
574
|
+
// DOM order only breaks ties between equal starts.
|
|
575
|
+
if (active && timing.start >= activeVideoProxyStart) {
|
|
576
|
+
activeVideoProxy = clip;
|
|
577
|
+
activeVideoProxyStart = timing.start;
|
|
578
|
+
}
|
|
308
579
|
} else {
|
|
309
580
|
setVisibility(clip, active);
|
|
310
581
|
}
|
|
311
582
|
if (clip.hasAttribute("data-kenburns")) syncKenBurnsClip(clip, timing);
|
|
312
583
|
if (clip.hasAttribute("data-caption-animation")) syncCaptionClip(clip, timing);
|
|
313
|
-
if (clip.hasAttribute("data-transition")) syncTransitionClip(clip, timing);
|
|
584
|
+
if (clip.hasAttribute("data-transition") || clip.hasAttribute("data-transition-out")) syncTransitionClip(clip, timing, hold);
|
|
314
585
|
}
|
|
315
586
|
if (clip instanceof HTMLMediaElement) {
|
|
316
587
|
applyMediaState(clip);
|
|
@@ -328,6 +599,8 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
328
599
|
}
|
|
329
600
|
}
|
|
330
601
|
}
|
|
602
|
+
syncGeneralCssAnimations();
|
|
603
|
+
syncRuntimeAdapters();
|
|
331
604
|
if (backingVideo instanceof HTMLVideoElement) {
|
|
332
605
|
applyMediaState(backingVideo);
|
|
333
606
|
const shouldShowBackingVideo = !hasVideoProxies || Boolean(activeVideoProxy);
|
|
@@ -436,6 +709,13 @@ export const COMPOSITION_RUNTIME_SCRIPT_BODY = `
|
|
|
436
709
|
if (!playing) apply(time, { forceSeek: true });
|
|
437
710
|
});
|
|
438
711
|
}
|
|
712
|
+
window.addEventListener("load", () => {
|
|
713
|
+
// Composition scripts may register adapter instances (GSAP timelines,
|
|
714
|
+
// Lottie players, ...) or start CSS animations on the load event —
|
|
715
|
+
// re-discover and re-scrub so late registrations preview correctly.
|
|
716
|
+
discoverGeneralCssAnimations();
|
|
717
|
+
if (!playing) apply(time, { forceSeek: true });
|
|
718
|
+
});
|
|
439
719
|
|
|
440
720
|
// Cache the parent frame's origin from the first accepted control message
|
|
441
721
|
// and pin all outbound postMessages to it. Falls back to document.referrer's
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
// pushes them identically to a browser-made edit. Pure DOM (linkedom) — no
|
|
7
7
|
// ffmpeg, no network.
|
|
8
8
|
import { parseHTML } from "linkedom";
|
|
9
|
-
import { CAPTION_ANIMATIONS, CAPTION_STYLE_PRESETS, captionStylePresetById, estimateCaptionWords, renderHyperframeLayerHtml } from "../hyperframes/composition.js";
|
|
9
|
+
import { CAPTION_ANIMATIONS, CAPTION_STYLE_PRESETS, TRANSITION_OUT_PRESETS, TRANSITION_PRESETS, captionStylePresetById, clampTransitionDuration, estimateCaptionWords, renderHyperframeLayerHtml, transitionOutDelaySeconds } from "../hyperframes/composition.js";
|
|
10
10
|
const KEN_BURNS_PRESETS = new Set([
|
|
11
11
|
"zoom-in", "zoom-out", "pan-left", "pan-right", "pan-up", "pan-down", "zoom-in-left", "zoom-in-right"
|
|
12
12
|
]);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
// Preset vocabulary comes straight from the canonical source so the devcli can
|
|
14
|
+
// never drift from the stylesheet.
|
|
15
|
+
const TRANSITION_PRESET_SET = new Set(TRANSITION_PRESETS);
|
|
16
|
+
const TRANSITION_OUT_PRESET_SET = new Set(TRANSITION_OUT_PRESETS);
|
|
17
17
|
const round3 = (v) => Number(v.toFixed(3));
|
|
18
18
|
const clampPercent = (v) => Math.min(100, Math.max(0, v));
|
|
19
19
|
function serialize(document) {
|
|
@@ -231,13 +231,19 @@ function buildMediaClip(document, opts, id, track, geom) {
|
|
|
231
231
|
// picks the keyframes; data-transition-duration + --vf-tr-dur set the span.
|
|
232
232
|
// The overlap with the previous clip is granted by the runtime/publish
|
|
233
233
|
// normalizer — the stored timeline stays butt-cut.
|
|
234
|
-
const transitionDuration =
|
|
235
|
-
? Math.max(0.1, Math.min(2.5, opts.transitionDuration))
|
|
236
|
-
: 0.5;
|
|
234
|
+
const transitionDuration = clampTransitionDuration(opts.transitionDuration ?? 0.5);
|
|
237
235
|
node.setAttribute("data-transition", opts.transition);
|
|
238
236
|
node.setAttribute("data-transition-duration", String(round3(transitionDuration)));
|
|
239
237
|
styles.push(`--vf-tr-dur:${round3(transitionDuration)}s`);
|
|
240
238
|
}
|
|
239
|
+
if (opts.transitionOut && TRANSITION_OUT_PRESET_SET.has(opts.transitionOut)) {
|
|
240
|
+
// Exit transition: the inline --vf-tr-out-delay (clip duration − out
|
|
241
|
+
// duration) parks the animation window at the clip's tail.
|
|
242
|
+
const outDuration = clampTransitionDuration(opts.transitionOutDuration ?? 0.5);
|
|
243
|
+
node.setAttribute("data-transition-out", opts.transitionOut);
|
|
244
|
+
node.setAttribute("data-transition-out-duration", String(round3(outDuration)));
|
|
245
|
+
styles.push(`--vf-tr-out-dur:${round3(outDuration)}s`, `--vf-tr-out-delay:${transitionOutDelaySeconds(geom.duration, outDuration)}s`);
|
|
246
|
+
}
|
|
241
247
|
node.setAttribute("style", `${styles.join(";")};`);
|
|
242
248
|
return node;
|
|
243
249
|
}
|
|
@@ -438,4 +444,166 @@ export function replaceLayerWithMedia(html, targetKey, opts) {
|
|
|
438
444
|
void targetId;
|
|
439
445
|
return { html: serialize(document), layerKey: id };
|
|
440
446
|
}
|
|
447
|
+
function upsertStyleDecl(node, name, value) {
|
|
448
|
+
const styleValue = node.getAttribute("style") || "";
|
|
449
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\-]/g, "\\$&");
|
|
450
|
+
const pattern = new RegExp(`(^|;)\\s*${escaped}\\s*:[^;]*`, "i");
|
|
451
|
+
let nextStyle;
|
|
452
|
+
if (value === null) {
|
|
453
|
+
nextStyle = styleValue.replace(pattern, (_match, lead) => lead);
|
|
454
|
+
}
|
|
455
|
+
else if (pattern.test(styleValue)) {
|
|
456
|
+
nextStyle = styleValue.replace(pattern, (_match, lead) => `${lead}${name}:${value}`);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
nextStyle = styleValue.length === 0 || styleValue.endsWith(";")
|
|
460
|
+
? `${styleValue}${name}:${value}`
|
|
461
|
+
: `${styleValue};${name}:${value}`;
|
|
462
|
+
}
|
|
463
|
+
if (nextStyle !== styleValue)
|
|
464
|
+
node.setAttribute("style", nextStyle);
|
|
465
|
+
}
|
|
466
|
+
// Scene clips are what junction transitions connect: video/image layers and
|
|
467
|
+
// timeline proxies. Audio, captions, text overlays and the backing source
|
|
468
|
+
// video are excluded (same filter as the editor's timeline chips).
|
|
469
|
+
function isSceneClipNode(node) {
|
|
470
|
+
if (node?.hasAttribute?.("data-vf-playback-source"))
|
|
471
|
+
return false;
|
|
472
|
+
const tag = String(node?.tagName || "").toLowerCase();
|
|
473
|
+
if (tag === "audio")
|
|
474
|
+
return false;
|
|
475
|
+
const kind = node?.getAttribute?.("data-layer-kind");
|
|
476
|
+
return tag === "video" || tag === "img"
|
|
477
|
+
|| node?.getAttribute?.("data-vf-timeline-proxy") === "video"
|
|
478
|
+
|| kind === "video" || kind === "image";
|
|
479
|
+
}
|
|
480
|
+
function setNodeTransition(node, preset, durationSeconds) {
|
|
481
|
+
if (!preset || preset === "none") {
|
|
482
|
+
node.removeAttribute("data-transition");
|
|
483
|
+
node.removeAttribute("data-transition-duration");
|
|
484
|
+
upsertStyleDecl(node, "--vf-tr-dur", null);
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
if (!TRANSITION_PRESET_SET.has(preset)) {
|
|
488
|
+
throw new Error(`Unknown transition preset "${preset}". Use one of: none, ${TRANSITION_PRESETS.join(", ")}.`);
|
|
489
|
+
}
|
|
490
|
+
const current = Number.parseFloat(node.getAttribute("data-transition-duration") ?? "");
|
|
491
|
+
const duration = clampTransitionDuration(durationSeconds ?? (Number.isFinite(current) ? current : undefined));
|
|
492
|
+
node.setAttribute("data-transition", preset);
|
|
493
|
+
node.setAttribute("data-transition-duration", String(round3(duration)));
|
|
494
|
+
upsertStyleDecl(node, "--vf-tr-dur", `${round3(duration)}s`);
|
|
495
|
+
}
|
|
496
|
+
function setNodeTransitionOut(node, preset, durationSeconds) {
|
|
497
|
+
if (!preset || preset === "none") {
|
|
498
|
+
node.removeAttribute("data-transition-out");
|
|
499
|
+
node.removeAttribute("data-transition-out-duration");
|
|
500
|
+
upsertStyleDecl(node, "--vf-tr-out-dur", null);
|
|
501
|
+
upsertStyleDecl(node, "--vf-tr-out-delay", null);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
if (!TRANSITION_OUT_PRESET_SET.has(preset)) {
|
|
505
|
+
throw new Error(`Unknown exit transition preset "${preset}". Use one of: none, ${TRANSITION_OUT_PRESETS.join(", ")}.`);
|
|
506
|
+
}
|
|
507
|
+
const current = Number.parseFloat(node.getAttribute("data-transition-out-duration") ?? "");
|
|
508
|
+
const duration = clampTransitionDuration(durationSeconds ?? (Number.isFinite(current) ? current : undefined));
|
|
509
|
+
const layerDuration = numAttr(node, "data-duration");
|
|
510
|
+
node.setAttribute("data-transition-out", preset);
|
|
511
|
+
node.setAttribute("data-transition-out-duration", String(round3(duration)));
|
|
512
|
+
upsertStyleDecl(node, "--vf-tr-out-dur", `${round3(duration)}s`);
|
|
513
|
+
upsertStyleDecl(node, "--vf-tr-out-delay", `${transitionOutDelaySeconds(Number.isFinite(layerDuration) ? layerDuration : 0, duration)}s`);
|
|
514
|
+
}
|
|
515
|
+
// Bulk pass over the whole timeline — the devcli twin of the AI's
|
|
516
|
+
// set_transitions action and the editor's junction chips.
|
|
517
|
+
export function applyTransitionsAcross(html, opts) {
|
|
518
|
+
if (opts.junction === undefined && opts.intro === undefined && opts.outro === undefined) {
|
|
519
|
+
throw new Error("applyTransitionsAcross needs a junction preset, an intro, and/or an outro.");
|
|
520
|
+
}
|
|
521
|
+
const { document, root } = readCompositionDoc(html);
|
|
522
|
+
const scenes = collectClips(root).filter(isSceneClipNode).map((node) => ({
|
|
523
|
+
node,
|
|
524
|
+
start: numAttr(node, "data-start") || 0,
|
|
525
|
+
duration: numAttr(node, "data-duration") || 0,
|
|
526
|
+
track: numAttr(node, "data-track-index") || 0
|
|
527
|
+
})).sort((a, b) => (a.start - b.start) || (a.track - b.track));
|
|
528
|
+
if (!scenes.length)
|
|
529
|
+
throw new Error("No scene clips (video/image layers) found in the composition.");
|
|
530
|
+
const firstByTrack = new Map();
|
|
531
|
+
for (const scene of scenes) {
|
|
532
|
+
const first = firstByTrack.get(scene.track);
|
|
533
|
+
if (!first || scene.start < first.start)
|
|
534
|
+
firstByTrack.set(scene.track, scene);
|
|
535
|
+
}
|
|
536
|
+
let junctions = 0;
|
|
537
|
+
if (opts.junction !== undefined) {
|
|
538
|
+
for (const scene of scenes) {
|
|
539
|
+
if (firstByTrack.get(scene.track) === scene)
|
|
540
|
+
continue;
|
|
541
|
+
setNodeTransition(scene.node, opts.junction, opts.duration);
|
|
542
|
+
junctions += 1;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const firstScene = scenes[0];
|
|
546
|
+
const lastScene = scenes.reduce((latest, scene) => (scene.start + scene.duration > latest.start + latest.duration ? scene : latest), scenes[0]);
|
|
547
|
+
if (opts.intro !== undefined && firstScene) {
|
|
548
|
+
setNodeTransition(firstScene.node, opts.intro, opts.duration);
|
|
549
|
+
}
|
|
550
|
+
if (opts.outro !== undefined && lastScene) {
|
|
551
|
+
setNodeTransitionOut(lastScene.node, opts.outro, opts.outroDuration ?? opts.duration);
|
|
552
|
+
}
|
|
553
|
+
return {
|
|
554
|
+
html: serialize(document),
|
|
555
|
+
junctions,
|
|
556
|
+
intro: opts.intro !== undefined && opts.intro !== "none" && opts.intro !== null,
|
|
557
|
+
outro: opts.outro !== undefined && opts.outro !== "none" && opts.outro !== null
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
// Per-layer control — the devcli twin of set_layer_media's transition fields.
|
|
561
|
+
export function setLayerTransitions(html, layerKey, opts) {
|
|
562
|
+
if (opts.transition === undefined && opts.transitionOut === undefined) {
|
|
563
|
+
throw new Error("setLayerTransitions needs --in and/or --out.");
|
|
564
|
+
}
|
|
565
|
+
const { document, root } = readCompositionDoc(html);
|
|
566
|
+
const node = resolveLayerNode(root, layerKey);
|
|
567
|
+
if (!node)
|
|
568
|
+
throw new Error(`Layer not found: ${layerKey}`);
|
|
569
|
+
if (!isSceneClipNode(node) && String(node.tagName || "").toLowerCase() === "audio") {
|
|
570
|
+
throw new Error("Transitions cannot be applied to audio layers.");
|
|
571
|
+
}
|
|
572
|
+
if (opts.transition !== undefined)
|
|
573
|
+
setNodeTransition(node, opts.transition, opts.transitionDuration);
|
|
574
|
+
if (opts.transitionOut !== undefined)
|
|
575
|
+
setNodeTransitionOut(node, opts.transitionOut, opts.transitionOutDuration);
|
|
576
|
+
return { html: serialize(document), layerKey: node.getAttribute("data-hf-id") || node.id || layerKey };
|
|
577
|
+
}
|
|
578
|
+
export function clearAllTransitions(html) {
|
|
579
|
+
const { document, root } = readCompositionDoc(html);
|
|
580
|
+
let cleared = 0;
|
|
581
|
+
for (const node of collectClips(root)) {
|
|
582
|
+
const had = node.hasAttribute("data-transition") || node.hasAttribute("data-transition-out");
|
|
583
|
+
if (!had)
|
|
584
|
+
continue;
|
|
585
|
+
setNodeTransition(node, null);
|
|
586
|
+
setNodeTransitionOut(node, null);
|
|
587
|
+
cleared += 1;
|
|
588
|
+
}
|
|
589
|
+
return { html: serialize(document), cleared };
|
|
590
|
+
}
|
|
591
|
+
export function readTransitions(html) {
|
|
592
|
+
const { root } = readCompositionDoc(html);
|
|
593
|
+
return collectClips(root).filter(isSceneClipNode).map((node) => {
|
|
594
|
+
const duration = Number.parseFloat(node.getAttribute("data-transition-duration") ?? "");
|
|
595
|
+
const outDuration = Number.parseFloat(node.getAttribute("data-transition-out-duration") ?? "");
|
|
596
|
+
return {
|
|
597
|
+
layerKey: node.getAttribute("data-hf-id") || node.id || "",
|
|
598
|
+
label: node.getAttribute("data-label"),
|
|
599
|
+
track: numAttr(node, "data-track-index") || 0,
|
|
600
|
+
start: numAttr(node, "data-start") || 0,
|
|
601
|
+
duration: numAttr(node, "data-duration") || 0,
|
|
602
|
+
transition: node.getAttribute("data-transition"),
|
|
603
|
+
transition_duration: Number.isFinite(duration) ? duration : null,
|
|
604
|
+
transition_out: node.getAttribute("data-transition-out"),
|
|
605
|
+
transition_out_duration: Number.isFinite(outDuration) ? outDuration : null
|
|
606
|
+
};
|
|
607
|
+
}).sort((a, b) => (a.start - b.start) || (a.track - b.track));
|
|
608
|
+
}
|
|
441
609
|
//# sourceMappingURL=composition-edit.js.map
|