@kenkaiiii/gg-editor 0.6.7 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/dist/cli.js +64 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/core/audio-mix.d.ts.map +1 -1
  4. package/dist/core/audio-mix.js +8 -1
  5. package/dist/core/audio-mix.js.map +1 -1
  6. package/dist/core/audio-mix.test.js +1 -1
  7. package/dist/core/audio-mix.test.js.map +1 -1
  8. package/dist/core/auth/api-keys.d.ts +1 -1
  9. package/dist/core/auth/api-keys.d.ts.map +1 -1
  10. package/dist/core/auth/api-keys.js +2 -1
  11. package/dist/core/auth/api-keys.js.map +1 -1
  12. package/dist/core/auth/index.d.ts +18 -5
  13. package/dist/core/auth/index.d.ts.map +1 -1
  14. package/dist/core/auth/index.js +16 -4
  15. package/dist/core/auth/index.js.map +1 -1
  16. package/dist/core/auth/login.d.ts.map +1 -1
  17. package/dist/core/auth/login.js +4 -31
  18. package/dist/core/auth/login.js.map +1 -1
  19. package/dist/core/beats.d.ts +59 -0
  20. package/dist/core/beats.d.ts.map +1 -0
  21. package/dist/core/beats.js +122 -0
  22. package/dist/core/beats.js.map +1 -0
  23. package/dist/core/beats.test.d.ts +2 -0
  24. package/dist/core/beats.test.d.ts.map +1 -0
  25. package/dist/core/beats.test.js +86 -0
  26. package/dist/core/beats.test.js.map +1 -0
  27. package/dist/core/brand-kit.d.ts +80 -0
  28. package/dist/core/brand-kit.d.ts.map +1 -0
  29. package/dist/core/brand-kit.js +96 -0
  30. package/dist/core/brand-kit.js.map +1 -0
  31. package/dist/core/brand-kit.test.d.ts +2 -0
  32. package/dist/core/brand-kit.test.d.ts.map +1 -0
  33. package/dist/core/brand-kit.test.js +76 -0
  34. package/dist/core/brand-kit.test.js.map +1 -0
  35. package/dist/core/bundled-sfx.d.ts +64 -0
  36. package/dist/core/bundled-sfx.d.ts.map +1 -0
  37. package/dist/core/bundled-sfx.js +218 -0
  38. package/dist/core/bundled-sfx.js.map +1 -0
  39. package/dist/core/bundled-sfx.test.d.ts +2 -0
  40. package/dist/core/bundled-sfx.test.d.ts.map +1 -0
  41. package/dist/core/bundled-sfx.test.js +81 -0
  42. package/dist/core/bundled-sfx.test.js.map +1 -0
  43. package/dist/core/child-abort.d.ts +57 -0
  44. package/dist/core/child-abort.d.ts.map +1 -0
  45. package/dist/core/child-abort.js +95 -0
  46. package/dist/core/child-abort.js.map +1 -0
  47. package/dist/core/child-abort.test.d.ts +2 -0
  48. package/dist/core/child-abort.test.d.ts.map +1 -0
  49. package/dist/core/child-abort.test.js +88 -0
  50. package/dist/core/child-abort.test.js.map +1 -0
  51. package/dist/core/clip-scoring.d.ts +44 -0
  52. package/dist/core/clip-scoring.d.ts.map +1 -0
  53. package/dist/core/clip-scoring.js +165 -0
  54. package/dist/core/clip-scoring.js.map +1 -0
  55. package/dist/core/clip-scoring.test.d.ts +2 -0
  56. package/dist/core/clip-scoring.test.d.ts.map +1 -0
  57. package/dist/core/clip-scoring.test.js +113 -0
  58. package/dist/core/clip-scoring.test.js.map +1 -0
  59. package/dist/core/emoji-captions.d.ts +45 -0
  60. package/dist/core/emoji-captions.d.ts.map +1 -0
  61. package/dist/core/emoji-captions.js +121 -0
  62. package/dist/core/emoji-captions.js.map +1 -0
  63. package/dist/core/face-reframe.d.ts +91 -0
  64. package/dist/core/face-reframe.d.ts.map +1 -0
  65. package/dist/core/face-reframe.js +141 -0
  66. package/dist/core/face-reframe.js.map +1 -0
  67. package/dist/core/face-reframe.test.d.ts +2 -0
  68. package/dist/core/face-reframe.test.d.ts.map +1 -0
  69. package/dist/core/face-reframe.test.js +171 -0
  70. package/dist/core/face-reframe.test.js.map +1 -0
  71. package/dist/core/filler-words.d.ts +57 -9
  72. package/dist/core/filler-words.d.ts.map +1 -1
  73. package/dist/core/filler-words.js +61 -9
  74. package/dist/core/filler-words.js.map +1 -1
  75. package/dist/core/filler-words.test.js +91 -17
  76. package/dist/core/filler-words.test.js.map +1 -1
  77. package/dist/core/hook-rewrite.d.ts +48 -0
  78. package/dist/core/hook-rewrite.d.ts.map +1 -0
  79. package/dist/core/hook-rewrite.js +151 -0
  80. package/dist/core/hook-rewrite.js.map +1 -0
  81. package/dist/core/hook-rewrite.test.d.ts +2 -0
  82. package/dist/core/hook-rewrite.test.d.ts.map +1 -0
  83. package/dist/core/hook-rewrite.test.js +58 -0
  84. package/dist/core/hook-rewrite.test.js.map +1 -0
  85. package/dist/core/hosts/lazy.d.ts.map +1 -1
  86. package/dist/core/hosts/lazy.js +2 -0
  87. package/dist/core/hosts/lazy.js.map +1 -1
  88. package/dist/core/hosts/premiere/adapter.d.ts +1 -0
  89. package/dist/core/hosts/premiere/adapter.d.ts.map +1 -1
  90. package/dist/core/hosts/premiere/adapter.js.map +1 -1
  91. package/dist/core/hosts/premiere/bridge-source.d.ts.map +1 -1
  92. package/dist/core/hosts/premiere/bridge-source.js +6 -3
  93. package/dist/core/hosts/premiere/bridge-source.js.map +1 -1
  94. package/dist/core/hosts/resolve/adapter.d.ts +1 -0
  95. package/dist/core/hosts/resolve/adapter.d.ts.map +1 -1
  96. package/dist/core/hosts/resolve/adapter.js.map +1 -1
  97. package/dist/core/hosts/resolve/bridge-source.d.ts.map +1 -1
  98. package/dist/core/hosts/resolve/bridge-source.js +31 -4
  99. package/dist/core/hosts/resolve/bridge-source.js.map +1 -1
  100. package/dist/core/hosts/resolve/bridge.d.ts +2 -19
  101. package/dist/core/hosts/resolve/bridge.d.ts.map +1 -1
  102. package/dist/core/hosts/resolve/bridge.js +70 -41
  103. package/dist/core/hosts/resolve/bridge.js.map +1 -1
  104. package/dist/core/hosts/resolve/bridge.test.js +130 -0
  105. package/dist/core/hosts/resolve/bridge.test.js.map +1 -1
  106. package/dist/core/hosts/types.d.ts +6 -0
  107. package/dist/core/hosts/types.d.ts.map +1 -1
  108. package/dist/core/hosts/types.js.map +1 -1
  109. package/dist/core/logger.d.ts +32 -0
  110. package/dist/core/logger.d.ts.map +1 -0
  111. package/dist/core/logger.js +188 -0
  112. package/dist/core/logger.js.map +1 -0
  113. package/dist/core/loop-match.d.ts +57 -0
  114. package/dist/core/loop-match.d.ts.map +1 -0
  115. package/dist/core/loop-match.js +91 -0
  116. package/dist/core/loop-match.js.map +1 -0
  117. package/dist/core/media/ffmpeg.d.ts.map +1 -1
  118. package/dist/core/media/ffmpeg.js +14 -3
  119. package/dist/core/media/ffmpeg.js.map +1 -1
  120. package/dist/core/multi-format.d.ts +67 -0
  121. package/dist/core/multi-format.d.ts.map +1 -0
  122. package/dist/core/multi-format.js +127 -0
  123. package/dist/core/multi-format.js.map +1 -0
  124. package/dist/core/multi-format.test.d.ts +2 -0
  125. package/dist/core/multi-format.test.d.ts.map +1 -0
  126. package/dist/core/multi-format.test.js +151 -0
  127. package/dist/core/multi-format.test.js.map +1 -0
  128. package/dist/core/python/beats.py +61 -0
  129. package/dist/core/python/face_reframe.py +163 -0
  130. package/dist/core/python/sidecar-path.d.ts +13 -0
  131. package/dist/core/python/sidecar-path.d.ts.map +1 -0
  132. package/dist/core/python/sidecar-path.js +24 -0
  133. package/dist/core/python/sidecar-path.js.map +1 -0
  134. package/dist/core/python.d.ts +57 -0
  135. package/dist/core/python.d.ts.map +1 -0
  136. package/dist/core/python.js +107 -0
  137. package/dist/core/python.js.map +1 -0
  138. package/dist/core/python.test.d.ts +2 -0
  139. package/dist/core/python.test.d.ts.map +1 -0
  140. package/dist/core/python.test.js +129 -0
  141. package/dist/core/python.test.js.map +1 -0
  142. package/dist/core/retention-structure.d.ts +81 -0
  143. package/dist/core/retention-structure.d.ts.map +1 -0
  144. package/dist/core/retention-structure.js +206 -0
  145. package/dist/core/retention-structure.js.map +1 -0
  146. package/dist/core/retention-structure.test.d.ts +2 -0
  147. package/dist/core/retention-structure.test.d.ts.map +1 -0
  148. package/dist/core/retention-structure.test.js +88 -0
  149. package/dist/core/retention-structure.test.js.map +1 -0
  150. package/dist/core/review.d.ts +17 -0
  151. package/dist/core/review.d.ts.map +1 -1
  152. package/dist/core/review.js +20 -24
  153. package/dist/core/review.js.map +1 -1
  154. package/dist/core/safe-paths.d.ts +11 -0
  155. package/dist/core/safe-paths.d.ts.map +1 -1
  156. package/dist/core/safe-paths.js +26 -10
  157. package/dist/core/safe-paths.js.map +1 -1
  158. package/dist/core/safe-paths.test.js +16 -0
  159. package/dist/core/safe-paths.test.js.map +1 -1
  160. package/dist/core/skills-loader.d.ts +48 -2
  161. package/dist/core/skills-loader.d.ts.map +1 -1
  162. package/dist/core/skills-loader.js +97 -19
  163. package/dist/core/skills-loader.js.map +1 -1
  164. package/dist/core/skills-loader.test.js +63 -1
  165. package/dist/core/skills-loader.test.js.map +1 -1
  166. package/dist/core/srt.d.ts +42 -7
  167. package/dist/core/srt.d.ts.map +1 -1
  168. package/dist/core/srt.js +101 -32
  169. package/dist/core/srt.js.map +1 -1
  170. package/dist/core/srt.test.js +54 -1
  171. package/dist/core/srt.test.js.map +1 -1
  172. package/dist/core/thumbnail-compose.d.ts +58 -0
  173. package/dist/core/thumbnail-compose.d.ts.map +1 -0
  174. package/dist/core/thumbnail-compose.js +101 -0
  175. package/dist/core/thumbnail-compose.js.map +1 -0
  176. package/dist/core/thumbnail-promise.d.ts +46 -0
  177. package/dist/core/thumbnail-promise.d.ts.map +1 -0
  178. package/dist/core/thumbnail-promise.js +133 -0
  179. package/dist/core/thumbnail-promise.js.map +1 -0
  180. package/dist/core/thumbnail-promise.test.d.ts +2 -0
  181. package/dist/core/thumbnail-promise.test.d.ts.map +1 -0
  182. package/dist/core/thumbnail-promise.test.js +52 -0
  183. package/dist/core/thumbnail-promise.test.js.map +1 -0
  184. package/dist/core/viral-moments.d.ts +70 -0
  185. package/dist/core/viral-moments.d.ts.map +1 -0
  186. package/dist/core/viral-moments.js +192 -0
  187. package/dist/core/viral-moments.js.map +1 -0
  188. package/dist/core/viral-moments.test.d.ts +2 -0
  189. package/dist/core/viral-moments.test.d.ts.map +1 -0
  190. package/dist/core/viral-moments.test.js +153 -0
  191. package/dist/core/viral-moments.test.js.map +1 -0
  192. package/dist/core/whisper.d.ts +16 -0
  193. package/dist/core/whisper.d.ts.map +1 -1
  194. package/dist/core/whisper.js +72 -5
  195. package/dist/core/whisper.js.map +1 -1
  196. package/dist/core/whisper.test.js +111 -1
  197. package/dist/core/whisper.test.js.map +1 -1
  198. package/dist/core/youtube-metadata.d.ts +44 -0
  199. package/dist/core/youtube-metadata.d.ts.map +1 -0
  200. package/dist/core/youtube-metadata.js +168 -0
  201. package/dist/core/youtube-metadata.js.map +1 -0
  202. package/dist/core/youtube-metadata.test.d.ts +2 -0
  203. package/dist/core/youtube-metadata.test.d.ts.map +1 -0
  204. package/dist/core/youtube-metadata.test.js +132 -0
  205. package/dist/core/youtube-metadata.test.js.map +1 -0
  206. package/dist/index.d.ts +1 -1
  207. package/dist/index.d.ts.map +1 -1
  208. package/dist/index.js +3 -2
  209. package/dist/index.js.map +1 -1
  210. package/dist/prompt-commands.d.ts +24 -0
  211. package/dist/prompt-commands.d.ts.map +1 -0
  212. package/dist/prompt-commands.js +243 -0
  213. package/dist/prompt-commands.js.map +1 -0
  214. package/dist/prompt-commands.test.d.ts +2 -0
  215. package/dist/prompt-commands.test.d.ts.map +1 -0
  216. package/dist/prompt-commands.test.js +46 -0
  217. package/dist/prompt-commands.test.js.map +1 -0
  218. package/dist/skills.d.ts +6 -6
  219. package/dist/skills.d.ts.map +1 -1
  220. package/dist/skills.js +1426 -445
  221. package/dist/skills.js.map +1 -1
  222. package/dist/system-prompt.d.ts.map +1 -1
  223. package/dist/system-prompt.js +108 -0
  224. package/dist/system-prompt.js.map +1 -1
  225. package/dist/tools/add-fades.d.ts.map +1 -1
  226. package/dist/tools/add-fades.js +2 -1
  227. package/dist/tools/add-fades.js.map +1 -1
  228. package/dist/tools/add-sfx-at-cuts.d.ts.map +1 -1
  229. package/dist/tools/add-sfx-at-cuts.js +36 -11
  230. package/dist/tools/add-sfx-at-cuts.js.map +1 -1
  231. package/dist/tools/add-sfx-to-timeline.d.ts +34 -0
  232. package/dist/tools/add-sfx-to-timeline.d.ts.map +1 -0
  233. package/dist/tools/add-sfx-to-timeline.js +169 -0
  234. package/dist/tools/add-sfx-to-timeline.js.map +1 -0
  235. package/dist/tools/add-sfx-to-timeline.test.d.ts +2 -0
  236. package/dist/tools/add-sfx-to-timeline.test.d.ts.map +1 -0
  237. package/dist/tools/add-sfx-to-timeline.test.js +181 -0
  238. package/dist/tools/add-sfx-to-timeline.test.js.map +1 -0
  239. package/dist/tools/audit-first-frame.d.ts +36 -0
  240. package/dist/tools/audit-first-frame.d.ts.map +1 -0
  241. package/dist/tools/audit-first-frame.js +181 -0
  242. package/dist/tools/audit-first-frame.js.map +1 -0
  243. package/dist/tools/audit-retention-structure.d.ts +20 -0
  244. package/dist/tools/audit-retention-structure.d.ts.map +1 -0
  245. package/dist/tools/audit-retention-structure.js +95 -0
  246. package/dist/tools/audit-retention-structure.js.map +1 -0
  247. package/dist/tools/audit-retention-structure.test.d.ts +2 -0
  248. package/dist/tools/audit-retention-structure.test.d.ts.map +1 -0
  249. package/dist/tools/audit-retention-structure.test.js +93 -0
  250. package/dist/tools/audit-retention-structure.test.js.map +1 -0
  251. package/dist/tools/bleep-words.d.ts +59 -0
  252. package/dist/tools/bleep-words.d.ts.map +1 -0
  253. package/dist/tools/bleep-words.js +211 -0
  254. package/dist/tools/bleep-words.js.map +1 -0
  255. package/dist/tools/bleep-words.test.d.ts +2 -0
  256. package/dist/tools/bleep-words.test.d.ts.map +1 -0
  257. package/dist/tools/bleep-words.test.js +96 -0
  258. package/dist/tools/bleep-words.test.js.map +1 -0
  259. package/dist/tools/burn-subtitles.d.ts.map +1 -1
  260. package/dist/tools/burn-subtitles.js +10 -5
  261. package/dist/tools/burn-subtitles.js.map +1 -1
  262. package/dist/tools/clean-audio.d.ts.map +1 -1
  263. package/dist/tools/clean-audio.js +2 -1
  264. package/dist/tools/clean-audio.js.map +1 -1
  265. package/dist/tools/cluster-takes.js +2 -1
  266. package/dist/tools/cluster-takes.js.map +1 -1
  267. package/dist/tools/compose-thumbnail-variants.d.ts +70 -0
  268. package/dist/tools/compose-thumbnail-variants.d.ts.map +1 -0
  269. package/dist/tools/compose-thumbnail-variants.js +274 -0
  270. package/dist/tools/compose-thumbnail-variants.js.map +1 -0
  271. package/dist/tools/compose-thumbnail.d.ts +6 -13
  272. package/dist/tools/compose-thumbnail.d.ts.map +1 -1
  273. package/dist/tools/compose-thumbnail.js +44 -81
  274. package/dist/tools/compose-thumbnail.js.map +1 -1
  275. package/dist/tools/concat-videos.d.ts.map +1 -1
  276. package/dist/tools/concat-videos.js +12 -5
  277. package/dist/tools/concat-videos.js.map +1 -1
  278. package/dist/tools/concat-videos.test.d.ts +2 -0
  279. package/dist/tools/concat-videos.test.d.ts.map +1 -0
  280. package/dist/tools/concat-videos.test.js +103 -0
  281. package/dist/tools/concat-videos.test.js.map +1 -0
  282. package/dist/tools/crossfade-videos.d.ts.map +1 -1
  283. package/dist/tools/crossfade-videos.js +2 -1
  284. package/dist/tools/crossfade-videos.js.map +1 -1
  285. package/dist/tools/cut-filler-words.d.ts.map +1 -1
  286. package/dist/tools/cut-filler-words.js +24 -8
  287. package/dist/tools/cut-filler-words.js.map +1 -1
  288. package/dist/tools/detect-speaker-changes.js +2 -1
  289. package/dist/tools/detect-speaker-changes.js.map +1 -1
  290. package/dist/tools/extract-audio.d.ts.map +1 -1
  291. package/dist/tools/extract-audio.js +13 -7
  292. package/dist/tools/extract-audio.js.map +1 -1
  293. package/dist/tools/face-reframe.d.ts +30 -0
  294. package/dist/tools/face-reframe.d.ts.map +1 -0
  295. package/dist/tools/face-reframe.js +143 -0
  296. package/dist/tools/face-reframe.js.map +1 -0
  297. package/dist/tools/face-reframe.test.d.ts +2 -0
  298. package/dist/tools/face-reframe.test.d.ts.map +1 -0
  299. package/dist/tools/face-reframe.test.js +139 -0
  300. package/dist/tools/face-reframe.test.js.map +1 -0
  301. package/dist/tools/find-viral-moments.d.ts +23 -0
  302. package/dist/tools/find-viral-moments.d.ts.map +1 -0
  303. package/dist/tools/find-viral-moments.js +176 -0
  304. package/dist/tools/find-viral-moments.js.map +1 -0
  305. package/dist/tools/find-viral-moments.test.d.ts +2 -0
  306. package/dist/tools/find-viral-moments.test.d.ts.map +1 -0
  307. package/dist/tools/find-viral-moments.test.js +144 -0
  308. package/dist/tools/find-viral-moments.test.js.map +1 -0
  309. package/dist/tools/generate-gif.d.ts.map +1 -1
  310. package/dist/tools/generate-gif.js +47 -40
  311. package/dist/tools/generate-gif.js.map +1 -1
  312. package/dist/tools/generate-gif.test.d.ts +2 -0
  313. package/dist/tools/generate-gif.test.d.ts.map +1 -0
  314. package/dist/tools/generate-gif.test.js +115 -0
  315. package/dist/tools/generate-gif.test.js.map +1 -0
  316. package/dist/tools/generate-outro.d.ts +18 -0
  317. package/dist/tools/generate-outro.d.ts.map +1 -0
  318. package/dist/tools/generate-outro.js +175 -0
  319. package/dist/tools/generate-outro.js.map +1 -0
  320. package/dist/tools/generate-youtube-metadata.d.ts +23 -0
  321. package/dist/tools/generate-youtube-metadata.d.ts.map +1 -0
  322. package/dist/tools/generate-youtube-metadata.js +103 -0
  323. package/dist/tools/generate-youtube-metadata.js.map +1 -0
  324. package/dist/tools/generate-youtube-metadata.test.d.ts +2 -0
  325. package/dist/tools/generate-youtube-metadata.test.d.ts.map +1 -0
  326. package/dist/tools/generate-youtube-metadata.test.js +118 -0
  327. package/dist/tools/generate-youtube-metadata.test.js.map +1 -0
  328. package/dist/tools/index.d.ts +14 -0
  329. package/dist/tools/index.d.ts.map +1 -1
  330. package/dist/tools/index.js +130 -1
  331. package/dist/tools/index.js.map +1 -1
  332. package/dist/tools/index.test.js +27 -1
  333. package/dist/tools/index.test.js.map +1 -1
  334. package/dist/tools/ken-burns.d.ts.map +1 -1
  335. package/dist/tools/ken-burns.js +2 -1
  336. package/dist/tools/ken-burns.js.map +1 -1
  337. package/dist/tools/loop-match-short.d.ts +22 -0
  338. package/dist/tools/loop-match-short.d.ts.map +1 -0
  339. package/dist/tools/loop-match-short.js +107 -0
  340. package/dist/tools/loop-match-short.js.map +1 -0
  341. package/dist/tools/mix-audio.d.ts.map +1 -1
  342. package/dist/tools/mix-audio.js +2 -1
  343. package/dist/tools/mix-audio.js.map +1 -1
  344. package/dist/tools/normalize-loudness.d.ts.map +1 -1
  345. package/dist/tools/normalize-loudness.js +2 -1
  346. package/dist/tools/normalize-loudness.js.map +1 -1
  347. package/dist/tools/path-traversal.test.d.ts +15 -0
  348. package/dist/tools/path-traversal.test.d.ts.map +1 -0
  349. package/dist/tools/path-traversal.test.js +223 -0
  350. package/dist/tools/path-traversal.test.js.map +1 -0
  351. package/dist/tools/pick-best-takes.js +2 -1
  352. package/dist/tools/pick-best-takes.js.map +1 -1
  353. package/dist/tools/punch-in.d.ts.map +1 -1
  354. package/dist/tools/punch-in.js +2 -1
  355. package/dist/tools/punch-in.js.map +1 -1
  356. package/dist/tools/read-transcript.js +2 -1
  357. package/dist/tools/read-transcript.js.map +1 -1
  358. package/dist/tools/render-multi-format.d.ts +35 -0
  359. package/dist/tools/render-multi-format.d.ts.map +1 -0
  360. package/dist/tools/render-multi-format.js +206 -0
  361. package/dist/tools/render-multi-format.js.map +1 -0
  362. package/dist/tools/render-multi-format.test.d.ts +2 -0
  363. package/dist/tools/render-multi-format.test.d.ts.map +1 -0
  364. package/dist/tools/render-multi-format.test.js +312 -0
  365. package/dist/tools/render-multi-format.test.js.map +1 -0
  366. package/dist/tools/render.d.ts.map +1 -1
  367. package/dist/tools/render.js +2 -2
  368. package/dist/tools/render.js.map +1 -1
  369. package/dist/tools/rewrite-hook.d.ts +32 -0
  370. package/dist/tools/rewrite-hook.d.ts.map +1 -0
  371. package/dist/tools/rewrite-hook.js +65 -0
  372. package/dist/tools/rewrite-hook.js.map +1 -0
  373. package/dist/tools/score-clip.d.ts +30 -0
  374. package/dist/tools/score-clip.d.ts.map +1 -0
  375. package/dist/tools/score-clip.js +109 -0
  376. package/dist/tools/score-clip.js.map +1 -0
  377. package/dist/tools/score-clip.test.d.ts +2 -0
  378. package/dist/tools/score-clip.test.d.ts.map +1 -0
  379. package/dist/tools/score-clip.test.js +110 -0
  380. package/dist/tools/score-clip.test.js.map +1 -0
  381. package/dist/tools/search-tools.d.ts +34 -0
  382. package/dist/tools/search-tools.d.ts.map +1 -0
  383. package/dist/tools/search-tools.js +86 -0
  384. package/dist/tools/search-tools.js.map +1 -0
  385. package/dist/tools/search-tools.test.d.ts +2 -0
  386. package/dist/tools/search-tools.test.d.ts.map +1 -0
  387. package/dist/tools/search-tools.test.js +60 -0
  388. package/dist/tools/search-tools.test.js.map +1 -0
  389. package/dist/tools/snap-cuts-to-beats.d.ts +18 -0
  390. package/dist/tools/snap-cuts-to-beats.d.ts.map +1 -0
  391. package/dist/tools/snap-cuts-to-beats.js +110 -0
  392. package/dist/tools/snap-cuts-to-beats.js.map +1 -0
  393. package/dist/tools/snap-cuts-to-beats.test.d.ts +2 -0
  394. package/dist/tools/snap-cuts-to-beats.test.d.ts.map +1 -0
  395. package/dist/tools/snap-cuts-to-beats.test.js +99 -0
  396. package/dist/tools/snap-cuts-to-beats.test.js.map +1 -0
  397. package/dist/tools/speed-ramp.d.ts.map +1 -1
  398. package/dist/tools/speed-ramp.js +2 -1
  399. package/dist/tools/speed-ramp.js.map +1 -1
  400. package/dist/tools/stabilize-video.d.ts.map +1 -1
  401. package/dist/tools/stabilize-video.js +2 -1
  402. package/dist/tools/stabilize-video.js.map +1 -1
  403. package/dist/tools/suggest-broll.d.ts +34 -0
  404. package/dist/tools/suggest-broll.d.ts.map +1 -0
  405. package/dist/tools/suggest-broll.js +367 -0
  406. package/dist/tools/suggest-broll.js.map +1 -0
  407. package/dist/tools/suggest-broll.test.d.ts +2 -0
  408. package/dist/tools/suggest-broll.test.d.ts.map +1 -0
  409. package/dist/tools/suggest-broll.test.js +217 -0
  410. package/dist/tools/suggest-broll.test.js.map +1 -0
  411. package/dist/tools/text-based-cut.d.ts +33 -0
  412. package/dist/tools/text-based-cut.d.ts.map +1 -0
  413. package/dist/tools/text-based-cut.js +172 -0
  414. package/dist/tools/text-based-cut.js.map +1 -0
  415. package/dist/tools/text-based-cut.test.d.ts +2 -0
  416. package/dist/tools/text-based-cut.test.d.ts.map +1 -0
  417. package/dist/tools/text-based-cut.test.js +32 -0
  418. package/dist/tools/text-based-cut.test.js.map +1 -0
  419. package/dist/tools/transcribe.d.ts +1 -1
  420. package/dist/tools/transition-videos.d.ts +1 -1
  421. package/dist/tools/transition-videos.d.ts.map +1 -1
  422. package/dist/tools/transition-videos.js +2 -1
  423. package/dist/tools/transition-videos.js.map +1 -1
  424. package/dist/tools/trim-dead-air.d.ts +59 -0
  425. package/dist/tools/trim-dead-air.d.ts.map +1 -0
  426. package/dist/tools/trim-dead-air.js +215 -0
  427. package/dist/tools/trim-dead-air.js.map +1 -0
  428. package/dist/tools/trim-dead-air.test.d.ts +2 -0
  429. package/dist/tools/trim-dead-air.test.d.ts.map +1 -0
  430. package/dist/tools/trim-dead-air.test.js +75 -0
  431. package/dist/tools/trim-dead-air.test.js.map +1 -0
  432. package/dist/tools/verify-thumbnail-promise.d.ts +33 -0
  433. package/dist/tools/verify-thumbnail-promise.d.ts.map +1 -0
  434. package/dist/tools/verify-thumbnail-promise.js +112 -0
  435. package/dist/tools/verify-thumbnail-promise.js.map +1 -0
  436. package/dist/tools/verify-thumbnail-promise.test.d.ts +2 -0
  437. package/dist/tools/verify-thumbnail-promise.test.d.ts.map +1 -0
  438. package/dist/tools/verify-thumbnail-promise.test.js +38 -0
  439. package/dist/tools/verify-thumbnail-promise.test.js.map +1 -0
  440. package/dist/tools/write-keyword-captions.d.ts +7 -0
  441. package/dist/tools/write-keyword-captions.d.ts.map +1 -1
  442. package/dist/tools/write-keyword-captions.js +35 -4
  443. package/dist/tools/write-keyword-captions.js.map +1 -1
  444. package/dist/ui/App.d.ts.map +1 -1
  445. package/dist/ui/App.js +75 -11
  446. package/dist/ui/App.js.map +1 -1
  447. package/dist/ui/tool-formatters.d.ts +30 -0
  448. package/dist/ui/tool-formatters.d.ts.map +1 -0
  449. package/dist/ui/tool-formatters.js +461 -0
  450. package/dist/ui/tool-formatters.js.map +1 -0
  451. package/dist/ui/tool-formatters.test.d.ts +2 -0
  452. package/dist/ui/tool-formatters.test.d.ts.map +1 -0
  453. package/dist/ui/tool-formatters.test.js +143 -0
  454. package/dist/ui/tool-formatters.test.js.map +1 -0
  455. package/package.json +10 -9
