@scenar/cli 0.10.0 → 0.11.1

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 (164) hide show
  1. package/example-bundle/assets/index-DxmqjG-8.js +388 -0
  2. package/example-bundle/assets/style-B2sxnVVZ.css +1 -0
  3. package/example-bundle/embed.js +1 -1
  4. package/example-bundle/index.html +2 -2
  5. package/example-bundle/logo.png +0 -0
  6. package/example-bundle/pack-manifest.json +33 -9
  7. package/example-bundle/soundtrack/music.mp3 +0 -0
  8. package/example-bundle/soundtrack/sfx/click.mp3 +0 -0
  9. package/example-bundle/soundtrack/sfx/keystroke.mp3 +0 -0
  10. package/package.json +4 -4
  11. package/src/__tests__/collect-pack-shots.test.ts +8 -0
  12. package/src/__tests__/elevenlabs-provider.test.ts +187 -0
  13. package/src/__tests__/embed-snippet.test.ts +5 -0
  14. package/src/__tests__/find-authored-soundtrack.test.ts +54 -0
  15. package/src/__tests__/find-authored-title-cards.test.ts +65 -0
  16. package/src/__tests__/load-bundle.test.ts +67 -0
  17. package/src/__tests__/narrate-command.test.ts +65 -1
  18. package/src/__tests__/narration-cache.test.ts +134 -0
  19. package/src/__tests__/pack-bundle-contract.test.ts +2 -0
  20. package/src/__tests__/pack-generate-embed-entry.test.ts +95 -16
  21. package/src/__tests__/presenter-command.test.ts +366 -0
  22. package/src/__tests__/render-command.test.ts +11 -0
  23. package/src/__tests__/render-generate-entry.test.ts +127 -0
  24. package/src/__tests__/resolve-provider.test.ts +32 -3
  25. package/src/__tests__/scenario-validator.test.ts +174 -0
  26. package/src/__tests__/stage-assets.test.ts +269 -0
  27. package/src/commands/narrate.js +1 -1
  28. package/src/commands/narrate.js.map +1 -1
  29. package/src/commands/narrate.ts +1 -1
  30. package/src/commands/presenter.d.ts +3 -0
  31. package/src/commands/presenter.d.ts.map +1 -0
  32. package/src/commands/presenter.js +89 -0
  33. package/src/commands/presenter.js.map +1 -0
  34. package/src/commands/presenter.ts +107 -0
  35. package/src/commands/render.d.ts.map +1 -1
  36. package/src/commands/render.js +2 -0
  37. package/src/commands/render.js.map +1 -1
  38. package/src/commands/render.ts +6 -0
  39. package/src/embed/embed-snippet.d.ts +5 -0
  40. package/src/embed/embed-snippet.d.ts.map +1 -1
  41. package/src/embed/embed-snippet.js +6 -1
  42. package/src/embed/embed-snippet.js.map +1 -1
  43. package/src/embed/embed-snippet.ts +6 -1
  44. package/src/index.d.ts.map +1 -1
  45. package/src/index.js +2 -0
  46. package/src/index.js.map +1 -1
  47. package/src/index.ts +2 -0
  48. package/src/narrate/run-narrate.d.ts +15 -1
  49. package/src/narrate/run-narrate.d.ts.map +1 -1
  50. package/src/narrate/run-narrate.js +11 -4
  51. package/src/narrate/run-narrate.js.map +1 -1
  52. package/src/narrate/run-narrate.ts +15 -6
  53. package/src/pack/bundle-contract.d.ts +1 -0
  54. package/src/pack/bundle-contract.d.ts.map +1 -1
  55. package/src/pack/bundle-contract.js +3 -0
  56. package/src/pack/bundle-contract.js.map +1 -1
  57. package/src/pack/bundle-contract.ts +3 -0
  58. package/src/pack/collect-pack-shots.d.ts +5 -1
  59. package/src/pack/collect-pack-shots.d.ts.map +1 -1
  60. package/src/pack/collect-pack-shots.js +3 -1
  61. package/src/pack/collect-pack-shots.js.map +1 -1
  62. package/src/pack/collect-pack-shots.ts +15 -1
  63. package/src/pack/generate-embed-entry.d.ts +7 -0
  64. package/src/pack/generate-embed-entry.d.ts.map +1 -1
  65. package/src/pack/generate-embed-entry.js +102 -7
  66. package/src/pack/generate-embed-entry.js.map +1 -1
  67. package/src/pack/generate-embed-entry.ts +107 -7
  68. package/src/pack/run-pack.d.ts +1 -0
  69. package/src/pack/run-pack.d.ts.map +1 -1
  70. package/src/pack/run-pack.js +100 -9
  71. package/src/pack/run-pack.js.map +1 -1
  72. package/src/pack/run-pack.ts +133 -9
  73. package/src/presenter/heygen-client.d.ts +69 -0
  74. package/src/presenter/heygen-client.d.ts.map +1 -0
  75. package/src/presenter/heygen-client.js +154 -0
  76. package/src/presenter/heygen-client.js.map +1 -0
  77. package/src/presenter/heygen-client.ts +224 -0
  78. package/src/presenter/run-presenter.d.ts +67 -0
  79. package/src/presenter/run-presenter.d.ts.map +1 -0
  80. package/src/presenter/run-presenter.js +348 -0
  81. package/src/presenter/run-presenter.js.map +1 -0
  82. package/src/presenter/run-presenter.ts +536 -0
  83. package/src/render/generate-entry.d.ts +4 -0
  84. package/src/render/generate-entry.d.ts.map +1 -1
  85. package/src/render/generate-entry.js +87 -9
  86. package/src/render/generate-entry.js.map +1 -1
  87. package/src/render/generate-entry.ts +96 -9
  88. package/src/render/run-render.d.ts +6 -0
  89. package/src/render/run-render.d.ts.map +1 -1
  90. package/src/render/run-render.js +58 -0
  91. package/src/render/run-render.js.map +1 -1
  92. package/src/render/run-render.ts +72 -0
  93. package/src/render/stage-assets.d.ts +44 -0
  94. package/src/render/stage-assets.d.ts.map +1 -0
  95. package/src/render/stage-assets.js +91 -0
  96. package/src/render/stage-assets.js.map +1 -0
  97. package/src/render/stage-assets.ts +130 -0
  98. package/src/tts/echogarden.d.ts.map +1 -1
  99. package/src/tts/echogarden.js +4 -2
  100. package/src/tts/echogarden.js.map +1 -1
  101. package/src/tts/echogarden.ts +5 -2
  102. package/src/tts/edge-tts.d.ts.map +1 -1
  103. package/src/tts/edge-tts.js +2 -1
  104. package/src/tts/edge-tts.js.map +1 -1
  105. package/src/tts/edge-tts.ts +2 -1
  106. package/src/tts/elevenlabs.d.ts +15 -0
  107. package/src/tts/elevenlabs.d.ts.map +1 -0
  108. package/src/tts/elevenlabs.js +73 -0
  109. package/src/tts/elevenlabs.js.map +1 -0
  110. package/src/tts/elevenlabs.ts +105 -0
  111. package/src/tts/openai.d.ts.map +1 -1
  112. package/src/tts/openai.js +2 -1
  113. package/src/tts/openai.js.map +1 -1
  114. package/src/tts/openai.ts +2 -1
  115. package/src/tts/resolve-provider.d.ts +1 -1
  116. package/src/tts/resolve-provider.d.ts.map +1 -1
  117. package/src/tts/resolve-provider.js +10 -3
  118. package/src/tts/resolve-provider.js.map +1 -1
  119. package/src/tts/resolve-provider.ts +12 -4
  120. package/src/tts/types.d.ts +9 -0
  121. package/src/tts/types.d.ts.map +1 -1
  122. package/src/tts/types.ts +10 -0
  123. package/src/util/confirm.d.ts +11 -0
  124. package/src/util/confirm.d.ts.map +1 -0
  125. package/src/util/confirm.js +24 -0
  126. package/src/util/confirm.js.map +1 -0
  127. package/src/util/confirm.ts +23 -0
  128. package/src/util/load-bundle.d.ts +17 -1
  129. package/src/util/load-bundle.d.ts.map +1 -1
  130. package/src/util/load-bundle.js +19 -11
  131. package/src/util/load-bundle.js.map +1 -1
  132. package/src/util/load-bundle.ts +38 -12
  133. package/src/util/load-ts.d.ts +77 -0
  134. package/src/util/load-ts.d.ts.map +1 -1
  135. package/src/util/load-ts.js +125 -0
  136. package/src/util/load-ts.js.map +1 -1
  137. package/src/util/load-ts.ts +165 -0
  138. package/src/util/narration-cache.d.ts +13 -5
  139. package/src/util/narration-cache.d.ts.map +1 -1
  140. package/src/util/narration-cache.js +10 -8
  141. package/src/util/narration-cache.js.map +1 -1
  142. package/src/util/narration-cache.ts +22 -6
  143. package/src/util/presenter-cache.d.ts +44 -0
  144. package/src/util/presenter-cache.d.ts.map +1 -0
  145. package/src/util/presenter-cache.js +43 -0
  146. package/src/util/presenter-cache.js.map +1 -0
  147. package/src/util/presenter-cache.ts +101 -0
  148. package/src/util/scenario-assets.d.ts +47 -0
  149. package/src/util/scenario-assets.d.ts.map +1 -0
  150. package/src/util/scenario-assets.js +71 -0
  151. package/src/util/scenario-assets.js.map +1 -0
  152. package/src/util/scenario-assets.ts +111 -0
  153. package/src/util/soundtrack-assets.d.ts +34 -0
  154. package/src/util/soundtrack-assets.d.ts.map +1 -0
  155. package/src/util/soundtrack-assets.js +48 -0
  156. package/src/util/soundtrack-assets.js.map +1 -0
  157. package/src/util/soundtrack-assets.ts +69 -0
  158. package/src/validate/scenario-validator.d.ts.map +1 -1
  159. package/src/validate/scenario-validator.js +82 -0
  160. package/src/validate/scenario-validator.js.map +1 -1
  161. package/src/validate/scenario-validator.ts +110 -0
  162. package/tsconfig.tsbuildinfo +1 -1
  163. package/example-bundle/assets/index-DpJUOVBT.js +0 -388
  164. package/example-bundle/assets/style-ix_q0zsc.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"generate-entry.js","sourceRoot":"","sources":["../../../src/render/generate-entry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-entry.js","sourceRoot":"","sources":["../../../src/render/generate-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AA6BlC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAA0B;IAC9D,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,GAAG,YAAY,QAAQ,CAAC;IAC5C,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAE3E,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,kBAAkB;IAElB,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACpE,KAAK,CAAC,IAAI,CACR,qGAAqG,CACtG,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAC5D,uEAAuE;IACvE,wEAAwE;IACxE,qEAAqE;IACrE,gEAAgE;IAChE,iEAAiE;IACjE,wEAAwE;IACxE,oEAAoE;IACpE,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAChD,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC,8BAA8B,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC1E,KAAK,CAAC,IAAI,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE5E,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,YAAY,GAAG,GAAG,YAAY,0BAA0B,CAAC;QAC/D,KAAK,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,qBAAqB,GAAG,GAAG,YAAY,0BAA0B,CAAC;QACxE,KAAK,CAAC,IAAI,CAAC,kCAAkC,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACzF,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACxB,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC7E,KAAK,CAAC,IAAI,CACR,kDAAkD,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,CACrF,CAAC;IACJ,CAAC;IAED,oEAAoE;IAEpE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IAC7E,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACxD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC1C,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACtC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IACvC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAChC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,8CAA8C,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAChG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAC;IAElG,6EAA6E;IAC7E,sEAAsE;IACtE,qEAAqE;IACrE,oEAAoE;IACpE,4CAA4C;IAE5C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC5E,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACxD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,KAAK,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;IACtF,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;IAC1F,KAAK,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;IACnG,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+FAA+F,CAAC,CAAC;IAE5G,8EAA8E;IAC9E,uEAAuE;IACvE,kEAAkE;IAClE,uEAAuE;IACvE,yDAAyD;IAEzD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC5E,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;IACxD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,KAAK,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;IACtF,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;IAC1F,KAAK,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;IACnG,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IACnD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+FAA+F,CAAC,CAAC;IAE5G,4BAA4B;IAC5B,qEAAqE;IACrE,uEAAuE;IAEvE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,uFAAuF,CAAC,CAAC;IACpG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAChC,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CACR,yFAAyF,KAAK,CAAC,GAAG,IAAI,CACvG,CAAC;IAEF,+BAA+B;IAE/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAEtC,wEAAwE;IACxE,yEAAyE;IACzE,qEAAqE;IACrE,MAAM,eAAe,GAAG,KAAK,CAAC,QAAQ;QACpC,CAAC,CAAC,iDAAiD;QACnD,CAAC,CAAC,wCAAwC,CAAC;IAE7C,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;QACxB,wEAAwE;QACxE,uEAAuE;QACvE,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,mEAAmE;QACnE,iCAAiC;QACjC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC1D,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,aAAa,eAAe,EAAE,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;QAC1F,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC1D,KAAK,CAAC,IAAI,CAAC,SAAS,eAAe,EAAE,CAAC,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;QACtF,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEhB,mCAAmC;IAEnC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC5C,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7B,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAC5D,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IACrC,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IACzC,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAChE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,2EAA2E;AAC3E,SAAS,OAAO,CAAC,MAAc;IAC7B,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpE,CAAC"}
@@ -15,12 +15,16 @@ export interface EntryGeneratorInput {
15
15
  scenarioId: string;
16
16
  /** Whether the scenario has a narration manifest. */
17
17
  hasNarration: boolean;
18
+ /** Whether the scenario has a presenter manifest (+ clips). */
19
+ hasPresenter: boolean;
18
20
  /** Absolute path to the providers file, or null if none found. */
19
21
  providersPath: string | null;
20
22
  fps: number;
21
23
  width: number;
22
24
  height: number;
23
25
  compositionId: string;
26
+ /** Burn step captions into the video (`scenar render --captions`). */
27
+ captions: boolean;
24
28
  }
25
29
 
26
30
  /**
@@ -52,8 +56,18 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
52
56
  lines.push(`import { registerRoot } from "remotion";`);
53
57
  lines.push(`import { Composition, AbsoluteFill } from "remotion";`);
54
58
  lines.push(
55
- `import { ScenarioComposition, calculateScenarioTimeline } from "@scenar/remotion";`,
59
+ `import { ScenarioComposition, applyTitleCards, calculateScenarioTimeline } from "@scenar/remotion";`,
56
60
  );
61
+ lines.push(`import { SCENAR_CLASS } from "@scenar/react";`);
62
+ // The same stylesheet pair the packed embed entry loads: without them,
63
+ // authored step content built on @scenar/react (shells, page templates)
64
+ // renders unstyled — black frames in the MP4 (scenar#23). Remotion's
65
+ // bundler handles plain CSS imports natively; styles.css is the
66
+ // self-contained build, so no Tailwind processing is needed. The
67
+ // composition root carries SCENAR_CLASS (below) so the `.scenar`-scoped
68
+ // theme tokens resolve, exactly as the embed entry scopes its tree.
69
+ lines.push(`import "@scenar/react/theme.css";`);
70
+ lines.push(`import "@scenar/react/styles.css";`);
57
71
  lines.push(`import { renderStep } from ${JSON.stringify(renderImport)};`);
58
72
  lines.push(`import * as _stepsModule from ${JSON.stringify(stepsImport)};`);
59
73
 
@@ -64,6 +78,13 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
64
78
  lines.push(`const _manifest = undefined;`);
65
79
  }
66
80
 
81
+ if (input.hasPresenter) {
82
+ const presenterManifestPath = `${scenarioPath}/presenter/manifest.json`;
83
+ lines.push(`import _presenterManifest from ${JSON.stringify(presenterManifestPath)};`);
84
+ } else {
85
+ lines.push(`const _presenterManifest = undefined;`);
86
+ }
87
+
67
88
  if (input.providersPath) {
68
89
  const providersImport = toPosix(input.providersPath).replace(/\.[^.]+$/, "");
69
90
  lines.push(
@@ -89,13 +110,62 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
89
110
  lines.push(``);
90
111
  lines.push(`const _steps: any = _findSteps(_stepsModule as unknown as Record<string, unknown>);`);
91
112
 
113
+ // --- Soundtrack resolution (mirror of the CLI's findAuthoredSoundtrack) ---
114
+ // Discovered from the very module the bundle bakes in, at module-eval
115
+ // time, so the render can never disagree with the authored config: a
116
+ // scenario-shaped export (createScenario) wins, then a `soundtrack`
117
+ // named export; absent means no soundtrack.
118
+
119
+ lines.push(``);
120
+ lines.push(`function _findSoundtrack(mod: Record<string, unknown>): any {`);
121
+ lines.push(` for (const val of Object.values(mod)) {`);
122
+ lines.push(` if (`);
123
+ lines.push(` typeof val === "object" && val !== null && !Array.isArray(val) &&`);
124
+ lines.push(` "soundtrack" in val &&`);
125
+ lines.push(` Array.isArray((val as any).steps) && (val as any).steps.length > 0 &&`);
126
+ lines.push(` typeof (val as any).steps[0] === "object" && (val as any).steps[0] !== null &&`);
127
+ lines.push(` "delayMs" in (val as any).steps[0]`);
128
+ lines.push(` ) return (val as any).soundtrack;`);
129
+ lines.push(` }`);
130
+ lines.push(` return (mod as any)["soundtrack"];`);
131
+ lines.push(`}`);
132
+ lines.push(``);
133
+ lines.push(`const _soundtrack: any = _findSoundtrack(_stepsModule as unknown as Record<string, unknown>);`);
134
+
135
+ // --- Title cards resolution (mirror of the CLI's findAuthoredTitleCards) ---
136
+ // Same discovery contract as _findSoundtrack. The config is discovered
137
+ // here and applied immediately below — bundle assembly is THE one
138
+ // card-synthesis point (applyTitleCards from @scenar/core, re-exported
139
+ // by @scenar/remotion so no extra dependency is needed).
140
+
141
+ lines.push(``);
142
+ lines.push(`function _findTitleCards(mod: Record<string, unknown>): any {`);
143
+ lines.push(` for (const val of Object.values(mod)) {`);
144
+ lines.push(` if (`);
145
+ lines.push(` typeof val === "object" && val !== null && !Array.isArray(val) &&`);
146
+ lines.push(` "titleCards" in val &&`);
147
+ lines.push(` Array.isArray((val as any).steps) && (val as any).steps.length > 0 &&`);
148
+ lines.push(` typeof (val as any).steps[0] === "object" && (val as any).steps[0] !== null &&`);
149
+ lines.push(` "delayMs" in (val as any).steps[0]`);
150
+ lines.push(` ) return (val as any).titleCards;`);
151
+ lines.push(` }`);
152
+ lines.push(` return (mod as any)["titleCards"];`);
153
+ lines.push(`}`);
154
+ lines.push(``);
155
+ lines.push(`const _titleCards: any = _findTitleCards(_stepsModule as unknown as Record<string, unknown>);`);
156
+
92
157
  // --- Bundle + timeline ---
158
+ // Card synthesis runs before the timeline calculation so an intro or
159
+ // outro card lengthens durationInFrames exactly like an authored step.
93
160
 
94
161
  lines.push(``);
162
+ lines.push(`const _applied = applyTitleCards(_steps, _manifest, _titleCards, _presenterManifest);`);
95
163
  lines.push(`const _bundle = {`);
96
164
  lines.push(` id: ${JSON.stringify(input.scenarioId)},`);
97
- lines.push(` steps: _steps,`);
98
- lines.push(` narrationManifest: _manifest,`);
165
+ lines.push(` steps: _applied.steps as any,`);
166
+ lines.push(` narrationManifest: _applied.narrationManifest,`);
167
+ lines.push(` soundtrack: _soundtrack,`);
168
+ lines.push(` presenterManifest: _applied.presenterManifest,`);
99
169
  lines.push(`};`);
100
170
  lines.push(``);
101
171
  lines.push(
@@ -107,20 +177,37 @@ export function generateRemotionEntry(input: EntryGeneratorInput): string {
107
177
  lines.push(``);
108
178
  lines.push(`function _VideoRoot() {`);
109
179
 
180
+ // `captions` is baked into the generated JSX (not read at render time):
181
+ // the entry is written per render invocation, so the flag's value IS the
182
+ // render's configuration — same treatment as fps/width/height above.
183
+ const compositionOpen = input.captions
184
+ ? `<ScenarioComposition bundle={_bundle} captions>`
185
+ : `<ScenarioComposition bundle={_bundle}>`;
186
+
110
187
  if (input.providersPath) {
188
+ // The inner AbsoluteFill is load-bearing: ScenarioComposition sizes its
189
+ // player through a CSS height chain, and providers are not required to
190
+ // be height-transparent — a provider that renders a real wrapper element
191
+ // with auto height (e.g. a theme-scope div) would otherwise collapse the
192
+ // chain, shrinking cards to content height and authored step surfaces to
193
+ // zero (black frames — scenar#33). Sandwiching the provider between two
194
+ // absolute fills makes the entry's layout guarantee independent of
195
+ // whatever the provider renders.
111
196
  lines.push(` return (`);
112
- lines.push(` <AbsoluteFill>`);
197
+ lines.push(` <AbsoluteFill className={SCENAR_CLASS}>`);
113
198
  lines.push(` <_Providers>`);
114
- lines.push(` <ScenarioComposition bundle={_bundle}>`);
115
- lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
116
- lines.push(` </ScenarioComposition>`);
199
+ lines.push(` <AbsoluteFill>`);
200
+ lines.push(` ${compositionOpen}`);
201
+ lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
202
+ lines.push(` </ScenarioComposition>`);
203
+ lines.push(` </AbsoluteFill>`);
117
204
  lines.push(` </_Providers>`);
118
205
  lines.push(` </AbsoluteFill>`);
119
206
  lines.push(` );`);
120
207
  } else {
121
208
  lines.push(` return (`);
122
- lines.push(` <AbsoluteFill>`);
123
- lines.push(` <ScenarioComposition bundle={_bundle}>`);
209
+ lines.push(` <AbsoluteFill className={SCENAR_CLASS}>`);
210
+ lines.push(` ${compositionOpen}`);
124
211
  lines.push(` {(data: any, stepIndex: number) => renderStep(data, stepIndex)}`);
125
212
  lines.push(` </ScenarioComposition>`);
126
213
  lines.push(` </AbsoluteFill>`);
@@ -8,6 +8,12 @@ export interface RunRenderOptions {
8
8
  readonly compositionId?: string;
9
9
  readonly entry?: string;
10
10
  readonly webpackOverride?: string;
11
+ /**
12
+ * Burn step captions into the video (each step's `narration` text as a
13
+ * subtitle overlay). Only applies to the auto-generated entry; a custom
14
+ * `--entry` owns its own `<ScenarioComposition>` props.
15
+ */
16
+ readonly captions?: boolean;
11
17
  readonly onLog?: (message: string) => void;
12
18
  }
