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,383 +0,0 @@
1
- import { Box, styled } from '@mui/material'
2
- import { Word } from '../types'
3
- import { useRef, useState } from 'react'
4
-
5
- interface TimelineEditorProps {
6
- words: Word[]
7
- startTime: number
8
- endTime: number
9
- onWordUpdate: (index: number, updates: Partial<Word>) => void
10
- onUnsyncWord?: (index: number) => void
11
- currentTime?: number
12
- onPlaySegment?: (time: number) => void
13
- showPlaybackIndicator?: boolean
14
- }
15
-
16
- const TimelineContainer = styled(Box)(({ theme }) => ({
17
- position: 'relative',
18
- height: '75px',
19
- backgroundColor: theme.palette.mode === 'dark'
20
- ? theme.palette.background.paper // Dark mode: use card background
21
- : theme.palette.grey[100], // Light mode: subtle gray
22
- borderRadius: theme.shape.borderRadius,
23
- margin: theme.spacing(1, 0),
24
- padding: theme.spacing(0, 1),
25
- border: `1px solid ${theme.palette.divider}`,
26
- }))
27
-
28
- const TimelineRuler = styled(Box)(({ theme }) => ({
29
- position: 'absolute',
30
- top: 0,
31
- left: 0,
32
- right: 0,
33
- height: '40px',
34
- borderBottom: `1px solid ${theme.palette.divider}`,
35
- cursor: 'pointer',
36
- }))
37
-
38
- const TimelineMark = styled(Box)(({ theme }) => ({
39
- position: 'absolute',
40
- top: '20px',
41
- width: '1px',
42
- height: '18px',
43
- backgroundColor: theme.palette.text.secondary,
44
- '&.subsecond': {
45
- top: '25px',
46
- height: '13px',
47
- backgroundColor: theme.palette.text.disabled,
48
- }
49
- }))
50
-
51
- const TimelineLabel = styled(Box)(({ theme }) => ({
52
- position: 'absolute',
53
- top: '5px',
54
- transform: 'translateX(-50%)',
55
- fontSize: '0.8rem',
56
- color: theme.palette.text.primary,
57
- fontWeight: 700,
58
- backgroundColor: theme.palette.mode === 'dark'
59
- ? theme.palette.background.paper
60
- : theme.palette.grey[100],
61
- padding: '0 4px',
62
- borderRadius: '2px',
63
- }))
64
-
65
- const TimelineWord = styled(Box)(({ theme }) => ({
66
- position: 'absolute',
67
- height: '30px',
68
- top: '40px',
69
- backgroundColor: theme.palette.primary.main,
70
- borderRadius: theme.shape.borderRadius,
71
- color: theme.palette.primary.contrastText,
72
- padding: theme.spacing(0.5, 1),
73
- cursor: 'move',
74
- userSelect: 'none',
75
- display: 'flex',
76
- alignItems: 'center',
77
- fontSize: '0.875rem',
78
- fontFamily: 'sans-serif',
79
- transition: 'background-color 0.1s ease',
80
- boxSizing: 'border-box',
81
- '&.highlighted': {
82
- backgroundColor: theme.palette.secondary.main,
83
- }
84
- }))
85
-
86
- const ResizeHandle = styled(Box)(({ theme }) => ({
87
- position: 'absolute',
88
- top: 0,
89
- width: 10,
90
- height: '100%',
91
- cursor: 'col-resize',
92
- '&:hover': {
93
- backgroundColor: theme.palette.primary.light,
94
- opacity: 0.8,
95
- boxShadow: `0 0 0 1px ${theme.palette.primary.dark}`,
96
- },
97
- '&.left': {
98
- left: 0,
99
- right: 'auto',
100
- paddingRight: 0,
101
- borderTopLeftRadius: theme.shape.borderRadius,
102
- borderBottomLeftRadius: theme.shape.borderRadius,
103
- },
104
- '&.right': {
105
- right: 0,
106
- left: 'auto',
107
- paddingLeft: 0,
108
- borderTopRightRadius: theme.shape.borderRadius,
109
- borderBottomRightRadius: theme.shape.borderRadius,
110
- }
111
- }))
112
-
113
- // Add new styled component for the cursor
114
- const TimelineCursor = styled(Box)(({ theme }) => ({
115
- position: 'absolute',
116
- top: 0,
117
- width: '2px',
118
- height: '100%', // Full height of container
119
- backgroundColor: theme.palette.error.main, // Red color
120
- pointerEvents: 'none', // Ensure it doesn't interfere with clicks
121
- transition: 'left 0.1s linear', // Smooth movement
122
- zIndex: 1, // Ensure it's above other elements
123
- }))
124
-
125
- export default function TimelineEditor({ words, startTime, endTime, onWordUpdate, onUnsyncWord, currentTime = 0, onPlaySegment, showPlaybackIndicator = true }: TimelineEditorProps) {
126
- const containerRef = useRef<HTMLDivElement>(null)
127
- const [dragState, setDragState] = useState<{
128
- wordIndex: number
129
- type: 'move' | 'resize-left' | 'resize-right'
130
- initialX: number
131
- initialTime: number
132
- word: Word
133
- } | null>(null)
134
-
135
- const MIN_DURATION = 0.1 // Minimum word duration in seconds
136
-
137
- const checkCollision = (
138
- proposedStart: number,
139
- proposedEnd: number,
140
- currentIndex: number,
141
- isResize: boolean
142
- ): boolean => {
143
- if (isResize) {
144
- if (currentIndex === words.length - 1) return false;
145
-
146
- const nextWord = words[currentIndex + 1]
147
- if (!nextWord || nextWord.start_time === null) return false
148
- return proposedEnd > nextWord.start_time
149
- }
150
-
151
- return words.some((word, index) => {
152
- if (index === currentIndex) return false
153
- if (word.start_time === null || word.end_time === null) return false
154
-
155
- return (
156
- (proposedStart >= word.start_time && proposedStart <= word.end_time) ||
157
- (proposedEnd >= word.start_time && proposedEnd <= word.end_time) ||
158
- (proposedStart <= word.start_time && proposedEnd >= word.end_time)
159
- )
160
- })
161
- }
162
-
163
- const timeToPosition = (time: number): number => {
164
- const duration = endTime - startTime
165
- const position = ((time - startTime) / duration) * 100
166
- return Math.max(0, Math.min(100, position))
167
- }
168
- const generateTimelineMarks = () => {
169
- const marks = []
170
- const startSecond = Math.floor(startTime)
171
- const endSecond = Math.ceil(endTime)
172
-
173
- // Generate marks for each second
174
- for (let time = startSecond; time <= endSecond; time++) {
175
- if (time >= startTime && time <= endTime) {
176
- const position = timeToPosition(time)
177
- marks.push(
178
- <Box key={time}>
179
- <TimelineMark sx={{ left: `${position}%` }} />
180
- <TimelineLabel sx={{ left: `${position}%` }}>
181
- {time}s
182
- </TimelineLabel>
183
- </Box>
184
- )
185
- }
186
- }
187
- return marks
188
- }
189
-
190
- const handleMouseDown = (e: React.MouseEvent, wordIndex: number, type: 'move' | 'resize-left' | 'resize-right') => {
191
- const rect = containerRef.current?.getBoundingClientRect()
192
- if (!rect) return
193
-
194
- const word = words[wordIndex]
195
- if (word.start_time === null || word.end_time === null) return
196
-
197
- const initialX = e.clientX - rect.left
198
- const initialTime = ((initialX / rect.width) * (endTime - startTime))
199
-
200
- setDragState({
201
- wordIndex,
202
- type,
203
- initialX,
204
- initialTime,
205
- word
206
- })
207
- }
208
-
209
- const handleMouseMove = (e: React.MouseEvent) => {
210
- if (!dragState || !containerRef.current) return
211
-
212
- const rect = containerRef.current.getBoundingClientRect()
213
- const x = e.clientX - rect.left
214
- const width = rect.width
215
-
216
- const currentWord = words[dragState.wordIndex]
217
- if (currentWord.start_time === null || currentWord.end_time === null ||
218
- dragState.word.start_time === null || dragState.word.end_time === null) return
219
-
220
- if (dragState.type === 'resize-right') {
221
- const initialWordDuration = dragState.word.end_time - dragState.word.start_time
222
- const initialWordWidth = (initialWordDuration / (endTime - startTime)) * width
223
- const pixelDelta = x - dragState.initialX
224
- const percentageMoved = pixelDelta / initialWordWidth
225
- const timeDelta = initialWordDuration * percentageMoved
226
-
227
- const proposedEnd = Math.max(
228
- currentWord.start_time + MIN_DURATION,
229
- dragState.word.end_time + timeDelta
230
- )
231
-
232
- if (checkCollision(currentWord.start_time, proposedEnd, dragState.wordIndex, true)) return
233
-
234
- onWordUpdate(dragState.wordIndex, {
235
- start_time: currentWord.start_time,
236
- end_time: proposedEnd
237
- })
238
- } else if (dragState.type === 'resize-left') {
239
- const initialWordDuration = dragState.word.end_time - dragState.word.start_time
240
- const initialWordWidth = (initialWordDuration / (endTime - startTime)) * width
241
- const pixelDelta = x - dragState.initialX
242
- const percentageMoved = pixelDelta / initialWordWidth
243
- const timeDelta = initialWordDuration * percentageMoved
244
-
245
- const proposedStart = Math.min(
246
- currentWord.end_time - MIN_DURATION,
247
- dragState.word.start_time + timeDelta
248
- )
249
-
250
- if (checkCollision(proposedStart, currentWord.end_time, dragState.wordIndex, true)) return
251
-
252
- onWordUpdate(dragState.wordIndex, {
253
- start_time: proposedStart,
254
- end_time: currentWord.end_time
255
- })
256
- } else if (dragState.type === 'move') {
257
- const pixelsPerSecond = width / (endTime - startTime)
258
- const pixelDelta = x - dragState.initialX
259
- const timeDelta = pixelDelta / pixelsPerSecond
260
-
261
- const wordDuration = currentWord.end_time - currentWord.start_time
262
- const proposedStart = dragState.word.start_time + timeDelta
263
- const proposedEnd = proposedStart + wordDuration
264
-
265
- if (proposedStart < startTime || proposedEnd > endTime) return
266
- if (checkCollision(proposedStart, proposedEnd, dragState.wordIndex, false)) return
267
-
268
- onWordUpdate(dragState.wordIndex, {
269
- start_time: proposedStart,
270
- end_time: proposedEnd
271
- })
272
- }
273
- }
274
-
275
- const handleMouseUp = () => {
276
- setDragState(null)
277
- }
278
-
279
- const handleContextMenu = (e: React.MouseEvent, wordIndex: number) => {
280
- e.preventDefault()
281
- e.stopPropagation()
282
-
283
- // Only unsync synced words
284
- const word = words[wordIndex]
285
- if (word.start_time === null || word.end_time === null) return
286
-
287
- // Directly unsync the word without showing a menu
288
- if (onUnsyncWord) {
289
- console.log('TimelineEditor - Right-click unsync word', {
290
- wordIndex,
291
- wordText: word.text
292
- })
293
- onUnsyncWord(wordIndex)
294
- }
295
- }
296
-
297
- const isWordHighlighted = (word: Word): boolean => {
298
- if (!currentTime || word.start_time === null || word.end_time === null) return false
299
- return currentTime >= word.start_time && currentTime <= word.end_time
300
- }
301
-
302
- const handleTimelineClick = (e: React.MouseEvent) => {
303
- const rect = containerRef.current?.getBoundingClientRect()
304
- if (!rect || !onPlaySegment) return
305
-
306
- const x = e.clientX - rect.left
307
- const clickedPosition = (x / rect.width) * (endTime - startTime) + startTime
308
-
309
- console.log('Timeline clicked:', {
310
- x,
311
- width: rect.width,
312
- clickedTime: clickedPosition
313
- })
314
-
315
- onPlaySegment(clickedPosition)
316
- }
317
-
318
- return (
319
- <TimelineContainer
320
- ref={containerRef}
321
- onMouseMove={handleMouseMove}
322
- onMouseUp={handleMouseUp}
323
- onMouseLeave={handleMouseUp}
324
- >
325
- <TimelineRuler onClick={handleTimelineClick}>
326
- {generateTimelineMarks()}
327
- </TimelineRuler>
328
-
329
- {/* Add cursor line */}
330
- {showPlaybackIndicator && (
331
- <TimelineCursor
332
- sx={{
333
- left: `${timeToPosition(currentTime)}%`,
334
- display: currentTime >= startTime && currentTime <= endTime ? 'block' : 'none'
335
- }}
336
- />
337
- )}
338
-
339
- {words.map((word, index) => {
340
- // Only render synced words on the timeline
341
- if (word.start_time === null || word.end_time === null) return null;
342
-
343
- const leftPosition = timeToPosition(word.start_time)
344
- const rightPosition = timeToPosition(word.end_time)
345
- const width = rightPosition - leftPosition
346
- const adjustedWidth = width
347
-
348
- return (
349
- <TimelineWord
350
- key={index}
351
- className={isWordHighlighted(word) ? 'highlighted' : ''}
352
- sx={{
353
- left: `${leftPosition}%`,
354
- width: `${adjustedWidth}%`,
355
- maxWidth: `calc(${100 - leftPosition}%)`,
356
- }}
357
- onMouseDown={(e) => {
358
- e.stopPropagation()
359
- handleMouseDown(e, index, 'move')
360
- }}
361
- onContextMenu={(e) => handleContextMenu(e, index)}
362
- >
363
- <ResizeHandle
364
- className="left"
365
- onMouseDown={(e) => {
366
- e.stopPropagation()
367
- handleMouseDown(e, index, 'resize-left')
368
- }}
369
- />
370
- {word.text}
371
- <ResizeHandle
372
- className="right"
373
- onMouseDown={(e) => {
374
- e.stopPropagation()
375
- handleMouseDown(e, index, 'resize-right')
376
- }}
377
- />
378
- </TimelineWord>
379
- )
380
- })}
381
- </TimelineContainer>
382
- )
383
- }
@@ -1,131 +0,0 @@
1
- import {
2
- Dialog,
3
- DialogTitle,
4
- DialogContent,
5
- DialogActions,
6
- Button,
7
- TextField,
8
- Box,
9
- Typography,
10
- ButtonGroup,
11
- IconButton,
12
- } from '@mui/material';
13
- import CloseIcon from '@mui/icons-material/Close';
14
- import { useState, useEffect } from 'react';
15
-
16
- interface TimingOffsetModalProps {
17
- open: boolean;
18
- onClose: () => void;
19
- currentOffset: number;
20
- onApply: (offsetMs: number) => void;
21
- }
22
-
23
- export default function TimingOffsetModal({
24
- open,
25
- onClose,
26
- currentOffset,
27
- onApply,
28
- }: TimingOffsetModalProps) {
29
- const [offsetMs, setOffsetMs] = useState(currentOffset);
30
-
31
- // Reset the offset value when the modal opens
32
- useEffect(() => {
33
- if (open) {
34
- setOffsetMs(currentOffset);
35
- }
36
- }, [open, currentOffset]);
37
-
38
- // Handle preset buttons click
39
- const handlePresetClick = (value: number) => {
40
- setOffsetMs((prev) => prev + value);
41
- };
42
-
43
- // Handle direct input change
44
- const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
45
- const value = e.target.value === '' ? 0 : parseInt(e.target.value, 10);
46
- if (!isNaN(value)) {
47
- setOffsetMs(value);
48
- }
49
- };
50
-
51
- // Apply the offset
52
- const handleApply = () => {
53
- onApply(offsetMs);
54
- onClose();
55
- };
56
-
57
- return (
58
- <Dialog
59
- open={open}
60
- onClose={onClose}
61
- maxWidth="sm"
62
- fullWidth
63
- PaperProps={{
64
- sx: {
65
- overflowY: 'visible',
66
- }
67
- }}
68
- >
69
- <DialogTitle sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
70
- Adjust Global Timing Offset
71
- <IconButton onClick={onClose} size="small">
72
- <CloseIcon />
73
- </IconButton>
74
- </DialogTitle>
75
- <DialogContent>
76
- <Box sx={{ mb: 3, mt: 1 }}>
77
- <Typography variant="body2" sx={{ mb: 1 }}>
78
- Adjust the timing of all words in the transcription. Positive values delay the timing, negative values advance it.
79
- </Typography>
80
-
81
- <Typography variant="body2" sx={{ fontStyle: 'italic', mb: 2 }}>
82
- Note: This offset is applied globally but doesn't modify the original timestamps.
83
- </Typography>
84
-
85
- <Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
86
- <Typography variant="body1" sx={{ mr: 2 }}>
87
- Offset:
88
- </Typography>
89
- <TextField
90
- value={offsetMs}
91
- onChange={handleInputChange}
92
- type="number"
93
- variant="outlined"
94
- size="small"
95
- InputProps={{
96
- endAdornment: <Typography variant="body2" sx={{ ml: 1 }}>ms</Typography>,
97
- }}
98
- sx={{ width: 120 }}
99
- />
100
- </Box>
101
-
102
- <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
103
- <Typography variant="body2">Quick adjust:</Typography>
104
- <Box sx={{ display: 'flex', justifyContent: 'center', gap: 1 }}>
105
- <ButtonGroup size="small">
106
- <Button onClick={() => handlePresetClick(-100)}>-100ms</Button>
107
- <Button onClick={() => handlePresetClick(-50)}>-50ms</Button>
108
- <Button onClick={() => handlePresetClick(-10)}>-10ms</Button>
109
- </ButtonGroup>
110
- <ButtonGroup size="small">
111
- <Button onClick={() => handlePresetClick(10)}>+10ms</Button>
112
- <Button onClick={() => handlePresetClick(50)}>+50ms</Button>
113
- <Button onClick={() => handlePresetClick(100)}>+100ms</Button>
114
- </ButtonGroup>
115
- </Box>
116
- </Box>
117
- </Box>
118
- </DialogContent>
119
- <DialogActions>
120
- <Button onClick={onClose}>Cancel</Button>
121
- <Button
122
- onClick={handleApply}
123
- variant="contained"
124
- color="primary"
125
- >
126
- {offsetMs === 0 ? "Remove Offset" : "Apply Offset"}
127
- </Button>
128
- </DialogActions>
129
- </Dialog>
130
- );
131
- }