dsh-remotion 0.3.4 → 0.4.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.
Files changed (293) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.en.md +26 -65
  3. package/README.md +25 -67
  4. package/docs/USAGE.en.md +93 -0
  5. package/docs/USAGE.md +97 -0
  6. package/docs/VALIDATION.md +22 -0
  7. package/lib/client.js +90 -0
  8. package/lib/index.d.ts +3 -0
  9. package/lib/index.js +5 -1
  10. package/lib/media-store.d.ts +25 -0
  11. package/lib/media-store.js +174 -0
  12. package/lib/media-templates.d.ts +52 -0
  13. package/lib/media-templates.js +91 -0
  14. package/lib/media-workbench.d.ts +42 -0
  15. package/lib/media-workbench.js +476 -0
  16. package/package.json +18 -5
  17. package/scripts/build-client.mjs +4 -0
  18. package/skills/remotion-best-practices/SKILL.md +54 -54
  19. package/skills/remotion-best-practices/agents/openai.yaml +7 -7
  20. package/skills/remotion-best-practices/assets/remotion-icon.svg +4 -4
  21. package/skills/remotion-best-practices/remotion-captions/REFERENCE.md +36 -36
  22. package/skills/remotion-best-practices/remotion-captions/agents/openai.yaml +7 -7
  23. package/skills/remotion-best-practices/remotion-captions/assets/remotion-icon.svg +4 -4
  24. package/skills/remotion-best-practices/remotion-captions/display-captions.md +190 -190
  25. package/skills/remotion-best-practices/remotion-captions/import-srt-captions.md +73 -73
  26. package/skills/remotion-best-practices/remotion-captions/transcribe-captions.md +70 -70
  27. package/skills/remotion-best-practices/remotion-create/REFERENCE.md +85 -85
  28. package/skills/remotion-best-practices/remotion-create/agents/openai.yaml +7 -7
  29. package/skills/remotion-best-practices/remotion-create/assets/remotion-icon.svg +4 -4
  30. package/skills/remotion-best-practices/remotion-create/tailwind.md +11 -11
  31. package/skills/remotion-best-practices/remotion-create/video-layout.md +9 -9
  32. package/skills/remotion-best-practices/remotion-docs/REFERENCE.md +46 -46
  33. package/skills/remotion-best-practices/remotion-docs/agents/openai.yaml +7 -7
  34. package/skills/remotion-best-practices/remotion-docs/assets/remotion-icon.svg +4 -4
  35. package/skills/remotion-best-practices/remotion-interactivity/REFERENCE.md +315 -315
  36. package/skills/remotion-best-practices/remotion-interactivity/agents/openai.yaml +7 -7
  37. package/skills/remotion-best-practices/remotion-interactivity/assets/remotion-icon.svg +4 -4
  38. package/skills/remotion-best-practices/remotion-maps/REFERENCE.md +36 -36
  39. package/skills/remotion-best-practices/remotion-maps/agents/openai.yaml +7 -7
  40. package/skills/remotion-best-practices/remotion-maps/assets/remotion-icon.svg +4 -4
  41. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -89
  42. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -284
  43. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -299
  44. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/city-path.json +12 -12
  45. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -39
  46. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -35
  47. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -215
  48. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -43
  49. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -128
  50. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -57
  51. package/skills/remotion-best-practices/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -161
  52. package/skills/remotion-best-practices/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -449
  53. package/skills/remotion-best-practices/remotion-maps/techniques/mapbox/references/render-stability.md +64 -64
  54. package/skills/remotion-best-practices/remotion-maps/techniques/maplibre/TECHNIQUE.md +484 -484
  55. package/skills/remotion-best-practices/remotion-maps/techniques/maplibre/references/render-stability.md +64 -64
  56. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -80
  57. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -70
  58. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -80
  59. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -363
  60. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -22
  61. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -7535
  62. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -605
  63. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -34
  64. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -91
  65. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -129
  66. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -85
  67. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/references/render-stability.md +64 -64
  68. package/skills/remotion-best-practices/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -202
  69. package/skills/remotion-best-practices/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -37
  70. package/skills/remotion-best-practices/remotion-markup/3d.md +86 -86
  71. package/skills/remotion-best-practices/remotion-markup/REFERENCE.md +358 -358
  72. package/skills/remotion-best-practices/remotion-markup/agents/openai.yaml +7 -7
  73. package/skills/remotion-best-practices/remotion-markup/assets/remotion-icon.svg +4 -4
  74. package/skills/remotion-best-practices/remotion-markup/audio-visualization.md +198 -198
  75. package/skills/remotion-best-practices/remotion-markup/audio.md +169 -169
  76. package/skills/remotion-best-practices/remotion-markup/calculate-metadata.md +136 -136
  77. package/skills/remotion-best-practices/remotion-markup/compositions.md +123 -123
  78. package/skills/remotion-best-practices/remotion-markup/connected-compositions.md +79 -79
  79. package/skills/remotion-best-practices/remotion-markup/cropping.md +34 -34
  80. package/skills/remotion-best-practices/remotion-markup/effects.md +251 -251
  81. package/skills/remotion-best-practices/remotion-markup/embedding-videos.md +171 -171
  82. package/skills/remotion-best-practices/remotion-markup/ffmpeg.md +38 -38
  83. package/skills/remotion-best-practices/remotion-markup/gifs.md +187 -187
  84. package/skills/remotion-best-practices/remotion-markup/google-fonts.md +76 -76
  85. package/skills/remotion-best-practices/remotion-markup/html-in-canvas.md +128 -128
  86. package/skills/remotion-best-practices/remotion-markup/images.md +73 -73
  87. package/skills/remotion-best-practices/remotion-markup/light-leaks.md +106 -106
  88. package/skills/remotion-best-practices/remotion-markup/local-fonts.md +69 -69
  89. package/skills/remotion-best-practices/remotion-markup/lottie.md +73 -73
  90. package/skills/remotion-best-practices/remotion-markup/measuring-dom-nodes.md +38 -38
  91. package/skills/remotion-best-practices/remotion-markup/measuring-text.md +146 -146
  92. package/skills/remotion-best-practices/remotion-markup/motion-blur.md +60 -60
  93. package/skills/remotion-best-practices/remotion-markup/multi-scene-video.md +81 -81
  94. package/skills/remotion-best-practices/remotion-markup/parameters.md +111 -111
  95. package/skills/remotion-best-practices/remotion-markup/remotion-maps/REFERENCE.md +36 -36
  96. package/skills/remotion-best-practices/remotion-markup/remotion-maps/agents/openai.yaml +7 -7
  97. package/skills/remotion-best-practices/remotion-markup/remotion-maps/assets/remotion-icon.svg +4 -4
  98. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -89
  99. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -284
  100. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -299
  101. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/city-path.json +12 -12
  102. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -39
  103. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -35
  104. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -215
  105. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -43
  106. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -128
  107. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -57
  108. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -161
  109. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -449
  110. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/mapbox/references/render-stability.md +64 -64
  111. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maplibre/TECHNIQUE.md +484 -484
  112. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maplibre/references/render-stability.md +64 -64
  113. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -80
  114. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -70
  115. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -80
  116. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -363
  117. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -22
  118. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -7535
  119. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -605
  120. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -34
  121. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -91
  122. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -129
  123. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -85
  124. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/references/render-stability.md +64 -64
  125. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -202
  126. package/skills/remotion-best-practices/remotion-markup/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -37
  127. package/skills/remotion-best-practices/remotion-markup/sequencing.md +169 -169
  128. package/skills/remotion-best-practices/remotion-markup/sfx.md +51 -51
  129. package/skills/remotion-best-practices/remotion-markup/silence-detection.md +71 -71
  130. package/skills/remotion-best-practices/remotion-markup/text-highlights.md +56 -56
  131. package/skills/remotion-best-practices/remotion-markup/timing.md +111 -111
  132. package/skills/remotion-best-practices/remotion-markup/transitions.md +239 -239
  133. package/skills/remotion-best-practices/remotion-markup/video-editing.md +90 -90
  134. package/skills/remotion-best-practices/remotion-markup/voiceover.md +99 -99
  135. package/skills/remotion-best-practices/remotion-multimedia/REFERENCE.md +20 -20
  136. package/skills/remotion-best-practices/remotion-multimedia/agents/openai.yaml +7 -7
  137. package/skills/remotion-best-practices/remotion-multimedia/assets/remotion-icon.svg +4 -4
  138. package/skills/remotion-best-practices/remotion-multimedia/get-audio-duration.md +56 -56
  139. package/skills/remotion-best-practices/remotion-multimedia/get-video-dimensions.md +66 -66
  140. package/skills/remotion-best-practices/remotion-multimedia/get-video-duration.md +58 -58
  141. package/skills/remotion-best-practices/remotion-render/REFERENCE.md +35 -35
  142. package/skills/remotion-best-practices/remotion-render/agents/openai.yaml +7 -7
  143. package/skills/remotion-best-practices/remotion-render/assets/remotion-icon.svg +4 -4
  144. package/skills/remotion-best-practices/remotion-render/transparent-videos.md +106 -106
  145. package/skills/remotion-best-practices/remotion-saas/REFERENCE.md +33 -33
  146. package/skills/remotion-best-practices/remotion-saas/agents/openai.yaml +7 -7
  147. package/skills/remotion-best-practices/remotion-saas/assets/remotion-icon.svg +4 -4
  148. package/skills/remotion-best-practices/remotion-saas/framework.md +19 -19
  149. package/skills/remotion-best-practices/remotion-saas/player.md +33 -33
  150. package/skills/remotion-best-practices/remotion-saas/rendering.md +69 -69
  151. package/skills/remotion-best-practices/remotion-studio/REFERENCE.md +24 -24
  152. package/skills/remotion-best-practices/remotion-studio/agents/openai.yaml +7 -7
  153. package/skills/remotion-best-practices/remotion-studio/assets/remotion-icon.svg +4 -4
  154. package/skills/remotion-best-practices/remotion-upgrade/REFERENCE.md +31 -31
  155. package/skills/remotion-best-practices/remotion-upgrade/agents/openai.yaml +7 -7
  156. package/skills/remotion-best-practices/remotion-upgrade/assets/remotion-icon.svg +4 -4
  157. package/skills/remotion-captions/SKILL.md +31 -31
  158. package/skills/remotion-captions/agents/openai.yaml +7 -7
  159. package/skills/remotion-captions/assets/remotion-icon.svg +4 -4
  160. package/skills/remotion-captions/display-captions.md +190 -190
  161. package/skills/remotion-captions/import-srt-captions.md +73 -73
  162. package/skills/remotion-captions/transcribe-captions.md +70 -70
  163. package/skills/remotion-create/SKILL.md +80 -80
  164. package/skills/remotion-create/agents/openai.yaml +7 -7
  165. package/skills/remotion-create/assets/remotion-icon.svg +4 -4
  166. package/skills/remotion-create/tailwind.md +11 -11
  167. package/skills/remotion-create/video-layout.md +9 -9
  168. package/skills/remotion-docs/SKILL.md +41 -41
  169. package/skills/remotion-docs/agents/openai.yaml +7 -7
  170. package/skills/remotion-docs/assets/remotion-icon.svg +4 -4
  171. package/skills/remotion-interactivity/SKILL.md +310 -310
  172. package/skills/remotion-interactivity/agents/openai.yaml +7 -7
  173. package/skills/remotion-interactivity/assets/remotion-icon.svg +4 -4
  174. package/skills/remotion-maps/SKILL.md +31 -31
  175. package/skills/remotion-maps/agents/openai.yaml +7 -7
  176. package/skills/remotion-maps/assets/remotion-icon.svg +4 -4
  177. package/skills/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -89
  178. package/skills/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -284
  179. package/skills/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -299
  180. package/skills/remotion-maps/techniques/cesium/assets/city-path.json +12 -12
  181. package/skills/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -39
  182. package/skills/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -35
  183. package/skills/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -215
  184. package/skills/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -43
  185. package/skills/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -128
  186. package/skills/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -57
  187. package/skills/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -161
  188. package/skills/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -449
  189. package/skills/remotion-maps/techniques/mapbox/references/render-stability.md +64 -64
  190. package/skills/remotion-maps/techniques/maplibre/TECHNIQUE.md +484 -484
  191. package/skills/remotion-maps/techniques/maplibre/references/render-stability.md +64 -64
  192. package/skills/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -80
  193. package/skills/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -70
  194. package/skills/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -80
  195. package/skills/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -363
  196. package/skills/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -22
  197. package/skills/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -7535
  198. package/skills/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -605
  199. package/skills/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -34
  200. package/skills/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -91
  201. package/skills/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -129
  202. package/skills/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -85
  203. package/skills/remotion-maps/techniques/maptiler/references/render-stability.md +64 -64
  204. package/skills/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -202
  205. package/skills/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -37
  206. package/skills/remotion-markup/3d.md +86 -86
  207. package/skills/remotion-markup/SKILL.md +353 -353
  208. package/skills/remotion-markup/agents/openai.yaml +7 -7
  209. package/skills/remotion-markup/assets/remotion-icon.svg +4 -4
  210. package/skills/remotion-markup/audio-visualization.md +198 -198
  211. package/skills/remotion-markup/audio.md +169 -169
  212. package/skills/remotion-markup/calculate-metadata.md +136 -136
  213. package/skills/remotion-markup/compositions.md +123 -123
  214. package/skills/remotion-markup/connected-compositions.md +79 -79
  215. package/skills/remotion-markup/cropping.md +34 -34
  216. package/skills/remotion-markup/effects.md +251 -251
  217. package/skills/remotion-markup/embedding-videos.md +171 -171
  218. package/skills/remotion-markup/ffmpeg.md +38 -38
  219. package/skills/remotion-markup/gifs.md +187 -187
  220. package/skills/remotion-markup/google-fonts.md +76 -76
  221. package/skills/remotion-markup/html-in-canvas.md +128 -128
  222. package/skills/remotion-markup/images.md +73 -73
  223. package/skills/remotion-markup/light-leaks.md +106 -106
  224. package/skills/remotion-markup/local-fonts.md +69 -69
  225. package/skills/remotion-markup/lottie.md +73 -73
  226. package/skills/remotion-markup/measuring-dom-nodes.md +38 -38
  227. package/skills/remotion-markup/measuring-text.md +146 -146
  228. package/skills/remotion-markup/motion-blur.md +60 -60
  229. package/skills/remotion-markup/multi-scene-video.md +81 -81
  230. package/skills/remotion-markup/parameters.md +111 -111
  231. package/skills/remotion-markup/remotion-maps/REFERENCE.md +36 -36
  232. package/skills/remotion-markup/remotion-maps/agents/openai.yaml +7 -7
  233. package/skills/remotion-markup/remotion-maps/assets/remotion-icon.svg +4 -4
  234. package/skills/remotion-markup/remotion-maps/techniques/cesium/TECHNIQUE.md +89 -89
  235. package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/CesiumFlythrough.tsx +284 -284
  236. package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/cesium-path.json +299 -299
  237. package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/city-path.json +12 -12
  238. package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/example-Root.tsx +39 -39
  239. package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/flight-path.ts +35 -35
  240. package/skills/remotion-markup/remotion-maps/techniques/cesium/assets/sample-river.geojson +215 -215
  241. package/skills/remotion-markup/remotion-maps/techniques/cesium/references/3d-data-sources.md +43 -43
  242. package/skills/remotion-markup/remotion-maps/techniques/cesium/references/3d-flyover-architecture.md +128 -128
  243. package/skills/remotion-markup/remotion-maps/techniques/cesium/references/3d-troubleshooting.md +57 -57
  244. package/skills/remotion-markup/remotion-maps/techniques/cesium/scripts/prep-cesium-path.mjs +161 -161
  245. package/skills/remotion-markup/remotion-maps/techniques/mapbox/TECHNIQUE.md +449 -449
  246. package/skills/remotion-markup/remotion-maps/techniques/mapbox/references/render-stability.md +64 -64
  247. package/skills/remotion-markup/remotion-maps/techniques/maplibre/TECHNIQUE.md +484 -484
  248. package/skills/remotion-markup/remotion-maps/techniques/maplibre/references/render-stability.md +64 -64
  249. package/skills/remotion-markup/remotion-maps/techniques/maptiler/TECHNIQUE.md +80 -80
  250. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/CountryLabel.tsx +70 -70
  251. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/MapTilerVectorElement.ts +80 -80
  252. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/RiverReveal.tsx +363 -363
  253. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/example-Root.tsx +22 -22
  254. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/country-meta.json +7535 -7535
  255. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/sample-data/yarlung-flow.json +605 -605
  256. package/skills/remotion-markup/remotion-maps/techniques/maptiler/assets/tokens.ts +34 -34
  257. package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/map-data-sources.md +91 -91
  258. package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/map-explainer-architecture.md +129 -129
  259. package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/map-geo-prep.md +85 -85
  260. package/skills/remotion-markup/remotion-maps/techniques/maptiler/references/render-stability.md +64 -64
  261. package/skills/remotion-markup/remotion-maps/techniques/maptiler/scripts/prep-geo.mjs +202 -202
  262. package/skills/remotion-markup/remotion-maps/techniques/static-map/TECHNIQUE.md +37 -37
  263. package/skills/remotion-markup/sequencing.md +169 -169
  264. package/skills/remotion-markup/sfx.md +51 -51
  265. package/skills/remotion-markup/silence-detection.md +71 -71
  266. package/skills/remotion-markup/text-highlights.md +56 -56
  267. package/skills/remotion-markup/timing.md +111 -111
  268. package/skills/remotion-markup/transitions.md +239 -239
  269. package/skills/remotion-markup/video-editing.md +90 -90
  270. package/skills/remotion-markup/voiceover.md +99 -99
  271. package/skills/remotion-multimedia/SKILL.md +15 -15
  272. package/skills/remotion-multimedia/agents/openai.yaml +7 -7
  273. package/skills/remotion-multimedia/assets/remotion-icon.svg +4 -4
  274. package/skills/remotion-multimedia/get-audio-duration.md +56 -56
  275. package/skills/remotion-multimedia/get-video-dimensions.md +66 -66
  276. package/skills/remotion-multimedia/get-video-duration.md +58 -58
  277. package/skills/remotion-render/SKILL.md +30 -30
  278. package/skills/remotion-render/agents/openai.yaml +7 -7
  279. package/skills/remotion-render/assets/remotion-icon.svg +4 -4
  280. package/skills/remotion-render/transparent-videos.md +106 -106
  281. package/skills/remotion-saas/SKILL.md +28 -28
  282. package/skills/remotion-saas/agents/openai.yaml +7 -7
  283. package/skills/remotion-saas/assets/remotion-icon.svg +4 -4
  284. package/skills/remotion-saas/framework.md +19 -19
  285. package/skills/remotion-saas/player.md +33 -33
  286. package/skills/remotion-saas/rendering.md +69 -69
  287. package/skills/remotion-studio/SKILL.md +19 -19
  288. package/skills/remotion-studio/agents/openai.yaml +7 -7
  289. package/skills/remotion-studio/assets/remotion-icon.svg +4 -4
  290. package/skills/remotion-upgrade/SKILL.md +26 -26
  291. package/skills/remotion-upgrade/agents/openai.yaml +7 -7
  292. package/skills/remotion-upgrade/assets/remotion-icon.svg +4 -4
  293. package/templates/DESIGN.md +26 -0