@@ -0,0 +1,141 @@
1
+ import { runPython } from "./python.js";
2
+ import { sidecarPath } from "./python/sidecar-path.js";
3
+ export function parseAspect(aspect) {
4
+ const [w, h] = aspect.split(":").map((n) => Number(n));
5
+ if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) {
6
+ throw new Error(`invalid aspect: ${aspect}`);
7
+ }
8
+ return { w, h };
9
+ }
10
+ /**
11
+ * Spawn the face-reframe sidecar; return the parsed shot plan.
12
+ * Throws on sidecar failure with the structured error embedded.
13
+ */
14
+ export async function analyzeReframe(videoPath, opts = {}) {
15
+ const script = sidecarPath("face_reframe.py");
16
+ const stdin = JSON.stringify({
17
+ videoPath,
18
+ sampleFps: opts.sampleFps,
19
+ minDetectionConfidence: opts.minDetectionConfidence,
20
+ smoothingWindowSec: opts.smoothingWindowSec,
21
+ });
22
+ const { code, stdout, stderr } = await runPython(script, [], {
23
+ signal: opts.signal,
24
+ stdin,
25
+ });
26
+ const trimmed = stdout.trim();
27
+ if (!trimmed) {
28
+ throw new Error(`face-reframe sidecar returned empty stdout (exit ${code}): ${tail(stderr)}`);
29
+ }
30
+ let parsed;
31
+ try {
32
+ parsed = JSON.parse(trimmed);
33
+ }
34
+ catch {
35
+ throw new Error(`face-reframe sidecar returned malformed output: ${trimmed.slice(-200)} | stderr: ${tail(stderr)}`);
36
+ }
37
+ if (parsed && typeof parsed === "object" && "error" in parsed) {
38
+ const err = parsed;
39
+ throw new Error(err.error ?? "unknown face-reframe sidecar error");
40
+ }
41
+ if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.shots)) {
42
+ throw new Error(`face-reframe sidecar returned unexpected shape: ${trimmed.slice(-200)}`);
43
+ }
44
+ return parsed;
45
+ }
46
+ /**
47
+ * Compute the crop dimensions for a target aspect when cropping FROM a
48
+ * source frame. The crop is sized to fit ENTIRELY inside the source — i.e.
49
+ * we letterbox neither dimension. The returned `outW` × `outH` matches the
50
+ * target aspect exactly.
51
+ *
52
+ * Pure / unit-testable.
53
+ */
54
+ export function reframeCropSize(srcW, srcH, aspect) {
55
+ if (srcW <= 0 || srcH <= 0) {
56
+ throw new Error("source dimensions must be positive");
57
+ }
58
+ const { w: aw, h: ah } = parseAspect(aspect);
59
+ // Two candidate crops:
60
+ // width-bound: outW = srcW, outH = srcW * ah / aw
61
+ // height-bound: outH = srcH, outW = srcH * aw / ah
62
+ // Pick whichever fits inside the source frame.
63
+ const heightFromW = (srcW * ah) / aw;
64
+ let outW;
65
+ let outH;
66
+ if (heightFromW <= srcH) {
67
+ // Width-bound (e.g. 16:9 source → 1:1 crop is height-bound; 16:9 source → 9:16 crop is height-bound;
68
+ // a square source → 9:16 crop is width-bound).
69
+ outW = srcW;
70
+ outH = heightFromW;
71
+ }
72
+ else {
73
+ outH = srcH;
74
+ outW = (srcH * aw) / ah;
75
+ }
76
+ // Round DOWN to even integers. ffmpeg's libx264 needs even crop dims;
77
+ // rounding down avoids exceeding the source.
78
+ outW = Math.floor(outW / 2) * 2;
79
+ outH = Math.floor(outH / 2) * 2;
80
+ if (outW <= 0 || outH <= 0) {
81
+ throw new Error("computed crop is degenerate");
82
+ }
83
+ return { outW, outH };
84
+ }
85
+ /**
86
+ * Compile a per-shot smoothed-face plan into one ffmpeg `crop` expression
87
+ * that switches X position by timestamp. Each shot contributes one
88
+ * `if(between(t, a, b), x_i, ...)` tier; the outermost ELSE is a centre
89
+ * crop so the filter is a no-op outside any defined shot.
90
+ *
91
+ * The crop's Y is left static (we don't currently track vertical motion;
92
+ * faces tend to dominate the upper third on portrait crops anyway).
93
+ *
94
+ * Pure / unit-testable. No ffmpeg execution.
95
+ */
96
+ export function buildReframeFilter(plan, aspect) {
97
+ const { sourceWidth: srcW, sourceHeight: srcH } = plan;
98
+ const { outW, outH } = reframeCropSize(srcW, srcH, aspect);
99
+ // For each shot compute the desired top-left X from the smoothed face
100
+ // centre, then clamp into the legal range so the crop never escapes the
101
+ // frame. Y is centred — vertical face position varies less for talking
102
+ // heads, and exposing both axes invites jitter.
103
+ const yCentre = Math.floor((srcH - outH) / 2);
104
+ const shots = plan.shots
105
+ .filter((s) => s.endSec > s.startSec)
106
+ .sort((a, b) => a.startSec - b.startSec);
107
+ const shotXs = [];
108
+ // Build `xExpr` from the LAST shot backwards so each `if` wraps the next.
109
+ // Default (outside all shots): centre crop.
110
+ const centreX = Math.floor((srcW - outW) / 2);
111
+ let xExpr = String(centreX);
112
+ for (let i = shots.length - 1; i >= 0; i--) {
113
+ const s = shots[i];
114
+ const desiredCx = Math.round(s.smoothedX * srcW);
115
+ let x = desiredCx - Math.floor(outW / 2);
116
+ // Clamp into [0, srcW - outW].
117
+ if (x < 0)
118
+ x = 0;
119
+ const maxX = srcW - outW;
120
+ if (x > maxX)
121
+ x = maxX;
122
+ shotXs[i] = x;
123
+ const a = fmt(s.startSec);
124
+ const b = fmt(s.endSec);
125
+ xExpr = `if(between(t\\,${a}\\,${b})\\,${x}\\,${xExpr})`;
126
+ }
127
+ // crop=W:H:x:y — single filter, single pass. We pin Y to a constant
128
+ // (centre) for now; if we extend to vertical tracking later this becomes
129
+ // a parallel piecewise expression.
130
+ const cropFilter = `crop=${outW}:${outH}:x='${xExpr}':y=${yCentre}`;
131
+ return { filter: cropFilter, outWidth: outW, outHeight: outH, shotXs };
132
+ }
133
+ function fmt(n) {
134
+ if (!Number.isFinite(n))
135
+ return "0";
136
+ return Number(n.toFixed(4)).toString();
137
+ }
138
+ function tail(s) {
139
+ return s.split("\n").filter(Boolean).slice(-3).join(" | ").slice(-300);
140
+ }
141
+ //# sourceMappingURL=face-reframe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"face-reframe.js","sourceRoot":"","sources":["../../src/core/face-reframe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=face-reframe.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"face-reframe.test.d.ts","sourceRoot":"","sources":["../../src/core/face-reframe.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,171 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildReframeFilter, parseAspect, reframeCropSize, } from "./face-reframe.js";
3
+ function plan(overrides = {}) {
4
+ return {
5
+ shots: [],
6
+ totalSec: 10,
7
+ fps: 30,
8
+ sourceWidth: 1920,
9
+ sourceHeight: 1080,
10
+ ...overrides,
11
+ };
12
+ }
13
+ describe("parseAspect", () => {
14
+ it("parses each supported ratio", () => {
15
+ expect(parseAspect("9:16")).toEqual({ w: 9, h: 16 });
16
+ expect(parseAspect("1:1")).toEqual({ w: 1, h: 1 });
17
+ expect(parseAspect("4:5")).toEqual({ w: 4, h: 5 });
18
+ expect(parseAspect("16:9")).toEqual({ w: 16, h: 9 });
19
+ });
20
+ });
21
+ describe("reframeCropSize", () => {
22
+ it("9:16 from 1920x1080 → height-bound; outW = 1080 * 9/16 = 607 → even 606", () => {
23
+ const { outW, outH } = reframeCropSize(1920, 1080, "9:16");
24
+ expect(outH).toBe(1080);
25
+ expect(outW).toBe(606); // floor(607.5) -> 607 -> even-floor 606
26
+ });
27
+ it("1:1 from 1920x1080 → height-bound; outW = outH = 1080", () => {
28
+ const { outW, outH } = reframeCropSize(1920, 1080, "1:1");
29
+ expect(outW).toBe(1080);
30
+ expect(outH).toBe(1080);
31
+ });
32
+ it("4:5 from 1920x1080 → height-bound; outW = 1080 * 4/5 = 864", () => {
33
+ const { outW, outH } = reframeCropSize(1920, 1080, "4:5");
34
+ expect(outH).toBe(1080);
35
+ expect(outW).toBe(864);
36
+ });
37
+ it("16:9 from 1920x1080 → width-bound (full source)", () => {
38
+ const { outW, outH } = reframeCropSize(1920, 1080, "16:9");
39
+ expect(outW).toBe(1920);
40
+ expect(outH).toBe(1080);
41
+ });
42
+ it("9:16 from a square 1080x1080 source → width-bound; outH > srcH? no — width-bound", () => {
43
+ // height-from-w = 1080 * 16/9 = 1920 > srcH 1080 → fall to height-bound:
44
+ // outH = 1080, outW = 1080 * 9 / 16 = 607.5 → 606
45
+ const { outW, outH } = reframeCropSize(1080, 1080, "9:16");
46
+ expect(outH).toBe(1080);
47
+ expect(outW).toBe(606);
48
+ });
49
+ it("rejects non-positive source dimensions", () => {
50
+ expect(() => reframeCropSize(0, 1080, "9:16")).toThrow();
51
+ expect(() => reframeCropSize(1920, -1, "9:16")).toThrow();
52
+ });
53
+ });
54
+ describe("buildReframeFilter", () => {
55
+ it("emits a centre-crop filter when there are no shots (filter falls through to centreX)", () => {
56
+ const r = buildReframeFilter(plan({ shots: [] }), "9:16");
57
+ // outW from 1920x1080 9:16 = 606; centreX = floor((1920-606)/2) = 657
58
+ expect(r.outWidth).toBe(606);
59
+ expect(r.outHeight).toBe(1080);
60
+ // No shots → no `if(...)` wrapping; filter = "crop=606:1080:x='657':y=0"
61
+ expect(r.filter).toBe("crop=606:1080:x='657':y=0");
62
+ expect(r.shotXs).toEqual([]);
63
+ });
64
+ it("clamps a face at the right edge to the maximum legal X", () => {
65
+ const p = plan({
66
+ shots: [
67
+ {
68
+ startSec: 0,
69
+ endSec: 5,
70
+ frames: [],
71
+ smoothedX: 0.99, // pushes crop way past the right edge
72
+ smoothedY: 0.5,
73
+ mode: "face",
74
+ },
75
+ ],
76
+ });
77
+ const r = buildReframeFilter(p, "9:16");
78
+ // maxX = 1920 - 606 = 1314
79
+ expect(r.shotXs[0]).toBe(1314);
80
+ expect(r.filter).toContain("between(t\\,0\\,5)");
81
+ expect(r.filter).toContain("\\,1314\\,");
82
+ });
83
+ it("clamps a face at the left edge to X=0", () => {
84
+ const p = plan({
85
+ shots: [
86
+ {
87
+ startSec: 1,
88
+ endSec: 2,
89
+ frames: [],
90
+ smoothedX: 0.01,
91
+ smoothedY: 0.5,
92
+ mode: "face",
93
+ },
94
+ ],
95
+ });
96
+ const r = buildReframeFilter(p, "9:16");
97
+ expect(r.shotXs[0]).toBe(0);
98
+ expect(r.filter).toContain("between(t\\,1\\,2)");
99
+ expect(r.filter).toContain("\\,0\\,");
100
+ });
101
+ it("uses centred X for a face at exact 0.5", () => {
102
+ const p = plan({
103
+ shots: [
104
+ {
105
+ startSec: 0,
106
+ endSec: 4,
107
+ frames: [],
108
+ smoothedX: 0.5,
109
+ smoothedY: 0.5,
110
+ mode: "face",
111
+ },
112
+ ],
113
+ });
114
+ const r = buildReframeFilter(p, "9:16");
115
+ // desiredCx = round(0.5 * 1920) = 960; x = 960 - floor(606/2) = 960 - 303 = 657
116
+ expect(r.shotXs[0]).toBe(657);
117
+ });
118
+ it("nests two shots into a single piecewise X expression", () => {
119
+ const p = plan({
120
+ shots: [
121
+ { startSec: 0, endSec: 3, frames: [], smoothedX: 0.3, smoothedY: 0.5, mode: "face" },
122
+ { startSec: 3, endSec: 6, frames: [], smoothedX: 0.7, smoothedY: 0.5, mode: "face" },
123
+ ],
124
+ });
125
+ const r = buildReframeFilter(p, "9:16");
126
+ expect(r.shotXs).toHaveLength(2);
127
+ expect(r.filter).toContain("between(t\\,0\\,3)");
128
+ expect(r.filter).toContain("between(t\\,3\\,6)");
129
+ // Outer if() should be the FIRST shot (sorted by start); inner the SECOND.
130
+ const idx0 = r.filter.indexOf("between(t\\,0\\,3)");
131
+ const idx3 = r.filter.indexOf("between(t\\,3\\,6)");
132
+ expect(idx0).toBeGreaterThanOrEqual(0);
133
+ expect(idx3).toBeGreaterThan(idx0);
134
+ // Final fallback (centre): 657 appears as the innermost else of x='...'.
135
+ // x is wrapped in single quotes; closing the y arg follows.
136
+ expect(r.filter).toMatch(/657\)\)':y=0$/);
137
+ });
138
+ it("produces an even outW × outH for libx264 compatibility", () => {
139
+ // Test a few odd source resolutions.
140
+ for (const [w, h] of [
141
+ [1280, 720],
142
+ [3840, 2160],
143
+ [1281, 721],
144
+ ]) {
145
+ const r = buildReframeFilter(plan({ sourceWidth: w, sourceHeight: h }), "9:16");
146
+ expect(r.outWidth % 2).toBe(0);
147
+ expect(r.outHeight % 2).toBe(0);
148
+ }
149
+ });
150
+ it("sorts shots by startSec even when caller passes them out of order", () => {
151
+ const p = plan({
152
+ shots: [
153
+ { startSec: 5, endSec: 7, frames: [], smoothedX: 0.7, smoothedY: 0.5, mode: "face" },
154
+ { startSec: 0, endSec: 2, frames: [], smoothedX: 0.3, smoothedY: 0.5, mode: "face" },
155
+ ],
156
+ });
157
+ const r = buildReframeFilter(p, "9:16");
158
+ const idx0 = r.filter.indexOf("between(t\\,0\\,2)");
159
+ const idx5 = r.filter.indexOf("between(t\\,5\\,7)");
160
+ // Outer wraps inner; the FIRST sorted shot must appear first in the string.
161
+ expect(idx0).toBeGreaterThanOrEqual(0);
162
+ expect(idx5).toBeGreaterThan(idx0);
163
+ });
164
+ it("includes scale-back? — nope; we only emit a single crop filter (no scale)", () => {
165
+ // The tool layer chooses whether to upscale; the filter we emit is a
166
+ // pure crop. Verify there's no `scale=` in the output.
167
+ const r = buildReframeFilter(plan({ shots: [] }), "9:16");
168
+ expect(r.filter).not.toContain("scale=");
169
+ });
170
+ });
171
+ //# sourceMappingURL=face-reframe.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"face-reframe.test.js","sourceRoot":"","sources":["../../src/core/face-reframe.test.ts"],"names":[],"mappings":"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"}
@@ -41,13 +41,23 @@ export interface DetectFillersOptions {
41
41
  /** Filler vocabulary; defaults to DEFAULT_FILLERS. Case-insensitive. */
42
42
  fillers?: readonly string[];
43
43
  /**
44
- * Pad the cut start by this many ms so the trailing audio of the
45
- * preceding word isn't clipped. Default 20ms.
44
+ * Trim the filler-cut start by this many ms so the trailing audio of
45
+ * the PREVIOUS word isn't clipped. Positive = keep more of the previous
46
+ * word (cut starts later than whisper's word boundary). Default 0 ms.
47
+ *
48
+ * Note: this used to default to 20 ms with the OPPOSITE sign — the cut
49
+ * would EXPAND outward by 20 ms on each side, eating ~5 s of speech
50
+ * across a typical podcast cut. Reverted to a 0 default in commit
51
+ * `keep more of the speaker's actual audio` (May 2026); set to a small
52
+ * positive value (e.g. 15 ms) only if whisper is over-reporting word
53
+ * end times in your specific dataset.
46
54
  */
47
55
  paddingStartMs?: number;
48
56
  /**
49
- * Pad the cut end by this many ms so the leading audio of the next
50
- * word isn't clipped. Default 20ms.
57
+ * Trim the filler-cut end by this many ms so the leading audio of the
58
+ * NEXT word isn't clipped. Positive = keep more of the next word (cut
59
+ * ends earlier than whisper's word boundary). Default 0 ms. See note on
60
+ * paddingStartMs above for the bug-fix history.
51
61
  */
52
62
  paddingEndMs?: number;
53
63
  /**
@@ -59,9 +69,17 @@ export interface DetectFillersOptions {
59
69
  * Aggressive single words like "like" / "so" / "actually" / "right" /
60
70
  * "honestly" / "literally" / "basically" are filler ONLY when they
61
71
  * appear as standalone disfluencies. When `aggressiveSingleWords` is
62
- * false (default true), these are excluded from matching even if
63
- * present in `fillers`. Toggle on for ruthless cuts; off when the
64
- * speaker uses them substantively (a chef saying "literally" = real).
72
+ * true, these are included; when false (the default), only the safe-list
73
+ * (um/uh/er/hmm/you know/i mean/kind of/sort of) is applied.
74
+ *
75
+ * Default is **false** — the conservative path — because the tool
76
+ * permanently removes audio and words like "like"/"so" are frequently
77
+ * substantive. Pass `true` for ruthless cuts on monologue-style content
78
+ * where the speaker's verbal tics are clearly fillers.
79
+ *
80
+ * Changed from `true` default (May 2026): the old default caused
81
+ * unintended removal of substantive speech for callers who didn't
82
+ * explicitly configure this option.
65
83
  */
66
84
  aggressiveSingleWords?: boolean;
67
85
  }
