karaoke-gen 0.105.4__py3-none-any.whl → 0.107.0__py3-none-any.whl

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 (322) hide show
  1. backend/api/routes/users.py +14 -3
  2. backend/config.py +3 -0
  3. backend/services/encoding_interface.py +4 -0
  4. backend/services/job_notification_service.py +4 -21
  5. backend/tests/test_job_notification_service.py +24 -58
  6. backend/tests/test_video_worker_orchestrator.py +189 -0
  7. backend/workers/video_worker_orchestrator.py +7 -0
  8. karaoke_gen/instrumental_review/server.py +145 -35
  9. karaoke_gen/nextjs_frontend/__init__.py +98 -0
  10. karaoke_gen/nextjs_frontend/out/404/index.html +1 -0
  11. karaoke_gen/nextjs_frontend/out/404.html +1 -0
  12. karaoke_gen/nextjs_frontend/out/__next.__PAGE__.txt +9 -0
  13. karaoke_gen/nextjs_frontend/out/__next._full.txt +22 -0
  14. karaoke_gen/nextjs_frontend/out/__next._head.txt +8 -0
  15. karaoke_gen/nextjs_frontend/out/__next._index.txt +9 -0
  16. karaoke_gen/nextjs_frontend/out/__next._tree.txt +2 -0
  17. karaoke_gen/nextjs_frontend/out/_next/static/chunks/01a7f8fe40f1ff47.js +1 -0
  18. karaoke_gen/nextjs_frontend/out/_next/static/chunks/112f346e31f991df.js +4 -0
  19. karaoke_gen/nextjs_frontend/out/_next/static/chunks/16d1a4dd9d8a873a.js +3 -0
  20. karaoke_gen/nextjs_frontend/out/_next/static/chunks/1ab85c362b8b0e86.js +9 -0
  21. karaoke_gen/nextjs_frontend/out/_next/static/chunks/247eb132b7f7b574.js +1 -0
  22. karaoke_gen/nextjs_frontend/out/_next/static/chunks/2b80d15cc95e4818.js +1 -0
  23. karaoke_gen/nextjs_frontend/out/_next/static/chunks/32c7eba5cd46c1bc.js +7 -0
  24. karaoke_gen/nextjs_frontend/out/_next/static/chunks/483f26794eae53d0.js +1 -0
  25. karaoke_gen/nextjs_frontend/out/_next/static/chunks/550c3b02e85f196a.js +1 -0
  26. karaoke_gen/nextjs_frontend/out/_next/static/chunks/55c5ade44387bef8.js +1 -0
  27. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5628d92b5893add2.css +1 -0
  28. karaoke_gen/nextjs_frontend/out/_next/static/chunks/56ebf7665e4341c8.js +7 -0
  29. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5997132b61dec430.js +1 -0
  30. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5ea55255bce3eb9e.js +5 -0
  31. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5eda89a57490b3cd.js +1 -0
  32. karaoke_gen/nextjs_frontend/out/_next/static/chunks/692f5d9e0d700c76.js +3 -0
  33. karaoke_gen/nextjs_frontend/out/_next/static/chunks/71d7a05b14f9f0f4.js +1 -0
  34. karaoke_gen/nextjs_frontend/out/_next/static/chunks/81ac355749ef3302.js +1 -0
  35. karaoke_gen/nextjs_frontend/out/_next/static/chunks/95f7e5934dbb0e5d.js +1 -0
  36. karaoke_gen/nextjs_frontend/out/_next/static/chunks/9bce8f19eaa46940.js +1 -0
  37. karaoke_gen/nextjs_frontend/out/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  38. karaoke_gen/nextjs_frontend/out/_next/static/chunks/a9ed54eed3e14c92.js +2 -0
  39. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b35cd41238ecfb17.js +1 -0
  40. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5bc3c3d5ebd49eb.js +1 -0
  41. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5c078c08db5ae32.js +5 -0
  42. karaoke_gen/nextjs_frontend/out/_next/static/chunks/be9c44a178104187.js +1 -0
  43. karaoke_gen/nextjs_frontend/out/_next/static/chunks/c4c840e18cb4861c.js +1 -0
  44. karaoke_gen/nextjs_frontend/out/_next/static/chunks/c645af7d6b65f73e.js +1 -0
  45. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d2c5e2575df784d4.js +1 -0
  46. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d30af02b96d81462.js +1 -0
  47. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d9bdf64f4ec1e9b7.js +7 -0
  48. karaoke_gen/nextjs_frontend/out/_next/static/chunks/dcde6ed684dacd0e.js +5 -0
  49. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e422cbe931246000.js +1 -0
  50. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e483af34fc792d38.js +1 -0
  51. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e57422aad6b897da.js +1 -0
  52. karaoke_gen/nextjs_frontend/out/_next/static/chunks/ef02697fb404726a.js +1 -0
  53. karaoke_gen/nextjs_frontend/out/_next/static/chunks/ff1a16fafef87110.js +1 -0
  54. karaoke_gen/nextjs_frontend/out/_next/static/chunks/turbopack-2d9ca3017a9deedf.js +3 -0
  55. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_buildManifest.js +11 -0
  56. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_clientMiddlewareManifest.json +1 -0
  57. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_ssgManifest.js +1 -0
  58. karaoke_gen/nextjs_frontend/out/_not-found/__next._full.txt +18 -0
  59. karaoke_gen/nextjs_frontend/out/_not-found/__next._head.txt +8 -0
  60. karaoke_gen/nextjs_frontend/out/_not-found/__next._index.txt +9 -0
  61. karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.__PAGE__.txt +5 -0
  62. karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.txt +4 -0
  63. karaoke_gen/nextjs_frontend/out/_not-found/__next._tree.txt +2 -0
  64. karaoke_gen/nextjs_frontend/out/_not-found/index.html +1 -0
  65. karaoke_gen/nextjs_frontend/out/_not-found/index.txt +18 -0
  66. karaoke_gen/nextjs_frontend/out/admin/__next._full.txt +25 -0
  67. karaoke_gen/nextjs_frontend/out/admin/__next._head.txt +8 -0
  68. karaoke_gen/nextjs_frontend/out/admin/__next._index.txt +9 -0
  69. karaoke_gen/nextjs_frontend/out/admin/__next._tree.txt +2 -0
  70. karaoke_gen/nextjs_frontend/out/admin/__next.admin.__PAGE__.txt +9 -0
  71. karaoke_gen/nextjs_frontend/out/admin/__next.admin.txt +7 -0
  72. karaoke_gen/nextjs_frontend/out/admin/beta/__next._full.txt +25 -0
  73. karaoke_gen/nextjs_frontend/out/admin/beta/__next._head.txt +8 -0
  74. karaoke_gen/nextjs_frontend/out/admin/beta/__next._index.txt +9 -0
  75. karaoke_gen/nextjs_frontend/out/admin/beta/__next._tree.txt +2 -0
  76. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.__PAGE__.txt +9 -0
  77. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.txt +4 -0
  78. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.txt +7 -0
  79. karaoke_gen/nextjs_frontend/out/admin/beta/index.html +1 -0
  80. karaoke_gen/nextjs_frontend/out/admin/beta/index.txt +25 -0
  81. karaoke_gen/nextjs_frontend/out/admin/index.html +1 -0
  82. karaoke_gen/nextjs_frontend/out/admin/index.txt +25 -0
  83. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._full.txt +25 -0
  84. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._head.txt +8 -0
  85. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._index.txt +9 -0
  86. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._tree.txt +2 -0
  87. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.__PAGE__.txt +9 -0
  88. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.txt +4 -0
  89. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.txt +7 -0
  90. karaoke_gen/nextjs_frontend/out/admin/jobs/index.html +1 -0
  91. karaoke_gen/nextjs_frontend/out/admin/jobs/index.txt +25 -0
  92. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._full.txt +25 -0
  93. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._head.txt +8 -0
  94. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._index.txt +9 -0
  95. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._tree.txt +2 -0
  96. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.__PAGE__.txt +9 -0
  97. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.txt +4 -0
  98. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.txt +7 -0
  99. karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.html +1 -0
  100. karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.txt +25 -0
  101. karaoke_gen/nextjs_frontend/out/admin/searches/__next._full.txt +25 -0
  102. karaoke_gen/nextjs_frontend/out/admin/searches/__next._head.txt +8 -0
  103. karaoke_gen/nextjs_frontend/out/admin/searches/__next._index.txt +9 -0
  104. karaoke_gen/nextjs_frontend/out/admin/searches/__next._tree.txt +2 -0
  105. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.__PAGE__.txt +9 -0
  106. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.txt +4 -0
  107. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.txt +7 -0
  108. karaoke_gen/nextjs_frontend/out/admin/searches/index.html +1 -0
  109. karaoke_gen/nextjs_frontend/out/admin/searches/index.txt +25 -0
  110. karaoke_gen/nextjs_frontend/out/admin/users/__next._full.txt +25 -0
  111. karaoke_gen/nextjs_frontend/out/admin/users/__next._head.txt +8 -0
  112. karaoke_gen/nextjs_frontend/out/admin/users/__next._index.txt +9 -0
  113. karaoke_gen/nextjs_frontend/out/admin/users/__next._tree.txt +2 -0
  114. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.txt +7 -0
  115. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.__PAGE__.txt +9 -0
  116. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.txt +4 -0
  117. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._full.txt +25 -0
  118. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._head.txt +8 -0
  119. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._index.txt +9 -0
  120. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._tree.txt +2 -0
  121. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.txt +7 -0
  122. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.__PAGE__.txt +9 -0
  123. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.txt +4 -0
  124. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.txt +4 -0
  125. karaoke_gen/nextjs_frontend/out/admin/users/detail/index.html +1 -0
  126. karaoke_gen/nextjs_frontend/out/admin/users/detail/index.txt +25 -0
  127. karaoke_gen/nextjs_frontend/out/admin/users/index.html +1 -0
  128. karaoke_gen/nextjs_frontend/out/admin/users/index.txt +25 -0
  129. karaoke_gen/nextjs_frontend/out/app/__next._full.txt +22 -0
  130. karaoke_gen/nextjs_frontend/out/app/__next._head.txt +8 -0
  131. karaoke_gen/nextjs_frontend/out/app/__next._index.txt +9 -0
  132. karaoke_gen/nextjs_frontend/out/app/__next._tree.txt +2 -0
  133. karaoke_gen/nextjs_frontend/out/app/__next.app.__PAGE__.txt +9 -0
  134. karaoke_gen/nextjs_frontend/out/app/__next.app.txt +4 -0
  135. karaoke_gen/nextjs_frontend/out/app/index.html +1 -0
  136. karaoke_gen/nextjs_frontend/out/app/index.txt +22 -0
  137. karaoke_gen/nextjs_frontend/out/app/jobs/__next._full.txt +19 -0
  138. karaoke_gen/nextjs_frontend/out/app/jobs/__next._head.txt +8 -0
  139. karaoke_gen/nextjs_frontend/out/app/jobs/__next._index.txt +9 -0
  140. karaoke_gen/nextjs_frontend/out/app/jobs/__next._tree.txt +2 -0
  141. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  142. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.txt +4 -0
  143. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.txt +4 -0
  144. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.txt +4 -0
  145. karaoke_gen/nextjs_frontend/out/app/jobs/index.html +1 -0
  146. karaoke_gen/nextjs_frontend/out/app/jobs/index.txt +19 -0
  147. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._full.txt +19 -0
  148. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._head.txt +8 -0
  149. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._index.txt +9 -0
  150. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._tree.txt +2 -0
  151. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  152. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.txt +4 -0
  153. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.txt +4 -0
  154. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.txt +4 -0
  155. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.html +1 -0
  156. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.txt +19 -0
  157. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._full.txt +19 -0
  158. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._head.txt +8 -0
  159. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._index.txt +9 -0
  160. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._tree.txt +2 -0
  161. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  162. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.txt +4 -0
  163. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.txt +4 -0
  164. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.txt +4 -0
  165. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.html +1 -0
  166. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.txt +19 -0
  167. karaoke_gen/nextjs_frontend/out/auth/verify/__next._full.txt +22 -0
  168. karaoke_gen/nextjs_frontend/out/auth/verify/__next._head.txt +8 -0
  169. karaoke_gen/nextjs_frontend/out/auth/verify/__next._index.txt +9 -0
  170. karaoke_gen/nextjs_frontend/out/auth/verify/__next._tree.txt +2 -0
  171. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.txt +4 -0
  172. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.__PAGE__.txt +9 -0
  173. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.txt +4 -0
  174. karaoke_gen/nextjs_frontend/out/auth/verify/index.html +1 -0
  175. karaoke_gen/nextjs_frontend/out/auth/verify/index.txt +22 -0
  176. karaoke_gen/nextjs_frontend/out/index.html +1 -0
  177. karaoke_gen/nextjs_frontend/out/index.txt +22 -0
  178. karaoke_gen/nextjs_frontend/out/manifest.webmanifest +31 -0
  179. karaoke_gen/nextjs_frontend/out/order/success/__next._full.txt +22 -0
  180. karaoke_gen/nextjs_frontend/out/order/success/__next._head.txt +8 -0
  181. karaoke_gen/nextjs_frontend/out/order/success/__next._index.txt +9 -0
  182. karaoke_gen/nextjs_frontend/out/order/success/__next._tree.txt +2 -0
  183. karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.__PAGE__.txt +9 -0
  184. karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.txt +4 -0
  185. karaoke_gen/nextjs_frontend/out/order/success/__next.order.txt +4 -0
  186. karaoke_gen/nextjs_frontend/out/order/success/index.html +1 -0
  187. karaoke_gen/nextjs_frontend/out/order/success/index.txt +22 -0
  188. karaoke_gen/nextjs_frontend/out/payment/success/__next._full.txt +22 -0
  189. karaoke_gen/nextjs_frontend/out/payment/success/__next._head.txt +8 -0
  190. karaoke_gen/nextjs_frontend/out/payment/success/__next._index.txt +9 -0
  191. karaoke_gen/nextjs_frontend/out/payment/success/__next._tree.txt +2 -0
  192. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.__PAGE__.txt +9 -0
  193. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.txt +4 -0
  194. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.txt +4 -0
  195. karaoke_gen/nextjs_frontend/out/payment/success/index.html +1 -0
  196. karaoke_gen/nextjs_frontend/out/payment/success/index.txt +22 -0
  197. karaoke_gen/nextjs_frontend/out/screenshots/email-action_reminder.png +0 -0
  198. karaoke_gen/nextjs_frontend/out/screenshots/email-beta_welcome.png +0 -0
  199. karaoke_gen/nextjs_frontend/out/screenshots/email-job_completion.png +0 -0
  200. karaoke_gen/nextjs_frontend/out/screenshots/example-output.avif +0 -0
  201. karaoke_gen/nextjs_frontend/out/screenshots/homepage-full.png +0 -0
  202. karaoke_gen/nextjs_frontend/out/screenshots/homepage-hero.png +0 -0
  203. karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.avif +0 -0
  204. karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.png +0 -0
  205. karaoke_gen/nextjs_frontend/out/screenshots/job-dashboard.avif +0 -0
  206. karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.avif +0 -0
  207. karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.png +0 -0
  208. karaoke_gen/nextjs_frontend/out/sw.js +183 -0
  209. karaoke_gen/utils/cli_args.py +3 -3
  210. karaoke_gen/utils/gen_cli.py +4 -0
  211. karaoke_gen/utils/remote_cli.py +8 -40
  212. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/METADATA +1 -1
  213. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/RECORD +227 -121
  214. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/WHEEL +1 -1
  215. lyrics_transcriber/correction/agentic/agent.py +83 -60
  216. lyrics_transcriber/correction/anchor_sequence.py +48 -3
  217. lyrics_transcriber/correction/corrector.py +92 -58
  218. lyrics_transcriber/review/server.py +165 -33
  219. lyrics_transcriber/utils/tracing.py +214 -0
  220. karaoke_gen/instrumental_review/static/index.html +0 -1721
  221. lyrics_transcriber/frontend/.gitignore +0 -24
  222. lyrics_transcriber/frontend/.yarn/releases/yarn-4.7.0.cjs +0 -935
  223. lyrics_transcriber/frontend/.yarnrc.yml +0 -3
  224. lyrics_transcriber/frontend/README.md +0 -50
  225. lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -210
  226. lyrics_transcriber/frontend/__init__.py +0 -25
  227. lyrics_transcriber/frontend/e2e/agentic-corrections.spec.ts +0 -207
  228. lyrics_transcriber/frontend/e2e/fixtures/agentic-correction-data.json +0 -226
  229. lyrics_transcriber/frontend/eslint.config.js +0 -28
  230. lyrics_transcriber/frontend/index.html +0 -22
  231. lyrics_transcriber/frontend/package-lock.json +0 -4553
  232. lyrics_transcriber/frontend/package.json +0 -48
  233. lyrics_transcriber/frontend/playwright.config.ts +0 -69
  234. lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
  235. lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
  236. lyrics_transcriber/frontend/src/App.tsx +0 -243
  237. lyrics_transcriber/frontend/src/api.ts +0 -262
  238. lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -111
  239. lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -114
  240. lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -204
  241. lyrics_transcriber/frontend/src/components/AppHeader.tsx +0 -65
  242. lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -180
  243. lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -175
  244. lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -359
  245. lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -281
  246. lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -162
  247. lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -257
  248. lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -94
  249. lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -720
  250. lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -592
  251. lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -431
  252. lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -77
  253. lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -467
  254. lyrics_transcriber/frontend/src/components/Header.tsx +0 -520
  255. lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -1526
  256. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +0 -216
  257. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +0 -721
  258. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/UpcomingWordsBar.tsx +0 -80
  259. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +0 -999
  260. lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -51
  261. lyrics_transcriber/frontend/src/components/ModeSelectionModal.tsx +0 -127
  262. lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -67
  263. lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -23
  264. lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -177
  265. lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -268
  266. lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -336
  267. lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -354
  268. lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -64
  269. lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -383
  270. lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -131
  271. lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -266
  272. lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -191
  273. lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -466
  274. lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -56
  275. lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -89
  276. lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -30
  277. lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -180
  278. lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -13
  279. lyrics_transcriber/frontend/src/components/shared/types.js +0 -2
  280. lyrics_transcriber/frontend/src/components/shared/types.ts +0 -135
  281. lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -177
  282. lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -78
  283. lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -75
  284. lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -360
  285. lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -110
  286. lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -22
  287. lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -537
  288. lyrics_transcriber/frontend/src/main.tsx +0 -11
  289. lyrics_transcriber/frontend/src/theme.ts +0 -406
  290. lyrics_transcriber/frontend/src/types/global.d.ts +0 -9
  291. lyrics_transcriber/frontend/src/types.js +0 -2
  292. lyrics_transcriber/frontend/src/types.ts +0 -199
  293. lyrics_transcriber/frontend/src/validation.ts +0 -132
  294. lyrics_transcriber/frontend/src/vite-env.d.ts +0 -1
  295. lyrics_transcriber/frontend/tsconfig.app.json +0 -26
  296. lyrics_transcriber/frontend/tsconfig.json +0 -25
  297. lyrics_transcriber/frontend/tsconfig.node.json +0 -23
  298. lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -1
  299. lyrics_transcriber/frontend/update_version.js +0 -11
  300. lyrics_transcriber/frontend/vite.config.d.ts +0 -2
  301. lyrics_transcriber/frontend/vite.config.js +0 -15
  302. lyrics_transcriber/frontend/vite.config.ts +0 -16
  303. lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
  304. lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
  305. lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
  306. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js +0 -44465
  307. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js.map +0 -1
  308. lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
  309. lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
  310. lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
  311. lyrics_transcriber/frontend/web_assets/index.html +0 -22
  312. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
  313. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.svg +0 -5
  314. lyrics_transcriber/frontend/yarn.lock +0 -3711
  315. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/apple-touch-icon.png +0 -0
  316. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-16x16.png +0 -0
  317. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-32x32.png +0 -0
  318. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon.ico +0 -0
  319. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/nomad-karaoke-logo.svg +0 -0
  320. /lyrics_transcriber/frontend/public/nomad-karaoke-logo.png → /karaoke_gen/nextjs_frontend/out/nomad-logo.png +0 -0
  321. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/entry_points.txt +0 -0
  322. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,48 +0,0 @@