package/lib/index.js CHANGED
@@ -5,6 +5,10 @@
5
5
  */
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { createSkillBundle } from './skill-bundle.js';
8
+ import { installMediaWorkbench } from './media-workbench.js';
9
+ export { MediaWorkbench } from './media-workbench.js';
10
+ export { MediaStore } from './media-store.js';
11
+ export { MEDIA_TEMPLATES, MEDIA_VERSIONS } from './media-templates.js';
8
12
  export { parseSkillFile } from './skill-bundle.js';
9
13
  export const name = 'remotion-skills';
10
14
  export const inject = ['skills', 'tools'];
@@ -35,4 +39,4 @@ const bundle = createSkillBundle({
35
39
  /** Re-read and validate disk resources; runtime state is checked by the health tool. */
36
40
  export function checkBundledSkills() { return bundle.checkFiles(); }
37
41
  /** Register this package's skills and its read-only health tool. */
38
- export function apply(ctx) { bundle.apply(ctx); }
42
+ export function apply(ctx) { bundle.apply(ctx); installMediaWorkbench(ctx, 'remotion'); }
@@ -0,0 +1,25 @@
1
+ import { type MediaEngine, type MediaProject, type MediaAsset } from './media-templates.js';
2
+ export declare function mediaId(value: unknown): string;
3
+ export declare class MediaConflict extends Error {
4
+ status: number;
5
+ }
6
+ export declare class MediaStore {
7
+ readonly root: string;
8
+ constructor(engine: MediaEngine, root?: string);
9
+ init(): Promise<void>;
10
+ path(id: string): Promise<string>;
11
+ checkPath(path: string): Promise<void>;
12
+ get(id: string): Promise<MediaProject>;
13
+ list(): Promise<MediaProject[]>;
14
+ private write;
15
+ create(value: unknown): Promise<MediaProject>;
16
+ edit(id: string, revision: unknown, fn: (p: MediaProject) => Promise<void> | void, bump?: boolean): Promise<MediaProject>;
17
+ update(id: string, revision: unknown, value: unknown): Promise<MediaProject>;
18
+ assetBytes(id: string, asset: MediaAsset): Promise<Buffer>;
19
+ upload(id: string, revision: unknown, name: string, bytes: Buffer): Promise<MediaProject>;
20
+ removeAsset(id: string, revision: unknown, assetId: string): Promise<MediaProject>;
21
+ snapshot(id: string, revision: unknown): Promise<{
22
+ project: MediaProject;
23
+ assets: Map<string, Buffer>;
24
+ }>;
25
+ }
@@ -0,0 +1,174 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdir, readFile, writeFile, rename, readdir, stat, lstat, unlink, realpath } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join, resolve, relative, isAbsolute, extname } from 'node:path';
5
+ import lockfile from 'proper-lockfile';
6
+ import { validateFields } from './media-templates.js';
7
+ export function mediaId(value) {
8
+ if (typeof value !== 'string' || !/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/.test(value))
9
+ throw new Error('项目或任务编号无效。');
10
+ return value;
11
+ }
12
+ export class MediaConflict extends Error {
13
+ status = 409;
14
+ }
15
+ export class MediaStore {
16
+ root;
17
+ constructor(engine, root) { this.root = resolve(root ?? join(process.env.DSH_HOME || join(homedir(), '.dsh'), 'data', 'dsh-' + engine)); }
18
+ async init() { await mkdir(join(this.root, 'projects'), { recursive: true, mode: 0o700 }); }
19
+ async path(id) {
20
+ await this.init();
21
+ const dir = join(this.root, 'projects', mediaId(id));
22
+ if ((await lstat(dir)).isSymbolicLink())
23
+ throw new Error('项目目录不能是符号链接。');
24
+ await this.checkPath(dir);
25
+ return dir;
26
+ }
27
+ async checkPath(path) {
28
+ const base = await realpath(this.root), actual = await realpath(path), rel = relative(base, actual);
29
+ if (rel === '..' || rel.startsWith('..' + (process.platform === 'win32' ? '\\' : '/')) || isAbsolute(rel))
30
+ throw new Error('文件不在本插件项目目录内。');
31
+ }
32
+ async get(id) {
33
+ const file = join(await this.path(id), 'project.json');
34
+ await this.checkPath(file);
35
+ if ((await stat(file)).size > 65536)
36
+ throw new Error('工程记录过大,请保留文件后检查。');
37
+ const p = JSON.parse(await readFile(file, 'utf8'));
38
+ validateFields(p);
39
+ if (p.id !== id || !Number.isInteger(p.revision) || p.revision < 1 || !Array.isArray(p.assets) || p.assets.length > 12 || !Array.isArray(p.renders))
40
+ throw new Error('工程记录损坏;原文件已保留。');
41
+ for (const a of p.assets) {
42
+ mediaId(a.id);
43
+ if (!new RegExp('^' + a.id + '\\.(png|jpg|mp3|wav|mp4)$').test(a.file))
44
+ throw new Error('素材记录无效。');
45
+ }
46
+ for (const r of p.renders)
47
+ mediaId(r.id);
48
+ return p;
49
+ }
50
+ async list() {
51
+ await this.init();
52
+ const result = [];
53
+ for (const id of await readdir(join(this.root, 'projects'))) {
54
+ if (/^[0-9a-f-]{36}$/.test(id))
55
+ result.push(await this.get(id));
56
+ }
57
+ return result.sort((a, b) => b.updated.localeCompare(a.updated));
58
+ }
59
+ async write(p) {
60
+ const dir = await this.path(p.id), temp = join(dir, randomUUID() + '.tmp');
61
+ try {
62
+ await writeFile(temp, JSON.stringify(p, null, 2), { flag: 'wx', mode: 0o600 });
63
+ await rename(temp, join(dir, 'project.json'));
64
+ }
65
+ finally {
66
+ await unlink(temp).catch(() => { });
67
+ }
68
+ }
69
+ async create(value) {
70
+ await this.init();
71
+ const unlock = await lockfile.lock(join(this.root, 'projects'), { retries: { retries: 8, minTimeout: 30, maxTimeout: 60 } });
72
+ try {
73
+ if ((await this.list()).length >= 30)
74
+ throw new Error('工作台最多保存 30 个项目,请先备份现有工程。');
75
+ const p = { ...validateFields(value), id: randomUUID(), revision: 1, updated: new Date().toISOString(), assets: [], renders: [] };
76
+ await mkdir(join(this.root, 'projects', p.id), { mode: 0o700 });
77
+ await this.write(p);
78
+ return p;
79
+ }
80
+ finally {
81
+ await unlock();
82
+ }
83
+ }
84
+ async edit(id, revision, fn, bump = true) {
85
+ const dir = await this.path(id);
86
+ const unlock = await lockfile.lock(dir, { retries: { retries: 8, minTimeout: 30, maxTimeout: 60 } });
87
+ try {
88
+ const p = await this.get(id);
89
+ if (revision !== undefined && revision !== p.revision)
90
+ throw new MediaConflict('工程已在另一窗口更新。你的输入仍保留,请重新打开最新版本后比较。');
91
+ await fn(p);
92
+ if (bump)
93
+ p.revision++;
94
+ p.updated = new Date().toISOString();
95
+ await this.write(p);
96
+ return p;
97
+ }
98
+ finally {
99
+ await unlock();
100
+ }
101
+ }
102
+ async update(id, revision, value) { return this.edit(id, revision, p => { Object.assign(p, validateFields(value)); }); }
103
+ async assetBytes(id, asset) {
104
+ const file = join(await this.path(id), 'assets', asset.file);
105
+ await this.checkPath(file);
106
+ if ((await stat(file)).size !== asset.bytes || asset.bytes > 20 * 1024 * 1024)
107
+ throw new Error('素材已改变,请重新上传并检查。');
108
+ return readFile(file);
109
+ }
110
+ async upload(id, revision, name, bytes) {
111
+ if (!bytes.length || bytes.length > 20 * 1024 * 1024)
112
+ throw new Error('单个素材需为 1 字节–20 MB。');
113
+ const ext = extname(name).toLowerCase(), isPng = bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]));
114
+ const isJpg = bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255;
115
+ let kind, suffix;
116
+ if (ext === '.png' && isPng) {
117
+ kind = 'image';
118
+ suffix = '.png';
119
+ }
120
+ else if (['.jpg', '.jpeg'].includes(ext) && isJpg) {
121
+ kind = 'image';
122
+ suffix = '.jpg';
123
+ }
124
+ else if (ext === '.wav' && bytes.toString('ascii', 0, 4) === 'RIFF' && bytes.toString('ascii', 8, 12) === 'WAVE') {
125
+ kind = 'audio';
126
+ suffix = '.wav';
127
+ }
128
+ else if (ext === '.mp3' && (bytes.toString('ascii', 0, 3) === 'ID3' || bytes[0] === 255 && (bytes[1] & 224) === 224)) {
129
+ kind = 'audio';
130
+ suffix = '.mp3';
131
+ }
132
+ else if (ext === '.mp4' && bytes.toString('ascii', 4, 8) === 'ftyp') {
133
+ kind = 'video';
134
+ suffix = '.mp4';
135
+ }
136
+ else
137
+ throw new Error('仅支持内容与扩展名一致的 PNG、JPEG、MP3、WAV 或 MP4。');
138
+ return this.edit(id, revision, async (p) => {
139
+ if (p.assets.length >= 12 || p.assets.reduce((n, a) => n + a.bytes, 0) + bytes.length > 40 * 1024 * 1024)
140
+ throw new Error('每个项目最多 12 个素材、合计 40 MB。');
141
+ if (kind !== 'image' && p.assets.some(a => a.kind === kind))
142
+ throw new Error(kind === 'audio' ? '已有背景音频,请先移除再替换。' : '已有背景视频,请先移除再替换。');
143
+ const assetId = randomUUID(), dir = join(await this.path(id), 'assets');
144
+ await mkdir(dir, { recursive: true });
145
+ const asset = { id: assetId, name: name.replace(/[\x00-\x1f/\\]/g, '_').slice(0, 100), file: assetId + suffix, kind, bytes: bytes.length };
146
+ await writeFile(join(dir, asset.file), bytes, { flag: 'wx', mode: 0o600 });
147
+ p.assets.push(asset);
148
+ });
149
+ }
150
+ async removeAsset(id, revision, assetId) {
151
+ let file;
152
+ const p = await this.edit(id, revision, async (p) => { const a = p.assets.find(a => a.id === mediaId(assetId)); if (!a)
153
+ throw new Error('素材不存在。'); file = join(await this.path(id), 'assets', a.file); p.assets = p.assets.filter(a => a.id !== assetId); });
154
+ // Unlink only this managed upload, never a source file or a resolved link target.
155
+ if (file)
156
+ await unlink(file).catch(() => { });
157
+ return p;
158
+ }
159
+ async snapshot(id, revision) {
160
+ const dir = await this.path(id), unlock = await lockfile.lock(dir, { retries: { retries: 8, minTimeout: 30, maxTimeout: 60 } });
161
+ try {
162
+ const project = await this.get(id);
163
+ if (project.revision !== revision)
164
+ throw new MediaConflict('项目已更新,请保存并重新预览。');
165
+ const assets = new Map();
166
+ for (const a of project.assets)
167
+ assets.set(a.file, await this.assetBytes(id, a));
168
+ return { project, assets };
169
+ }
170
+ finally {
171
+ await unlock();
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,52 @@
1
+ /** Original managed templates. Visual identity: templates/DESIGN.md. */
2
+ export type MediaEngine = 'hyperframes' | 'remotion';
3
+ export interface MediaAsset {
4
+ id: string;
5
+ name: string;
6
+ file: string;
7
+ kind: 'image' | 'audio' | 'video';
8
+ bytes: number;
9
+ }
10
+ export interface MediaFields {
11
+ template: string;
12
+ title: string;
13
+ body: string;
14
+ format: string;
15
+ duration: number;
16
+ }
17
+ export interface MediaProject extends MediaFields {
18
+ id: string;
19
+ revision: number;
20
+ updated: string;
21
+ assets: MediaAsset[];
22
+ renders: Array<{
23
+ id: string;
24
+ revision: number;
25
+ bytes: number;
26
+ created: string;
27
+ }>;
28
+ }
29
+ export declare const MEDIA_VERSIONS: {
30
+ readonly hyperframes: "0.8.114";
31
+ readonly remotion: "4.0.532";
32
+ readonly gsap: "3.14.2";
33
+ };
34
+ export declare const MEDIA_TEMPLATES: readonly [{
35
+ readonly id: "title";
36
+ readonly zh: "标题卡";
37
+ readonly en: "Title card";
38
+ readonly description: "一句标题、一段介绍,适合开场与通知。";
39
+ }, {
40
+ readonly id: "product";
41
+ readonly zh: "产品介绍";
42
+ readonly en: "Product card";
43
+ readonly description: "深色画布与一张主图,适合产品亮点。";
44
+ }, {
45
+ readonly id: "slideshow";
46
+ readonly zh: "图文轮播";
47
+ readonly en: "Slideshow";
48
+ readonly description: "上传的图片依次展示,正文每行对应一页。";
49
+ }];
50
+ export declare const MEDIA_FORMATS: Record<string, [number, number]>;
51
+ export declare function validateFields(value: unknown): MediaFields;
52
+ export declare function projectSources(p: MediaProject, engine: MediaEngine): Record<string, string>;
@@ -0,0 +1,91 @@
1
+ export const MEDIA_VERSIONS = { hyperframes: '0.8.114', remotion: '4.0.532', gsap: '3.14.2' };
2
+ export const MEDIA_TEMPLATES = [
3
+ { id: 'title', zh: '标题卡', en: 'Title card', description: '一句标题、一段介绍,适合开场与通知。' },
4
+ { id: 'product', zh: '产品介绍', en: 'Product card', description: '深色画布与一张主图,适合产品亮点。' },
5
+ { id: 'slideshow', zh: '图文轮播', en: 'Slideshow', description: '上传的图片依次展示,正文每行对应一页。' },
6
+ ];
7
+ export const MEDIA_FORMATS = { landscape: [1280, 720], portrait: [720, 1280], square: [720, 720] };
8
+ export function validateFields(value) {
9
+ if (!value || typeof value !== 'object' || Array.isArray(value))
10
+ throw new Error('请填写项目内容。');
11
+ const v = value;
12
+ if (!MEDIA_TEMPLATES.some(row => row.id === v.template))
13
+ throw new Error('请选择支持的模板。');
14
+ if (typeof v.title !== 'string' || !v.title.trim() || v.title.length > 72)
15
+ throw new Error('标题需为 1–72 个字符。');
16
+ if (typeof v.body !== 'string' || v.body.length > 360)
17
+ throw new Error('正文最多 360 个字符。');
18
+ if (typeof v.format !== 'string' || !Object.hasOwn(MEDIA_FORMATS, v.format))
19
+ throw new Error('请选择支持的画幅。');
20
+ if (typeof v.duration !== 'number' || !Number.isInteger(v.duration) || v.duration < 3 || v.duration > 30)
21
+ throw new Error('时长需为 3–30 整秒。');
22
+ return { template: v.template, title: v.title.trim(), body: v.body.trim(), format: v.format, duration: v.duration };
23
+ }
24
+ const escapeHtml = (text) => text.replace(/[&<>"']/g, char => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[char]));
25
+ export function projectSources(p, engine) {
26
+ const [width, height] = MEDIA_FORMATS[p.format];
27
+ const images = p.assets.filter(a => a.kind === 'image'), audio = p.assets.find(a => a.kind === 'audio'), video = p.assets.find(a => a.kind === 'video');
28
+ const count = p.template === 'slideshow' ? Math.max(images.length, 1) : 1;
29
+ if (p.duration < count * 2)
30
+ throw new Error(`轮播 ${count} 张图片至少需要 ${count * 2} 秒,请增加时长。`);
31
+ const dark = p.template === 'product', portrait = width <= height;
32
+ const copyWidth = (width - (portrait ? 96 : 128)) * (!portrait && images.length ? .51 : 1);
33
+ const copyHeight = (height - (portrait ? 120 : 112)) * (portrait && images.length ? .55 : 1) - 36;
34
+ // Conservatively fit full-width CJK characters and explicit newlines in the safe area.
35
+ const linesAt = (text, size) => text.split('\n').reduce((n, line) => n + Math.max(1, Math.ceil([...line].length / Math.max(1, Math.floor(copyWidth / size)))), 0);
36
+ let titleSize = Math.round((portrait ? 52 : 68) * (p.title.length > 40 ? .72 : p.title.length > 24 ? .85 : 1));
37
+ let bodySize = p.body.length > 200 ? 21 : 27;
38
+ const bodies = count > 1 ? p.body.split('\n').slice(0, count) : [p.body];
39
+ const fits = () => 42 + linesAt(p.title, titleSize) * titleSize * 1.15 + 22 + Math.max(...bodies.map(body => linesAt(body, bodySize) * bodySize * 1.6)) <= copyHeight;
40
+ while (!fits() && (bodySize > 16 || titleSize > 28)) {
41
+ if (bodySize > 16)
42
+ bodySize--;
43
+ else
44
+ titleSize--;
45
+ }
46
+ if (!fits())
47
+ throw new Error('文字超过此画幅的可读空间。请缩短正文或分成轮播页后再导出。');
48
+ if (count > 1 && p.body.split('\n').length > count)
49
+ throw new Error('正文行数多于轮播图片数,请增加图片或合并文字。');
50
+ const css = `@font-face{font-family:"Microsoft YaHei";src:local("Microsoft YaHei")}*{box-sizing:border-box}body{margin:0;font-family:system-ui,"Microsoft YaHei",sans-serif} #root{position:relative;width:${width}px;height:${height}px;overflow:hidden;background:${dark ? '#142D39' : '#FFF8ED'};color:${dark ? '#FFF8ED' : '#142D39'}} .scene{position:absolute;inset:0;padding:${portrait ? '60px 48px' : '56px 64px'};display:flex;${portrait ? 'flex-direction:column;' : ''}align-items:center;justify-content:center;gap:36px} .copy{flex:1;min-width:0;width:100%} .eyebrow{color:#F26445;font-size:18px;letter-spacing:4px;font-weight:700;margin-bottom:18px} h1{font-size:${titleSize}px;line-height:1.15;margin:0;overflow-wrap:anywhere} p{font-size:${bodySize}px;line-height:1.6;margin:22px 0 0;white-space:pre-line;overflow-wrap:anywhere} .visual{${portrait ? 'height:40%;width:100%;' : 'width:45%;height:80%;'}flex-shrink:0;object-fit:contain;border-radius:18px} .accent{position:absolute;left:0;top:0;width:14px;height:100%;background:#F26445} .page{position:absolute;right:40px;bottom:22px;font-size:18px;opacity:.65}`;
51
+ const design = `# Design\nOriginal DSH managed templates.\n\nPaper #FFF8ED; ink #142D39; coral #F26445; mint #79CDB4. Local system-ui / Microsoft YaHei. Safe margins, wrapped text, deterministic entrances. No remote fonts, random or infinite animation.\n`;
52
+ const info = { ...p, width, height, fps: 24, titleSize, bodySize, dark, portrait };
53
+ const sources = {
54
+ 'project.json': JSON.stringify(p, null, 2), 'DESIGN.md': design,
55
+ 'README.md': `# ${p.title.replace(/[\r\n]/g, ' ')}\n\nManaged ${engine} project, revision ${p.revision}.\n\nRun npm install, then npm run preview or npm run render. Media files are local copies in public/assets. Generated template code is MIT. Renderer dependencies keep their own licenses; Remotion: https://www.remotion.dev/license .\n`,
56
+ };
57
+ if (engine === 'hyperframes') {
58
+ sources['meta.json'] = JSON.stringify({ id: p.id, name: p.title, createdAt: p.updated }, null, 2);
59
+ sources['hyperframes.json'] = JSON.stringify({ $schema: 'https://hyperframes.heygen.com/schema/hyperframes.json', paths: { blocks: 'compositions', components: 'compositions/components', assets: 'public/assets' }, media: { autoProxy: true } }, null, 2);
60
+ let clips = '';
61
+ for (let i = 0; i < count; i++) {
62
+ const start = i * p.duration / count, duration = p.duration / count;
63
+ const body = count > 1 ? (p.body.split('\n')[i] ?? '') : p.body;
64
+ const scene = 'scene-' + i;
65
+ clips += `<div id="${scene}" class="clip" data-composition-id="${scene}" data-composition-src="compositions/${scene}.html" data-start="${start}" data-duration="${duration}" data-track-index="1" style="position:absolute;inset:0;width:100%;height:100%"></div>`;
66
+ sources['compositions/' + scene + '.html'] = `<!doctype html><html lang="zh"><head><meta charset="utf-8"><style>${css}#root{background:transparent}</style></head><body><div id="root" data-composition-id="${scene}" data-start="0" data-duration="${duration}" data-width="${width}" data-height="${height}"><div class="scene"><div class="copy"><div class="eyebrow">${escapeHtml(p.template.toUpperCase())}</div><h1 id="title-${i}">${escapeHtml(p.title)}</h1><p id="body-${i}">${escapeHtml(body)}</p></div>${images.length ? `<img class="visual" src="public/assets/${images[i % images.length].file}" alt="">` : ''}<div class="page">${i + 1} / ${count}</div></div><div class="accent" data-layout-ignore></div></div><script src="vendor/gsap.min.js"></script><script>window.__timelines=window.__timelines||{};const tl=gsap.timeline({paused:true});tl.to({},{duration:${duration}},0);tl.from('#title-${i}',{y:24,opacity:0,duration:.45},.08);tl.from('#body-${i}',{y:16,opacity:0,duration:.4},.2);window.__timelines['${scene}']=tl;</script></body></html>`;
67
+ }
68
+ const media = `${video ? `<video id="bg-video" class="clip" style="position:absolute;inset:0;width:100%;height:100%;opacity:.22;object-fit:cover" src="public/assets/${video.file}" muted playsinline data-start="0" data-duration="${p.duration}" data-track-index="0"></video>` : ''}${audio ? `<audio id="music" class="clip" src="public/assets/${audio.file}" data-start="0" data-duration="${p.duration}" data-track-index="2" data-volume="0.4"></audio>` : ''}`;
69
+ sources['index.html'] = `<!doctype html><html lang="zh"><head><meta charset="utf-8"><style>${css}</style></head><body><div id="root" data-composition-id="managed-video" data-start="0" data-duration="${p.duration}" data-width="${width}" data-height="${height}" data-fps="24">${media}${clips}</div><script src="vendor/gsap.min.js"></script><script>window.__timelines=window.__timelines||{};const tl=gsap.timeline({paused:true});tl.to({},{duration:${p.duration}},0);window.__timelines['managed-video']=tl;</script></body></html>`;
70
+ sources['setup.mjs'] = `import{mkdirSync,copyFileSync}from'node:fs';mkdirSync('vendor',{recursive:true});copyFileSync('node_modules/gsap/dist/gsap.min.js','vendor/gsap.min.js');\n`;
71
+ sources['package.json'] = JSON.stringify({ private: true, type: 'module', dependencies: { hyperframes: MEDIA_VERSIONS.hyperframes, gsap: MEDIA_VERSIONS.gsap }, scripts: { prepare: 'node setup.mjs', preview: 'hyperframes preview --no-open --foreground', render: 'hyperframes browser ensure && hyperframes render --workers 1 --no-best-effort --strict --output final.mp4 --fps 24' } }, null, 2);
72
+ }
73
+ else {
74
+ sources['data.json'] = JSON.stringify(info);
75
+ sources['src/index.jsx'] = `import React from 'react';
76
+ import {registerRoot,Composition,AbsoluteFill,Img,Audio,OffthreadVideo,staticFile,useCurrentFrame,interpolate} from 'remotion';
77
+ import data from '../data.json';
78
+ function Video(){const frame=useCurrentFrame();const photos=data.assets.filter(a=>a.kind==='image'),music=data.assets.find(a=>a.kind==='audio'),video=data.assets.find(a=>a.kind==='video');const count=data.template==='slideshow'?Math.max(photos.length,1):1;const length=data.duration*24/count;const page=Math.min(count-1,Math.floor(frame/length));const local=frame-page*length;const opacity=interpolate(local,[0,12,length-10,length],[0,1,1,0],{extrapolateLeft:'clamp',extrapolateRight:'clamp'});const body=count>1?(data.body.split('\\n')[page]||''):data.body;
79
+ return <AbsoluteFill style={{background:data.dark?'#142D39':'#FFF8ED',color:data.dark?'#FFF8ED':'#142D39',fontFamily:'system-ui,Microsoft YaHei,sans-serif'}}>
80
+ {video&&<OffthreadVideo muted src={staticFile('assets/'+video.file)} style={{position:'absolute',width:'100%',height:'100%',objectFit:'cover',opacity:.22}}/>}
81
+ <div style={{position:'absolute',inset:0,padding:data.portrait?'60px 48px':'56px 64px',display:'flex',flexDirection:data.portrait?'column':'row',alignItems:'center',justifyContent:'center',gap:36,opacity}}>
82
+ <div style={{flex:1,minWidth:0,width:'100%'}}><div style={{color:'#F26445',fontSize:18,letterSpacing:4,fontWeight:700,marginBottom:18}}>{data.template.toUpperCase()}</div><h1 style={{fontSize:data.titleSize,lineHeight:1.15,margin:0,overflowWrap:'anywhere'}}>{data.title}</h1><p style={{fontSize:data.bodySize,lineHeight:1.6,marginTop:22,whiteSpace:'pre-line',overflowWrap:'anywhere'}}>{body}</p></div>
83
+ {photos.length>0&&<Img src={staticFile('assets/'+photos[page%photos.length].file)} style={{width:data.portrait?'100%':'45%',height:data.portrait?'40%':'80%',flexShrink:0,objectFit:'contain',borderRadius:18}}/>}</div>
84
+ <div style={{position:'absolute',left:0,top:0,width:14,height:'100%',background:'#F26445'}}/><div style={{position:'absolute',right:40,bottom:22,fontSize:18,opacity:.65}}>{page+1} / {count}</div>{music&&<Audio src={staticFile('assets/'+music.file)} volume={.4}/>}</AbsoluteFill>}
85
+ const Root=()=> <Composition id="ManagedVideo" component={Video} durationInFrames={data.duration*24} fps={24} width={data.width} height={data.height}/>;
86
+ registerRoot(Root);
87
+ `;
88
+ sources['package.json'] = JSON.stringify({ private: true, dependencies: { '@remotion/cli': MEDIA_VERSIONS.remotion, remotion: MEDIA_VERSIONS.remotion, react: '18.3.1', 'react-dom': '18.3.1' }, scripts: { preview: 'remotion studio src/index.jsx --no-open', render: 'remotion render src/index.jsx ManagedVideo final.mp4 --concurrency 1 --codec h264' } }, null, 2);
89
+ }
90
+ return sources;
91
+ }
@@ -0,0 +1,42 @@
1
+ import { MediaStore } from './media-store.js';
2
+ import { type MediaEngine } from './media-templates.js';
3
+ interface MediaJob {
4
+ id: string;
5
+ kind: 'prepare' | 'preview' | 'render';
6
+ projectId?: string;
7
+ revision?: number;
8
+ state: 'running' | 'done' | 'failed' | 'cancelled';
9
+ stage: string;
10
+ lines: string[];
11
+ url?: string;
12
+ output?: string;
13
+ }
14
+ export declare class MediaWorkbench {
15
+ readonly engine: MediaEngine;
16
+ readonly store: MediaStore;
17
+ readonly route: string;
18
+ readonly runtime: string;
19
+ private jobs;
20
+ private disposed;
21
+ constructor(engine: MediaEngine, root?: string);
22
+ private browserFile;
23
+ environment(): Promise<{
24
+ ready: boolean;
25
+ version: string;
26
+ node: string;
27
+ hint: string;
28
+ }>;
29
+ job(id: string): MediaJob;
30
+ private log;
31
+ private stopChild;
32
+ private run;
33
+ private cli;
34
+ start(kind: MediaJob['kind'], id?: string, revision?: unknown): Promise<MediaJob>;
35
+ private execute;
36
+ cancel(id: string): MediaJob;
37
+ dispose(): void;
38
+ private guard;
39
+ fetch(request: Request): Promise<Response>;
40
+ }
41
+ export declare function installMediaWorkbench(ctx: any, engine: MediaEngine): MediaWorkbench;
42
+ export {};