voxflow 1.15.0 → 1.15.2

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 (453) hide show
  1. package/README.md +34 -0
  2. package/bin/voxflow.js +27 -0
  3. package/dist/index.js +1 -1
  4. package/dist/remotion-bundle/02a2fb2eb80bc7bf.woff2 +0 -0
  5. package/dist/remotion-bundle/052ca5351e5e06ba.woff2 +0 -0
  6. package/dist/remotion-bundle/05853dd28f4019cb.woff2 +0 -0
  7. package/dist/remotion-bundle/072ead3737f7c0d0.woff2 +0 -0
  8. package/dist/remotion-bundle/07d4248613c86a2e.woff2 +0 -0
  9. package/dist/remotion-bundle/0884a5c2d1d2d99b.woff2 +0 -0
  10. package/dist/remotion-bundle/0b0e185b2752095e.woff2 +0 -0
  11. package/dist/remotion-bundle/0e66c11bde067d91.woff2 +0 -0
  12. package/dist/remotion-bundle/0f7794cfba2c5d21.woff2 +0 -0
  13. package/dist/remotion-bundle/0fdbae5a4365783a.woff2 +0 -0
  14. package/dist/remotion-bundle/112.bundle.js +11 -0
  15. package/dist/remotion-bundle/112.bundle.js.map +1 -0
  16. package/dist/remotion-bundle/113.bundle.js +11 -0
  17. package/dist/remotion-bundle/113.bundle.js.map +1 -0
  18. package/dist/remotion-bundle/119cae0c4c16f7ed.woff2 +0 -0
  19. package/dist/remotion-bundle/14725f649fd1e78c.woff2 +0 -0
  20. package/dist/remotion-bundle/14abe9e3f95f7888.woff2 +0 -0
  21. package/dist/remotion-bundle/163.bundle.js +14678 -0
  22. package/dist/remotion-bundle/163.bundle.js.map +1 -0
  23. package/dist/remotion-bundle/1808c54072bf6d14.woff2 +0 -0
  24. package/dist/remotion-bundle/18948bec3e3012fe.woff2 +0 -0
  25. package/dist/remotion-bundle/1a661c60d0fc84fc.woff2 +0 -0
  26. package/dist/remotion-bundle/1af94941e1bc7e1e.woff2 +0 -0
  27. package/dist/remotion-bundle/1bee0219595f606c.woff2 +0 -0
  28. package/dist/remotion-bundle/1bfd5da7ce9d4ec4.woff2 +0 -0
  29. package/dist/remotion-bundle/1c158d56f1884f3f.woff2 +0 -0
  30. package/dist/remotion-bundle/1cf5e88e667610eb.woff2 +0 -0
  31. package/dist/remotion-bundle/1d431bd10f53c481.woff2 +0 -0
  32. package/dist/remotion-bundle/1d701a81a7670db2.woff2 +0 -0
  33. package/dist/remotion-bundle/1da0fecad4240f16.woff2 +0 -0
  34. package/dist/remotion-bundle/1ed14d3d0c5c63fe.woff2 +0 -0
  35. package/dist/remotion-bundle/1edfecf40e586f53.woff2 +0 -0
  36. package/dist/remotion-bundle/1f479711bc34b054.woff +0 -0
  37. package/dist/remotion-bundle/1f86e54a0ff5fcd1.woff2 +0 -0
  38. package/dist/remotion-bundle/2043ea87d9aabd11.woff2 +0 -0
  39. package/dist/remotion-bundle/20563c39ee8a0e40.woff2 +0 -0
  40. package/dist/remotion-bundle/20c231590fd12c44.woff2 +0 -0
  41. package/dist/remotion-bundle/20ce61713f754c07.woff2 +0 -0
  42. package/dist/remotion-bundle/21eb9306fce24bb1.woff2 +0 -0
  43. package/dist/remotion-bundle/244bf71c0cc851af.woff2 +0 -0
  44. package/dist/remotion-bundle/274d4cfc02bffbcb.woff2 +0 -0
  45. package/dist/remotion-bundle/275.bundle.js +21 -0
  46. package/dist/remotion-bundle/275.bundle.js.map +1 -0
  47. package/dist/remotion-bundle/2958f540b39513dc.woff2 +0 -0
  48. package/dist/remotion-bundle/2a168b98fd97722e.woff2 +0 -0
  49. package/dist/remotion-bundle/2d1f6373937ab55f.woff2 +0 -0
  50. package/dist/remotion-bundle/2d213ae47ff6daa9.woff2 +0 -0
  51. package/dist/remotion-bundle/2e4b1f04fcd05047.woff2 +0 -0
  52. package/dist/remotion-bundle/304170d98f4c4563.woff2 +0 -0
  53. package/dist/remotion-bundle/30d02e136e7a5642.woff2 +0 -0
  54. package/dist/remotion-bundle/3135562b52a714cd.woff2 +0 -0
  55. package/dist/remotion-bundle/313713af2c8144e9.woff2 +0 -0
  56. package/dist/remotion-bundle/325fa4108d2285b9.woff2 +0 -0
  57. package/dist/remotion-bundle/338e927ed3345e0c.woff2 +0 -0
  58. package/dist/remotion-bundle/35fc6b190365bc17.woff2 +0 -0
  59. package/dist/remotion-bundle/37a51f1122d4efc5.woff2 +0 -0
  60. package/dist/remotion-bundle/39a4d63e02736f5e.woff2 +0 -0
  61. package/dist/remotion-bundle/3a00e0d62dfc4171.woff2 +0 -0
  62. package/dist/remotion-bundle/3a6955e6561affe1.woff2 +0 -0
  63. package/dist/remotion-bundle/3c573945aef49b89.woff2 +0 -0
  64. package/dist/remotion-bundle/3cdbfbfa23b516a5.woff2 +0 -0
  65. package/dist/remotion-bundle/3e42f85a9e64ca8a.woff2 +0 -0
  66. package/dist/remotion-bundle/3e83eaf1ec859415.woff2 +0 -0
  67. package/dist/remotion-bundle/3f3c8c90de1250ee.woff2 +0 -0
  68. package/dist/remotion-bundle/434.bundle.js +205 -0
  69. package/dist/remotion-bundle/434.bundle.js.map +1 -0
  70. package/dist/remotion-bundle/44ffc6ca4d781692.woff2 +0 -0
  71. package/dist/remotion-bundle/4670d9c4580b09eb.woff2 +0 -0
  72. package/dist/remotion-bundle/479756881b302824.woff2 +0 -0
  73. package/dist/remotion-bundle/481b82134bfa9c82.woff2 +0 -0
  74. package/dist/remotion-bundle/48d27029626f4328.woff2 +0 -0
  75. package/dist/remotion-bundle/49b7b2a30329c511.woff2 +0 -0
  76. package/dist/remotion-bundle/4c8b25a1a9337045.woff2 +0 -0
  77. package/dist/remotion-bundle/4cba14788ca9259b.woff2 +0 -0
  78. package/dist/remotion-bundle/4cd6c589c004a6a7.woff2 +0 -0
  79. package/dist/remotion-bundle/4cd8d79c1021608d.woff2 +0 -0
  80. package/dist/remotion-bundle/4d8fa99b3f00f9f0.woff2 +0 -0
  81. package/dist/remotion-bundle/4e7805a643f86d53.woff2 +0 -0
  82. package/dist/remotion-bundle/4ff91be454542e3f.woff2 +0 -0
  83. package/dist/remotion-bundle/504cbcba1f63591b.woff2 +0 -0
  84. package/dist/remotion-bundle/5202d792e5791d6c.woff2 +0 -0
  85. package/dist/remotion-bundle/534db5ad4770cc1d.woff2 +0 -0
  86. package/dist/remotion-bundle/53b9568eb85f866b.woff2 +0 -0
  87. package/dist/remotion-bundle/543ad386ca171de9.woff2 +0 -0
  88. package/dist/remotion-bundle/54798e55bbf7976e.woff2 +0 -0
  89. package/dist/remotion-bundle/580.bundle.js +11 -0
  90. package/dist/remotion-bundle/580.bundle.js.map +1 -0
  91. package/dist/remotion-bundle/58d174d1193af6d1.woff2 +0 -0
  92. package/dist/remotion-bundle/591d29ff3ff53c80.woff2 +0 -0
  93. package/dist/remotion-bundle/5c28c4f4824383c6.woff2 +0 -0
  94. package/dist/remotion-bundle/5da9740d2ce894c8.woff2 +0 -0
  95. package/dist/remotion-bundle/6197735364642360.woff2 +0 -0
  96. package/dist/remotion-bundle/6265a4335724080f.woff2 +0 -0
  97. package/dist/remotion-bundle/633f5e4f6394daa7.woff2 +0 -0
  98. package/dist/remotion-bundle/637d95ace6a69c49.woff2 +0 -0
  99. package/dist/remotion-bundle/648e04a04dacff8f.woff2 +0 -0
  100. package/dist/remotion-bundle/64a6e83045a008b2.woff2 +0 -0
  101. package/dist/remotion-bundle/651.bundle.js +11 -0
  102. package/dist/remotion-bundle/651.bundle.js.map +1 -0
  103. package/dist/remotion-bundle/65e2a988c070facc.woff2 +0 -0
  104. package/dist/remotion-bundle/66a2f6ce5cc69105.woff2 +0 -0
  105. package/dist/remotion-bundle/690.bundle.js +3479 -0
  106. package/dist/remotion-bundle/690.bundle.js.map +1 -0
  107. package/dist/remotion-bundle/690ff55252ca715d.woff2 +0 -0
  108. package/dist/remotion-bundle/6a01a1cff49314fc.woff2 +0 -0
  109. package/dist/remotion-bundle/6cbc32670982986c.woff2 +0 -0
  110. package/dist/remotion-bundle/6d3cc42ae547f454.woff2 +0 -0
  111. package/dist/remotion-bundle/6d8f4cfa1ddc0830.woff2 +0 -0
  112. package/dist/remotion-bundle/6e4d7c6ae65e2dc3.woff2 +0 -0
  113. package/dist/remotion-bundle/6e86418bbcefb2e8.woff2 +0 -0
  114. package/dist/remotion-bundle/6ee02884b29cf7fb.woff2 +0 -0
  115. package/dist/remotion-bundle/6f436a74c9e3252c.woff2 +0 -0
  116. package/dist/remotion-bundle/78c8022f1657618b.woff2 +0 -0
  117. package/dist/remotion-bundle/7c5444169792bca4.woff2 +0 -0
  118. package/dist/remotion-bundle/7c86bddd9d997212.woff2 +0 -0
  119. package/dist/remotion-bundle/7e1284684767f584.woff2 +0 -0
  120. package/dist/remotion-bundle/7e81c17522d182b2.woff2 +0 -0
  121. package/dist/remotion-bundle/7eb87be198f7858c.woff2 +0 -0
  122. package/dist/remotion-bundle/8060c928f948aab5.woff2 +0 -0
  123. package/dist/remotion-bundle/80bc9dfbea2b35ae.woff2 +0 -0
  124. package/dist/remotion-bundle/811b83f69963bb48.woff2 +0 -0
  125. package/dist/remotion-bundle/813.bundle.js +117511 -0
  126. package/dist/remotion-bundle/813.bundle.js.map +1 -0
  127. package/dist/remotion-bundle/84df492e349f82e9.woff2 +0 -0
  128. package/dist/remotion-bundle/8501bfd73eb36f2b.woff2 +0 -0
  129. package/dist/remotion-bundle/854236a8376093fe.woff2 +0 -0
  130. package/dist/remotion-bundle/8571d74529082753.woff2 +0 -0
  131. package/dist/remotion-bundle/860bf44f8e6f4b5d.woff2 +0 -0
  132. package/dist/remotion-bundle/879.bundle.js +64 -0
  133. package/dist/remotion-bundle/879.bundle.js.map +1 -0
  134. package/dist/remotion-bundle/887dd482f848d56f.woff2 +0 -0
  135. package/dist/remotion-bundle/89b2132e85fbbb5a.woff2 +0 -0
  136. package/dist/remotion-bundle/8ba60d6c306010c2.woff2 +0 -0
  137. package/dist/remotion-bundle/8c7c4dadea897806.woff2 +0 -0
  138. package/dist/remotion-bundle/8c943f9999706f61.woff2 +0 -0
  139. package/dist/remotion-bundle/8f2a718c90575cc9.woff2 +0 -0
  140. package/dist/remotion-bundle/906b6edb3e1772c9.woff2 +0 -0
  141. package/dist/remotion-bundle/930ff9daccdf14eb.woff2 +0 -0
  142. package/dist/remotion-bundle/934db2f1c403c4d0.woff2 +0 -0
  143. package/dist/remotion-bundle/938.bundle.js +451 -0
  144. package/dist/remotion-bundle/938.bundle.js.map +1 -0
  145. package/dist/remotion-bundle/967.bundle.js +4462 -0
  146. package/dist/remotion-bundle/967.bundle.js.map +1 -0
  147. package/dist/remotion-bundle/9684a1093d3c02ce.woff2 +0 -0
  148. package/dist/remotion-bundle/973dcd0faa6116cc.woff2 +0 -0
  149. package/dist/remotion-bundle/9745400694e76cd8.woff2 +0 -0
  150. package/dist/remotion-bundle/999ef957bed3bdca.woff2 +0 -0
  151. package/dist/remotion-bundle/99a3d67c8b0f43e3.woff2 +0 -0
  152. package/dist/remotion-bundle/a0586c3e03127283.woff2 +0 -0
  153. package/dist/remotion-bundle/a0eb654fdae46269.woff2 +0 -0
  154. package/dist/remotion-bundle/a20e35d3b08f7994.woff2 +0 -0
  155. package/dist/remotion-bundle/a2dcaced7c8c25ab.woff2 +0 -0
  156. package/dist/remotion-bundle/a79255a972a2681a.woff2 +0 -0
  157. package/dist/remotion-bundle/a804b352cb9fec1a.woff2 +0 -0
  158. package/dist/remotion-bundle/aae7117164e1eabc.woff2 +0 -0
  159. package/dist/remotion-bundle/affd121385d0442d.woff2 +0 -0
  160. package/dist/remotion-bundle/b19a6083987ee0d7.woff2 +0 -0
  161. package/dist/remotion-bundle/b1b2bd04d8637981.woff2 +0 -0
  162. package/dist/remotion-bundle/b2c07f341486be87.woff2 +0 -0
  163. package/dist/remotion-bundle/b33d8f82e575c4ce.woff2 +0 -0
  164. package/dist/remotion-bundle/b366c0bed35ef491.woff2 +0 -0
  165. package/dist/remotion-bundle/b41e857ec1b85642.woff2 +0 -0
  166. package/dist/remotion-bundle/b420bb34ccf23e7f.woff2 +0 -0
  167. package/dist/remotion-bundle/b4f7bf4efb0c0ccf.woff2 +0 -0
  168. package/dist/remotion-bundle/b60fe5eca03cff93.woff2 +0 -0
  169. package/dist/remotion-bundle/b6bd31a336e64bce.woff2 +0 -0
  170. package/dist/remotion-bundle/b6d2befba3dfefeb.woff2 +0 -0
  171. package/dist/remotion-bundle/b75f39ab06c43bf4.woff2 +0 -0
  172. package/dist/remotion-bundle/b77880e8c413d4fd.woff2 +0 -0
  173. package/dist/remotion-bundle/b7e38ec441e4a77a.woff2 +0 -0
  174. package/dist/remotion-bundle/b83baa383ff0bf2b.woff2 +0 -0
  175. package/dist/remotion-bundle/b9ad7b6c0a11450a.woff2 +0 -0
  176. package/dist/remotion-bundle/baf84486e8ae3aaf.woff2 +0 -0
  177. package/dist/remotion-bundle/bc047b1f6869cffa.woff2 +0 -0
  178. package/dist/remotion-bundle/bf4f3ac6e93f33aa.woff2 +0 -0
  179. package/dist/remotion-bundle/bf6835ffec5897a2.woff2 +0 -0
  180. package/dist/remotion-bundle/bf8885f581eb1724.woff2 +0 -0
  181. package/dist/remotion-bundle/bundle.js +83376 -0
  182. package/dist/remotion-bundle/bundle.js.map +1 -0
  183. package/dist/remotion-bundle/c03f046bccd789d0.woff2 +0 -0
  184. package/dist/remotion-bundle/c0bb1f8962b73bc3.woff2 +0 -0
  185. package/dist/remotion-bundle/c1003f9a7db6e1cf.woff2 +0 -0
  186. package/dist/remotion-bundle/c15d83fb1e199515.woff2 +0 -0
  187. package/dist/remotion-bundle/c28e7e5d310f73ef.woff2 +0 -0
  188. package/dist/remotion-bundle/c2b840274db78aea.woff2 +0 -0
  189. package/dist/remotion-bundle/c3000e3299d4e45f.woff2 +0 -0
  190. package/dist/remotion-bundle/c83ce886e5288510.woff2 +0 -0
  191. package/dist/remotion-bundle/c87a5a64d4ac0918.woff2 +0 -0
  192. package/dist/remotion-bundle/c8a7e0d049e965fa.woff2 +0 -0
  193. package/dist/remotion-bundle/c949a35d3a3b1faf.woff2 +0 -0
  194. package/dist/remotion-bundle/c9618c9b9ac2bc78.woff2 +0 -0
  195. package/dist/remotion-bundle/ca3add3b84152d5b.woff2 +0 -0
  196. package/dist/remotion-bundle/cad9dd036408d707.woff2 +0 -0
  197. package/dist/remotion-bundle/cbb24916619df439.woff2 +0 -0
  198. package/dist/remotion-bundle/cc054f0b5514e177.woff2 +0 -0
  199. package/dist/remotion-bundle/ccc248ed9312bc71.woff2 +0 -0
  200. package/dist/remotion-bundle/cd9d623aa07af925.woff2 +0 -0
  201. package/dist/remotion-bundle/ce2ba7a321bd1247.woff2 +0 -0
  202. package/dist/remotion-bundle/cf72455f79a29b14.woff2 +0 -0
  203. package/dist/remotion-bundle/d267cbfefab452ac.woff2 +0 -0
  204. package/dist/remotion-bundle/d435cff46a64955f.woff +0 -0
  205. package/dist/remotion-bundle/d494d07f67e363f6.woff2 +0 -0
  206. package/dist/remotion-bundle/d7aa0cc1fa47bf38.woff2 +0 -0
  207. package/dist/remotion-bundle/d7c5ca93d885160a.woff2 +0 -0
  208. package/dist/remotion-bundle/d855d3e252db74e2.woff2 +0 -0
  209. package/dist/remotion-bundle/d8f13d47f02f82c2.woff2 +0 -0
  210. package/dist/remotion-bundle/d9567cce2ee11019.woff2 +0 -0
  211. package/dist/remotion-bundle/db8d4456fc75dd86.woff +0 -0
  212. package/dist/remotion-bundle/dc274628378c47ee.woff2 +0 -0
  213. package/dist/remotion-bundle/dc3e06947bb69903.woff2 +0 -0
  214. package/dist/remotion-bundle/dd67040ac3b6d523.woff2 +0 -0
  215. package/dist/remotion-bundle/e0b04bd488f953f4.woff2 +0 -0
  216. package/dist/remotion-bundle/e2a572ff95089370.woff2 +0 -0
  217. package/dist/remotion-bundle/e2e18a86b1c2b0cc.woff2 +0 -0
  218. package/dist/remotion-bundle/e3a78ee2fc9c6931.woff2 +0 -0
  219. package/dist/remotion-bundle/e654c9d547605a9f.woff2 +0 -0
  220. package/dist/remotion-bundle/e67a3a64c129927c.woff2 +0 -0
  221. package/dist/remotion-bundle/e6be28b4203cd6ce.woff2 +0 -0
  222. package/dist/remotion-bundle/e841907ad9b0a191.woff +0 -0
  223. package/dist/remotion-bundle/e889d1541c69fffa.woff2 +0 -0
  224. package/dist/remotion-bundle/e88ef8c76373a9e2.woff2 +0 -0
  225. package/dist/remotion-bundle/e9c72f4bc37defef.woff2 +0 -0
  226. package/dist/remotion-bundle/e9e35f863403a255.woff2 +0 -0
  227. package/dist/remotion-bundle/eb23b37b009375da.woff2 +0 -0
  228. package/dist/remotion-bundle/ee1342b741625721.woff2 +0 -0
  229. package/dist/remotion-bundle/f07da88543a57ec9.woff2 +0 -0
  230. package/dist/remotion-bundle/f522982115306f8a.woff2 +0 -0
  231. package/dist/remotion-bundle/f8449bd864e6d8bc.woff2 +0 -0
  232. package/dist/remotion-bundle/f906dd5bd95ff9ab.woff2 +0 -0
  233. package/dist/remotion-bundle/f9e9e9413e3c38bb.woff2 +0 -0
  234. package/dist/remotion-bundle/fa5a5b16280994a8.woff2 +0 -0
  235. package/dist/remotion-bundle/favicon.ico +0 -0
  236. package/dist/remotion-bundle/fb19c0517725599b.woff2 +0 -0
  237. package/dist/remotion-bundle/fcaf24232f684b9b.woff2 +0 -0
  238. package/dist/remotion-bundle/fe09e084a3eea8cf.woff2 +0 -0
  239. package/dist/remotion-bundle/ff38d5317df7345a.woff2 +0 -0
  240. package/dist/remotion-bundle/ffe7ea1ea08f455a.woff2 +0 -0
  241. package/dist/remotion-bundle/index.html +49 -0
  242. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/0.mp3 +0 -0
  243. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/1.mp3 +0 -0
  244. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/2.mp3 +0 -0
  245. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/3.mp3 +0 -0
  246. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/0.mp3 +0 -0
  247. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/1.mp3 +0 -0
  248. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/2.mp3 +0 -0
  249. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/3.mp3 +0 -0
  250. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/0.mp3 +0 -0
  251. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/1.mp3 +0 -0
  252. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/2.mp3 +0 -0
  253. package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/3.mp3 +0 -0
  254. package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/0.mp3 +0 -0
  255. package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/1.mp3 +0 -0
  256. package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/2.mp3 +0 -0
  257. package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/3.mp3 +0 -0
  258. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/0.mp3 +0 -0
  259. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/1.mp3 +0 -0
  260. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/2.mp3 +0 -0
  261. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/3.mp3 +0 -0
  262. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/0.mp3 +0 -0
  263. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/1.mp3 +0 -0
  264. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/2.mp3 +0 -0
  265. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/3.mp3 +0 -0
  266. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/0.mp3 +0 -0
  267. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/1.mp3 +0 -0
  268. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/2.mp3 +0 -0
  269. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/3.mp3 +0 -0
  270. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/0.mp3 +0 -0
  271. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/1.mp3 +0 -0
  272. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/2.mp3 +0 -0
  273. package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/3.mp3 +0 -0
  274. package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/0.mp3 +0 -0
  275. package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/1.mp3 +0 -0
  276. package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/2.mp3 +0 -0
  277. package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/3.mp3 +0 -0
  278. package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/0.mp3 +0 -0
  279. package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/1.mp3 +0 -0
  280. package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/2.mp3 +0 -0
  281. package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/3.mp3 +0 -0
  282. package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/0.mp3 +0 -0
  283. package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/1.mp3 +0 -0
  284. package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/2.mp3 +0 -0
  285. package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/3.mp3 +0 -0
  286. package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/4.mp3 +0 -0
  287. package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/0.mp3 +0 -0
  288. package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/1.mp3 +0 -0
  289. package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/2.mp3 +0 -0
  290. package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/3.mp3 +0 -0
  291. package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/0.mp3 +0 -0
  292. package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/1.mp3 +0 -0
  293. package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/2.mp3 +0 -0
  294. package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/3.mp3 +0 -0
  295. package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/4.mp3 +0 -0
  296. package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/0.mp3 +0 -0
  297. package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/1.mp3 +0 -0
  298. package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/2.mp3 +0 -0
  299. package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/3.mp3 +0 -0
  300. package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/4.mp3 +0 -0
  301. package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/0.mp3 +0 -0
  302. package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/1.mp3 +0 -0
  303. package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/2.mp3 +0 -0
  304. package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/3.mp3 +0 -0
  305. package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/4.mp3 +0 -0
  306. package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/0.mp3 +0 -0
  307. package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/1.mp3 +0 -0
  308. package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/2.mp3 +0 -0
  309. package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/3.mp3 +0 -0
  310. package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/4.mp3 +0 -0
  311. package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/0.mp3 +0 -0
  312. package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/1.mp3 +0 -0
  313. package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/2.mp3 +0 -0
  314. package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/3.mp3 +0 -0
  315. package/dist/remotion-bundle/public/paper-slide-experiments/product-update/0.mp3 +0 -0
  316. package/dist/remotion-bundle/public/paper-slide-experiments/product-update/1.mp3 +0 -0
  317. package/dist/remotion-bundle/public/paper-slide-experiments/product-update/2.mp3 +0 -0
  318. package/dist/remotion-bundle/public/paper-slide-experiments/product-update/3.mp3 +0 -0
  319. package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/0.mp3 +0 -0
  320. package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/1.mp3 +0 -0
  321. package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/2.mp3 +0 -0
  322. package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/3.mp3 +0 -0
  323. package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/0.mp3 +0 -0
  324. package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/1.mp3 +0 -0
  325. package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/2.mp3 +0 -0
  326. package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/3.mp3 +0 -0
  327. package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/4.mp3 +0 -0
  328. package/dist/remotion-bundle/public/voiceover/ai-life/card-0.mp3 +0 -0
  329. package/dist/remotion-bundle/public/voiceover/ai-life/card-1.mp3 +0 -0
  330. package/dist/remotion-bundle/public/voiceover/ai-life/card-2.mp3 +0 -0
  331. package/dist/remotion-bundle/public/voiceover/ai-life/card-3.mp3 +0 -0
  332. package/dist/remotion-bundle/public/voiceover/ai-life/card-4.mp3 +0 -0
  333. package/dist/remotion-bundle/public/voiceover/ai-life/card-5.mp3 +0 -0
  334. package/dist/remotion-bundle/public/voiceover/coffee-science/card-0.mp3 +0 -0
  335. package/dist/remotion-bundle/public/voiceover/coffee-science/card-1.mp3 +0 -0
  336. package/dist/remotion-bundle/public/voiceover/coffee-science/card-2.mp3 +0 -0
  337. package/dist/remotion-bundle/public/voiceover/coffee-science/card-3.mp3 +0 -0
  338. package/dist/remotion-bundle/public/voiceover/coffee-science/card-4.mp3 +0 -0
  339. package/dist/remotion-bundle/public/voiceover/coffee-science/card-5.mp3 +0 -0
  340. package/dist/remotion-bundle/public/voiceover/coffee-science/card-6.mp3 +0 -0
  341. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-0.mp3 +0 -0
  342. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-1.mp3 +0 -0
  343. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-2.mp3 +0 -0
  344. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-3.mp3 +0 -0
  345. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-4.mp3 +0 -0
  346. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-5.mp3 +0 -0
  347. package/dist/remotion-bundle/public/voiceover/reading-secrets/card-6.mp3 +0 -0
  348. package/dist/remotion-bundle/public/voiceover/remote-work/card-0.mp3 +0 -0
  349. package/dist/remotion-bundle/public/voiceover/remote-work/card-1.mp3 +0 -0
  350. package/dist/remotion-bundle/public/voiceover/remote-work/card-2.mp3 +0 -0
  351. package/dist/remotion-bundle/public/voiceover/remote-work/card-3.mp3 +0 -0
  352. package/dist/remotion-bundle/public/voiceover/remote-work/card-4.mp3 +0 -0
  353. package/dist/remotion-bundle/public/voiceover/remote-work/card-5.mp3 +0 -0
  354. package/dist/remotion-bundle/source-map-helper.wasm +0 -0
  355. package/lib/cli.js +270 -0
  356. package/lib/commands/_registry.js +48 -0
  357. package/lib/commands/add.js +242 -0
  358. package/lib/commands/asr/azure-transcribe.js +336 -0
  359. package/lib/commands/asr/cloud-transcribe.js +384 -0
  360. package/lib/commands/asr/helpers.js +76 -0
  361. package/lib/commands/asr/index.js +236 -0
  362. package/lib/commands/asr/local-transcribe.js +125 -0
  363. package/lib/commands/asr-jobs.js +257 -0
  364. package/lib/commands/asr.js +11 -0
  365. package/lib/commands/auth-cmds.js +358 -0
  366. package/lib/commands/dub.js +542 -0
  367. package/lib/commands/explain.js +512 -0
  368. package/lib/commands/feedback.js +152 -0
  369. package/lib/commands/image.js +207 -0
  370. package/lib/commands/mcp-key.js +166 -0
  371. package/lib/commands/narrate.js +639 -0
  372. package/lib/commands/picstory-templates.js +276 -0
  373. package/lib/commands/picstory.js +547 -0
  374. package/lib/commands/podcast/dialogue.js +109 -0
  375. package/lib/commands/podcast/generate.js +127 -0
  376. package/lib/commands/podcast/index.js +561 -0
  377. package/lib/commands/podcast/synthesize.js +188 -0
  378. package/lib/commands/podcast.js +11 -0
  379. package/lib/commands/present.js +519 -0
  380. package/lib/commands/publish.js +415 -0
  381. package/lib/commands/skills.js +473 -0
  382. package/lib/commands/slice-render.js +282 -0
  383. package/lib/commands/slice-stage.js +264 -0
  384. package/lib/commands/slice.js +346 -0
  385. package/lib/commands/slides/constants.js +108 -0
  386. package/lib/commands/slides/html-renderer.js +338 -0
  387. package/lib/commands/slides/index.js +345 -0
  388. package/lib/commands/slides.js +11 -0
  389. package/lib/commands/story.js +302 -0
  390. package/lib/commands/summarize.js +532 -0
  391. package/lib/commands/synthesize.js +261 -0
  392. package/lib/commands/translate.js +593 -0
  393. package/lib/commands/upgrade.js +249 -0
  394. package/lib/commands/video-translate.js +577 -0
  395. package/lib/commands/voices.js +292 -0
  396. package/lib/core/agent-env.js +104 -0
  397. package/lib/core/args.js +107 -0
  398. package/lib/core/asr-client.js +448 -0
  399. package/lib/core/asr-jobs-client.js +126 -0
  400. package/lib/core/asr-jobs-store.js +105 -0
  401. package/lib/core/asr-r2-upload.js +181 -0
  402. package/lib/core/asr-upload.js +132 -0
  403. package/lib/core/audio-extract.js +150 -0
  404. package/lib/core/audio.js +219 -0
  405. package/lib/core/auth.js +880 -0
  406. package/lib/core/config.js +197 -0
  407. package/lib/core/feedback.js +64 -0
  408. package/lib/core/ffmpeg.js +476 -0
  409. package/lib/core/http.js +188 -0
  410. package/lib/core/image-client.js +55 -0
  411. package/lib/core/intent-params.js +11 -0
  412. package/lib/core/llm-client.js +76 -0
  413. package/lib/core/logger.js +208 -0
  414. package/lib/core/mic-recorder.js +182 -0
  415. package/lib/core/pause-markers.js +94 -0
  416. package/lib/core/podcast-pacing.js +118 -0
  417. package/lib/core/spinner.js +33 -0
  418. package/lib/core/srt.js +394 -0
  419. package/lib/core/telemetry.js +100 -0
  420. package/lib/core/timeline.js +92 -0
  421. package/lib/core/tts-synthesizer.js +70 -0
  422. package/lib/core/update-check.js +185 -0
  423. package/lib/core/url-download.js +148 -0
  424. package/lib/core/whisper-local.js +279 -0
  425. package/lib/internal/deck-validator.js +488 -0
  426. package/lib/internal/slice-themes.json +370 -0
  427. package/lib/stage-core/cloud-render.js +170 -0
  428. package/lib/stage-core/deck-format.js +133 -0
  429. package/lib/stage-core/edit-prompt.js +104 -0
  430. package/lib/stage-core/event-bus.js +31 -0
  431. package/lib/stage-core/port.js +46 -0
  432. package/lib/stage-core/server.js +352 -0
  433. package/lib/stage-core/snapshot-store.js +198 -0
  434. package/lib/stage-core/watcher.js +106 -0
  435. package/lib/stage-ui/slice/template.js +1672 -0
  436. package/package.json +9 -4
  437. package/skills/.claude-plugin/marketplace.json +22 -0
  438. package/skills/.claude-plugin/plugin.json +25 -0
  439. package/skills/LICENSE +21 -0
  440. package/skills/README.md +120 -0
  441. package/skills/hub/SKILL.md +317 -0
  442. package/skills/podcast/SKILL.md +146 -0
  443. package/skills/slice/SKILL.md +205 -0
  444. package/skills/slice/agents/openai.yaml +4 -0
  445. package/skills/slice/references/deck-schema.md +183 -0
  446. package/skills/slice/references/example-decks.md +108 -0
  447. package/skills/slice/references/themes.md +172 -0
  448. package/skills/transcribe/SKILL.md +473 -0
  449. package/skills/video/SKILL.md +261 -0
  450. package/skills/voxflow-slice/SKILL.md +271 -0
  451. package/skills/voxflow-slice/examples/article.md +13 -0
  452. package/skills/voxflow-slice/examples/expected-deck.json +39 -0
  453. package/skills/voxflow-slice/examples/validate.mjs +46 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * VoxFlow CLI — Timeline audio builder
