dsh-remotion 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +7 -5
- package/README.md +3 -3
- package/lib/index.d.ts +2 -2
- package/lib/index.js +15 -2
- package/package.json +1 -1
- package/skills/remotion-best-practices/SKILL.md +59 -0
- package/skills/remotion-best-practices/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-captions/SKILL.md +36 -0
- package/skills/remotion-best-practices/remotion-captions/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-captions/assets/remotion-icon.png +0 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-captions}/display-captions.md +9 -3
- package/skills/{remotion/rules → remotion-best-practices/remotion-captions}/import-srt-captions.md +5 -1
- package/skills/remotion-best-practices/remotion-create/SKILL.md +68 -0
- package/skills/remotion-best-practices/remotion-create/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-create/assets/remotion-icon.png +0 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-create}/tailwind.md +1 -1
- package/skills/remotion-best-practices/remotion-create/video-layout.md +9 -0
- package/skills/remotion-best-practices/remotion-docs/SKILL.md +46 -0
- package/skills/remotion-best-practices/remotion-docs/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-docs/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-interactivity/SKILL.md +247 -0
- package/skills/remotion-best-practices/remotion-interactivity/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-interactivity/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-maps/SKILL.md +36 -0
- package/skills/remotion-best-practices/remotion-maps/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-maps/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/city-path.json +12 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/mapbox/references/render-stability.md +64 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maplibre/TECHNIQUE.md +465 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maplibre/references/render-stability.md +64 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/render-stability.md +64 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -0
- package/skills/remotion-best-practices/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -0
- package/skills/remotion-best-practices/remotion-markup/SKILL.md +365 -0
- package/skills/remotion-best-practices/remotion-markup/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-markup/assets/remotion-icon.png +0 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/audio.md +4 -2
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/calculate-metadata.md +4 -2
- package/skills/remotion-best-practices/remotion-markup/compositions.md +117 -0
- package/skills/remotion-best-practices/remotion-markup/cropping.md +34 -0
- package/skills/remotion-best-practices/remotion-markup/effects.md +251 -0
- package/skills/{remotion/rules/videos.md → remotion-best-practices/remotion-markup/embedding-videos.md} +6 -4
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/ffmpeg.md +5 -1
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/gifs.md +55 -9
- package/skills/remotion-best-practices/remotion-markup/google-fonts.md +76 -0
- package/skills/remotion-best-practices/remotion-markup/html-in-canvas.md +128 -0
- package/skills/remotion-best-practices/remotion-markup/images.md +73 -0
- package/skills/remotion-best-practices/remotion-markup/light-leaks.md +106 -0
- package/skills/remotion-best-practices/remotion-markup/local-fonts.md +69 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/lottie.md +4 -1
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/measuring-dom-nodes.md +5 -1
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/measuring-text.md +8 -2
- package/skills/remotion-best-practices/remotion-markup/multi-scene-video.md +81 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/parameters.md +3 -1
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/SKILL.md +36 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/city-path.json +12 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/mapbox/references/render-stability.md +64 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maplibre/TECHNIQUE.md +465 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maplibre/references/render-stability.md +64 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/render-stability.md +64 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -0
- package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/sequencing.md +63 -12
- package/skills/remotion-best-practices/remotion-markup/sfx.md +51 -0
- package/skills/remotion-best-practices/remotion-markup/text-highlights.md +56 -0
- package/skills/remotion-best-practices/remotion-markup/timing.md +111 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/transitions.md +49 -7
- package/skills/remotion-best-practices/remotion-markup/video-editing.md +90 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/voiceover.md +2 -2
- package/skills/remotion-best-practices/remotion-multimedia/SKILL.md +20 -0
- package/skills/remotion-best-practices/remotion-multimedia/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-multimedia/assets/remotion-icon.png +0 -0
- package/skills/{remotion/rules → remotion-best-practices/remotion-multimedia}/get-audio-duration.md +1 -3
- package/skills/{remotion/rules → remotion-best-practices/remotion-multimedia}/get-video-dimensions.md +1 -3
- package/skills/{remotion/rules → remotion-best-practices/remotion-multimedia}/get-video-duration.md +1 -3
- package/skills/remotion-best-practices/remotion-render/SKILL.md +27 -0
- package/skills/remotion-best-practices/remotion-render/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-render/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-saas/SKILL.md +33 -0
- package/skills/remotion-best-practices/remotion-saas/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-saas/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-saas/framework.md +21 -0
- package/skills/remotion-best-practices/remotion-saas/player.md +33 -0
- package/skills/remotion-best-practices/remotion-saas/rendering.md +69 -0
- package/skills/remotion-best-practices/remotion-studio/SKILL.md +24 -0
- package/skills/remotion-best-practices/remotion-studio/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-studio/assets/remotion-icon.png +0 -0
- package/skills/remotion-best-practices/remotion-upgrade/SKILL.md +31 -0
- package/skills/remotion-best-practices/remotion-upgrade/agents/openai.yaml +7 -0
- package/skills/remotion-best-practices/remotion-upgrade/assets/remotion-icon.png +0 -0
- package/skills/remotion-captions/SKILL.md +36 -0
- package/skills/remotion-captions/agents/openai.yaml +7 -0
- package/skills/remotion-captions/assets/remotion-icon.png +0 -0
- package/skills/remotion-captions/display-captions.md +190 -0
- package/skills/remotion-captions/import-srt-captions.md +73 -0
- package/skills/remotion-captions/transcribe-captions.md +70 -0
- package/skills/remotion-create/SKILL.md +68 -0
- package/skills/remotion-create/agents/openai.yaml +7 -0
- package/skills/remotion-create/assets/remotion-icon.png +0 -0
- package/skills/remotion-create/tailwind.md +11 -0
- package/skills/remotion-create/video-layout.md +9 -0
- package/skills/remotion-docs/SKILL.md +46 -0
- package/skills/remotion-docs/agents/openai.yaml +7 -0
- package/skills/remotion-docs/assets/remotion-icon.png +0 -0
- package/skills/remotion-interactivity/SKILL.md +247 -0
- package/skills/remotion-interactivity/agents/openai.yaml +7 -0
- package/skills/remotion-interactivity/assets/remotion-icon.png +0 -0
- package/skills/remotion-maps/SKILL.md +36 -0
- package/skills/remotion-maps/agents/openai.yaml +7 -0
- package/skills/remotion-maps/assets/remotion-icon.png +0 -0
- package/skills/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -0
- package/skills/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -0
- package/skills/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -0
- package/skills/remotion-maps/techniques/cesium/assets/city-path.json +12 -0
- package/skills/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -0
- package/skills/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -0
- package/skills/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -0
- package/skills/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -0
- package/skills/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -0
- package/skills/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -0
- package/skills/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -0
- package/skills/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -0
- package/skills/remotion-maps/techniques/mapbox/references/render-stability.md +64 -0
- package/skills/remotion-maps/techniques/maplibre/TECHNIQUE.md +465 -0
- package/skills/remotion-maps/techniques/maplibre/references/render-stability.md +64 -0
- package/skills/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -0
- package/skills/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -0
- package/skills/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -0
- package/skills/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -0
- package/skills/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -0
- package/skills/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -0
- package/skills/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -0
- package/skills/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -0
- package/skills/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -0
- package/skills/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -0
- package/skills/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -0
- package/skills/remotion-maps/techniques/maptiler/references/render-stability.md +64 -0
- package/skills/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -0
- package/skills/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -0
- package/skills/remotion-markup/3d.md +86 -0
- package/skills/remotion-markup/SKILL.md +365 -0
- package/skills/remotion-markup/agents/openai.yaml +7 -0
- package/skills/remotion-markup/assets/remotion-icon.png +0 -0
- package/skills/remotion-markup/audio-visualization.md +198 -0
- package/skills/remotion-markup/audio.md +171 -0
- package/skills/remotion-markup/calculate-metadata.md +136 -0
- package/skills/remotion-markup/compositions.md +117 -0
- package/skills/remotion-markup/cropping.md +34 -0
- package/skills/remotion-markup/effects.md +251 -0
- package/skills/remotion-markup/embedding-videos.md +173 -0
- package/skills/remotion-markup/ffmpeg.md +38 -0
- package/skills/remotion-markup/gifs.md +187 -0
- package/skills/remotion-markup/google-fonts.md +76 -0
- package/skills/remotion-markup/html-in-canvas.md +128 -0
- package/skills/remotion-markup/images.md +73 -0
- package/skills/remotion-markup/light-leaks.md +106 -0
- package/skills/remotion-markup/local-fonts.md +69 -0
- package/skills/remotion-markup/lottie.md +73 -0
- package/skills/remotion-markup/measuring-dom-nodes.md +38 -0
- package/skills/remotion-markup/measuring-text.md +146 -0
- package/skills/remotion-markup/multi-scene-video.md +81 -0
- package/skills/remotion-markup/parameters.md +111 -0
- package/skills/remotion-markup/remotion-maps/SKILL.md +36 -0
- package/skills/remotion-markup/remotion-maps/agents/openai.yaml +7 -0
- package/skills/remotion-markup/remotion-maps/assets/remotion-icon.png +0 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/city-path.json +12 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -0
- package/skills/remotion-markup/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -0
- package/skills/remotion-markup/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -0
- package/skills/remotion-markup/remotion-maps/techniques/mapbox/references/render-stability.md +64 -0
- package/skills/remotion-markup/remotion-maps/techniques/maplibre/TECHNIQUE.md +465 -0
- package/skills/remotion-markup/remotion-maps/techniques/maplibre/references/render-stability.md +64 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/render-stability.md +64 -0
- package/skills/remotion-markup/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -0
- package/skills/remotion-markup/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -0
- package/skills/remotion-markup/sequencing.md +169 -0
- package/skills/remotion-markup/sfx.md +51 -0
- package/skills/remotion-markup/silence-detection.md +71 -0
- package/skills/remotion-markup/text-highlights.md +56 -0
- package/skills/remotion-markup/timing.md +111 -0
- package/skills/remotion-markup/transitions.md +239 -0
- package/skills/remotion-markup/video-editing.md +90 -0
- package/skills/remotion-markup/voiceover.md +99 -0
- package/skills/remotion-multimedia/SKILL.md +20 -0
- package/skills/remotion-multimedia/agents/openai.yaml +7 -0
- package/skills/remotion-multimedia/assets/remotion-icon.png +0 -0
- package/skills/remotion-multimedia/get-audio-duration.md +56 -0
- package/skills/remotion-multimedia/get-video-dimensions.md +66 -0
- package/skills/remotion-multimedia/get-video-duration.md +58 -0
- package/skills/remotion-render/SKILL.md +27 -0
- package/skills/remotion-render/agents/openai.yaml +7 -0
- package/skills/remotion-render/assets/remotion-icon.png +0 -0
- package/skills/remotion-render/transparent-videos.md +106 -0
- package/skills/remotion-saas/SKILL.md +33 -0
- package/skills/remotion-saas/agents/openai.yaml +7 -0
- package/skills/remotion-saas/assets/remotion-icon.png +0 -0
- package/skills/remotion-saas/framework.md +21 -0
- package/skills/remotion-saas/player.md +33 -0
- package/skills/remotion-saas/rendering.md +69 -0
- package/skills/remotion-studio/SKILL.md +24 -0
- package/skills/remotion-studio/agents/openai.yaml +7 -0
- package/skills/remotion-studio/assets/remotion-icon.png +0 -0
- package/skills/remotion-upgrade/SKILL.md +31 -0
- package/skills/remotion-upgrade/agents/openai.yaml +7 -0
- package/skills/remotion-upgrade/assets/remotion-icon.png +0 -0
- package/skills/remotion/SKILL.md +0 -95
- package/skills/remotion/rules/animations.md +0 -31
- package/skills/remotion/rules/assets.md +0 -78
- package/skills/remotion/rules/can-decode.md +0 -81
- package/skills/remotion/rules/charts.md +0 -120
- package/skills/remotion/rules/compositions.md +0 -154
- package/skills/remotion/rules/extract-frames.md +0 -229
- package/skills/remotion/rules/fonts.md +0 -152
- package/skills/remotion/rules/images.md +0 -134
- package/skills/remotion/rules/light-leaks.md +0 -73
- package/skills/remotion/rules/maps.md +0 -412
- package/skills/remotion/rules/sfx.md +0 -30
- package/skills/remotion/rules/subtitles.md +0 -36
- package/skills/remotion/rules/text-animations.md +0 -20
- package/skills/remotion/rules/timing.md +0 -136
- package/skills/remotion/rules/trimming.md +0 -51
- /package/skills/{remotion/rules → remotion-best-practices/remotion-captions}/transcribe-captions.md +0 -0
- /package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/3d.md +0 -0
- /package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/audio-visualization.md +0 -0
- /package/skills/{remotion/rules → remotion-best-practices/remotion-markup}/silence-detection.md +0 -0
- /package/skills/{remotion/rules → remotion-best-practices/remotion-render}/transparent-videos.md +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# 3D Flyover — architecture reference
|
|
2
|
+
|
|
3
|
+
Deep detail behind `TECHNIQUE.md`: provider loading, the camera-path pipeline, per-frame camera math, and
|
|
4
|
+
the proven terrain values. Both landscape and city modes have been forward-tested through Remotion.
|
|
5
|
+
|
|
6
|
+
## 1. Provider initialization
|
|
7
|
+
|
|
8
|
+
Create the Viewer with `baseLayer: false`, UI widgets disabled, and
|
|
9
|
+
`contextOptions.webgl.preserveDrawingBuffer: true`. Never hide the credit display.
|
|
10
|
+
|
|
11
|
+
### Landscape
|
|
12
|
+
|
|
13
|
+
Add MapTiler `satellite-v2` with `UrlTemplateImageryProvider`, then load
|
|
14
|
+
`terrain-quantized-mesh-v2` with `CesiumTerrainProvider.fromUrl({requestVertexNormals: true})`.
|
|
15
|
+
MapTiler supplies both datasets; no Cesium ion token is required.
|
|
16
|
+
|
|
17
|
+
### City
|
|
18
|
+
|
|
19
|
+
Do not add MapTiler. Hide the globe, then add:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
viewer.scene.globe.show = false;
|
|
23
|
+
const tileset = await Cesium.Cesium3DTileset.fromUrl(
|
|
24
|
+
`https://tile.googleapis.com/v1/3dtiles/root.json?key=${GOOGLE_KEY}`,
|
|
25
|
+
{showCreditsOnScreen: true, maximumScreenSpaceError: 4},
|
|
26
|
+
);
|
|
27
|
+
viewer.scene.primitives.add(tileset);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Lower `maximumScreenSpaceError` improves refinement at substantial download/render cost. Start at
|
|
31
|
+
`4` for a hero landmark and `6–8` for wider urban shots. Enforce the Google 30-second promotional
|
|
32
|
+
video ceiling in the component.
|
|
33
|
+
|
|
34
|
+
Load Cesium from the CDN after setting `window.CESIUM_BASE_URL`; the tested version is `1.143`.
|
|
35
|
+
|
|
36
|
+
## 2. The camera path — structure & generation
|
|
37
|
+
|
|
38
|
+
Four properties matter, in order:
|
|
39
|
+
|
|
40
|
+
1. **Continuous curvature** — the camera must flow through curves, never "fly straight, snap to a new
|
|
41
|
+
heading, fly straight." The component applies three passes of **Chaikin corner cutting** to every
|
|
42
|
+
supplied path. Each pass replaces a segment with quarter and three-quarter points, rounding a
|
|
43
|
+
corner into a curve. Three passes are the default; four is softer, two is tighter.
|
|
44
|
+
2. **Constant ground speed** — precompute cumulative distance along the rounded curve and interpolate
|
|
45
|
+
by arc length. Do not animate by source-point index; unequal source spacing creates speed bumps.
|
|
46
|
+
3. **Minimized amplitude** — for detailed landscape centerlines, dampen the prepared path toward its
|
|
47
|
+
straight start→end chord by a fixed fraction `DAMP` (0 = dead straight, 1 = full river). This is
|
|
48
|
+
the single swerve-amplitude knob.
|
|
49
|
+
4. **Enough length** — `PATHKM ≥ TRAVEL_KM + 2·LOOK_AHEAD_KM` so the look-ahead aim never clamps.
|
|
50
|
+
|
|
51
|
+
`../scripts/prep-cesium-path.mjs` does: clip a window of the source centerline → resample to even
|
|
52
|
+
arc-length spacing (0.1 km) → moving-average smooth (±2.8 km window, 2 passes) → dampen toward the chord
|
|
53
|
+
(`DAMP=0.45`). Validate with the heading-delta probe it prints — deltas should be small and change
|
|
54
|
+
_gradually_ (water-wars: `3,0,-1,-3,-4,1,7,9,5,-5,-12,-7,…`). Big jumps = corners = bad.
|
|
55
|
+
|
|
56
|
+
The component then applies Chaikin smoothing to this prepared route, or directly to a short
|
|
57
|
+
hand-authored city route. Keep city control points sparse and intentional; smoothing cannot rescue a
|
|
58
|
+
zig-zagging route that crosses the subject repeatedly.
|
|
59
|
+
|
|
60
|
+
**Source data:** OSM via Overpass (~0.3 km vertex spacing) — Natural Earth is too coarse for inner
|
|
61
|
+
gorges. overpass-api.de is often busy → mirror `overpass.kumi.systems`.
|
|
62
|
+
|
|
63
|
+
## 3. Camera animation per frame (position, heading, pitch, bank)
|
|
64
|
+
|
|
65
|
+
Walk the path by **arc length** (precompute cumulative distances once). Every frame:
|
|
66
|
+
|
|
67
|
+
- **Position** = the point at `dCam` km along the path, altitude `lerp(ALT_START, ALT_END, prog)`.
|
|
68
|
+
- **Heading** = bearing from the camera point to a **real point `LOOK_AHEAD_KM` further along the same
|
|
69
|
+
path**. A far aim averages wiggle → smooth heading; on a curved path it leads into the bend, so the
|
|
70
|
+
heading turns gently with the path. (A local-tangent aim spins the camera at every kink — don't.)
|
|
71
|
+
- **Pitch** = constant. We keep a MapLibre-style param `PITCH_FROM_NADIR` (90 = horizon), then convert:
|
|
72
|
+
**Cesium pitch = `-(90 - PITCH_FROM_NADIR)`** (Cesium: 0 = horizon, -90 = straight down). 76° → -14°.
|
|
73
|
+
- **Bank (roll)** = lean _into_ the turn — the helicopter tell. Measure turn rate as the bearing change
|
|
74
|
+
between `aim` and a point `2·LOOK_AHEAD_KM` ahead; `roll = clamp(dH · BANK_GAIN, ±MAX_BANK)`. Because
|
|
75
|
+
the path is smooth, `dH` changes gradually → the bank eases in and out, never jerks.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const setCamera = (C, viewer, prog) => {
|
|
79
|
+
const dCam = Math.min(TRAVEL_KM, PATHKM - LOOK_AHEAD_KM * 2) * prog;
|
|
80
|
+
const cam = alongPath(dCam); // arc-length point
|
|
81
|
+
const aim = alongPath(dCam + LOOK_AHEAD_KM); // heading target (real point on the path)
|
|
82
|
+
const aim2 = alongPath(dCam + LOOK_AHEAD_KM * 2); // turn-rate probe → bank
|
|
83
|
+
const heading = bearing(cam, aim);
|
|
84
|
+
let dH = bearing(aim, aim2) - heading; while (dH > Math.PI) dH -= 2*Math.PI; while (dH < -Math.PI) dH += 2*Math.PI;
|
|
85
|
+
viewer.camera.setView({
|
|
86
|
+
destination: C.Cartesian3.fromDegrees(cam[0], cam[1], lerp(ALT_START, ALT_END, prog)),
|
|
87
|
+
orientation: { heading, pitch: C.Math.toRadians(-(90 - PITCH_FROM_NADIR)), roll: clamp(dH * BANK_GAIN, -MAX_BANK, MAX_BANK) },
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
> **Cesium vs MapLibre conventions (gotcha):** Cesium heading is radians, 0 = north, clockwise. Pitch
|
|
93
|
+
> 0 = horizon, negative = down (MapLibre is the inverse). Roll positive = bank right; tune the sign by eye.
|
|
94
|
+
|
|
95
|
+
## 4. The feel — proven water-wars values
|
|
96
|
+
|
|
97
|
+
| Param | Value | Meaning |
|
|
98
|
+
| ------------------------ | ---------------------- | ------------------------------------------------------------------------------------ |
|
|
99
|
+
| `TRAVEL_KM` | 13 | How far the camera travels. **Speed = `TRAVEL_KM / durationSeconds`.** |
|
|
100
|
+
| duration | 24 s (720 f @30) | 13 km / 24 s ≈ **0.54 km/s** — a slow, peaceful glide. 8 s felt "extremely rushed". |
|
|
101
|
+
| `ALT_START → ALT_END` | 4600 → 4300 m ASL | Absolute (terrain-independent). Inside the corridor walls → fly _through_, not over. |
|
|
102
|
+
| `LOOK_AHEAD_KM` | 1.5 | Heading smoothness vs responsiveness. |
|
|
103
|
+
| `PITCH_FROM_NADIR` | 76° | Stare-ahead down the corridor (90 = level). → Cesium -14°. |
|
|
104
|
+
| `MAX_BANK` / `BANK_GAIN` | 0.13 rad (~7.5°) / 0.6 | Helicopter lean into turns. |
|
|
105
|
+
| `verticalExaggeration` | 1.1 | Subtle terrain drama. |
|
|
106
|
+
| `DAMP` (prep) | 0.45 | Swerve amount: higher = weavier, lower = straighter. |
|
|
107
|
+
|
|
108
|
+
**A slow camera renders fast.** At 0.54 km/s the camera moves ~18 m/frame, so tiles stay cached and each
|
|
109
|
+
`settle()` returns almost immediately; the 720-frame render completed in one pass (no chunk-rendering).
|
|
110
|
+
|
|
111
|
+
## 5. The complete component
|
|
112
|
+
|
|
113
|
+
The full, runnable component is `../assets/CesiumFlythrough.tsx` — read it directly. Its shape:
|
|
114
|
+
|
|
115
|
+
- `loadCesium()` — inject `CESIUM_BASE_URL` + the CDN `Cesium.js`, resolve when loaded.
|
|
116
|
+
- init effect — build the Viewer (§1), `setCamera(…, 0)`, `await settle(viewer)`, `continueRender`.
|
|
117
|
+
- `settle(viewer)` — loop `viewer.render()` until `globe.tilesLoaded` for landscapes or
|
|
118
|
+
`tileset.tilesLoaded` for cities is stable for ~8 ticks (cap ~600).
|
|
119
|
+
- per-frame effect — `delayRender({timeoutInMilliseconds: 60000})` → `setCamera(prog)` → `settle()` → `continueRender`.
|
|
120
|
+
|
|
121
|
+
## 6. Render
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
bunx remotion still src/index.ts <Comp> out.png --frame=N --gl=angle --timeout=180000 # validate framing/bank first
|
|
125
|
+
bunx remotion render src/index.ts <Comp> out.mp4 --gl=angle --concurrency=1 --timeout=180000
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`--gl=angle` is mandatory. Use `--concurrency=1`; `settle()` already serializes tile loading.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 3D Flyover — troubleshooting
|
|
2
|
+
|
|
3
|
+
## The headless dead-end (why we render through Remotion)
|
|
4
|
+
|
|
5
|
+
Cesium's globe **will not draw in a standalone headless Playwright/Chromium** harness. Verified on
|
|
6
|
+
Apple M4 (ANGLE Metal active, WebGL working): the skybox/stars render, but the globe surface produces
|
|
7
|
+
**zero draw commands** (`scene.frameState.commandList.length === 0`), `globe.tilesLoaded` never goes
|
|
8
|
+
true, and frames come back as the black starfield. No network failures; `sampleTerrainMostDetailed`
|
|
9
|
+
succeeds (terrain data is reachable). Dead-ends tried, all failed:
|
|
10
|
+
|
|
11
|
+
- default render loop, manual `scene.render()`, manual `viewer.render()`, headed mode (context-destroyed).
|
|
12
|
+
|
|
13
|
+
**What works:** render Cesium **through Remotion** — same headless Chrome, but driven by Remotion's frame
|
|
14
|
+
loop with these four non-negotiables:
|
|
15
|
+
|
|
16
|
+
1. `useDefaultRenderLoop = false` — drive frames by hand.
|
|
17
|
+
2. Per frame call **`viewer.render()`**, NOT `scene.render()`. `viewer.render()` does the full frame
|
|
18
|
+
(`initializeFrame` → tile streaming → render); `scene.render()` skips frame-init, so tiles never
|
|
19
|
+
advance and the globe never appears. **This is the single most important line.**
|
|
20
|
+
3. `contextOptions: { webgl: { preserveDrawingBuffer: true } }` so Remotion's screenshot captures pixels.
|
|
21
|
+
4. Gate init + every frame with `delayRender(…, {timeoutInMilliseconds})` — tile loading can exceed Remotion's
|
|
22
|
+
default; use 60–120 s.
|
|
23
|
+
|
|
24
|
+
The standalone `flythrough.html` / `render.mjs` / `probe.mjs` from the original spike are kept only as the
|
|
25
|
+
record of this dead-end. The canonical render path is the Remotion component
|
|
26
|
+
(`../assets/CesiumFlythrough.tsx`).
|
|
27
|
+
|
|
28
|
+
## Symptom → fix
|
|
29
|
+
|
|
30
|
+
| Symptom | Cause | Fix |
|
|
31
|
+
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
32
|
+
| Frames are black with stars | Globe not drawing (headless Playwright, or `scene.render()` used) | Render through Remotion; use `viewer.render()`; `useDefaultRenderLoop=false`. |
|
|
33
|
+
| Screenshots blank/transparent | No `preserveDrawingBuffer` | `contextOptions:{ webgl:{ preserveDrawingBuffer:true } }`. |
|
|
34
|
+
| "delayRender timed out" | Cold tiles exceed the default | `delayRender(…, {timeoutInMilliseconds: 120000})` + `--timeout=180000`. |
|
|
35
|
+
| Globe is a dark/navy sphere | Imagery layer didn't attach | `baseLayer:false` then `viewer.imageryLayers.addImageryProvider(...)`. |
|
|
36
|
+
| High-pitch frame shows a void/starfield above the horizon | No atmosphere | `viewer.scene.skyAtmosphere.show = true`. |
|
|
37
|
+
| 403 on tiles in headless | Domain-locked MapTiler key | Use an **unrestricted** key. |
|
|
38
|
+
| Google root tileset returns 403 | Map Tiles API disabled, billing absent, wrong key, or application restriction blocks local headless rendering | Enable Map Tiles API and billing; restrict the key to that API while allowing the Remotion request. |
|
|
39
|
+
| Google scene shows a duplicate/competing surface | MapTiler or the Cesium globe is still enabled | Do not add MapTiler; set `viewer.scene.globe.show=false`. |
|
|
40
|
+
| Google mesh remains coarse | Screen-space error is too high or the capture starts before refinement | Lower `maximumScreenSpaceError`; settle on `tileset.tilesLoaded`. |
|
|
41
|
+
| WebGL unavailable / software renderer | Missing GL flag | Render with `--gl=angle`. |
|
|
42
|
+
| Camera looks at sky / ground, not terrain | Pitch sign / convention | Cesium pitch 0 = horizon, negative = down (inverse of MapLibre); `-(90 - PITCH_FROM_NADIR)`. |
|
|
43
|
+
| Aim/turn-probe clamps near the end | Path too short | `PATHKM ≥ TRAVEL_KM + 2·LOOK_AHEAD_KM`; raise `WINDOW_KM` in prep. |
|
|
44
|
+
| Path feels like straight-then-corner | Douglas-Peucker simplification | Use resample → moving-average smooth (see architecture §2), not `turf.simplify`. |
|
|
45
|
+
| Camera bumps left and right instead of swerving | Sparse route vertices are still being followed as straight segments | Keep `pathSmoothingPasses={3}`; use sparse intentional control points and arc-length movement. |
|
|
46
|
+
|
|
47
|
+
## Gotchas checklist
|
|
48
|
+
|
|
49
|
+
- **`viewer.render()`, never `scene.render()`** per frame. The single biggest trap.
|
|
50
|
+
- Cesium loads from **CDN**; set `window.CESIUM_BASE_URL` _before_ injecting the script.
|
|
51
|
+
- `preserveDrawingBuffer: true` or screenshots are blank.
|
|
52
|
+
- `delayRender` uses `timeoutInMilliseconds`; set it to at least 60,000.
|
|
53
|
+
- Terrain: `baseLayer:false`, then add MapTiler imagery.
|
|
54
|
+
- Google: no MapTiler, hide the globe, retain `showCreditsOnScreen:true`.
|
|
55
|
+
- Always `skyAtmosphere.show = true`.
|
|
56
|
+
- Validate the path's heading-delta probe and render one **still** (framing + bank) before the full mp4.
|
|
57
|
+
- Cesium pitch/roll conventions are inverted vs MapLibre.
|
package/skills/remotion-best-practices/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// Camera-path generator for the Cesium flythrough. Turns a river/route centerline GeoJSON into a LONG,
|
|
2
|
+
// CONTINUOUSLY-curving camera path so the camera banks through smooth flowing curves (no
|
|
3
|
+
// straight-then-corner). Method: clip → resample to even spacing → moving-average smooth (inherently
|
|
4
|
+
// continuous curvature) → dampen lateral deviation toward the straight chord (dials swerve amplitude).
|
|
5
|
+
// No Douglas-Peucker (that concentrates curvature at sparse control points → corners).
|
|
6
|
+
//
|
|
7
|
+
// RUN (out of the box, against the shipped sample):
|
|
8
|
+
// node prep-cesium-path.mjs
|
|
9
|
+
// → reads assets/sample-river.geojson (override: node prep-cesium-path.mjs <input.geojson> <output.json>)
|
|
10
|
+
// → writes assets/cesium-path.json (then import that JSON in CesiumFlythrough.tsx, or copy it
|
|
11
|
+
// into your Remotion project's src/geo/ and adjust the import)
|
|
12
|
+
//
|
|
13
|
+
// ADAPT for a new location: change START (a point ON your centerline where the corridor opens),
|
|
14
|
+
// WINDOW_KM, and DAMP/SMOOTH below. Input must be a single LineString feature (features[0].geometry).
|
|
15
|
+
|
|
16
|
+
import {readFileSync, writeFileSync, mkdirSync} from 'fs';
|
|
17
|
+
import {dirname, resolve} from 'path';
|
|
18
|
+
import {fileURLToPath} from 'url';
|
|
19
|
+
|
|
20
|
+
const __dir = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const IN = process.argv[2] || resolve(__dir, '../assets/sample-river.geojson');
|
|
22
|
+
const OUT = process.argv[3] || resolve(__dir, '../assets/cesium-path.json');
|
|
23
|
+
const havKm = (a, b) => {
|
|
24
|
+
const R = 6371,
|
|
25
|
+
r = Math.PI / 180,
|
|
26
|
+
dLat = (b[1] - a[1]) * r,
|
|
27
|
+
dLng = (b[0] - a[0]) * r;
|
|
28
|
+
const h =
|
|
29
|
+
Math.sin(dLat / 2) ** 2 +
|
|
30
|
+
Math.cos(a[1] * r) * Math.cos(b[1] * r) * Math.sin(dLng / 2) ** 2;
|
|
31
|
+
return 2 * R * Math.asin(Math.sqrt(h));
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const gorge = JSON.parse(readFileSync(IN, 'utf8')).features[0].geometry
|
|
35
|
+
.coordinates;
|
|
36
|
+
|
|
37
|
+
// ADAPT: clip ~24 km of river from the reach where the flythrough opens. START must be a point ON the
|
|
38
|
+
// centerline (the script snaps to the nearest vertex). The sample's opening is the Yarlung gorge:
|
|
39
|
+
const START = [94.968, 29.757];
|
|
40
|
+
let s0 = 0,
|
|
41
|
+
best = Infinity;
|
|
42
|
+
gorge.forEach((p, i) => {
|
|
43
|
+
const d = havKm(p, START);
|
|
44
|
+
if (d < best) {
|
|
45
|
+
best = d;
|
|
46
|
+
s0 = i;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const WINDOW_KM = 30; // clip to ~end of gorge data; smoothing+dampening shrink it to the usable corridor
|
|
50
|
+
const clip = [];
|
|
51
|
+
for (let i = s0, acc = 0; i < gorge.length; i++) {
|
|
52
|
+
if (i > s0) acc += havKm(gorge[i - 1], gorge[i]);
|
|
53
|
+
if (acc > WINDOW_KM) break;
|
|
54
|
+
clip.push(gorge[i]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Resample to even arc-length spacing so curvature is distributed evenly along the path.
|
|
58
|
+
const STEP_KM = 0.1;
|
|
59
|
+
const resample = (coords) => {
|
|
60
|
+
const out = [coords[0].slice()];
|
|
61
|
+
let carry = 0,
|
|
62
|
+
from = coords[0];
|
|
63
|
+
for (let i = 1; i < coords.length; i++) {
|
|
64
|
+
let segLen = havKm(from, coords[i]);
|
|
65
|
+
while (carry + segLen >= STEP_KM) {
|
|
66
|
+
const t = (STEP_KM - carry) / segLen;
|
|
67
|
+
const np = [
|
|
68
|
+
from[0] + (coords[i][0] - from[0]) * t,
|
|
69
|
+
from[1] + (coords[i][1] - from[1]) * t,
|
|
70
|
+
];
|
|
71
|
+
out.push(np);
|
|
72
|
+
from = np;
|
|
73
|
+
segLen = havKm(from, coords[i]);
|
|
74
|
+
carry = 0;
|
|
75
|
+
}
|
|
76
|
+
carry += segLen;
|
|
77
|
+
from = coords[i];
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Moving-average smoothing — inherently continuous (no kinks). Window in points; repeat for extra glass.
|
|
83
|
+
const smoothMA = (coords, w, passes) => {
|
|
84
|
+
let c = coords;
|
|
85
|
+
for (let p = 0; p < passes; p++) {
|
|
86
|
+
c = c.map((_, i) => {
|
|
87
|
+
let sx = 0,
|
|
88
|
+
sy = 0,
|
|
89
|
+
n = 0;
|
|
90
|
+
for (
|
|
91
|
+
let j = Math.max(0, i - w);
|
|
92
|
+
j <= Math.min(c.length - 1, i + w);
|
|
93
|
+
j++
|
|
94
|
+
) {
|
|
95
|
+
sx += c[j][0];
|
|
96
|
+
sy += c[j][1];
|
|
97
|
+
n++;
|
|
98
|
+
}
|
|
99
|
+
return [sx / n, sy / n];
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return c;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const SMOOTH_W = 28; // ±2.8 km window — turns meanders into smooth flowing curves
|
|
106
|
+
const SMOOTH_PASSES = 2;
|
|
107
|
+
const DAMP = 0.45; // keep 45% of the (already-smooth) deviation → gentle, continuous swerve
|
|
108
|
+
|
|
109
|
+
const even = resample(clip);
|
|
110
|
+
const sm = smoothMA(even, SMOOTH_W, SMOOTH_PASSES);
|
|
111
|
+
|
|
112
|
+
const lat0 = (sm[0][1] * Math.PI) / 180;
|
|
113
|
+
const kx = 111.32 * Math.cos(lat0),
|
|
114
|
+
ky = 110.57;
|
|
115
|
+
const toXY = (p) => [(p[0] - sm[0][0]) * kx, (p[1] - sm[0][1]) * ky];
|
|
116
|
+
const toLL = (xy) => [sm[0][0] + xy[0] / kx, sm[0][1] + xy[1] / ky];
|
|
117
|
+
const A = toXY(sm[0]),
|
|
118
|
+
B = toXY(sm[sm.length - 1]);
|
|
119
|
+
const AB = [B[0] - A[0], B[1] - A[1]],
|
|
120
|
+
len2 = AB[0] ** 2 + AB[1] ** 2;
|
|
121
|
+
const path = sm.map((p) => {
|
|
122
|
+
const P = toXY(p);
|
|
123
|
+
const t = ((P[0] - A[0]) * AB[0] + (P[1] - A[1]) * AB[1]) / len2;
|
|
124
|
+
const proj = [A[0] + t * AB[0], A[1] + t * AB[1]];
|
|
125
|
+
return toLL([
|
|
126
|
+
proj[0] + (P[0] - proj[0]) * DAMP,
|
|
127
|
+
proj[1] + (P[1] - proj[1]) * DAMP,
|
|
128
|
+
]);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
mkdirSync(dirname(OUT), {recursive: true});
|
|
132
|
+
writeFileSync(OUT, JSON.stringify(path));
|
|
133
|
+
|
|
134
|
+
let len = 0;
|
|
135
|
+
for (let i = 1; i < path.length; i++) len += havKm(path[i - 1], path[i]);
|
|
136
|
+
console.log(
|
|
137
|
+
`cesium-path: clip ${clip.length} → resample ${even.length} → smooth → ${path.length} pts · ${len.toFixed(1)} km`,
|
|
138
|
+
);
|
|
139
|
+
const bear = (a, b) => {
|
|
140
|
+
const r = Math.PI / 180;
|
|
141
|
+
const y = Math.sin((b[0] - a[0]) * r) * Math.cos(b[1] * r);
|
|
142
|
+
const x =
|
|
143
|
+
Math.cos(a[1] * r) * Math.sin(b[1] * r) -
|
|
144
|
+
Math.sin(a[1] * r) * Math.cos(b[1] * r) * Math.cos((b[0] - a[0]) * r);
|
|
145
|
+
return (Math.atan2(y, x) * 180) / Math.PI;
|
|
146
|
+
};
|
|
147
|
+
// heading sampled every ~1.5 km — should change gradually & continuously (no big jumps = no corners)
|
|
148
|
+
const stepPts = Math.round(1.5 / STEP_KM);
|
|
149
|
+
let prev = null,
|
|
150
|
+
hs = [];
|
|
151
|
+
for (let i = 0; i + stepPts < path.length; i += stepPts) {
|
|
152
|
+
const h = bear(path[i], path[i + stepPts]);
|
|
153
|
+
if (prev !== null) {
|
|
154
|
+
let d = h - prev;
|
|
155
|
+
while (d > 180) d -= 360;
|
|
156
|
+
while (d < -180) d += 360;
|
|
157
|
+
hs.push(d.toFixed(0));
|
|
158
|
+
}
|
|
159
|
+
prev = h;
|
|
160
|
+
}
|
|
161
|
+
console.log(` heading deltas every 1.5km (deg): ${hs.join(', ')}`);
|