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.
- package/README.md +34 -0
- package/bin/voxflow.js +27 -0
- package/dist/index.js +1 -1
- package/dist/remotion-bundle/02a2fb2eb80bc7bf.woff2 +0 -0
- package/dist/remotion-bundle/052ca5351e5e06ba.woff2 +0 -0
- package/dist/remotion-bundle/05853dd28f4019cb.woff2 +0 -0
- package/dist/remotion-bundle/072ead3737f7c0d0.woff2 +0 -0
- package/dist/remotion-bundle/07d4248613c86a2e.woff2 +0 -0
- package/dist/remotion-bundle/0884a5c2d1d2d99b.woff2 +0 -0
- package/dist/remotion-bundle/0b0e185b2752095e.woff2 +0 -0
- package/dist/remotion-bundle/0e66c11bde067d91.woff2 +0 -0
- package/dist/remotion-bundle/0f7794cfba2c5d21.woff2 +0 -0
- package/dist/remotion-bundle/0fdbae5a4365783a.woff2 +0 -0
- package/dist/remotion-bundle/112.bundle.js +11 -0
- package/dist/remotion-bundle/112.bundle.js.map +1 -0
- package/dist/remotion-bundle/113.bundle.js +11 -0
- package/dist/remotion-bundle/113.bundle.js.map +1 -0
- package/dist/remotion-bundle/119cae0c4c16f7ed.woff2 +0 -0
- package/dist/remotion-bundle/14725f649fd1e78c.woff2 +0 -0
- package/dist/remotion-bundle/14abe9e3f95f7888.woff2 +0 -0
- package/dist/remotion-bundle/163.bundle.js +14678 -0
- package/dist/remotion-bundle/163.bundle.js.map +1 -0
- package/dist/remotion-bundle/1808c54072bf6d14.woff2 +0 -0
- package/dist/remotion-bundle/18948bec3e3012fe.woff2 +0 -0
- package/dist/remotion-bundle/1a661c60d0fc84fc.woff2 +0 -0
- package/dist/remotion-bundle/1af94941e1bc7e1e.woff2 +0 -0
- package/dist/remotion-bundle/1bee0219595f606c.woff2 +0 -0
- package/dist/remotion-bundle/1bfd5da7ce9d4ec4.woff2 +0 -0
- package/dist/remotion-bundle/1c158d56f1884f3f.woff2 +0 -0
- package/dist/remotion-bundle/1cf5e88e667610eb.woff2 +0 -0
- package/dist/remotion-bundle/1d431bd10f53c481.woff2 +0 -0
- package/dist/remotion-bundle/1d701a81a7670db2.woff2 +0 -0
- package/dist/remotion-bundle/1da0fecad4240f16.woff2 +0 -0
- package/dist/remotion-bundle/1ed14d3d0c5c63fe.woff2 +0 -0
- package/dist/remotion-bundle/1edfecf40e586f53.woff2 +0 -0
- package/dist/remotion-bundle/1f479711bc34b054.woff +0 -0
- package/dist/remotion-bundle/1f86e54a0ff5fcd1.woff2 +0 -0
- package/dist/remotion-bundle/2043ea87d9aabd11.woff2 +0 -0
- package/dist/remotion-bundle/20563c39ee8a0e40.woff2 +0 -0
- package/dist/remotion-bundle/20c231590fd12c44.woff2 +0 -0
- package/dist/remotion-bundle/20ce61713f754c07.woff2 +0 -0
- package/dist/remotion-bundle/21eb9306fce24bb1.woff2 +0 -0
- package/dist/remotion-bundle/244bf71c0cc851af.woff2 +0 -0
- package/dist/remotion-bundle/274d4cfc02bffbcb.woff2 +0 -0
- package/dist/remotion-bundle/275.bundle.js +21 -0
- package/dist/remotion-bundle/275.bundle.js.map +1 -0
- package/dist/remotion-bundle/2958f540b39513dc.woff2 +0 -0
- package/dist/remotion-bundle/2a168b98fd97722e.woff2 +0 -0
- package/dist/remotion-bundle/2d1f6373937ab55f.woff2 +0 -0
- package/dist/remotion-bundle/2d213ae47ff6daa9.woff2 +0 -0
- package/dist/remotion-bundle/2e4b1f04fcd05047.woff2 +0 -0
- package/dist/remotion-bundle/304170d98f4c4563.woff2 +0 -0
- package/dist/remotion-bundle/30d02e136e7a5642.woff2 +0 -0
- package/dist/remotion-bundle/3135562b52a714cd.woff2 +0 -0
- package/dist/remotion-bundle/313713af2c8144e9.woff2 +0 -0
- package/dist/remotion-bundle/325fa4108d2285b9.woff2 +0 -0
- package/dist/remotion-bundle/338e927ed3345e0c.woff2 +0 -0
- package/dist/remotion-bundle/35fc6b190365bc17.woff2 +0 -0
- package/dist/remotion-bundle/37a51f1122d4efc5.woff2 +0 -0
- package/dist/remotion-bundle/39a4d63e02736f5e.woff2 +0 -0
- package/dist/remotion-bundle/3a00e0d62dfc4171.woff2 +0 -0
- package/dist/remotion-bundle/3a6955e6561affe1.woff2 +0 -0
- package/dist/remotion-bundle/3c573945aef49b89.woff2 +0 -0
- package/dist/remotion-bundle/3cdbfbfa23b516a5.woff2 +0 -0
- package/dist/remotion-bundle/3e42f85a9e64ca8a.woff2 +0 -0
- package/dist/remotion-bundle/3e83eaf1ec859415.woff2 +0 -0
- package/dist/remotion-bundle/3f3c8c90de1250ee.woff2 +0 -0
- package/dist/remotion-bundle/434.bundle.js +205 -0
- package/dist/remotion-bundle/434.bundle.js.map +1 -0
- package/dist/remotion-bundle/44ffc6ca4d781692.woff2 +0 -0
- package/dist/remotion-bundle/4670d9c4580b09eb.woff2 +0 -0
- package/dist/remotion-bundle/479756881b302824.woff2 +0 -0
- package/dist/remotion-bundle/481b82134bfa9c82.woff2 +0 -0
- package/dist/remotion-bundle/48d27029626f4328.woff2 +0 -0
- package/dist/remotion-bundle/49b7b2a30329c511.woff2 +0 -0
- package/dist/remotion-bundle/4c8b25a1a9337045.woff2 +0 -0
- package/dist/remotion-bundle/4cba14788ca9259b.woff2 +0 -0
- package/dist/remotion-bundle/4cd6c589c004a6a7.woff2 +0 -0
- package/dist/remotion-bundle/4cd8d79c1021608d.woff2 +0 -0
- package/dist/remotion-bundle/4d8fa99b3f00f9f0.woff2 +0 -0
- package/dist/remotion-bundle/4e7805a643f86d53.woff2 +0 -0
- package/dist/remotion-bundle/4ff91be454542e3f.woff2 +0 -0
- package/dist/remotion-bundle/504cbcba1f63591b.woff2 +0 -0
- package/dist/remotion-bundle/5202d792e5791d6c.woff2 +0 -0
- package/dist/remotion-bundle/534db5ad4770cc1d.woff2 +0 -0
- package/dist/remotion-bundle/53b9568eb85f866b.woff2 +0 -0
- package/dist/remotion-bundle/543ad386ca171de9.woff2 +0 -0
- package/dist/remotion-bundle/54798e55bbf7976e.woff2 +0 -0
- package/dist/remotion-bundle/580.bundle.js +11 -0
- package/dist/remotion-bundle/580.bundle.js.map +1 -0
- package/dist/remotion-bundle/58d174d1193af6d1.woff2 +0 -0
- package/dist/remotion-bundle/591d29ff3ff53c80.woff2 +0 -0
- package/dist/remotion-bundle/5c28c4f4824383c6.woff2 +0 -0
- package/dist/remotion-bundle/5da9740d2ce894c8.woff2 +0 -0
- package/dist/remotion-bundle/6197735364642360.woff2 +0 -0
- package/dist/remotion-bundle/6265a4335724080f.woff2 +0 -0
- package/dist/remotion-bundle/633f5e4f6394daa7.woff2 +0 -0
- package/dist/remotion-bundle/637d95ace6a69c49.woff2 +0 -0
- package/dist/remotion-bundle/648e04a04dacff8f.woff2 +0 -0
- package/dist/remotion-bundle/64a6e83045a008b2.woff2 +0 -0
- package/dist/remotion-bundle/651.bundle.js +11 -0
- package/dist/remotion-bundle/651.bundle.js.map +1 -0
- package/dist/remotion-bundle/65e2a988c070facc.woff2 +0 -0
- package/dist/remotion-bundle/66a2f6ce5cc69105.woff2 +0 -0
- package/dist/remotion-bundle/690.bundle.js +3479 -0
- package/dist/remotion-bundle/690.bundle.js.map +1 -0
- package/dist/remotion-bundle/690ff55252ca715d.woff2 +0 -0
- package/dist/remotion-bundle/6a01a1cff49314fc.woff2 +0 -0
- package/dist/remotion-bundle/6cbc32670982986c.woff2 +0 -0
- package/dist/remotion-bundle/6d3cc42ae547f454.woff2 +0 -0
- package/dist/remotion-bundle/6d8f4cfa1ddc0830.woff2 +0 -0
- package/dist/remotion-bundle/6e4d7c6ae65e2dc3.woff2 +0 -0
- package/dist/remotion-bundle/6e86418bbcefb2e8.woff2 +0 -0
- package/dist/remotion-bundle/6ee02884b29cf7fb.woff2 +0 -0
- package/dist/remotion-bundle/6f436a74c9e3252c.woff2 +0 -0
- package/dist/remotion-bundle/78c8022f1657618b.woff2 +0 -0
- package/dist/remotion-bundle/7c5444169792bca4.woff2 +0 -0
- package/dist/remotion-bundle/7c86bddd9d997212.woff2 +0 -0
- package/dist/remotion-bundle/7e1284684767f584.woff2 +0 -0
- package/dist/remotion-bundle/7e81c17522d182b2.woff2 +0 -0
- package/dist/remotion-bundle/7eb87be198f7858c.woff2 +0 -0
- package/dist/remotion-bundle/8060c928f948aab5.woff2 +0 -0
- package/dist/remotion-bundle/80bc9dfbea2b35ae.woff2 +0 -0
- package/dist/remotion-bundle/811b83f69963bb48.woff2 +0 -0
- package/dist/remotion-bundle/813.bundle.js +117511 -0
- package/dist/remotion-bundle/813.bundle.js.map +1 -0
- package/dist/remotion-bundle/84df492e349f82e9.woff2 +0 -0
- package/dist/remotion-bundle/8501bfd73eb36f2b.woff2 +0 -0
- package/dist/remotion-bundle/854236a8376093fe.woff2 +0 -0
- package/dist/remotion-bundle/8571d74529082753.woff2 +0 -0
- package/dist/remotion-bundle/860bf44f8e6f4b5d.woff2 +0 -0
- package/dist/remotion-bundle/879.bundle.js +64 -0
- package/dist/remotion-bundle/879.bundle.js.map +1 -0
- package/dist/remotion-bundle/887dd482f848d56f.woff2 +0 -0
- package/dist/remotion-bundle/89b2132e85fbbb5a.woff2 +0 -0
- package/dist/remotion-bundle/8ba60d6c306010c2.woff2 +0 -0
- package/dist/remotion-bundle/8c7c4dadea897806.woff2 +0 -0
- package/dist/remotion-bundle/8c943f9999706f61.woff2 +0 -0
- package/dist/remotion-bundle/8f2a718c90575cc9.woff2 +0 -0
- package/dist/remotion-bundle/906b6edb3e1772c9.woff2 +0 -0
- package/dist/remotion-bundle/930ff9daccdf14eb.woff2 +0 -0
- package/dist/remotion-bundle/934db2f1c403c4d0.woff2 +0 -0
- package/dist/remotion-bundle/938.bundle.js +451 -0
- package/dist/remotion-bundle/938.bundle.js.map +1 -0
- package/dist/remotion-bundle/967.bundle.js +4462 -0
- package/dist/remotion-bundle/967.bundle.js.map +1 -0
- package/dist/remotion-bundle/9684a1093d3c02ce.woff2 +0 -0
- package/dist/remotion-bundle/973dcd0faa6116cc.woff2 +0 -0
- package/dist/remotion-bundle/9745400694e76cd8.woff2 +0 -0
- package/dist/remotion-bundle/999ef957bed3bdca.woff2 +0 -0
- package/dist/remotion-bundle/99a3d67c8b0f43e3.woff2 +0 -0
- package/dist/remotion-bundle/a0586c3e03127283.woff2 +0 -0
- package/dist/remotion-bundle/a0eb654fdae46269.woff2 +0 -0
- package/dist/remotion-bundle/a20e35d3b08f7994.woff2 +0 -0
- package/dist/remotion-bundle/a2dcaced7c8c25ab.woff2 +0 -0
- package/dist/remotion-bundle/a79255a972a2681a.woff2 +0 -0
- package/dist/remotion-bundle/a804b352cb9fec1a.woff2 +0 -0
- package/dist/remotion-bundle/aae7117164e1eabc.woff2 +0 -0
- package/dist/remotion-bundle/affd121385d0442d.woff2 +0 -0
- package/dist/remotion-bundle/b19a6083987ee0d7.woff2 +0 -0
- package/dist/remotion-bundle/b1b2bd04d8637981.woff2 +0 -0
- package/dist/remotion-bundle/b2c07f341486be87.woff2 +0 -0
- package/dist/remotion-bundle/b33d8f82e575c4ce.woff2 +0 -0
- package/dist/remotion-bundle/b366c0bed35ef491.woff2 +0 -0
- package/dist/remotion-bundle/b41e857ec1b85642.woff2 +0 -0
- package/dist/remotion-bundle/b420bb34ccf23e7f.woff2 +0 -0
- package/dist/remotion-bundle/b4f7bf4efb0c0ccf.woff2 +0 -0
- package/dist/remotion-bundle/b60fe5eca03cff93.woff2 +0 -0
- package/dist/remotion-bundle/b6bd31a336e64bce.woff2 +0 -0
- package/dist/remotion-bundle/b6d2befba3dfefeb.woff2 +0 -0
- package/dist/remotion-bundle/b75f39ab06c43bf4.woff2 +0 -0
- package/dist/remotion-bundle/b77880e8c413d4fd.woff2 +0 -0
- package/dist/remotion-bundle/b7e38ec441e4a77a.woff2 +0 -0
- package/dist/remotion-bundle/b83baa383ff0bf2b.woff2 +0 -0
- package/dist/remotion-bundle/b9ad7b6c0a11450a.woff2 +0 -0
- package/dist/remotion-bundle/baf84486e8ae3aaf.woff2 +0 -0
- package/dist/remotion-bundle/bc047b1f6869cffa.woff2 +0 -0
- package/dist/remotion-bundle/bf4f3ac6e93f33aa.woff2 +0 -0
- package/dist/remotion-bundle/bf6835ffec5897a2.woff2 +0 -0
- package/dist/remotion-bundle/bf8885f581eb1724.woff2 +0 -0
- package/dist/remotion-bundle/bundle.js +83376 -0
- package/dist/remotion-bundle/bundle.js.map +1 -0
- package/dist/remotion-bundle/c03f046bccd789d0.woff2 +0 -0
- package/dist/remotion-bundle/c0bb1f8962b73bc3.woff2 +0 -0
- package/dist/remotion-bundle/c1003f9a7db6e1cf.woff2 +0 -0
- package/dist/remotion-bundle/c15d83fb1e199515.woff2 +0 -0
- package/dist/remotion-bundle/c28e7e5d310f73ef.woff2 +0 -0
- package/dist/remotion-bundle/c2b840274db78aea.woff2 +0 -0
- package/dist/remotion-bundle/c3000e3299d4e45f.woff2 +0 -0
- package/dist/remotion-bundle/c83ce886e5288510.woff2 +0 -0
- package/dist/remotion-bundle/c87a5a64d4ac0918.woff2 +0 -0
- package/dist/remotion-bundle/c8a7e0d049e965fa.woff2 +0 -0
- package/dist/remotion-bundle/c949a35d3a3b1faf.woff2 +0 -0
- package/dist/remotion-bundle/c9618c9b9ac2bc78.woff2 +0 -0
- package/dist/remotion-bundle/ca3add3b84152d5b.woff2 +0 -0
- package/dist/remotion-bundle/cad9dd036408d707.woff2 +0 -0
- package/dist/remotion-bundle/cbb24916619df439.woff2 +0 -0
- package/dist/remotion-bundle/cc054f0b5514e177.woff2 +0 -0
- package/dist/remotion-bundle/ccc248ed9312bc71.woff2 +0 -0
- package/dist/remotion-bundle/cd9d623aa07af925.woff2 +0 -0
- package/dist/remotion-bundle/ce2ba7a321bd1247.woff2 +0 -0
- package/dist/remotion-bundle/cf72455f79a29b14.woff2 +0 -0
- package/dist/remotion-bundle/d267cbfefab452ac.woff2 +0 -0
- package/dist/remotion-bundle/d435cff46a64955f.woff +0 -0
- package/dist/remotion-bundle/d494d07f67e363f6.woff2 +0 -0
- package/dist/remotion-bundle/d7aa0cc1fa47bf38.woff2 +0 -0
- package/dist/remotion-bundle/d7c5ca93d885160a.woff2 +0 -0
- package/dist/remotion-bundle/d855d3e252db74e2.woff2 +0 -0
- package/dist/remotion-bundle/d8f13d47f02f82c2.woff2 +0 -0
- package/dist/remotion-bundle/d9567cce2ee11019.woff2 +0 -0
- package/dist/remotion-bundle/db8d4456fc75dd86.woff +0 -0
- package/dist/remotion-bundle/dc274628378c47ee.woff2 +0 -0
- package/dist/remotion-bundle/dc3e06947bb69903.woff2 +0 -0
- package/dist/remotion-bundle/dd67040ac3b6d523.woff2 +0 -0
- package/dist/remotion-bundle/e0b04bd488f953f4.woff2 +0 -0
- package/dist/remotion-bundle/e2a572ff95089370.woff2 +0 -0
- package/dist/remotion-bundle/e2e18a86b1c2b0cc.woff2 +0 -0
- package/dist/remotion-bundle/e3a78ee2fc9c6931.woff2 +0 -0
- package/dist/remotion-bundle/e654c9d547605a9f.woff2 +0 -0
- package/dist/remotion-bundle/e67a3a64c129927c.woff2 +0 -0
- package/dist/remotion-bundle/e6be28b4203cd6ce.woff2 +0 -0
- package/dist/remotion-bundle/e841907ad9b0a191.woff +0 -0
- package/dist/remotion-bundle/e889d1541c69fffa.woff2 +0 -0
- package/dist/remotion-bundle/e88ef8c76373a9e2.woff2 +0 -0
- package/dist/remotion-bundle/e9c72f4bc37defef.woff2 +0 -0
- package/dist/remotion-bundle/e9e35f863403a255.woff2 +0 -0
- package/dist/remotion-bundle/eb23b37b009375da.woff2 +0 -0
- package/dist/remotion-bundle/ee1342b741625721.woff2 +0 -0
- package/dist/remotion-bundle/f07da88543a57ec9.woff2 +0 -0
- package/dist/remotion-bundle/f522982115306f8a.woff2 +0 -0
- package/dist/remotion-bundle/f8449bd864e6d8bc.woff2 +0 -0
- package/dist/remotion-bundle/f906dd5bd95ff9ab.woff2 +0 -0
- package/dist/remotion-bundle/f9e9e9413e3c38bb.woff2 +0 -0
- package/dist/remotion-bundle/fa5a5b16280994a8.woff2 +0 -0
- package/dist/remotion-bundle/favicon.ico +0 -0
- package/dist/remotion-bundle/fb19c0517725599b.woff2 +0 -0
- package/dist/remotion-bundle/fcaf24232f684b9b.woff2 +0 -0
- package/dist/remotion-bundle/fe09e084a3eea8cf.woff2 +0 -0
- package/dist/remotion-bundle/ff38d5317df7345a.woff2 +0 -0
- package/dist/remotion-bundle/ffe7ea1ea08f455a.woff2 +0 -0
- package/dist/remotion-bundle/index.html +49 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaomei/communication/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoxin/career/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/female-kefu-xiaoyue/parenting/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/male-kefu-xiaoxu/time-trap/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/cognition/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/growth/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/parenting/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-A6b7WpG3/soothing/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-female-R2s4N9qJ/cognition/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-Bk7vD3xP/decision/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-W1tH9jVc/manager/4.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide/v-male-s5NqE0rZ/founder/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/career-advice/4.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/founder-lesson/4.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/incident-review/4.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/learning-loop/4.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/meeting-closure/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/product-update/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/product-update/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/product-update/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/product-update/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/research-reading/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/0.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/1.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/2.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/3.mp3 +0 -0
- package/dist/remotion-bundle/public/paper-slide-experiments/sales-enablement/4.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/ai-life/card-0.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/ai-life/card-1.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/ai-life/card-2.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/ai-life/card-3.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/ai-life/card-4.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/ai-life/card-5.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-0.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-1.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-2.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-3.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-4.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-5.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/coffee-science/card-6.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-0.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-1.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-2.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-3.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-4.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-5.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/reading-secrets/card-6.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/remote-work/card-0.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/remote-work/card-1.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/remote-work/card-2.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/remote-work/card-3.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/remote-work/card-4.mp3 +0 -0
- package/dist/remotion-bundle/public/voiceover/remote-work/card-5.mp3 +0 -0
- package/dist/remotion-bundle/source-map-helper.wasm +0 -0
- package/lib/cli.js +270 -0
- package/lib/commands/_registry.js +48 -0
- package/lib/commands/add.js +242 -0
- package/lib/commands/asr/azure-transcribe.js +336 -0
- package/lib/commands/asr/cloud-transcribe.js +384 -0
- package/lib/commands/asr/helpers.js +76 -0
- package/lib/commands/asr/index.js +236 -0
- package/lib/commands/asr/local-transcribe.js +125 -0
- package/lib/commands/asr-jobs.js +257 -0
- package/lib/commands/asr.js +11 -0
- package/lib/commands/auth-cmds.js +358 -0
- package/lib/commands/dub.js +542 -0
- package/lib/commands/explain.js +512 -0
- package/lib/commands/feedback.js +152 -0
- package/lib/commands/image.js +207 -0
- package/lib/commands/mcp-key.js +166 -0
- package/lib/commands/narrate.js +639 -0
- package/lib/commands/picstory-templates.js +276 -0
- package/lib/commands/picstory.js +547 -0
- package/lib/commands/podcast/dialogue.js +109 -0
- package/lib/commands/podcast/generate.js +127 -0
- package/lib/commands/podcast/index.js +561 -0
- package/lib/commands/podcast/synthesize.js +188 -0
- package/lib/commands/podcast.js +11 -0
- package/lib/commands/present.js +519 -0
- package/lib/commands/publish.js +415 -0
- package/lib/commands/skills.js +473 -0
- package/lib/commands/slice-render.js +282 -0
- package/lib/commands/slice-stage.js +264 -0
- package/lib/commands/slice.js +346 -0
- package/lib/commands/slides/constants.js +108 -0
- package/lib/commands/slides/html-renderer.js +338 -0
- package/lib/commands/slides/index.js +345 -0
- package/lib/commands/slides.js +11 -0
- package/lib/commands/story.js +302 -0
- package/lib/commands/summarize.js +532 -0
- package/lib/commands/synthesize.js +261 -0
- package/lib/commands/translate.js +593 -0
- package/lib/commands/upgrade.js +249 -0
- package/lib/commands/video-translate.js +577 -0
- package/lib/commands/voices.js +292 -0
- package/lib/core/agent-env.js +104 -0
- package/lib/core/args.js +107 -0
- package/lib/core/asr-client.js +448 -0
- package/lib/core/asr-jobs-client.js +126 -0
- package/lib/core/asr-jobs-store.js +105 -0
- package/lib/core/asr-r2-upload.js +181 -0
- package/lib/core/asr-upload.js +132 -0
- package/lib/core/audio-extract.js +150 -0
- package/lib/core/audio.js +219 -0
- package/lib/core/auth.js +880 -0
- package/lib/core/config.js +197 -0
- package/lib/core/feedback.js +64 -0
- package/lib/core/ffmpeg.js +476 -0
- package/lib/core/http.js +188 -0
- package/lib/core/image-client.js +55 -0
- package/lib/core/intent-params.js +11 -0
- package/lib/core/llm-client.js +76 -0
- package/lib/core/logger.js +208 -0
- package/lib/core/mic-recorder.js +182 -0
- package/lib/core/pause-markers.js +94 -0
- package/lib/core/podcast-pacing.js +118 -0
- package/lib/core/spinner.js +33 -0
- package/lib/core/srt.js +394 -0
- package/lib/core/telemetry.js +100 -0
- package/lib/core/timeline.js +92 -0
- package/lib/core/tts-synthesizer.js +70 -0
- package/lib/core/update-check.js +185 -0
- package/lib/core/url-download.js +148 -0
- package/lib/core/whisper-local.js +279 -0
- package/lib/internal/deck-validator.js +488 -0
- package/lib/internal/slice-themes.json +370 -0
- package/lib/stage-core/cloud-render.js +170 -0
- package/lib/stage-core/deck-format.js +133 -0
- package/lib/stage-core/edit-prompt.js +104 -0
- package/lib/stage-core/event-bus.js +31 -0
- package/lib/stage-core/port.js +46 -0
- package/lib/stage-core/server.js +352 -0
- package/lib/stage-core/snapshot-store.js +198 -0
- package/lib/stage-core/watcher.js +106 -0
- package/lib/stage-ui/slice/template.js +1672 -0
- package/package.json +9 -4
- package/skills/.claude-plugin/marketplace.json +22 -0
- package/skills/.claude-plugin/plugin.json +25 -0
- package/skills/LICENSE +21 -0
- package/skills/README.md +120 -0
- package/skills/hub/SKILL.md +317 -0
- package/skills/podcast/SKILL.md +146 -0
- package/skills/slice/SKILL.md +205 -0
- package/skills/slice/agents/openai.yaml +4 -0
- package/skills/slice/references/deck-schema.md +183 -0
- package/skills/slice/references/example-decks.md +108 -0
- package/skills/slice/references/themes.md +172 -0
- package/skills/transcribe/SKILL.md +473 -0
- package/skills/video/SKILL.md +261 -0
- package/skills/voxflow-slice/SKILL.md +271 -0
- package/skills/voxflow-slice/examples/article.md +13 -0
- package/skills/voxflow-slice/examples/expected-deck.json +39 -0
- package/skills/voxflow-slice/examples/validate.mjs +46 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VoxFlow CLI — Slice command
|
|
3
|
+
*
|
|
4
|
+
* Slice an article (markdown / plain text) into a 5–8 card narrated deck JSON
|
|
5
|
+
* via /api/slice/deck (renamed from /api/paper-slide/slice in #3307 Deploy 2).
|
|
6
|
+
* Charges `slice-deck` (200 quota) under the new mount; legacy `paper-slide-slice`
|
|
7
|
+
* op still exists for the soft-deprecated `/api/paper-slide/slice` path that
|
|
8
|
+
* stays mounted for ~30 days.
|
|
9
|
+
*
|
|
10
|
+
* The cloud renderer that turns this deck into a 1080×1920 mp4 lives in the
|
|
11
|
+
* web app (voxflow.studio/apps/slice) — this command only produces the
|
|
12
|
+
* structured deck JSON, suitable for piping into custom pipelines or for
|
|
13
|
+
* inspection / iteration on the AI's slicing quality.
|
|
14
|
+
*
|
|
15
|
+
* Thirty-three themes supported (paper-slide / editorial-mag / bold-poster /
|
|
16
|
+
* notion-card / brutalist / glass-dark / broadsheet / blueprint /
|
|
17
|
+
* daisy-pastel / showa-catalog / photo-feature / atmospheric / art-mag /
|
|
18
|
+
* tome-noir / flomo-mute / substack-drop / ink-scroll / podcast-clip /
|
|
19
|
+
* ink-wash / morandi-calm / douyin-data / highlighter-note / memphis-design /
|
|
20
|
+
* bauhaus-grid / riso-print / chrome-y2k / botanical-press / art-nouveau /
|
|
21
|
+
* tabloid-print / arcade-pixel / hand-lettered / stamp-collector /
|
|
22
|
+
* tropical-postcard) — must match backend's VALID_THEMES set
|
|
23
|
+
* (backend/services/paper-slide/deck-validator.js) or the API rejects with
|
|
24
|
+
* `invalid_theme`. Both lists derive from /slice-themes.json so they
|
|
25
|
+
* auto-sync.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
const { request, throwApiError, throwNetworkError, ApiError } = require('../core/http');
|
|
31
|
+
|
|
32
|
+
// Sourced from the canonical registry at repo root. The CLI gates user
|
|
33
|
+
// input against this list, so adding a theme to slice-themes.json is enough
|
|
34
|
+
// for `voxflow slice --theme xxx` to accept it.
|
|
35
|
+
const SLICE_THEME_REGISTRY = require('../../../slice-themes.json');
|
|
36
|
+
const VALID_THEMES = SLICE_THEME_REGISTRY.themes.map((t) => t.id);
|
|
37
|
+
const DEFAULT_THEME = SLICE_THEME_REGISTRY.default;
|
|
38
|
+
// Theme id -> array of valid variant ids (palette swaps within a theme).
|
|
39
|
+
// Mirrors backend/services/paper-slide/deck-validator.js#THEME_VARIANTS so
|
|
40
|
+
// the CLI rejects unknown variants client-side before paying a network round
|
|
41
|
+
// trip. Themes without variants get an empty array — passing --variant for
|
|
42
|
+
// them is a hard error too (theme typo'd or feature confusion).
|
|
43
|
+
const THEME_VARIANTS = Object.fromEntries(
|
|
44
|
+
SLICE_THEME_REGISTRY.themes.map((t) => [
|
|
45
|
+
t.id,
|
|
46
|
+
(t.variants || []).map((v) => v.id),
|
|
47
|
+
])
|
|
48
|
+
);
|
|
49
|
+
const MIN_ARTICLE_CHARS = 80;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Slice an article via the backend.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} opts
|
|
55
|
+
* @param {string} opts.token JWT token
|
|
56
|
+
* @param {string} opts.api API base URL
|
|
57
|
+
* @param {string} opts.article Article text (≥ 80 chars)
|
|
58
|
+
* @param {string} [opts.theme] Slice theme id (default: paper-slide)
|
|
59
|
+
* @param {string} [opts.output] Output JSON path (default: stdout)
|
|
60
|
+
* @param {boolean} [opts.json] Pure-JSON mode (suppress logs / spinners)
|
|
61
|
+
* @returns {Promise<{deck: object, usage: object, quotaUsed: number, outputPath: string|null}>}
|
|
62
|
+
*/
|
|
63
|
+
async function slice(opts) {
|
|
64
|
+
const article = opts.article;
|
|
65
|
+
if (typeof article !== 'string' || article.trim().length < MIN_ARTICLE_CHARS) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Article must be a non-empty string of at least ${MIN_ARTICLE_CHARS} characters ` +
|
|
68
|
+
`(got ${article ? article.trim().length : 0}).`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const theme = opts.theme || DEFAULT_THEME;
|
|
73
|
+
if (!VALID_THEMES.includes(theme)) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Unknown theme "${theme}". Valid: ${VALID_THEMES.join(', ')}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const variantId = opts.variant;
|
|
80
|
+
if (variantId != null) {
|
|
81
|
+
const validVariants = THEME_VARIANTS[theme] || [];
|
|
82
|
+
if (validVariants.length === 0) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`--variant set but theme "${theme}" declares no variants. ` +
|
|
85
|
+
`Themes with variants: ${
|
|
86
|
+
Object.entries(THEME_VARIANTS)
|
|
87
|
+
.filter(([, ids]) => ids.length > 0)
|
|
88
|
+
.map(([id]) => id)
|
|
89
|
+
.join(', ') || '(none yet)'
|
|
90
|
+
}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
if (!validVariants.includes(variantId)) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`Unknown variant "${variantId}" for theme "${theme}". Valid: ${validVariants.join(', ')}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const api = opts.api;
|
|
101
|
+
const token = opts.token;
|
|
102
|
+
const quiet = opts.json === true;
|
|
103
|
+
|
|
104
|
+
if (!quiet) {
|
|
105
|
+
console.log('\n=== VoxFlow Slice ===');
|
|
106
|
+
console.log(`Theme: ${theme}${variantId ? ` (variant: ${variantId})` : ''}`);
|
|
107
|
+
console.log(`Article: ${article.trim().length} chars`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let status, data;
|
|
111
|
+
try {
|
|
112
|
+
({ status, data } = await request(`${api}/api/slice/deck`, {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
'Authorization': `Bearer ${token}`,
|
|
117
|
+
},
|
|
118
|
+
// Slice runs a structured-output Claude call producing 5–8
|
|
119
|
+
// narrated cards. P50 is 10–20s but P95 spikes past the 60s
|
|
120
|
+
// default request timeout under upstream load (verified
|
|
121
|
+
// against api.voxflow.studio/api/slice/deck with the
|
|
122
|
+
// 1.11.1 client). Match the 180s convention used by every
|
|
123
|
+
// other LLM-bound CLI command (image / picstory / explain /
|
|
124
|
+
// present / story).
|
|
125
|
+
timeoutMs: 180_000,
|
|
126
|
+
}, {
|
|
127
|
+
article: article.trim(),
|
|
128
|
+
theme,
|
|
129
|
+
...(variantId ? { variantId } : {}),
|
|
130
|
+
}));
|
|
131
|
+
} catch (err) {
|
|
132
|
+
throwNetworkError(err, api);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (status !== 200 || !data || data.code !== 'success') {
|
|
136
|
+
throwApiError(status, data, 'slice');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const deck = data.data?.deck;
|
|
140
|
+
const usage = data.data?.usage || {};
|
|
141
|
+
if (!deck) {
|
|
142
|
+
throw new Error('Slice response missing `data.deck`');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Authoritative cost from quota response, fallback to catalog.
|
|
146
|
+
const PAPER_SLIDE_SLICE_CATALOG_COST = 200;
|
|
147
|
+
const quotaUsed = typeof data.quota?.costDelta === 'number'
|
|
148
|
+
? data.quota.costDelta
|
|
149
|
+
: PAPER_SLIDE_SLICE_CATALOG_COST;
|
|
150
|
+
|
|
151
|
+
const payload = JSON.stringify({ deck, usage, theme }, null, 2);
|
|
152
|
+
let outputPath = null;
|
|
153
|
+
if (opts.output) {
|
|
154
|
+
outputPath = path.resolve(opts.output);
|
|
155
|
+
const outDir = path.dirname(outputPath);
|
|
156
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
157
|
+
fs.writeFileSync(outputPath, payload + '\n', 'utf8');
|
|
158
|
+
if (!quiet) {
|
|
159
|
+
console.log(`\nWrote ${outputPath} (${(payload.length / 1024).toFixed(1)} KB)`);
|
|
160
|
+
}
|
|
161
|
+
} else if (quiet) {
|
|
162
|
+
process.stdout.write(payload + '\n');
|
|
163
|
+
} else {
|
|
164
|
+
console.log('\n--- Deck JSON ---');
|
|
165
|
+
console.log(payload);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!quiet) {
|
|
169
|
+
const cardCount = Array.isArray(deck.cards) ? deck.cards.length : 0;
|
|
170
|
+
console.log('\n=== Done ===');
|
|
171
|
+
console.log(`Cards: ${cardCount}`);
|
|
172
|
+
console.log(`Quota: ${quotaUsed} used, ${data.quota?.remaining ?? '?'} remaining`);
|
|
173
|
+
// Two next-step paths: (1) iterate locally with stage if an output
|
|
174
|
+
// file exists (no quota cost, hot-reload); (2) ship via the web
|
|
175
|
+
// renderer. Only print the stage hint when we actually have a path
|
|
176
|
+
// to feed it — stdout-only runs have nowhere for stage to attach.
|
|
177
|
+
if (outputPath) {
|
|
178
|
+
console.log(`\nPreview locally: voxflow slice stage ${outputPath}`);
|
|
179
|
+
console.log(`Or render mp4: https://voxflow.studio/apps/slice (paste/import the JSON)`);
|
|
180
|
+
} else {
|
|
181
|
+
console.log(`\nNext: render the deck at https://voxflow.studio/apps/slice (paste the JSON or import).`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return { deck, usage, quotaUsed, outputPath };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ─── CLI Handler ────────────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
async function handle(args) {
|
|
191
|
+
// Sub-action dispatch: `voxflow slice stage <deck.json>` boots the local
|
|
192
|
+
// preview/iteration server instead of generating a deck. Kept as a
|
|
193
|
+
// first-positional-arg check so the legacy `voxflow slice <article>`
|
|
194
|
+
// signature is unchanged. slice-stage.js has no `meta` export of its
|
|
195
|
+
// own — it would otherwise need to be in _registry.js (parity test).
|
|
196
|
+
if (args.length > 0 && args[0] === 'stage') {
|
|
197
|
+
const sliceStage = require('./slice-stage');
|
|
198
|
+
return sliceStage.handle(args.slice(1));
|
|
199
|
+
}
|
|
200
|
+
// `voxflow slice render <deck.json>` — offline local Remotion render
|
|
201
|
+
// (Phase 0: silent video). Same first-positional dispatch pattern as
|
|
202
|
+
// `stage`; the subcommand file has no `meta` export so it stays out of
|
|
203
|
+
// _registry.js (parity test).
|
|
204
|
+
if (args.length > 0 && args[0] === 'render') {
|
|
205
|
+
const sliceRender = require('./slice-render');
|
|
206
|
+
return sliceRender.handle(args.slice(1));
|
|
207
|
+
}
|
|
208
|
+
// `voxflow slice preview <deck.json>` — alias for `slice stage`. The
|
|
209
|
+
// earlier static-thumbnail Phase 0 preview was strictly less capable
|
|
210
|
+
// than stage's hot-reload edit workflow (no file watcher, no live
|
|
211
|
+
// updates, no version history), so we route both to the same handler
|
|
212
|
+
// and keep "preview" as a discoverable name for new users.
|
|
213
|
+
if (args.length > 0 && (args[0] === 'preview')) {
|
|
214
|
+
const sliceStage = require('./slice-stage');
|
|
215
|
+
return sliceStage.handle(args.slice(1));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const { parseFlag, runWithRetry } = require('../core/args');
|
|
219
|
+
const { getToken, getTokenInfo } = require('../core/auth');
|
|
220
|
+
const { API_BASE } = require('../core/config');
|
|
221
|
+
|
|
222
|
+
const api = parseFlag(args, '--api') || API_BASE;
|
|
223
|
+
const explicitToken = parseFlag(args, '--token');
|
|
224
|
+
|
|
225
|
+
const inlineText = parseFlag(args, '--text');
|
|
226
|
+
const theme = parseFlag(args, '--theme');
|
|
227
|
+
const variant = parseFlag(args, '--variant');
|
|
228
|
+
const output = parseFlag(args, '--output', '-o');
|
|
229
|
+
const jsonMode = args.includes('--json');
|
|
230
|
+
|
|
231
|
+
let article;
|
|
232
|
+
if (inlineText) {
|
|
233
|
+
article = inlineText;
|
|
234
|
+
} else {
|
|
235
|
+
// First positional arg that isn't a flag value
|
|
236
|
+
const valuedFlags = new Set([
|
|
237
|
+
'--text', '--theme', '--variant', '--output', '-o',
|
|
238
|
+
'--token', '--api',
|
|
239
|
+
]);
|
|
240
|
+
let filePath;
|
|
241
|
+
for (let i = 0; i < args.length; i++) {
|
|
242
|
+
if (args[i].startsWith('-')) {
|
|
243
|
+
if (valuedFlags.has(args[i])) i++;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
filePath = args[i];
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
if (!filePath) {
|
|
250
|
+
console.error('Error: provide an article file or --text "..."');
|
|
251
|
+
console.error('Usage: voxflow slice <file> [--theme <id>] [-o <out.json>]');
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
try {
|
|
255
|
+
article = fs.readFileSync(path.resolve(filePath), 'utf8');
|
|
256
|
+
} catch (err) {
|
|
257
|
+
console.error(`Error: cannot read file "${filePath}": ${err.message}`);
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (theme && !VALID_THEMES.includes(theme)) {
|
|
263
|
+
console.error(`Error: --theme "${theme}" not in: ${VALID_THEMES.join(', ')}`);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
if (variant) {
|
|
267
|
+
const targetTheme = theme || DEFAULT_THEME;
|
|
268
|
+
const validVariants = THEME_VARIANTS[targetTheme] || [];
|
|
269
|
+
if (validVariants.length === 0) {
|
|
270
|
+
console.error(
|
|
271
|
+
`Error: --variant set but theme "${targetTheme}" declares no variants.`
|
|
272
|
+
);
|
|
273
|
+
const themesWithVariants = Object.entries(THEME_VARIANTS)
|
|
274
|
+
.filter(([, ids]) => ids.length > 0)
|
|
275
|
+
.map(([id]) => id);
|
|
276
|
+
if (themesWithVariants.length > 0) {
|
|
277
|
+
console.error(`Themes with variants: ${themesWithVariants.join(', ')}`);
|
|
278
|
+
}
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
if (!validVariants.includes(variant)) {
|
|
282
|
+
console.error(
|
|
283
|
+
`Error: --variant "${variant}" not in ${targetTheme}'s variants: ${validVariants.join(', ')}`
|
|
284
|
+
);
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
let token;
|
|
290
|
+
if (explicitToken) {
|
|
291
|
+
token = explicitToken;
|
|
292
|
+
} else {
|
|
293
|
+
token = await getToken({ api });
|
|
294
|
+
if (!jsonMode) {
|
|
295
|
+
const info = getTokenInfo();
|
|
296
|
+
if (info) {
|
|
297
|
+
console.log(`\x1b[32mLogged in as ${info.email}\x1b[0m`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const opts = {
|
|
303
|
+
token, api, article,
|
|
304
|
+
theme: theme || undefined,
|
|
305
|
+
variant: variant || undefined,
|
|
306
|
+
output: output || undefined,
|
|
307
|
+
json: jsonMode,
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
await runWithRetry(slice, opts, api, explicitToken);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const meta = {
|
|
314
|
+
slice: {
|
|
315
|
+
usage: '<file> [--theme <id>] [--variant <id>] [--text <s>] [-o <file>] [--json]',
|
|
316
|
+
description: 'Slice an article into a 5–8 card deck JSON (Slice / paper-slide AI; 200 quota)',
|
|
317
|
+
options: [
|
|
318
|
+
'<file> Article file (markdown / plain text, ≥ 80 chars)',
|
|
319
|
+
'--text <string> Pass article inline instead of reading a file',
|
|
320
|
+
`--theme <id> One of: ${VALID_THEMES.join(', ')} (default: ${DEFAULT_THEME})`,
|
|
321
|
+
'--variant <id> Palette swap within the theme (e.g. editorial-mag → cream / sepia / cold-grey). Themes without variants reject this flag.',
|
|
322
|
+
'-o, --output <path> Write deck JSON to file (default: print to stdout/console)',
|
|
323
|
+
'--json Pure JSON mode — suppress all logs, emit only the deck JSON to stdout (for piping)',
|
|
324
|
+
],
|
|
325
|
+
examples: [
|
|
326
|
+
'voxflow slice article.md',
|
|
327
|
+
'voxflow slice article.md --theme editorial-mag -o deck.json',
|
|
328
|
+
'voxflow slice article.md --theme editorial-mag --variant sepia -o deck.json',
|
|
329
|
+
'voxflow slice --text "..." --theme bold-poster --json | jq .deck',
|
|
330
|
+
'voxflow slice stage deck.json # local preview, hot-reload',
|
|
331
|
+
'voxflow slice stage deck.json --port 5180 --no-open',
|
|
332
|
+
'voxflow slice render deck.json --output out.mp4 # offline render (no quota, no cloud)',
|
|
333
|
+
],
|
|
334
|
+
},
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
module.exports = {
|
|
338
|
+
slice,
|
|
339
|
+
handle,
|
|
340
|
+
meta,
|
|
341
|
+
VALID_THEMES,
|
|
342
|
+
THEME_VARIANTS,
|
|
343
|
+
DEFAULT_THEME,
|
|
344
|
+
MIN_ARTICLE_CHARS,
|
|
345
|
+
ApiError,
|
|
346
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slides command — Constants, templates, and LLM prompts.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const VALID_THEMES = ['midnight', 'paper', 'ember', 'forest', 'ocean'];
|
|
8
|
+
const VALID_TEMPLATES = ['product', 'report', 'tutorial', 'pitch', 'free'];
|
|
9
|
+
const VALID_MODELS = ['swift', 'balanced', 'pro', 'creative'];
|
|
10
|
+
|
|
11
|
+
const SLIDE_LAYOUTS = [
|
|
12
|
+
'hero', 'title-bullets', 'two-column', 'three-cards',
|
|
13
|
+
'image-left', 'image-right', 'quote', 'timeline', 'stats', 'section',
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const TEMPLATE_HINTS = {
|
|
17
|
+
product: 'This is a product launch presentation. Focus on value proposition, clear feature benefits, and persuasive metrics. End with a strong call to action.',
|
|
18
|
+
report: 'This is an annual/quarterly report. Use real-looking data, professional tone, clear metrics with year-over-year comparisons. Be factual and concise.',
|
|
19
|
+
tutorial: 'This is a step-by-step tutorial. Number each step clearly, use practical examples, and include actionable tips. Keep instructions concise and easy to follow.',
|
|
20
|
+
pitch: 'This is a startup investor pitch deck. Be compelling with real-looking metrics, clear market sizing (TAM/SAM/SOM), and a persuasive narrative arc. Show traction with specific numbers.',
|
|
21
|
+
free: '',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const TEMPLATE_STRUCTURES = {
|
|
25
|
+
product: [
|
|
26
|
+
{ layout: 'hero', hint: 'Product name and tagline' },
|
|
27
|
+
{ layout: 'title-bullets', hint: 'Pain points the product solves' },
|
|
28
|
+
{ layout: 'two-column', hint: 'Problem vs Solution comparison' },
|
|
29
|
+
{ layout: 'three-cards', hint: 'Key feature 1, 2, 3' },
|
|
30
|
+
{ layout: 'three-cards', hint: 'More features or benefits' },
|
|
31
|
+
{ layout: 'stats', hint: 'Performance metrics or user stats' },
|
|
32
|
+
{ layout: 'quote', hint: 'Customer testimonial or endorsement' },
|
|
33
|
+
{ layout: 'hero', hint: 'Call to action and next steps' },
|
|
34
|
+
],
|
|
35
|
+
report: [
|
|
36
|
+
{ layout: 'hero', hint: 'Report title, year, organization' },
|
|
37
|
+
{ layout: 'title-bullets', hint: 'Executive summary highlights' },
|
|
38
|
+
{ layout: 'stats', hint: 'Quarterly or annual key metrics' },
|
|
39
|
+
{ layout: 'two-column', hint: 'Achievements and highlights' },
|
|
40
|
+
{ layout: 'title-bullets', hint: 'Challenges and lessons learned' },
|
|
41
|
+
{ layout: 'timeline', hint: 'Key milestones or roadmap' },
|
|
42
|
+
{ layout: 'hero', hint: 'Outlook and closing statement' },
|
|
43
|
+
],
|
|
44
|
+
tutorial: [
|
|
45
|
+
{ layout: 'hero', hint: 'Tutorial title and what you will learn' },
|
|
46
|
+
{ layout: 'title-bullets', hint: 'Overview and prerequisites' },
|
|
47
|
+
{ layout: 'two-column', hint: 'Step 1 with details' },
|
|
48
|
+
{ layout: 'two-column', hint: 'Step 2 with details' },
|
|
49
|
+
{ layout: 'two-column', hint: 'Step 3 with details' },
|
|
50
|
+
{ layout: 'two-column', hint: 'Step 4 with details' },
|
|
51
|
+
{ layout: 'three-cards', hint: 'Pro tips and best practices' },
|
|
52
|
+
{ layout: 'hero', hint: 'Summary and next steps' },
|
|
53
|
+
],
|
|
54
|
+
pitch: [
|
|
55
|
+
{ layout: 'hero', hint: 'Company name, one-line pitch' },
|
|
56
|
+
{ layout: 'title-bullets', hint: 'The problem being solved' },
|
|
57
|
+
{ layout: 'stats', hint: 'Market size and opportunity' },
|
|
58
|
+
{ layout: 'two-column', hint: 'Solution and how it works' },
|
|
59
|
+
{ layout: 'three-cards', hint: 'Business model and revenue streams' },
|
|
60
|
+
{ layout: 'stats', hint: 'Traction and key metrics' },
|
|
61
|
+
{ layout: 'three-cards', hint: 'Team members and expertise' },
|
|
62
|
+
{ layout: 'hero', hint: 'The ask — funding, partnerships, next steps' },
|
|
63
|
+
],
|
|
64
|
+
free: [],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const SLIDES_SYSTEM_PROMPT = `You are a professional presentation designer creating business-quality slide decks. Generate structured JSON.
|
|
68
|
+
|
|
69
|
+
STRICT RULES:
|
|
70
|
+
1. Output ONLY valid JSON, no markdown fences, no extra text
|
|
71
|
+
2. Each slide must have: id (number), layout (string), content (object), narration (string)
|
|
72
|
+
3. narration: speaker script, 2-3 sentences, natural professional tone
|
|
73
|
+
4. Layout choices: ${SLIDE_LAYOUTS.join(', ')}
|
|
74
|
+
5. NEVER use emoji characters anywhere — not in titles, bullets, headings, or card icons. Use short text labels instead (e.g. "01", "A", "i", or leave icon field empty string "")
|
|
75
|
+
6. Write concise, data-driven text. No vague filler. Every bullet should contain a specific fact, number, or insight.
|
|
76
|
+
7. First slide: "hero". Last slide: "hero" or "section" for closing. Use varied layouts in between — avoid repeating the same layout consecutively.
|
|
77
|
+
8. 8-10 slides total. Prefer stats, timeline, two-column, quote layouts for variety.
|
|
78
|
+
9. For three-cards: set icon to "" (empty string). For stats: use real-looking numbers with units.
|
|
79
|
+
|
|
80
|
+
CONTENT STRUCTURE per layout:
|
|
81
|
+
- hero: { title, subtitle }
|
|
82
|
+
- title-bullets: { title, bullets: string[] } (max 5 bullets)
|
|
83
|
+
- two-column: { title, left: { heading, text }, right: { heading, text } }
|
|
84
|
+
- three-cards: { title, cards: [{ icon: "", heading, text }] } (exactly 3 cards)
|
|
85
|
+
- image-left / image-right: { title, imagePrompt, text }
|
|
86
|
+
- quote: { quote, author, context }
|
|
87
|
+
- timeline: { title, events: [{ year, text }] } (3-5 events)
|
|
88
|
+
- stats: { title, stats: [{ value, label }] } (2-4 stats with realistic numbers)
|
|
89
|
+
- section: { title, subtitle }
|
|
90
|
+
|
|
91
|
+
OUTPUT FORMAT:
|
|
92
|
+
{
|
|
93
|
+
"meta": { "title": "..." },
|
|
94
|
+
"slides": [ ... ]
|
|
95
|
+
}`;
|
|
96
|
+
|
|
97
|
+
const VALID_MODEL_ALIASES = ['swift', 'balanced', 'pro', 'creative'];
|
|
98
|
+
|
|
99
|
+
module.exports = {
|
|
100
|
+
VALID_THEMES,
|
|
101
|
+
VALID_TEMPLATES,
|
|
102
|
+
VALID_MODELS,
|
|
103
|
+
SLIDE_LAYOUTS,
|
|
104
|
+
TEMPLATE_HINTS,
|
|
105
|
+
TEMPLATE_STRUCTURES,
|
|
106
|
+
SLIDES_SYSTEM_PROMPT,
|
|
107
|
+
VALID_MODEL_ALIASES,
|
|
108
|
+
};
|