1
- {
2
- "name": "lyrics-transcriber-frontend",
3
- "private": true,
4
- "homepage": "https://nomadkaraoke.github.io/lyrics-transcriber-frontend",
5
- "version": "0.86.0",
6
- "type": "module",
7
- "scripts": {
8
- "dev": "vite",
9
- "build": "tsc -b && vite build --mode development",
10
- "build-prod": "tsc -b && vite build",
11
- "lint": "eslint .",
12
- "preview": "vite preview",
13
- "predeploy": "npm run build-prod",
14
- "deploy": "gh-pages -d dist",
15
- "test": "playwright test",
16
- "test:ui": "playwright test --ui",
17
- "test:headed": "playwright test --headed"
18
- },
19
- "dependencies": {
20
- "@emotion/react": "^11.14.0",
21
- "@emotion/styled": "^11.14.0",
22
- "@mui/icons-material": "^6.3.0",
23
- "@mui/material": "^6.3.0",
24
- "@mui/system": "^6.4.3",
25
- "lucide-react": "^0.562.0",
26
- "nanoid": "^5.0.9",
27
- "react": "^18.3.1",
28
- "react-dom": "^18.3.1",
29
- "zod": "^3.24.1"
30
- },
31
- "devDependencies": {
32
- "@eslint/js": "^9.17.0",
33
- "@playwright/test": "^1.57.0",
34
- "@types/react": "^18.3.18",
35
- "@types/react-dom": "^18.3.5",
36
- "@vitejs/plugin-react": "^4.3.4",
37
- "eslint": "^9.17.0",
38
- "eslint-plugin-react-hooks": "^5.0.0",
39
- "eslint-plugin-react-refresh": "^0.4.16",
40
- "gh-pages": "^6.3.0",
41
- "globals": "^15.14.0",
42
- "playwright": "^1.57.0",
43
- "typescript": "~5.6.2",
44
- "typescript-eslint": "^8.18.2",
45
- "vite": "^6.0.5"
46
- },
47
- "packageManager": "yarn@4.7.0"
48
- }
@@ -1,69 +0,0 @@
1
- import { defineConfig, devices } from '@playwright/test';
2
-
3
- /**
4
- * Playwright configuration for lyrics-transcriber frontend E2E tests.
5
- * Tests run against the local dev server (localhost:5173) served by vite.
6
- */
7
- export default defineConfig({
8
- testDir: './e2e',
9
-
10
- // Run tests sequentially for now
11
- fullyParallel: false,
12
-
13
- // Fail the build on CI if you accidentally left test.only in the source code
14
- forbidOnly: !!process.env.CI,
15
-
16
- // Retry on CI only
17
- retries: process.env.CI ? 2 : 0,
18
-
19
- // Single worker
20
- workers: 1,
21
-
22
- // Reporter to use
23
- reporter: [
24
- ['html', { open: 'never' }],
25
- ['list'],
26
- ],
27
-
28
- // Shared settings for all tests
29
- use: {
30
- // Base URL for the local dev server
31
- baseURL: 'http://localhost:5173',
32
-
33
- // Collect trace on failure for debugging
34
- trace: 'on-first-retry',
35
-
36
- // Screenshot on failure
37
- screenshot: 'only-on-failure',
38
-
39
- // Video on failure
40
- video: 'on-first-retry',
41
-
42
- // Increase timeout for complex interactions
43
- actionTimeout: 30000,
44
- },
45
-
46
- // Longer timeout for tests
47
- timeout: 120000, // 2 minutes per test
48
-
49
- // Expect timeout for assertions
50
- expect: {
51
- timeout: 30000, // 30 seconds for expects
52
- },
53
-
54
- // Configure projects (browsers)
55
- projects: [
56
- {
57
- name: 'chromium',
58
- use: { ...devices['Desktop Chrome'] },
59
- },
60
- ],
61
-
62
- // Run local dev server before starting tests
63
- webServer: {
64
- command: 'npm run dev',
65
- url: 'http://localhost:5173',
66
- reuseExistingServer: !process.env.CI,
67
- timeout: 120000,
68
- },
69
- });
@@ -1,243 +0,0 @@
1
- import UploadFileIcon from '@mui/icons-material/UploadFile'
2
- import { Alert, Box, Button, Modal, Typography } from '@mui/material'
3
- import { ThemeProvider } from '@mui/material/styles'
4
- import CssBaseline from '@mui/material/CssBaseline'
5
- import { useEffect, useState, useMemo } from 'react'
6
- import { ApiClient, FileOnlyClient, LiveApiClient } from './api'
7
- import CorrectionMetrics from './components/CorrectionMetrics'
8
- import LyricsAnalyzer from './components/LyricsAnalyzer'
9
- import AppHeader from './components/AppHeader'
10
- import { CorrectionData } from './types'
11
- import { createAppTheme } from './theme'
12
-
13
- const THEME_STORAGE_KEY = 'nomad-karaoke-lyrics-theme'
14
-
15
- export default function App() {
16
- const [isDarkMode, setIsDarkMode] = useState(() => {
17
- // Initialize from localStorage
18
- const stored = localStorage.getItem(THEME_STORAGE_KEY)
19
- return stored !== 'light' // Default to dark
20
- })
21
- const [data, setData] = useState<CorrectionData | null>(null)
22
- const [showMetadata, setShowMetadata] = useState(false)
23
- const [error, setError] = useState<string | null>(null)
24
- const [apiClient, setApiClient] = useState<ApiClient | null>(null)
25
- const [isReadOnly, setIsReadOnly] = useState(true)
26
- const [audioHash, setAudioHash] = useState<string>('')
27
-
28
- // Create theme based on mode
29
- const theme = useMemo(() => createAppTheme(isDarkMode ? 'dark' : 'light'), [isDarkMode])
30
-
31
- // Handle theme toggle
32
- const handleToggleTheme = () => {
33
- const newIsDark = !isDarkMode
34
- setIsDarkMode(newIsDark)
35
- localStorage.setItem(THEME_STORAGE_KEY, newIsDark ? 'dark' : 'light')
36
- }
37
-
38
- useEffect(() => {
39
- // Parse query parameters
40
- const params = new URLSearchParams(window.location.search)
41
- const encodedApiUrl = params.get('baseApiUrl')
42
- const audioHashParam = params.get('audioHash')
43
- const reviewTokenParam = params.get('reviewToken')
44
-
45
- if (encodedApiUrl) {
46
- const baseApiUrl = decodeURIComponent(encodedApiUrl)
47
- // Pass reviewToken to LiveApiClient for authentication
48
- setApiClient(new LiveApiClient(baseApiUrl, reviewTokenParam || undefined))
49
- setIsReadOnly(false)
50
- if (audioHashParam) {
51
- setAudioHash(audioHashParam)
52
- }
53
- // Fetch initial data
54
- fetchData(baseApiUrl, reviewTokenParam || undefined)
55
- } else {
56
- setApiClient(new FileOnlyClient())
57
- setIsReadOnly(true)
58
- }
59
- }, [])
60
-
61
- const fetchData = async (baseUrl: string, reviewToken?: string) => {
62
- try {
63
- const client = new LiveApiClient(baseUrl, reviewToken)
64
- const data = await client.getCorrectionData()
65
- // console.log('Full correction data from API:', data)
66
- setData(data)
67
- } catch (err) {
68
- const error = err as Error
69
- setError(`Failed to fetch data: ${error.message}`)
70
- }
71
- }
72
-
73
- const handleFileLoad = async () => {
74
- const input = document.createElement('input')
75
- input.type = 'file'
76
- input.accept = '.json'
77
-
78
- input.onchange = async (e) => {
79
- const file = (e.target as HTMLInputElement).files?.[0]
80
- if (!file) return
81
-
82
- try {
83
- const text = await file.text()
84
- const parsedData = JSON.parse(text) as CorrectionData
85
- console.log('File data loaded:', {
86
- sampleGap: parsedData.gap_sequences?.[0],
87
- sampleWord: parsedData.corrected_segments?.[0]?.words?.[0],
88
- sampleCorrection: parsedData.corrections?.[0]
89
- })
90
-
91
- // Validate the structure
92
- if (!parsedData.corrected_segments || !parsedData.gap_sequences) {
93
- throw new Error('Invalid file format: missing required fields')
94
- }
95
-
96
- setData(parsedData)
97
- } catch (err) {
98
- const error = err as Error
99
- setError(`Error loading file: ${error.message}. Please make sure it is a valid JSON file.`)
100
- }
101
- }
102
-
103
- input.click()
104
- }
105
-
106
- const renderMetadataModal = () => {
107
- if (!data) return null
108
-
109
- return (
110
- <Modal
111
- open={showMetadata}
112
- onClose={() => setShowMetadata(false)}
113
- aria-labelledby="metadata-modal"
114
- >
115
- <Box sx={{
116
- position: 'absolute',
117
- top: '50%',
118
- left: '50%',
119
- transform: 'translate(-50%, -50%)',
120
- width: 400,
121
- bgcolor: 'background.paper',
122
- boxShadow: 24,
123
- p: 4,
124
- borderRadius: 1,
125
- }}>
126
- <Typography variant="h6" gutterBottom>
127
- Correction Process Details
128
- </Typography>
129
- <Box sx={{ mb: 2 }}>
130
- <Typography variant="subtitle2" color="text.secondary">
131
- Total Words
132
- </Typography>
133
- <Typography>
134
- {data.metadata.total_words}
135
- </Typography>
136
- </Box>
137
- <Box sx={{ mb: 2 }}>
138
- <Typography variant="subtitle2" color="text.secondary">
139
- Gap Sequences
140
- </Typography>
141
- <Typography>
142
- {data.metadata.gap_sequences_count}
143
- </Typography>
144
- </Box>
145
- <Box sx={{ mb: 2 }}>
146
- <Typography variant="subtitle2" color="text.secondary">
147
- Corrections Made
148
- </Typography>
149
- <Typography>
150
- {data.corrections_made}
151
- </Typography>
152
- </Box>
153
- <Box sx={{ mb: 2 }}>
154
- <Typography variant="subtitle2" color="text.secondary">
155
- Correction Ratio
156
- </Typography>
157
- <Typography>
158
- {(data.metadata.correction_ratio * 100).toFixed(1)}%
159
- </Typography>
160
- </Box>
161
- {/* Add any other metadata fields that are available */}
162
- </Box>
163
- </Modal>
164
- )
165
- }
166
-
167
- if (!data) {
168
- return (
169
- <ThemeProvider theme={theme}>
170
- <CssBaseline />
171
- <AppHeader isDarkMode={isDarkMode} onToggleTheme={handleToggleTheme} />
172
- <Box sx={{ p: 3 }}>
173
- {error && (
174
- <Alert severity="error" sx={{ mb: 2 }} onClose={() => setError(null)}>
175
- {error}
176
- </Alert>
177
- )}
178
- {isReadOnly ? (
179
- <>
180
- <Alert severity="info" sx={{ mb: 2 }}>
181
- Running in read-only mode. Connect to an API to enable editing.
182
- </Alert>
183
- <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
184
- <Typography variant="h4">
185
- Lyrics Correction Review
186
- </Typography>
187
- <Button
188
- variant="outlined"
189
- startIcon={<UploadFileIcon />}
190
- onClick={handleFileLoad}
191
- >
192
- Load File
193
- </Button>
194
- </Box>
195
- <Box sx={{ mb: 3 }}>
196
- <CorrectionMetrics />
197
- </Box>
198
- </>
199
- ) : (
200
- <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }}>
201
- <Typography variant="h6" color="text.secondary">
202
- Loading Lyrics Transcription Review...
203
- </Typography>
204
- </Box>
205
- )}
206
- </Box>
207
- </ThemeProvider>
208
- )
209
- }
210
-
211
- return (
212
- <ThemeProvider theme={theme}>
213
- <CssBaseline />
214
- <AppHeader isDarkMode={isDarkMode} onToggleTheme={handleToggleTheme} />
215
- <Box sx={{
216
- p: 1.5,
217
- pb: 3,
218
- maxWidth: '100%',
219
- overflowX: 'hidden'
220
- }}>
221
- {error && (
222
- <Alert severity="error" sx={{ mb: 1 }} onClose={() => setError(null)}>
223
- {error}
224
- </Alert>
225
- )}
226
- {isReadOnly && (
227
- <Alert severity="info" sx={{ mb: 1 }}>
228
- Running in read-only mode. Connect to an API to enable editing.
229
- </Alert>
230
- )}
231
- <LyricsAnalyzer
232
- data={data}
233
- onFileLoad={handleFileLoad}
234
- onShowMetadata={() => setShowMetadata(true)}
235
- apiClient={apiClient}
236
- isReadOnly={isReadOnly}
237
- audioHash={audioHash}
238
- />
239
- {renderMetadataModal()}
240
- </Box>
241
- </ThemeProvider>
242
- )
243
- }
@@ -1,262 +0,0 @@
1
- import { CorrectionData, CorrectionAnnotation } from './types';
2
- import { validateCorrectionData } from './validation';
3
-
4
- // New file to handle API communication
5
- export interface ApiClient {
6
- getCorrectionData: () => Promise<CorrectionData>;
7
- submitCorrections: (data: CorrectionData) => Promise<void>;
8
- getAudioUrl: (audioHash: string) => string;
9
- generatePreviewVideo: (data: CorrectionData, options?: PreviewOptions) => Promise<PreviewVideoResponse>;
10
- getPreviewVideoUrl: (previewHash: string) => string;
11
- updateHandlers: (enabledHandlers: string[]) => Promise<CorrectionData>;
12
- isUpdatingHandlers?: boolean;
13
- addLyrics: (source: string, lyrics: string) => Promise<CorrectionData>;
14
- submitAnnotations: (annotations: Omit<CorrectionAnnotation, 'annotation_id' | 'timestamp'>[]) => Promise<void>;
15
- getAnnotationStats: () => Promise<any>;
16
- }
17
-
18
- // Add new interface for the minimal update payload
19
- interface CorrectionUpdate {
20
- corrections: CorrectionData['corrections'];
21
- corrected_segments: CorrectionData['corrected_segments'];
22
- }
23
-
24
- // Add interface for preview generation options
25
- export interface PreviewOptions {
26
- use_background_image?: boolean;
27
- }
28
-
29
- // Add new interface for preview response
30
- interface PreviewVideoResponse {
31
- status: "success" | "error";
32
- preview_hash?: string;
33
- message?: string;
34
- }
35
-
36
- // Add new interface for adding lyrics
37
- interface AddLyricsRequest {
38
- source: string;
39
- lyrics: string;
40
- }
41
-
42
- export class LiveApiClient implements ApiClient {
43
- private reviewToken?: string;
44
-
45
- constructor(private baseUrl: string, reviewToken?: string) {
46
- this.baseUrl = baseUrl.replace(/\/$/, '')
47
- this.reviewToken = reviewToken
48
- }
49
-
50
- public isUpdatingHandlers = false;
51
-
52
- /**
53
- * Build URL with reviewToken query parameter if available
54
- */
55
- private buildUrl(path: string): string {
56
- const url = `${this.baseUrl}${path}`
57
- if (this.reviewToken) {
58
- const separator = url.includes('?') ? '&' : '?'
59
- return `${url}${separator}review_token=${encodeURIComponent(this.reviewToken)}`
60
- }
61
- return url
62
- }
63
-
64
- async getCorrectionData(): Promise<CorrectionData> {
65
- const response = await fetch(this.buildUrl('/correction-data'));
66
- if (!response.ok) {
67
- throw new Error(`API error: ${response.statusText}`);
68
- }
69
- const rawData = await response.json();
70
-
71
- try {
72
- // This will throw if validation fails
73
- return validateCorrectionData(rawData);
74
- } catch (error) {
75
- console.error('Data validation failed:', error);
76
- throw new Error('Invalid data received from server: missing or incorrect fields');
77
- }
78
- }
79
-
80
- async submitCorrections(data: CorrectionData): Promise<void> {
81
- // Extract only the needed fields
82
- const updatePayload: CorrectionUpdate = {
83
- corrections: data.corrections,
84
- corrected_segments: data.corrected_segments
85
- };
86
-
87
- const response = await fetch(this.buildUrl('/complete'), {
88
- method: 'POST',
89
- headers: {
90
- 'Content-Type': 'application/json',
91
- },
92
- body: JSON.stringify(updatePayload)
93
- });
94
-
95
- if (!response.ok) {
96
- throw new Error(`API error: ${response.statusText}`);
97
- }
98
- }
99
-
100
- getAudioUrl(audioHash: string): string {
101
- return this.buildUrl(`/audio/${audioHash}`)
102
- }
103
-
104
- async generatePreviewVideo(data: CorrectionData, options?: PreviewOptions): Promise<PreviewVideoResponse> {
105
- // Extract only the needed fields, just like in submitCorrections
106
- // Include use_background_image option (defaults to false for fast black background)
107
- const updatePayload = {
108
- corrections: data.corrections,
109
- corrected_segments: data.corrected_segments,
110
- use_background_image: options?.use_background_image ?? false,
111
- };
112
-
113
- const response = await fetch(this.buildUrl('/preview-video'), {
114
- method: 'POST',
115
- headers: {
116
- 'Content-Type': 'application/json',
117
- },
118
- body: JSON.stringify(updatePayload)
119
- });
120
-
121
- if (!response.ok) {
122
- return {
123
- status: 'error',
124
- message: `API error: ${response.statusText}`
125
- };
126
- }
127
-
128
- return await response.json();
129
- }
130
-
131
- getPreviewVideoUrl(previewHash: string): string {
132
- return this.buildUrl(`/preview-video/${previewHash}`);
133
- }
134
-
135
- async updateHandlers(enabledHandlers: string[]): Promise<CorrectionData> {
136
- console.log('API: Starting handler update...');
137
- this.isUpdatingHandlers = true;
138
- console.log('API: Set isUpdatingHandlers to', this.isUpdatingHandlers);
139
-
140
- try {
141
- const response = await fetch(this.buildUrl('/handlers'), {
142
- method: 'POST',
143
- headers: {
144
- 'Content-Type': 'application/json',
145
- },
146
- body: JSON.stringify(enabledHandlers)
147
- });
148
-
149
- if (!response.ok) {
150
- throw new Error(`API error: ${response.statusText}`);
151
- }
152
-
153
- const data = await response.json();
154
- if (data.status === 'error') {
155
- throw new Error(data.message || 'Failed to update handlers');
156
- }
157
-
158
- console.log('API: Handler update successful');
159
- return validateCorrectionData(data.data);
160
- } finally {
161
- this.isUpdatingHandlers = false;
162
- console.log('API: Set isUpdatingHandlers to', this.isUpdatingHandlers);
163
- }
164
- }
165
-
166
- async addLyrics(source: string, lyrics: string): Promise<CorrectionData> {
167
- const payload: AddLyricsRequest = {
168
- source,
169
- lyrics
170
- };
171
-
172
- const response = await fetch(this.buildUrl('/add-lyrics'), {
173
- method: 'POST',
174
- headers: {
175
- 'Content-Type': 'application/json',
176
- },
177
- body: JSON.stringify(payload)
178
- });
179
-
180
- if (!response.ok) {
181
- throw new Error(`API error: ${response.statusText}`);
182
- }
183
-
184
- const data = await response.json();
185
- if (data.status === 'error') {
186
- throw new Error(data.message || 'Failed to add lyrics');
187
- }
188
-
189
- return validateCorrectionData(data.data);
190
- }
191
-
192
- async submitAnnotations(annotations: Omit<CorrectionAnnotation, 'annotation_id' | 'timestamp'>[]): Promise<void> {
193
- // Submit each annotation to the backend
194
- for (const annotation of annotations) {
195
- const response = await fetch(this.buildUrl('/v1/annotations'), {
196
- method: 'POST',
197
- headers: {
198
- 'Content-Type': 'application/json',
199
- },
200
- body: JSON.stringify(annotation)
201
- });
202
-
203
- if (!response.ok) {
204
- console.error(`Failed to submit annotation:`, annotation);
205
- // Continue with other annotations even if one fails
206
- }
207
- }
208
- }
209
-
210
- async getAnnotationStats(): Promise<any> {
211
- const response = await fetch(this.buildUrl('/v1/annotations/stats'));
212
- if (!response.ok) {
213
- throw new Error(`API error: ${response.statusText}`);
214
- }
215
- return await response.json();
216
- }
217
- }
218
-
219
- export class FileOnlyClient implements ApiClient {
220
- async getCorrectionData(): Promise<CorrectionData> {
221
- throw new Error('Not supported in file-only mode');
222
- }
223
-
224
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
225
- async submitCorrections(_data: CorrectionData): Promise<void> {
226
- throw new Error('Not supported in file-only mode');
227
- }
228
-
229
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
230
- getAudioUrl(_audioHash: string): string {
231
- throw new Error('Not supported in file-only mode');
232
- }
233
-
234
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
235
- async generatePreviewVideo(_data: CorrectionData, _options?: PreviewOptions): Promise<PreviewVideoResponse> {
236
- throw new Error('Not supported in file-only mode');
237
- }
238
-
239
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
240
- getPreviewVideoUrl(_previewHash: string): string {
241
- throw new Error('Not supported in file-only mode');
242
- }
243
-
244
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
245
- async updateHandlers(_enabledHandlers: string[]): Promise<CorrectionData> {
246
- throw new Error('Not supported in file-only mode');
247
- }
248
-
249
- async addLyrics(): Promise<CorrectionData> {
250
- throw new Error('Not supported in file-only mode');
251
- }
252
-
253
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
254
- async submitAnnotations(_annotations: Omit<CorrectionAnnotation, 'annotation_id' | 'timestamp'>[]): Promise<void> {
255
- throw new Error('Not supported in file-only mode');
256
- }
257
-
258
- async getAnnotationStats(): Promise<any> {
259
- throw new Error('Not supported in file-only mode');
260
- }
261
- }
262
-