13
19
  /** The outcome of a successful render. */
@@ -1 +1 @@
1
- {"version":3,"file":"run-render.d.ts","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"AAQA,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkFhF"}
1
+ {"version":3,"file":"run-render.d.ts","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"AAUA,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAyIhF"}
@@ -2,9 +2,11 @@ import { resolve, join } from "node:path";
2
2
  import { stat, mkdir, access, writeFile, rm } from "node:fs/promises";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { loadBundle } from "../util/load-bundle.js";
5
+ import { resolveSfxAssetPaths } from "../util/soundtrack-assets.js";
5
6
  import { generateRemotionEntry } from "./generate-entry.js";
6
7
  import { resolveProvidersPath } from "./resolve-providers.js";
7
8
  import { detectRenderExport } from "./detect-render-export.js";
9
+ import { stageRenderAssets } from "./stage-assets.js";
8
10
  /**
9
11
  * Render a scenario directory to an MP4 via Remotion — the pure orchestration
10
12
  * behind `scenar render`, with no process/exit coupling. Throws on any failure
@@ -25,6 +27,13 @@ export async function runRender(options) {
25
27
  const fps = options.fps ?? 30;
26
28
  const width = options.width ?? 1920;
27
29
  const height = options.height ?? 1080;
30
+ const captions = options.captions ?? false;
31
+ // A custom entry owns its own <ScenarioComposition> props, so --captions
32
+ // cannot reach it. Say so instead of silently ignoring the flag.
33
+ if (captions && options.entry) {
34
+ onLog("Warning: --captions has no effect with --entry. " +
35
+ 'Pass captions to <ScenarioComposition> in your entry file instead.');
36
+ }
28
37
  let tempDir;
29
38
  try {
30
39
  const bundle = await loadBundle(scenarioDir);
@@ -37,9 +46,11 @@ export async function runRender(options) {
37
46
  scenarioId,
38
47
  compositionId,
39
48
  hasNarration: !!bundle.narrationManifest,
49
+ hasPresenter: !!bundle.presenterManifest,
40
50
  fps,
41
51
  width,
42
52
  height,
53
+ captions,
43
54
  });
44
55
  tempDir = generated?.tempDir;
45
56
  const webpackOverride = options.webpackOverride
@@ -48,6 +59,47 @@ export async function runRender(options) {
48
59
  onLog(`Scenario: ${scenarioId}`);
49
60
  onLog(`Steps: ${bundle.steps.length}`);
50
61
  onLog(`Audio: ${bundle.narrationManifest ? "yes (manifest found)" : "none"}`);
62
+ if (bundle.soundtrack) {
63
+ const parts = [
64
+ bundle.soundtrack.musicSrc ? `music (${bundle.soundtrack.musicSrc})` : null,
65
+ bundle.soundtrack.sfx ? "sfx" : null,
66
+ ].filter(Boolean);
67
+ onLog(`Soundtrack: ${parts.length > 0 ? parts.join(" + ") : "configured (silent)"}`);
68
+ }
69
+ if (bundle.titleCards?.intro || bundle.titleCards?.outro) {
70
+ const parts = [
71
+ bundle.titleCards.intro ? "intro" : null,
72
+ bundle.titleCards.outro ? "outro" : null,
73
+ ].filter(Boolean);
74
+ onLog(`Cards: ${parts.join(" + ")}`);
75
+ }
76
+ if (captions) {
77
+ onLog(`Captions: burned in (from step narration text)`);
78
+ }
79
+ // Stage every local asset into a Remotion public dir so staticFile()
80
+ // resolution finds real bytes — narration clips, the music asset, the
81
+ // built-in SFX set, and title-card logos. Only for the auto-generated
82
+ // entry: a custom --entry project owns its own public dir convention.
83
+ let publicDir;
84
+ if (generated) {
85
+ const candidatePublicDir = join(generated.tempDir, "public");
86
+ const sfxPaths = bundle.soundtrack?.sfx
87
+ ? resolveSfxAssetPaths(scenarioDir)
88
+ : undefined;
89
+ const stagedCount = await stageRenderAssets({
90
+ scenarioDir,
91
+ publicDir: candidatePublicDir,
92
+ hasNarration: !!bundle.narrationManifest,
93
+ hasPresenter: !!bundle.presenterManifest,
94
+ soundtrack: bundle.soundtrack,
95
+ sfxPaths,
96
+ titleCards: bundle.titleCards,
97
+ });
98
+ if (stagedCount > 0) {
99
+ publicDir = candidatePublicDir;
100
+ onLog(`Staged: ${stagedCount} asset file(s) for the render`);
101
+ }
102
+ }
51
103
  onLog(`Entry: ${generated ? "(auto-generated)" : entryPoint}`);
52
104
  if (generated?.providersPath) {
53
105
  onLog(`Providers: ${generated.providersPath}`);
@@ -66,6 +118,7 @@ export async function runRender(options) {
66
118
  width,
67
119
  height,
68
120
  webpackOverride,
121
+ publicDir,
69
122
  onLog,
70
123
  });
71
124
  return {
@@ -114,11 +167,13 @@ async function resolveEntryPoint(input) {
114
167
  renderFilePath,
115
168
  scenarioId: input.scenarioId,
116
169
  hasNarration: input.hasNarration,
170
+ hasPresenter: input.hasPresenter,
117
171
  providersPath,
118
172
  fps: input.fps,
119
173
  width: input.width,
120
174
  height: input.height,
121
175
  compositionId: input.compositionId,
176
+ captions: input.captions,
122
177
  });
123
178
  // Write the entry inside the scenario directory so webpack's standard
124
179
  // node_modules resolution walks up from here into the consumer project.
@@ -170,6 +225,9 @@ async function renderScenario(config) {
170
225
  if (config.webpackOverride) {
171
226
  bundleOptions.webpackOverride = config.webpackOverride;
172
227
  }
228
+ if (config.publicDir) {
229
+ bundleOptions.publicDir = config.publicDir;
230
+ }
173
231
  const serveUrl = await bundler.bundle(bundleOptions);
174
232
  config.onLog(`Selecting composition: ${config.compositionId}`);
175
233
  const composition = await renderer.selectComposition({
@@ -1 +1 @@
1
- {"version":3,"file":"run-render.js","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-render.js","sourceRoot":"","sources":["../../../src/render/run-render.ts"],"names":[],"mappings":"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"}
@@ -2,9 +2,11 @@ import { resolve, join } from "node:path";
2
2
  import { stat, mkdir, access, writeFile, rm } from "node:fs/promises";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { loadBundle, type CliBundle } from "../util/load-bundle.js";
5
+ import { resolveSfxAssetPaths } from "../util/soundtrack-assets.js";
5
6
  import { generateRemotionEntry } from "./generate-entry.js";
6
7
  import { resolveProvidersPath } from "./resolve-providers.js";
7
8
  import { detectRenderExport } from "./detect-render-export.js";
9
+ import { stageRenderAssets } from "./stage-assets.js";
8
10
 
9
11
  /** Options for {@link runRender}. Paths may be relative; resolved here. */
10
12
  export interface RunRenderOptions {
@@ -16,6 +18,12 @@ export interface RunRenderOptions {
16
18
  readonly compositionId?: string;
17
19
  readonly entry?: string;
18
20
  readonly webpackOverride?: string;
21
+ /**
22
+ * Burn step captions into the video (each step's `narration` text as a
23
+ * subtitle overlay). Only applies to the auto-generated entry; a custom
24
+ * `--entry` owns its own `<ScenarioComposition>` props.
25
+ */
26
+ readonly captions?: boolean;
19
27
  readonly onLog?: (message: string) => void;
20
28
  }
21
29
 
@@ -55,6 +63,16 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
55
63
  const fps = options.fps ?? 30;
56
64
  const width = options.width ?? 1920;
57
65
  const height = options.height ?? 1080;
66
+ const captions = options.captions ?? false;
67
+
68
+ // A custom entry owns its own <ScenarioComposition> props, so --captions
69
+ // cannot reach it. Say so instead of silently ignoring the flag.
70
+ if (captions && options.entry) {
71
+ onLog(
72
+ "Warning: --captions has no effect with --entry. " +
73
+ 'Pass captions to <ScenarioComposition> in your entry file instead.',
74
+ );
75
+ }
58
76
 
59
77
  let tempDir: string | undefined;
60
78
  try {
@@ -69,9 +87,11 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
69
87
  scenarioId,
70
88
  compositionId,
71
89
  hasNarration: !!bundle.narrationManifest,
90
+ hasPresenter: !!bundle.presenterManifest,
72
91
  fps,
73
92
  width,
74
93
  height,
94
+ captions,
75
95
  });
76
96
  tempDir = generated?.tempDir;
77
97
 
@@ -82,6 +102,48 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
82
102
  onLog(`Scenario: ${scenarioId}`);
83
103
  onLog(`Steps: ${bundle.steps.length}`);
84
104
  onLog(`Audio: ${bundle.narrationManifest ? "yes (manifest found)" : "none"}`);
105
+ if (bundle.soundtrack) {
106
+ const parts = [
107
+ bundle.soundtrack.musicSrc ? `music (${bundle.soundtrack.musicSrc})` : null,
108
+ bundle.soundtrack.sfx ? "sfx" : null,
109
+ ].filter(Boolean);
110
+ onLog(`Soundtrack: ${parts.length > 0 ? parts.join(" + ") : "configured (silent)"}`);
111
+ }
112
+ if (bundle.titleCards?.intro || bundle.titleCards?.outro) {
113
+ const parts = [
114
+ bundle.titleCards.intro ? "intro" : null,
115
+ bundle.titleCards.outro ? "outro" : null,
116
+ ].filter(Boolean);
117
+ onLog(`Cards: ${parts.join(" + ")}`);
118
+ }
119
+ if (captions) {
120
+ onLog(`Captions: burned in (from step narration text)`);
121
+ }
122
+
123
+ // Stage every local asset into a Remotion public dir so staticFile()
124
+ // resolution finds real bytes — narration clips, the music asset, the
125
+ // built-in SFX set, and title-card logos. Only for the auto-generated
126
+ // entry: a custom --entry project owns its own public dir convention.
127
+ let publicDir: string | undefined;
128
+ if (generated) {
129
+ const candidatePublicDir = join(generated.tempDir, "public");
130
+ const sfxPaths = bundle.soundtrack?.sfx
131
+ ? resolveSfxAssetPaths(scenarioDir)
132
+ : undefined;
133
+ const stagedCount = await stageRenderAssets({
134
+ scenarioDir,
135
+ publicDir: candidatePublicDir,
136
+ hasNarration: !!bundle.narrationManifest,
137
+ hasPresenter: !!bundle.presenterManifest,
138
+ soundtrack: bundle.soundtrack,
139
+ sfxPaths,
140
+ titleCards: bundle.titleCards,
141
+ });
142
+ if (stagedCount > 0) {
143
+ publicDir = candidatePublicDir;
144
+ onLog(`Staged: ${stagedCount} asset file(s) for the render`);
145
+ }
146
+ }
85
147
  onLog(`Entry: ${generated ? "(auto-generated)" : entryPoint}`);
86
148
  if (generated?.providersPath) {
87
149
  onLog(`Providers: ${generated.providersPath}`);
@@ -101,6 +163,7 @@ export async function runRender(options: RunRenderOptions): Promise<RenderResult
101
163
  width,
102
164
  height,
103
165
  webpackOverride,
166
+ publicDir,
104
167
  onLog,
105
168
  });
106
169
 
@@ -137,9 +200,11 @@ interface EntryResolutionInput {
137
200
  scenarioId: string;
138
201
  compositionId: string;
139
202
  hasNarration: boolean;
203
+ hasPresenter: boolean;
140
204
  fps: number;
141
205
  width: number;
142
206
  height: number;
207
+ captions: boolean;
143
208
  }
144
209
 
145
210
  interface EntryResolutionResult {
@@ -171,11 +236,13 @@ async function resolveEntryPoint(input: EntryResolutionInput): Promise<EntryReso
171
236
  renderFilePath,
172
237
  scenarioId: input.scenarioId,
173
238
  hasNarration: input.hasNarration,
239
+ hasPresenter: input.hasPresenter,
174
240
  providersPath,
175
241
  fps: input.fps,
176
242
  width: input.width,
177
243
  height: input.height,
178
244
  compositionId: input.compositionId,
245
+ captions: input.captions,
179
246
  });