3
+ *
4
+ * Places audio segments at precise millisecond positions on a timeline,
5
+ * filling gaps with silence. Used for dubbing where each caption must
6
+ * start at its exact SRT timestamp.
7
+ *
8
+ * Audio format: 24kHz, 16-bit, mono PCM (matches TTS API output).
9
+ */
10
+
11
+ const { buildWav } = require('./audio');
12
+
13
+ const SAMPLE_RATE = 24000;
14
+ const BYTES_PER_SAMPLE = 2; // 16-bit
15
+ const BYTES_PER_MS = (SAMPLE_RATE * BYTES_PER_SAMPLE) / 1000; // 48 bytes/ms
16
+
17
+ /**
18
+ * Convert milliseconds to PCM byte offset.
19
+ * @param {number} ms - Time in milliseconds
20
+ * @returns {number} Byte offset (even number, aligned to sample boundary)
21
+ */
22
+ function msToBytes(ms) {
23
+ const bytes = Math.round(ms * BYTES_PER_MS);
24
+ // Ensure alignment to 2-byte (sample) boundary
25
+ return bytes - (bytes % BYTES_PER_SAMPLE);
26
+ }
27
+
28
+ /**
29
+ * Build a single PCM buffer with audio segments placed at their timeline positions.
30
+ *
31
+ * @param {Array<{startMs: number, endMs: number, audioBuffer: Buffer}>} segments
32
+ * Audio segments with their target start/end times.
33
+ * audioBuffer is raw PCM data (24kHz, 16-bit, mono).
34
+ * @param {number} [totalDurationMs] - Total timeline duration in ms.
35
+ * If omitted, uses the endMs of the last segment.
36
+ * @returns {{ pcm: Buffer, durationMs: number }}
37
+ */
38
+ function buildTimelinePcm(segments, totalDurationMs) {
39
+ if (!segments || segments.length === 0) {
40
+ return { pcm: Buffer.alloc(0), durationMs: 0 };
41
+ }
42
+
43
+ // Determine total length
44
+ const lastEndMs = Math.max(...segments.map((s) => s.endMs));
45
+ const durationMs = totalDurationMs || lastEndMs;
46
+ const totalBytes = msToBytes(durationMs);
47
+
48
+ // Allocate zero-filled buffer (silence by default)
49
+ const pcm = Buffer.alloc(totalBytes, 0);
50
+
51
+ // Place each segment at its start position
52
+ for (const seg of segments) {
53
+ const startByte = msToBytes(seg.startMs);
54
+ const slotBytes = msToBytes(seg.endMs) - startByte;
55
+
56
+ // Determine how many bytes to copy (don't exceed slot or total buffer)
57
+ const copyLen = Math.min(seg.audioBuffer.length, slotBytes, totalBytes - startByte);
58
+ if (copyLen > 0 && startByte < totalBytes) {
59
+ seg.audioBuffer.copy(pcm, startByte, 0, copyLen);
60
+ }
61
+ }
62
+
63
+ return { pcm, durationMs };
64
+ }
65
+
66
+ /**
67
+ * Build a complete WAV file with audio segments placed at timeline positions.
68
+ *
69
+ * @param {Array<{startMs: number, endMs: number, audioBuffer: Buffer}>} segments
70
+ * @param {number} [totalDurationMs]
71
+ * @returns {{ wav: Buffer, duration: number }} wav buffer and duration in seconds
72
+ */
73
+ function buildTimelineAudio(segments, totalDurationMs) {
74
+ const { pcm, durationMs } = buildTimelinePcm(segments, totalDurationMs);
75
+
76
+ if (pcm.length === 0) {
77
+ return { wav: Buffer.alloc(0), duration: 0 };
78
+ }
79
+
80
+ // Use buildWav with a single PCM buffer and zero silence gap
81
+ const { wav } = buildWav([pcm], 0);
82
+ return { wav, duration: durationMs / 1000 };
83
+ }
84
+
85
+ module.exports = {
86
+ buildTimelinePcm,
87
+ buildTimelineAudio,
88
+ msToBytes,
89
+ SAMPLE_RATE,
90
+ BYTES_PER_SAMPLE,
91
+ BYTES_PER_MS,
92
+ };
@@ -0,0 +1,70 @@
1
+ /**
2
+ * VoxFlow CLI — Shared TTS synthesis function
3
+ *
4
+ * Consolidates the duplicated TTS API call pattern from narrate, dub, story,
5
+ * and podcast commands into a single reusable function.
6
+ */
7
+
8
+ const { request, throwApiError, throwNetworkError } = require('./http');
9
+
10
+ /**
11
+ * Synthesize text to audio via the TTS API.
12
+ *
13
+ * @param {object} opts
14
+ * @param {string} opts.apiBase - API base URL
15
+ * @param {string} opts.token - JWT auth token
16
+ * @param {string} opts.text - Text to synthesize
17
+ * @param {string} opts.voiceId - TTS voice ID
18
+ * @param {number} [opts.speed=1.0] - TTS speed (0.5-2.0)
19
+ * @param {number} [opts.volume=1.0] - TTS volume (0-2.0)
20
+ * @param {number} [opts.pitch] - TTS pitch adjustment
21
+ * @param {string} [opts.format='pcm'] - Audio format: pcm | wav | mp3
22
+ * @param {number} opts.index - Current segment index (0-based)
23
+ * @param {number} opts.total - Total number of segments
24
+ * @param {string} [opts.label] - Optional label for progress output (e.g. speaker name)
25
+ * @returns {Promise<{ audio: Buffer, quota: object }>}
26
+ */
27
+ async function synthesizeTTS(opts) {
28
+ const {
29
+ apiBase, token, text, voiceId,
30
+ speed = 1.0, volume = 1.0, pitch,
31
+ format = 'pcm',
32
+ index, total, label,
33
+ } = opts;
34
+
35
+ // Progress output
36
+ const labelSuffix = label ? ` ${label}` : '';
37
+ process.stdout.write(` TTS [${index + 1}/${total}]${labelSuffix}...`);
38
+
39
+ // Build request body
40
+ const body = { text, voiceId, speed, volume, format };
41
+ if (pitch != null && pitch !== 0) body.pitch = pitch;
42
+
43
+ let status, data, headers;
44
+ try {
45
+ // 180s — server-side TTS synthesis for a long paragraph can take ~60-90s
46
+ // on first hit (cold edge) and the previous 60s default was timing out
47
+ // the very first segment of `voxflow story` (issue #2916).
48
+ ({ status, data, headers } = await request(`${apiBase}/api/tts/synthesize`, {
49
+ method: 'POST',
50
+ headers: {
51
+ 'Content-Type': 'application/json',
52
+ 'Authorization': `Bearer ${token}`,
53
+ },
54
+ timeoutMs: 180_000,
55
+ }, body));
56
+ } catch (err) {
57
+ console.log(' FAIL');
58
+ throwNetworkError(err, apiBase);
59
+ }
60
+
61
+ if (status !== 200 || data.code !== 'success') {
62
+ console.log(' FAIL');
63
+ throwApiError(status, data, `TTS segment ${index + 1}`, headers);
64
+ }
65
+
66
+ const audio = Buffer.from(data.audio, 'base64');
67
+ return { audio, quota: data.quota };
68
+ }
69
+
70
+ module.exports = { synthesizeTTS };
@@ -0,0 +1,185 @@
1
+ /**
2
+ * VoxFlow CLI — update-notifier
3
+ *
4
+ * Background check against the npm registry; prints a one-line stderr hint at
5
+ * process exit when a newer version is available. Zero runtime deps.
6
+ *
7
+ * Design:
8
+ * - Cached at `<configDir>/update-check.json`, refreshed at most once / 24h.
9
+ * - Fire-and-forget: never blocks the CLI command. Errors are swallowed.
10
+ * - Skipped when stderr is not a TTY, in CI, or when `VOXFLOW_NO_UPDATE_CHECK=1`.
11
+ * - The hint is printed at `process.on('exit')`, so it never interleaves with
12
+ * the command's own output (which finishes synchronously before exit).
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const https = require('https');
18
+
19
+ const { getConfigDir } = require('./config');
20
+
21
+ const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24h
22
+ const REGISTRY_URL = 'https://registry.npmjs.org/voxflow/latest';
23
+ const NETWORK_TIMEOUT_MS = 2_000;
24
+
25
+ function cachePath() {
26
+ return path.join(getConfigDir(), 'update-check.json');
27
+ }
28
+
29
+ function readCache() {
30
+ try {
31
+ return JSON.parse(fs.readFileSync(cachePath(), 'utf8'));
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ function writeCache(payload) {
38
+ try {
39
+ fs.mkdirSync(getConfigDir(), { recursive: true });
40
+ fs.writeFileSync(cachePath(), JSON.stringify(payload), 'utf8');
41
+ } catch {
42
+ // Cache is best-effort; ignore failures.
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Detect whether an AI agent is reading this CLI's stderr.
48
+ * We use a single explicit signal: `CLAUDECODE=1`. Other agents that want the
49
+ * structured hint can set `VOXFLOW_AGENT=1`. We intentionally do NOT treat
50
+ * generic `CI=true` as "agent reading" — many CI users still benefit from a
51
+ * fail-silent CLI, not a banner on every job.
52
+ */
53
+ function isAgentChannel() {
54
+ return process.env.CLAUDECODE === '1' || process.env.VOXFLOW_AGENT === '1';
55
+ }
56
+
57
+ /**
58
+ * Decide whether the update check should run at all. Agents skip the human
59
+ * `▲` banner but still get the structured `<voxflow-hint>` tag; the test
60
+ * suite + NO_UPDATE_NOTIFIER opt-out skip everything.
61
+ */
62
+ function shouldSkip() {
63
+ if (process.env.VOXFLOW_NO_UPDATE_CHECK === '1') return true;
64
+ if (process.env.NO_UPDATE_NOTIFIER === '1') return true; // industry standard (npm, update-notifier)
65
+ if (process.env.NODE_ENV === 'test') return true;
66
+ // Skip when neither a human TTY nor an agent is reading stderr.
67
+ if (!process.stderr.isTTY && !isAgentChannel()) return true;
68
+ return false;
69
+ }
70
+
71
+ /**
72
+ * Compare semver-ish versions. Returns positive if a > b, 0 if equal, negative
73
+ * if a < b. Ignores pre-release suffixes (good enough for "is there an update").
74
+ */
75
+ function cmpVersion(a, b) {
76
+ const parse = (v) => String(v).split('-')[0].split('.').map((n) => parseInt(n, 10) || 0);
77
+ const pa = parse(a);
78
+ const pb = parse(b);
79
+ for (let i = 0; i < 3; i++) {
80
+ const diff = (pa[i] || 0) - (pb[i] || 0);
81
+ if (diff !== 0) return diff;
82
+ }
83
+ return 0;
84
+ }
85
+
86
+ function fetchLatest() {
87
+ return new Promise((resolve, reject) => {
88
+ const req = https.get(REGISTRY_URL, { timeout: NETWORK_TIMEOUT_MS }, (res) => {
89
+ if (res.statusCode !== 200) {
90
+ res.resume();
91
+ reject(new Error(`registry HTTP ${res.statusCode}`));
92
+ return;
93
+ }
94
+ let body = '';
95
+ res.setEncoding('utf8');
96
+ res.on('data', (chunk) => { body += chunk; });
97
+ res.on('end', () => {
98
+ try {
99
+ const json = JSON.parse(body);
100
+ if (typeof json.version === 'string') resolve(json.version);
101
+ else reject(new Error('no version field'));
102
+ } catch (err) {
103
+ reject(err);
104
+ }
105
+ });
106
+ });
107
+ req.on('error', reject);
108
+ req.on('timeout', () => { req.destroy(new Error('timeout')); });
109
+ });
110
+ }
111
+
112
+ /**
113
+ * Kick off an update check. Non-blocking. Schedules a stderr hint at exit
114
+ * if a newer version is available (either from cache or a fresh fetch).
115
+ *
116
+ * @param {string} currentVersion - from package.json
117
+ */
118
+ function scheduleUpdateCheck(currentVersion) {
119
+ if (shouldSkip() || !currentVersion) return;
120
+
121
+ const cached = readCache();
122
+ const now = Date.now();
123
+ const fresh = cached && typeof cached.checkedAt === 'number' && (now - cached.checkedAt) < CHECK_INTERVAL_MS;
124
+
125
+ // If cache is fresh and reports a newer version, queue the hint now.
126
+ if (fresh && cached.latest && cmpVersion(cached.latest, currentVersion) > 0) {
127
+ queueHint(currentVersion, cached.latest);
128
+ return;
129
+ }
130
+
131
+ // Otherwise, fetch in the background. Don't await — the process can exit
132
+ // earlier; that's fine, we'll just check again on the next run.
133
+ fetchLatest()
134
+ .then((latest) => {
135
+ writeCache({ latest, checkedAt: now });
136
+ if (cmpVersion(latest, currentVersion) > 0) queueHint(currentVersion, latest);
137
+ })
138
+ .catch(() => { /* swallow — update check is best-effort */ });
139
+ }
140
+
141
+ let hintQueued = false;
142
+ /**
143
+ * Render the hint line(s) for a (current, latest) version pair.
144
+ * Returns the exact stderr string (or empty string when nothing to emit).
145
+ *
146
+ * The agent line is a stable, regex-parseable contract — SKILL.md grep-rules
147
+ * depend on this format. Don't reorder attrs or change tag name without
148
+ * updating cli/skills/hub/SKILL.md in the same commit.
149
+ */
150
+ function renderHintLines(current, latest, { agent, human }) {
151
+ const lines = [];
152
+ if (agent) {
153
+ // Mirrors the shape of Anthropic's <claude-code-hint v="1" type="plugin" .../>
154
+ // (the only structured agent-targeted hint protocol in the wild today).
155
+ // type="cli-outdated" is our own, forward-compatible; Anthropic may
156
+ // someday standardize a variant we can swap in.
157
+ lines.push(
158
+ `<voxflow-hint v="1" type="cli-outdated" current="${current}" latest="${latest}" action="voxflow upgrade -y" />`
159
+ );
160
+ }
161
+ if (human) {
162
+ lines.push(
163
+ `\x1b[2m▲ voxflow ${current} → ${latest} available · run \`voxflow upgrade -y\` (or \`npm i -g voxflow@latest\`)\x1b[0m`
164
+ );
165
+ }
166
+ return lines.length ? '\n' + lines.join('\n') + '\n' : '';
167
+ }
168
+
169
+ function queueHint(current, latest) {
170
+ if (hintQueued) return;
171
+ hintQueued = true;
172
+ process.on('exit', () => {
173
+ const out = renderHintLines(current, latest, {
174
+ agent: isAgentChannel(),
175
+ human: process.stderr.isTTY && !isAgentChannel(),
176
+ });
177
+ if (out) process.stderr.write(out);
178
+ });
179
+ }
180
+
181
+ module.exports = {
182
+ scheduleUpdateCheck,
183
+ // Exposed for tests:
184
+ _test: { cmpVersion, shouldSkip, cachePath, readCache, writeCache, isAgentChannel, renderHintLines },
185
+ };
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Stream a remote URL to a temp file.
5
+ *
6
+ * Used by `voxflow asr --url` to work around Tencent Flash ASR not being
7
+ * able to resolve arbitrary external hosts — we fetch the file ourselves,
8
+ * then re-upload it via the existing Supabase Storage path.
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const os = require('os');
13
+ const path = require('path');
14
+ const http = require('http');
15
+ const https = require('https');
16
+
17
+ const MAX_DOWNLOAD_BYTES = 500 * 1024 * 1024; // 500 MB hard cap
18
+
19
+ function pickClient(urlObj) {
20
+ if (urlObj.protocol === 'https:') return https;
21
+ if (urlObj.protocol === 'http:') return http;
22
+ return null;
23
+ }
24
+
25
+ function suggestExt(urlObj, contentType) {
26
+ const fromPath = path.extname(urlObj.pathname);
27
+ if (fromPath && fromPath.length <= 5) return fromPath;
28
+ if (contentType) {
29
+ const ct = contentType.split(';')[0].trim().toLowerCase();
30
+ if (ct === 'audio/mpeg') return '.mp3';
31
+ if (ct === 'audio/wav' || ct === 'audio/x-wav') return '.wav';
32
+ if (ct === 'audio/ogg') return '.ogg';
33
+ if (ct === 'audio/mp4' || ct === 'audio/m4a') return '.m4a';
34
+ if (ct === 'audio/flac') return '.flac';
35
+ if (ct === 'video/mp4') return '.mp4';
36
+ }
37
+ return '.bin';
38
+ }
39
+
40
+ /**
41
+ * Download `url` to a temp file. Follows up to 5 redirects.
42
+ *
43
+ * @param {string} url
44
+ * @param {object} [opts]
45
+ * @param {(received: number, total: number|null) => void} [opts.onProgress]
46
+ * @param {number} [opts.maxBytes] hard cap, default 500 MB
47
+ * @returns {Promise<{ filePath: string, size: number }>}
48
+ */
49
+ async function downloadUrlToTempFile(url, opts = {}) {
50
+ const maxBytes = opts.maxBytes ?? MAX_DOWNLOAD_BYTES;
51
+ const onProgress = opts.onProgress || (() => {});
52
+
53
+ return new Promise((resolve, reject) => {
54
+ const visited = new Set();
55
+ const start = (target, redirectsLeft) => {
56
+ let urlObj;
57
+ try {
58
+ urlObj = new URL(target);
59
+ } catch {
60
+ reject(new Error(`Invalid URL: ${target}`));
61
+ return;
62
+ }
63
+
64
+ const client = pickClient(urlObj);
65
+ if (!client) {
66
+ reject(new Error(`Unsupported URL scheme: ${urlObj.protocol} (use http or https)`));
67
+ return;
68
+ }
69
+
70
+ if (visited.has(target)) {
71
+ reject(new Error(`Redirect loop detected at ${target}`));
72
+ return;
73
+ }
74
+ visited.add(target);
75
+
76
+ const req = client.get(target, { headers: { 'User-Agent': 'voxflow-cli' } }, (res) => {
77
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
78
+ if (redirectsLeft <= 0) {
79
+ res.resume();
80
+ reject(new Error('Too many redirects (>5)'));
81
+ return;
82
+ }
83
+ const next = new URL(res.headers.location, target).toString();
84
+ res.resume();
85
+ start(next, redirectsLeft - 1);
86
+ return;
87
+ }
88
+ if (res.statusCode !== 200) {
89
+ res.resume();
90
+ reject(new Error(`Download failed: HTTP ${res.statusCode} for ${target}`));
91
+ return;
92
+ }
93
+
94
+ const contentLength = res.headers['content-length']
95
+ ? parseInt(res.headers['content-length'], 10)
96
+ : null;
97
+ if (contentLength != null && contentLength > maxBytes) {
98
+ res.resume();
99
+ reject(new Error(`Remote file too large (${contentLength} bytes, max ${maxBytes})`));
100
+ return;
101
+ }
102
+
103
+ const ext = suggestExt(urlObj, res.headers['content-type']);
104
+ const filePath = path.join(
105
+ os.tmpdir(),
106
+ `voxflow-asr-${Date.now()}-${Math.random().toString(36).slice(2, 8)}${ext}`
107
+ );
108
+ const out = fs.createWriteStream(filePath);
109
+ let received = 0;
110
+ let aborted = false;
111
+
112
+ res.on('data', (chunk) => {
113
+ if (aborted) return;
114
+ received += chunk.length;
115
+ if (received > maxBytes) {
116
+ aborted = true;
117
+ out.destroy();
118
+ res.destroy();
119
+ try { fs.unlinkSync(filePath); } catch { /* ignore */ }
120
+ reject(new Error(`Remote file exceeded ${maxBytes} bytes during download`));
121
+ return;
122
+ }
123
+ onProgress(received, contentLength);
124
+ });
125
+
126
+ res.pipe(out);
127
+
128
+ out.on('finish', () => {
129
+ if (aborted) return;
130
+ out.close(() => resolve({ filePath, size: received }));
131
+ });
132
+ out.on('error', (err) => {
133
+ try { fs.unlinkSync(filePath); } catch { /* ignore */ }
134
+ reject(err);
135
+ });
136
+ });
137
+
138
+ req.on('error', reject);
139
+ req.setTimeout(60_000, () => {
140
+ req.destroy(new Error(`Download timed out after 60s: ${target}`));
141
+ });
142
+ };
143
+
144
+ start(url, 5);
145
+ });
146
+ }
147
+
148
+ module.exports = { downloadUrlToTempFile, MAX_DOWNLOAD_BYTES };