@@ -82,8 +100,38 @@ export declare function detectFillerRanges(transcript: Transcript, opts?: Detect
82
100
  */
83
101
  export declare function keepRangesFromFillers(fillers: FillerRange[], totalSec: number, minKeepDurSec?: number): KeepRange[];
84
102
  /**
85
- * Frame-align keep ranges. Rounds INWARD (start ceils, end floors) so
86
- * cuts never extend into a filler.
103
+ * From a sorted keep-range list, compute the TIMELINE-space cut points.
104
+ *
105
+ * After `import_edl` lands the keep ranges concatenated onto the timeline,
106
+ * each junction between adjacent keeps becomes a visible cut at the
107
+ * timeline-relative timestamp = sum of all earlier keep durations.
108
+ *
109
+ * Example: keeps = [[0,10], [12,25], [28,40]]
110
+ * timeline = [0..10] + [10..23] + [23..35]
111
+ * cuts at = 10s, 23s (two junctions)
112
+ *
113
+ * Why this matters: tools like `add_sfx_to_timeline` and `add_sfx_at_cuts`
114
+ * place SFX at TIMELINE timestamps. If callers pass SOURCE timestamps from
115
+ * the transcript, the drift compounds with every cut and the SFX lands
116
+ * progressively further out of sync (fine for the first ~30s, off by 20+s
117
+ * by the end of a typical podcast). This helper exists to remove that
118
+ * footgun.
119
+ */
120
+ export declare function keepRangesToTimelineCuts(keeps: KeepRange[]): number[];
121
+ /**
122
+ * Frame-align keep ranges. Rounds OUTWARD (start floors, end ceils) so
123
+ * we never DROP speech that lives in a partial frame at the keep's edge.
124
+ *
125
+ * Was: rounds inward (start ceils, end floors). Inward rounding never
126
+ * extends INTO an adjacent filler, but it ALSO loses up to one frame at
127
+ * each end of every keep — ~33 ms at 30 fps, ~17 ms at 60 fps. Across
128
+ * a 73-cut podcast that's 5+ seconds of speech disappearing into
129
+ * sub-frame rounding error.
130
+ *
131
+ * Trade-off: outward rounding can include up to one frame of an adjacent
132
+ * filler at each junction. That's ~33 ms at 30 fps — well within whisper
133
+ * timing noise (typically ±50 ms) and inaudible compared to losing 5 s
134
+ * of actual speech. Worth it.
87
135
  */
88
136
  export declare function keepRangesToFrameRanges(keeps: KeepRange[], fps: number): Array<{
89
137
  startFrame: number;
@@ -1 +1 @@
1
- {"version":3,"file":"filler-words.d.ts","sourceRoot":"","sources":["../../src/core/filler-words.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,oLAoBlB,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAiBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,IAAI,GAAE,oBAAyB,GAC9B,WAAW,EAAE,CA6Cf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,EAAE,EACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,SAAO,GACnB,SAAS,EAAE,CAuBb;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,SAAS,EAAE,EAClB,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAQjD;AA6DD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW,CAmBpE"}
1
+ {"version":3,"file":"filler-words.d.ts","sourceRoot":"","sources":["../../src/core/filler-words.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,6CAA6C;AAC7C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,oLAoBlB,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC,wEAAwE;IACxE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAiBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,IAAI,GAAE,oBAAyB,GAC9B,WAAW,EAAE,CAyDf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,WAAW,EAAE,EACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,SAAO,GACnB,SAAS,EAAE,CAuBb;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CASrE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,SAAS,EAAE,EAClB,GAAG,EAAE,MAAM,GACV,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAQjD;AA6DD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,WAAW,CAmBpE"}
@@ -63,10 +63,13 @@ const NON_AGGRESSIVE_SAFE_LIST = new Set([
63
63
  * within `mergeGapMs` are merged into a single cut.
64
64
  */
65
65
  export function detectFillerRanges(transcript, opts = {}) {
66
- const padStart = (opts.paddingStartMs ?? 20) / 1000;
67
- const padEnd = (opts.paddingEndMs ?? 20) / 1000;
66
+ // Default 0 ms — trust whisper's word timings. Previously defaulted to
67
+ // 20 ms with the wrong sign, producing 5+ s of unintended speech loss
68
+ // across a 73-cut podcast. See DetectFillersOptions docs.
69
+ const padStart = (opts.paddingStartMs ?? 0) / 1000;
70
+ const padEnd = (opts.paddingEndMs ?? 0) / 1000;
68
71
  const mergeGap = (opts.mergeGapMs ?? 150) / 1000;
69
- const aggressive = opts.aggressiveSingleWords ?? true;
72
+ const aggressive = opts.aggressiveSingleWords ?? false;
70
73
  const vocab = (opts.fillers ?? DEFAULT_FILLERS)
71
74
  .map((f) => f.trim().toLowerCase())
72
75
  .filter((f) => f.length > 0)
@@ -89,8 +92,17 @@ export function detectFillerRanges(transcript, opts = {}) {
89
92
  }
90
93
  const startWord = words[i];
91
94
  const endWord = words[i + match.length - 1];
92
- const startSec = Math.max(0, startWord.start - padStart);
93
- const endSec = endWord.end + padEnd;
95
+ // Padding now SHRINKS the filler range — positive padStart means
96
+ // the cut starts LATER (preserves more of the previous word's tail);
97
+ // positive padEnd means the cut ends EARLIER (preserves more of the
98
+ // next word's head). Old code used `- padStart` / `+ padEnd` which
99
+ // EXPANDED the cut outward, eating ~40 ms per filler.
100
+ const rawStart = startWord.start + padStart;
101
+ const rawEnd = endWord.end - padEnd;
102
+ // Clamp: padding can't make the filler range negative-duration; if
103
+ // it would, keep the original word boundaries unpadded.
104
+ const startSec = rawEnd > rawStart ? Math.max(0, rawStart) : Math.max(0, startWord.start);
105
+ const endSec = rawEnd > rawStart ? rawEnd : endWord.end;
94
106
  out.push({
95
107
  startSec,
96
108
  endSec,
@@ -135,14 +147,54 @@ export function keepRangesFromFillers(fillers, totalSec, minKeepDurSec = 0.05) {
135
147
  return keeps;
136
148
  }
137
149
  /**
138
- * Frame-align keep ranges. Rounds INWARD (start ceils, end floors) so
139
- * cuts never extend into a filler.
150
+ * From a sorted keep-range list, compute the TIMELINE-space cut points.
151
+ *
152
+ * After `import_edl` lands the keep ranges concatenated onto the timeline,
153
+ * each junction between adjacent keeps becomes a visible cut at the
154
+ * timeline-relative timestamp = sum of all earlier keep durations.
155
+ *
156
+ * Example: keeps = [[0,10], [12,25], [28,40]]
157
+ * timeline = [0..10] + [10..23] + [23..35]
158
+ * cuts at = 10s, 23s (two junctions)
159
+ *
160
+ * Why this matters: tools like `add_sfx_to_timeline` and `add_sfx_at_cuts`
161
+ * place SFX at TIMELINE timestamps. If callers pass SOURCE timestamps from
162
+ * the transcript, the drift compounds with every cut and the SFX lands
163
+ * progressively further out of sync (fine for the first ~30s, off by 20+s
164
+ * by the end of a typical podcast). This helper exists to remove that
165
+ * footgun.
166
+ */
167
+ export function keepRangesToTimelineCuts(keeps) {
168
+ if (keeps.length <= 1)
169
+ return [];
170
+ const cuts = [];
171
+ let acc = 0;
172
+ for (let i = 0; i < keeps.length - 1; i++) {
173
+ acc += keeps[i].endSec - keeps[i].startSec;
174
+ cuts.push(+acc.toFixed(3));
175
+ }
176
+ return cuts;
177
+ }
178
+ /**
179
+ * Frame-align keep ranges. Rounds OUTWARD (start floors, end ceils) so
180
+ * we never DROP speech that lives in a partial frame at the keep's edge.
181
+ *
182
+ * Was: rounds inward (start ceils, end floors). Inward rounding never
183
+ * extends INTO an adjacent filler, but it ALSO loses up to one frame at
184
+ * each end of every keep — ~33 ms at 30 fps, ~17 ms at 60 fps. Across
185
+ * a 73-cut podcast that's 5+ seconds of speech disappearing into
186
+ * sub-frame rounding error.
187
+ *
188
+ * Trade-off: outward rounding can include up to one frame of an adjacent
189
+ * filler at each junction. That's ~33 ms at 30 fps — well within whisper
190
+ * timing noise (typically ±50 ms) and inaudible compared to losing 5 s
191
+ * of actual speech. Worth it.
140
192
  */
141
193
  export function keepRangesToFrameRanges(keeps, fps) {
142
194
  const out = [];
143
195
  for (const k of keeps) {
144
- const sf = Math.ceil(k.startSec * fps);
145
- const ef = Math.floor(k.endSec * fps);
196
+ const sf = Math.floor(k.startSec * fps);
197
+ const ef = Math.ceil(k.endSec * fps);
146
198
  if (ef > sf)
147
199
  out.push({ startFrame: sf, endFrame: ef });
148
200
  }
@@ -1 +1 @@
1
- {"version":3,"file":"filler-words.js","sourceRoot":"","sources":["../../src/core/filler-words.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filler-words.js","sourceRoot":"","sources":["../../src/core/filler-words.ts"],"names":[],"mappings":"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"}