180
247
 
181
248
  // Write the entry inside the scenario directory so webpack's standard
@@ -232,6 +299,8 @@ interface RenderConfig {
232
299
  width: number;
233
300
  height: number;
234
301
  webpackOverride?: (config: unknown) => unknown;
302
+ /** Staged audio dir for Remotion's staticFile() resolution, if any. */
303
+ publicDir?: string;
235
304
  onLog: (message: string) => void;
236
305
  }
237
306
 
@@ -254,6 +323,9 @@ async function renderScenario(config: RenderConfig): Promise<void> {
254
323
  if (config.webpackOverride) {
255
324
  bundleOptions.webpackOverride = config.webpackOverride;
256
325
  }
326
+ if (config.publicDir) {
327
+ bundleOptions.publicDir = config.publicDir;
328
+ }
257
329
  const serveUrl = await (bundler.bundle as (opts: Record<string, unknown>) => Promise<string>)(
258
330
  bundleOptions,
259
331
  );
@@ -0,0 +1,44 @@
1
+ import type { AuthoredSoundtrack, AuthoredTitleCards } from "../util/load-ts.js";
2
+ import { type SfxAssetPaths } from "../util/soundtrack-assets.js";
3
+ export interface StageRenderAssetsInput {
4
+ /** Absolute path to the scenario directory. */
5
+ readonly scenarioDir: string;
6
+ /** Absolute path of the Remotion public dir to stage into (created). */
7
+ readonly publicDir: string;
8
+ /** Whether the scenario has a narration manifest (+ clips to stage). */
9
+ readonly hasNarration: boolean;
10
+ /** Whether the scenario has a presenter manifest (+ clips to stage). */
11
+ readonly hasPresenter?: boolean;
12
+ /** The scenario's authored soundtrack, if any. */
13
+ readonly soundtrack?: AuthoredSoundtrack;
14
+ /**
15
+ * Absolute locations of the built-in SFX assets — required when
16
+ * `soundtrack.sfx` is enabled (the caller resolves them from
17
+ * `@scenar/react` via `resolveSfxAssetPaths`).
18
+ */
19
+ readonly sfxPaths?: SfxAssetPaths;
20
+ /** The scenario's authored title cards, if any (logo assets to stage). */
21
+ readonly titleCards?: AuthoredTitleCards;
22
+ }
23
+ /**
24
+ * Stage every local asset a render needs into a Remotion public dir, so
25
+ * `staticFile()` resolution inside `ScenarioComposition` finds real files.
26
+ *
27
+ * The layout mirrors how each src is written:
28
+ * - Narration clips: manifest srcs are manifest-relative (`./step-N.mp3`),
29
+ * so the clips stage flat at the public root.
30
+ * - Presenter clips: same convention (`./step-N.mp4`), staged flat at the
31
+ * public root beside the narration clips — the extensions never collide.
32
+ * - Music: `musicSrc` is scenario-relative (`./soundtrack/music.mp3`), so
33
+ * the file stages at that same relative path. Remote URLs stage nothing.
34
+ * - Built-in SFX: staged at {@link SFX_DEST_PATHS}, the composition's
35
+ * default `sfxSrcs`.
36
+ * - Title-card logos: `logoSrc` is scenario-relative like music, staged
37
+ * at its relative path (intro and outro may share one file — it stages
38
+ * once). Remote URLs stage nothing.
39
+ *
40
+ * Returns the number of files staged. Zero means the render needs no
41
+ * local assets and the caller can skip the public dir entirely.
42
+ */
43
+ export declare function stageRenderAssets(input: StageRenderAssetsInput): Promise<number>;
44
+ //# sourceMappingURL=stage-assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage-assets.d.ts","sourceRoot":"","sources":["../../../src/render/stage-assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,sBAAsB;IACrC,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDtF"}
@@ -0,0 +1,91 @@
1
+ import { copyFile, mkdir, readdir } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { SFX_DEST_PATHS, resolveMusicAsset, } from "../util/soundtrack-assets.js";
4
+ import { resolveLogoAsset } from "../util/scenario-assets.js";
5
+ /**
6
+ * Stage every local asset a render needs into a Remotion public dir, so
7
+ * `staticFile()` resolution inside `ScenarioComposition` finds real files.
8
+ *
9
+ * The layout mirrors how each src is written:
10
+ * - Narration clips: manifest srcs are manifest-relative (`./step-N.mp3`),
11
+ * so the clips stage flat at the public root.
12
+ * - Presenter clips: same convention (`./step-N.mp4`), staged flat at the
13
+ * public root beside the narration clips — the extensions never collide.
14
+ * - Music: `musicSrc` is scenario-relative (`./soundtrack/music.mp3`), so
15
+ * the file stages at that same relative path. Remote URLs stage nothing.
16
+ * - Built-in SFX: staged at {@link SFX_DEST_PATHS}, the composition's
17
+ * default `sfxSrcs`.
18
+ * - Title-card logos: `logoSrc` is scenario-relative like music, staged
19
+ * at its relative path (intro and outro may share one file — it stages
20
+ * once). Remote URLs stage nothing.
21
+ *
22
+ * Returns the number of files staged. Zero means the render needs no
23
+ * local assets and the caller can skip the public dir entirely.
24
+ */
25
+ export async function stageRenderAssets(input) {
26
+ let staged = 0;
27
+ if (input.hasNarration) {
28
+ staged += await stageClipDirectory(input.scenarioDir, "narration", ".mp3", input.publicDir);
29
+ }
30
+ if (input.hasPresenter) {
31
+ staged += await stageClipDirectory(input.scenarioDir, "presenter", ".mp4", input.publicDir);
32
+ }
33
+ const musicSrc = input.soundtrack?.musicSrc;
34
+ if (musicSrc) {
35
+ const music = await resolveMusicAsset(input.scenarioDir, musicSrc);
36
+ if (music) {
37
+ const dest = join(input.publicDir, music.destRelPath);
38
+ await mkdir(dirname(dest), { recursive: true });
39
+ await copyFile(music.sourcePath, dest);
40
+ staged += 1;
41
+ }
42
+ }
43
+ if (input.soundtrack?.sfx && input.sfxPaths) {
44
+ for (const sound of ["click", "keystroke"]) {
45
+ const dest = join(input.publicDir, SFX_DEST_PATHS[sound]);
46
+ await mkdir(dirname(dest), { recursive: true });
47
+ await copyFile(input.sfxPaths[sound], dest);
48
+ staged += 1;
49
+ }
50
+ }
51
+ const stagedLogos = new Set();
52
+ for (const side of ["intro", "outro"]) {
53
+ const logoSrc = input.titleCards?.[side]?.logoSrc;
54
+ if (!logoSrc)
55
+ continue;
56
+ const logo = await resolveLogoAsset(input.scenarioDir, logoSrc, `titleCards.${side}.logoSrc`);
57
+ if (!logo || stagedLogos.has(logo.destRelPath))
58
+ continue;
59
+ const dest = join(input.publicDir, logo.destRelPath);
60
+ await mkdir(dirname(dest), { recursive: true });
61
+ await copyFile(logo.sourcePath, dest);
62
+ stagedLogos.add(logo.destRelPath);
63
+ staged += 1;
64
+ }
65
+ return staged;
66
+ }
67
+ /**
68
+ * Copy every clip of one track (narration mp3s, presenter mp4s) flat into
69
+ * the public root — manifest srcs are manifest-relative (`./step-N.<ext>`),
70
+ * which `staticFile()` resolves at the root.
71
+ */
72
+ async function stageClipDirectory(scenarioDir, trackDir, extension, publicDir) {
73
+ const sourceDir = join(scenarioDir, trackDir);
74
+ let entries;
75
+ try {
76
+ entries = await readdir(sourceDir, { withFileTypes: true });
77
+ }
78
+ catch {
79
+ return 0;
80
+ }
81
+ let staged = 0;
82
+ await mkdir(publicDir, { recursive: true });
83
+ for (const entry of entries) {
84
+ if (!entry.isFile() || !entry.name.toLowerCase().endsWith(extension))
85
+ continue;
86
+ await copyFile(join(sourceDir, entry.name), join(publicDir, entry.name));
87
+ staged += 1;
88
+ }
89
+ return staged;
90
+ }
91
+ //# sourceMappingURL=stage-assets.js.map