scitex 2.7.0__py3-none-any.whl → 2.7.3__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 (297) hide show
  1. scitex/__init__.py +6 -2
  2. scitex/__version__.py +1 -1
  3. scitex/audio/README.md +52 -0
  4. scitex/audio/__init__.py +384 -0
  5. scitex/audio/__main__.py +129 -0
  6. scitex/audio/_tts.py +334 -0
  7. scitex/audio/engines/__init__.py +44 -0
  8. scitex/audio/engines/base.py +275 -0
  9. scitex/audio/engines/elevenlabs_engine.py +143 -0
  10. scitex/audio/engines/gtts_engine.py +162 -0
  11. scitex/audio/engines/pyttsx3_engine.py +131 -0
  12. scitex/audio/mcp_server.py +757 -0
  13. scitex/bridge/_helpers.py +1 -1
  14. scitex/bridge/_plt_vis.py +1 -1
  15. scitex/bridge/_stats_vis.py +1 -1
  16. scitex/dev/plt/__init__.py +272 -0
  17. scitex/dev/plt/plot_mpl_axhline.py +28 -0
  18. scitex/dev/plt/plot_mpl_axhspan.py +28 -0
  19. scitex/dev/plt/plot_mpl_axvline.py +28 -0
  20. scitex/dev/plt/plot_mpl_axvspan.py +28 -0
  21. scitex/dev/plt/plot_mpl_bar.py +29 -0
  22. scitex/dev/plt/plot_mpl_barh.py +29 -0
  23. scitex/dev/plt/plot_mpl_boxplot.py +28 -0
  24. scitex/dev/plt/plot_mpl_contour.py +31 -0
  25. scitex/dev/plt/plot_mpl_contourf.py +31 -0
  26. scitex/dev/plt/plot_mpl_errorbar.py +30 -0
  27. scitex/dev/plt/plot_mpl_eventplot.py +28 -0
  28. scitex/dev/plt/plot_mpl_fill.py +30 -0
  29. scitex/dev/plt/plot_mpl_fill_between.py +31 -0
  30. scitex/dev/plt/plot_mpl_hexbin.py +28 -0
  31. scitex/dev/plt/plot_mpl_hist.py +28 -0
  32. scitex/dev/plt/plot_mpl_hist2d.py +28 -0
  33. scitex/dev/plt/plot_mpl_imshow.py +29 -0
  34. scitex/dev/plt/plot_mpl_pcolormesh.py +31 -0
  35. scitex/dev/plt/plot_mpl_pie.py +29 -0
  36. scitex/dev/plt/plot_mpl_plot.py +29 -0
  37. scitex/dev/plt/plot_mpl_quiver.py +31 -0
  38. scitex/dev/plt/plot_mpl_scatter.py +28 -0
  39. scitex/dev/plt/plot_mpl_stackplot.py +31 -0
  40. scitex/dev/plt/plot_mpl_stem.py +29 -0
  41. scitex/dev/plt/plot_mpl_step.py +29 -0
  42. scitex/dev/plt/plot_mpl_violinplot.py +28 -0
  43. scitex/dev/plt/plot_sns_barplot.py +29 -0
  44. scitex/dev/plt/plot_sns_boxplot.py +29 -0
  45. scitex/dev/plt/plot_sns_heatmap.py +28 -0
  46. scitex/dev/plt/plot_sns_histplot.py +29 -0
  47. scitex/dev/plt/plot_sns_kdeplot.py +29 -0
  48. scitex/dev/plt/plot_sns_lineplot.py +31 -0
  49. scitex/dev/plt/plot_sns_scatterplot.py +29 -0
  50. scitex/dev/plt/plot_sns_stripplot.py +29 -0
  51. scitex/dev/plt/plot_sns_swarmplot.py +29 -0
  52. scitex/dev/plt/plot_sns_violinplot.py +29 -0
  53. scitex/dev/plt/plot_stx_bar.py +29 -0
  54. scitex/dev/plt/plot_stx_barh.py +29 -0
  55. scitex/dev/plt/plot_stx_box.py +28 -0
  56. scitex/dev/plt/plot_stx_boxplot.py +28 -0
  57. scitex/dev/plt/plot_stx_conf_mat.py +28 -0
  58. scitex/dev/plt/plot_stx_contour.py +31 -0
  59. scitex/dev/plt/plot_stx_ecdf.py +28 -0
  60. scitex/dev/plt/plot_stx_errorbar.py +30 -0
  61. scitex/dev/plt/plot_stx_fill_between.py +31 -0
  62. scitex/dev/plt/plot_stx_fillv.py +28 -0
  63. scitex/dev/plt/plot_stx_heatmap.py +28 -0
  64. scitex/dev/plt/plot_stx_image.py +28 -0
  65. scitex/dev/plt/plot_stx_imshow.py +28 -0
  66. scitex/dev/plt/plot_stx_joyplot.py +28 -0
  67. scitex/dev/plt/plot_stx_kde.py +28 -0
  68. scitex/dev/plt/plot_stx_line.py +28 -0
  69. scitex/dev/plt/plot_stx_mean_ci.py +28 -0
  70. scitex/dev/plt/plot_stx_mean_std.py +28 -0
  71. scitex/dev/plt/plot_stx_median_iqr.py +28 -0
  72. scitex/dev/plt/plot_stx_raster.py +28 -0
  73. scitex/dev/plt/plot_stx_rectangle.py +28 -0
  74. scitex/dev/plt/plot_stx_scatter.py +29 -0
  75. scitex/dev/plt/plot_stx_shaded_line.py +29 -0
  76. scitex/dev/plt/plot_stx_violin.py +28 -0
  77. scitex/dev/plt/plot_stx_violinplot.py +28 -0
  78. scitex/fig/__init__.py +352 -0
  79. scitex/{vis → fig}/backend/_parser.py +1 -1
  80. scitex/{vis → fig}/canvas.py +1 -1
  81. scitex/{vis → fig}/editor/_defaults.py +70 -5
  82. scitex/fig/editor/_edit.py +751 -0
  83. scitex/{vis → fig}/editor/_qt_editor.py +181 -1
  84. scitex/fig/editor/flask_editor/_bbox.py +1276 -0
  85. scitex/fig/editor/flask_editor/_core.py +624 -0
  86. scitex/{vis → fig}/editor/flask_editor/_plotter.py +38 -4
  87. scitex/fig/editor/flask_editor/_renderer.py +739 -0
  88. scitex/{vis → fig}/editor/flask_editor/templates/__init__.py +1 -1
  89. scitex/fig/editor/flask_editor/templates/_html.py +834 -0
  90. scitex/fig/editor/flask_editor/templates/_scripts.py +3136 -0
  91. scitex/{vis → fig}/editor/flask_editor/templates/_styles.py +625 -18
  92. scitex/{vis → fig}/io/__init__.py +13 -1
  93. scitex/fig/io/_bundle.py +973 -0
  94. scitex/{vis → fig}/io/_canvas.py +1 -1
  95. scitex/{vis → fig}/io/_data.py +1 -1
  96. scitex/{vis → fig}/io/_export.py +1 -1
  97. scitex/{vis → fig}/io/_load.py +1 -1
  98. scitex/{vis → fig}/io/_panel.py +1 -1
  99. scitex/{vis → fig}/io/_save.py +1 -1
  100. scitex/{vis → fig}/model/__init__.py +1 -1
  101. scitex/{vis → fig}/model/_annotations.py +1 -1
  102. scitex/{vis → fig}/model/_axes.py +1 -1
  103. scitex/{vis → fig}/model/_figure.py +1 -1
  104. scitex/{vis → fig}/model/_guides.py +1 -1
  105. scitex/{vis → fig}/model/_plot.py +1 -1
  106. scitex/{vis → fig}/model/_styles.py +1 -1
  107. scitex/{vis → fig}/utils/__init__.py +1 -1
  108. scitex/io/__init__.py +10 -26
  109. scitex/io/_bundle.py +434 -0
  110. scitex/io/_flush.py +5 -2
  111. scitex/io/_load.py +98 -0
  112. scitex/io/_load_modules/_H5Explorer.py +5 -2
  113. scitex/io/_load_modules/_canvas.py +2 -2
  114. scitex/io/_load_modules/_image.py +3 -4
  115. scitex/io/_load_modules/_txt.py +4 -2
  116. scitex/io/_metadata.py +34 -324
  117. scitex/io/_metadata_modules/__init__.py +46 -0
  118. scitex/io/_metadata_modules/_embed.py +70 -0
  119. scitex/io/_metadata_modules/_read.py +64 -0
  120. scitex/io/_metadata_modules/_utils.py +79 -0
  121. scitex/io/_metadata_modules/embed_metadata_jpeg.py +74 -0
  122. scitex/io/_metadata_modules/embed_metadata_pdf.py +53 -0
  123. scitex/io/_metadata_modules/embed_metadata_png.py +26 -0
  124. scitex/io/_metadata_modules/embed_metadata_svg.py +62 -0
  125. scitex/io/_metadata_modules/read_metadata_jpeg.py +57 -0
  126. scitex/io/_metadata_modules/read_metadata_pdf.py +51 -0
  127. scitex/io/_metadata_modules/read_metadata_png.py +39 -0
  128. scitex/io/_metadata_modules/read_metadata_svg.py +44 -0
  129. scitex/io/_qr_utils.py +5 -3
  130. scitex/io/_save.py +548 -30
  131. scitex/io/_save_modules/_canvas.py +3 -3
  132. scitex/io/_save_modules/_image.py +5 -9
  133. scitex/io/_save_modules/_tex.py +7 -4
  134. scitex/io/utils/h5_to_zarr.py +11 -9
  135. scitex/msword/__init__.py +255 -0
  136. scitex/msword/profiles.py +357 -0
  137. scitex/msword/reader.py +753 -0
  138. scitex/msword/utils.py +289 -0
  139. scitex/msword/writer.py +362 -0
  140. scitex/plt/__init__.py +5 -2
  141. scitex/plt/_subplots/_AxesWrapper.py +6 -6
  142. scitex/plt/_subplots/_AxisWrapper.py +15 -9
  143. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +36 -0
  144. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +264 -0
  145. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +213 -0
  146. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +128 -0
  147. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +59 -0
  148. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +34 -0
  149. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +593 -0
  150. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +654 -0
  151. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +527 -0
  152. scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +321 -0
  153. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +33 -0
  154. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +152 -0
  155. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +600 -0
  156. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +79 -5
  157. scitex/plt/_subplots/_FigWrapper.py +6 -6
  158. scitex/plt/_subplots/_SubplotsWrapper.py +28 -18
  159. scitex/plt/_subplots/_export_as_csv.py +35 -5
  160. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +8 -0
  161. scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +10 -21
  162. scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +18 -7
  163. scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +28 -12
  164. scitex/plt/_subplots/_export_as_csv_formatters/_format_matshow.py +10 -4
  165. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_imshow.py +13 -1
  166. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +12 -2
  167. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +10 -3
  168. scitex/plt/_subplots/_export_as_csv_formatters/_format_quiver.py +10 -4
  169. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +18 -3
  170. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +44 -36
  171. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +14 -2
  172. scitex/plt/_subplots/_export_as_csv_formatters/_format_streamplot.py +11 -5
  173. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +84 -0
  174. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +85 -0
  175. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_conf_mat.py +14 -3
  176. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_contour.py +54 -0
  177. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_ecdf.py +14 -2
  178. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +120 -0
  179. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_heatmap.py +16 -6
  180. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_image.py +29 -19
  181. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_imshow.py +63 -0
  182. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_joyplot.py +22 -5
  183. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_mean_ci.py +18 -14
  184. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_mean_std.py +18 -14
  185. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_median_iqr.py +18 -14
  186. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_raster.py +10 -2
  187. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +51 -0
  188. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter_hist.py +18 -9
  189. scitex/plt/ax/_plot/_stx_ecdf.py +4 -2
  190. scitex/plt/gallery/_generate.py +421 -14
  191. scitex/plt/io/__init__.py +53 -0
  192. scitex/plt/io/_bundle.py +490 -0
  193. scitex/plt/io/_layered_bundle.py +1343 -0
  194. scitex/plt/styles/SCITEX_STYLE.yaml +26 -0
  195. scitex/plt/styles/__init__.py +14 -0
  196. scitex/plt/styles/presets.py +78 -0
  197. scitex/plt/utils/__init__.py +13 -1
  198. scitex/plt/utils/_collect_figure_metadata.py +10 -14
  199. scitex/plt/utils/_configure_mpl.py +6 -18
  200. scitex/plt/utils/_crop.py +32 -14
  201. scitex/plt/utils/_csv_column_naming.py +54 -0
  202. scitex/plt/utils/_figure_mm.py +116 -1
  203. scitex/plt/utils/_hitmap.py +1643 -0
  204. scitex/plt/utils/metadata/__init__.py +25 -0
  205. scitex/plt/utils/metadata/_core.py +9 -10
  206. scitex/plt/utils/metadata/_dimensions.py +6 -3
  207. scitex/plt/utils/metadata/_editable_export.py +405 -0
  208. scitex/plt/utils/metadata/_geometry_extraction.py +570 -0
  209. scitex/schema/__init__.py +109 -16
  210. scitex/schema/_canvas.py +1 -1
  211. scitex/schema/_plot.py +1015 -0
  212. scitex/schema/_stats.py +2 -2
  213. scitex/stats/__init__.py +117 -0
  214. scitex/stats/io/__init__.py +29 -0
  215. scitex/stats/io/_bundle.py +156 -0
  216. scitex/tex/__init__.py +4 -0
  217. scitex/tex/_export.py +890 -0
  218. {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/METADATA +11 -1
  219. {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/RECORD +238 -170
  220. scitex/io/memo.md +0 -2827
  221. scitex/plt/REQUESTS.md +0 -191
  222. scitex/plt/_subplots/TODO.md +0 -53
  223. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +0 -559
  224. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +0 -1609
  225. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +0 -447
  226. scitex/plt/templates/research-master/scitex/vis/gallery/area/fill_between.json +0 -110
  227. scitex/plt/templates/research-master/scitex/vis/gallery/area/fill_betweenx.json +0 -88
  228. scitex/plt/templates/research-master/scitex/vis/gallery/area/stx_fill_between.json +0 -103
  229. scitex/plt/templates/research-master/scitex/vis/gallery/area/stx_fillv.json +0 -106
  230. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/bar.json +0 -92
  231. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/barh.json +0 -92
  232. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/boxplot.json +0 -92
  233. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_bar.json +0 -84
  234. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_barh.json +0 -84
  235. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_box.json +0 -83
  236. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_boxplot.json +0 -93
  237. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_violin.json +0 -91
  238. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_violinplot.json +0 -91
  239. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/violinplot.json +0 -91
  240. scitex/plt/templates/research-master/scitex/vis/gallery/contour/contour.json +0 -97
  241. scitex/plt/templates/research-master/scitex/vis/gallery/contour/contourf.json +0 -98
  242. scitex/plt/templates/research-master/scitex/vis/gallery/contour/stx_contour.json +0 -84
  243. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/hist.json +0 -101
  244. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/hist2d.json +0 -96
  245. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_ecdf.json +0 -95
  246. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_joyplot.json +0 -95
  247. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_kde.json +0 -93
  248. scitex/plt/templates/research-master/scitex/vis/gallery/grid/imshow.json +0 -95
  249. scitex/plt/templates/research-master/scitex/vis/gallery/grid/matshow.json +0 -95
  250. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_conf_mat.json +0 -83
  251. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_heatmap.json +0 -92
  252. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_image.json +0 -121
  253. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_imshow.json +0 -84
  254. scitex/plt/templates/research-master/scitex/vis/gallery/line/plot.json +0 -110
  255. scitex/plt/templates/research-master/scitex/vis/gallery/line/step.json +0 -92
  256. scitex/plt/templates/research-master/scitex/vis/gallery/line/stx_line.json +0 -95
  257. scitex/plt/templates/research-master/scitex/vis/gallery/line/stx_shaded_line.json +0 -96
  258. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/hexbin.json +0 -95
  259. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/scatter.json +0 -95
  260. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/stem.json +0 -92
  261. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/stx_scatter.json +0 -84
  262. scitex/plt/templates/research-master/scitex/vis/gallery/special/pie.json +0 -94
  263. scitex/plt/templates/research-master/scitex/vis/gallery/special/stx_raster.json +0 -109
  264. scitex/plt/templates/research-master/scitex/vis/gallery/special/stx_rectangle.json +0 -108
  265. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/errorbar.json +0 -93
  266. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_errorbar.json +0 -84
  267. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_mean_ci.json +0 -96
  268. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_mean_std.json +0 -96
  269. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_median_iqr.json +0 -96
  270. scitex/plt/templates/research-master/scitex/vis/gallery/vector/quiver.json +0 -99
  271. scitex/plt/templates/research-master/scitex/vis/gallery/vector/streamplot.json +0 -100
  272. scitex/vis/__init__.py +0 -177
  273. scitex/vis/editor/_edit.py +0 -390
  274. scitex/vis/editor/flask_editor/_bbox.py +0 -529
  275. scitex/vis/editor/flask_editor/_core.py +0 -168
  276. scitex/vis/editor/flask_editor/_renderer.py +0 -393
  277. scitex/vis/editor/flask_editor/templates/_html.py +0 -513
  278. scitex/vis/editor/flask_editor/templates/_scripts.py +0 -1261
  279. /scitex/{vis → fig}/README.md +0 -0
  280. /scitex/{vis → fig}/backend/__init__.py +0 -0
  281. /scitex/{vis → fig}/backend/_export.py +0 -0
  282. /scitex/{vis → fig}/backend/_render.py +0 -0
  283. /scitex/{vis → fig}/docs/CANVAS_ARCHITECTURE.md +0 -0
  284. /scitex/{vis → fig}/editor/__init__.py +0 -0
  285. /scitex/{vis → fig}/editor/_dearpygui_editor.py +0 -0
  286. /scitex/{vis → fig}/editor/_flask_editor.py +0 -0
  287. /scitex/{vis → fig}/editor/_mpl_editor.py +0 -0
  288. /scitex/{vis → fig}/editor/_tkinter_editor.py +0 -0
  289. /scitex/{vis → fig}/editor/flask_editor/__init__.py +0 -0
  290. /scitex/{vis → fig}/editor/flask_editor/_utils.py +0 -0
  291. /scitex/{vis → fig}/io/_directory.py +0 -0
  292. /scitex/{vis → fig}/model/_plot_types.py +0 -0
  293. /scitex/{vis → fig}/utils/_defaults.py +0 -0
  294. /scitex/{vis → fig}/utils/_validate.py +0 -0
  295. {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/WHEEL +0 -0
  296. {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/entry_points.txt +0 -0
  297. {scitex-2.7.0.dist-info → scitex-2.7.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-12-11 (ywatanabe)"
4
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/audio/engines/elevenlabs_engine.py
5
+ # ----------------------------------------
6
+
7
+ """
8
+ ElevenLabs TTS backend - High quality, requires API key and payment.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ from pathlib import Path
15
+ from typing import List, Optional
16
+
17
+ from .base import BaseTTS
18
+
19
+ __all__ = ["ElevenLabsTTS"]
20
+
21
+
22
+ class ElevenLabsTTS(BaseTTS):
23
+ """ElevenLabs TTS backend.
24
+
25
+ High-quality voices but requires API key and has usage costs.
26
+
27
+ Environment:
28
+ ELEVENLABS_API_KEY: Your ElevenLabs API key
29
+ """
30
+
31
+ VOICES = {
32
+ "rachel": "21m00Tcm4TlvDq8ikWAM",
33
+ "adam": "pNInz6obpgDQGcFmaJgB",
34
+ "antoni": "ErXwobaYiN019PkySvjV",
35
+ "bella": "EXAVITQu4vr4xnSDxMaL",
36
+ "domi": "AZnzlk1XvdvUeBnXmlld",
37
+ "elli": "MF3mGyEYCl7XYWbV9V6O",
38
+ "josh": "TxGEqnHWrfWFTfGW9XjX",
39
+ "sam": "yoZ06aMxZJJ28mfd3POQ",
40
+ }
41
+
42
+ def __init__(
43
+ self,
44
+ api_key: Optional[str] = None,
45
+ voice: str = "rachel",
46
+ model_id: str = "eleven_multilingual_v2",
47
+ stability: float = 0.5,
48
+ similarity_boost: float = 0.75,
49
+ speed: float = 1.0,
50
+ **kwargs,
51
+ ):
52
+ super().__init__(**kwargs)
53
+ self.api_key = api_key or os.environ.get("ELEVENLABS_API_KEY")
54
+ self.voice = voice
55
+ self.model_id = model_id
56
+ self.stability = stability
57
+ self.similarity_boost = similarity_boost
58
+ self.speed = speed
59
+ self._client = None
60
+
61
+ @property
62
+ def name(self) -> str:
63
+ return "elevenlabs"
64
+
65
+ @property
66
+ def requires_api_key(self) -> bool:
67
+ return True
68
+
69
+ @property
70
+ def requires_internet(self) -> bool:
71
+ return True
72
+
73
+ @property
74
+ def client(self):
75
+ """Lazy-load ElevenLabs client."""
76
+ if self._client is None:
77
+ try:
78
+ from elevenlabs.client import ElevenLabs
79
+
80
+ self._client = ElevenLabs(api_key=self.api_key)
81
+ except ImportError:
82
+ raise ImportError(
83
+ "elevenlabs package not installed. "
84
+ "Install with: pip install elevenlabs"
85
+ )
86
+ return self._client
87
+
88
+ def _get_voice_id(self, voice: Optional[str] = None) -> str:
89
+ """Get voice ID from name or return as-is if already an ID."""
90
+ v = voice or self.voice
91
+ normalized = v.lower()
92
+ return self.VOICES.get(normalized, v)
93
+
94
+ def synthesize(self, text: str, output_path: str) -> Path:
95
+ """Synthesize text using ElevenLabs API."""
96
+ voice_id = self._get_voice_id(self.config.get("voice"))
97
+
98
+ audio = self.client.text_to_speech.convert(
99
+ text=text,
100
+ voice_id=voice_id,
101
+ model_id=self.model_id,
102
+ voice_settings={
103
+ "stability": self.stability,
104
+ "similarity_boost": self.similarity_boost,
105
+ "speed": self.speed,
106
+ },
107
+ output_format="mp3_44100_128",
108
+ )
109
+
110
+ out_path = Path(output_path)
111
+ with open(out_path, "wb") as f:
112
+ for chunk in audio:
113
+ f.write(chunk)
114
+
115
+ return out_path
116
+
117
+ def get_voices(self) -> List[dict]:
118
+ """Get available voices."""
119
+ # Start with preset voices
120
+ voices = [
121
+ {"name": name, "id": vid, "type": "preset"}
122
+ for name, vid in self.VOICES.items()
123
+ ]
124
+
125
+ # Try to get custom voices
126
+ try:
127
+ response = self.client.voices.get_all()
128
+ for v in response.voices:
129
+ voices.append(
130
+ {
131
+ "name": v.name,
132
+ "id": v.voice_id,
133
+ "type": "custom",
134
+ "labels": v.labels,
135
+ }
136
+ )
137
+ except Exception:
138
+ pass
139
+
140
+ return voices
141
+
142
+
143
+ # EOF
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-12-11 (ywatanabe)"
4
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/audio/engines/gtts_engine.py
5
+ # ----------------------------------------
6
+
7
+ """
8
+ Google Text-to-Speech (gTTS) backend - Free, requires internet.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import io
14
+ from pathlib import Path
15
+ from typing import List, Optional
16
+
17
+ from .base import BaseTTS
18
+
19
+ __all__ = ["GoogleTTS"]
20
+
21
+
22
+ class GoogleTTS(BaseTTS):
23
+ """Google Text-to-Speech backend using gTTS.
24
+
25
+ Free to use, requires internet connection.
26
+ Good quality voices with multi-language support.
27
+ Supports speed control via pydub (requires ffmpeg).
28
+
29
+ Install: pip install gTTS pydub
30
+ """
31
+
32
+ # Supported languages (subset of most common)
33
+ LANGUAGES = {
34
+ "en": "English",
35
+ "es": "Spanish",
36
+ "fr": "French",
37
+ "de": "German",
38
+ "it": "Italian",
39
+ "pt": "Portuguese",
40
+ "ru": "Russian",
41
+ "ja": "Japanese",
42
+ "ko": "Korean",
43
+ "zh-CN": "Chinese (Simplified)",
44
+ "zh-TW": "Chinese (Traditional)",
45
+ "ar": "Arabic",
46
+ "hi": "Hindi",
47
+ "nl": "Dutch",
48
+ "pl": "Polish",
49
+ "sv": "Swedish",
50
+ "tr": "Turkish",
51
+ "vi": "Vietnamese",
52
+ }
53
+
54
+ def __init__(
55
+ self,
56
+ lang: str = "en",
57
+ slow: bool = False,
58
+ speed: float = 1.5,
59
+ **kwargs,
60
+ ):
61
+ super().__init__(**kwargs)
62
+ self.lang = lang
63
+ self.slow = slow
64
+ self.speed = speed # 1.0 = normal, >1.0 = faster, <1.0 = slower
65
+
66
+ @property
67
+ def name(self) -> str:
68
+ return "gtts"
69
+
70
+ @property
71
+ def requires_internet(self) -> bool:
72
+ return True
73
+
74
+ def synthesize(self, text: str, output_path: str) -> Path:
75
+ """Synthesize text using Google TTS with optional speed control."""
76
+ try:
77
+ from gtts import gTTS
78
+ except ImportError:
79
+ raise ImportError(
80
+ "gTTS package not installed. Install with: pip install gTTS"
81
+ )
82
+
83
+ # Get language from config or use default
84
+ lang = self.config.get("voice", self.lang)
85
+ if lang in self.LANGUAGES:
86
+ pass # Valid language code
87
+ elif lang.lower() in [l.lower() for l in self.LANGUAGES.values()]:
88
+ # Convert language name to code
89
+ for code, name in self.LANGUAGES.items():
90
+ if name.lower() == lang.lower():
91
+ lang = code
92
+ break
93
+
94
+ # Get speed from config or use instance default
95
+ speed = self.config.get("speed", self.speed)
96
+
97
+ out_path = Path(output_path)
98
+
99
+ if speed != 1.0:
100
+ # Use pydub for speed control
101
+ audio_data = self._synthesize_with_speed(text, lang, speed)
102
+ audio_data.export(str(out_path), format="mp3")
103
+ else:
104
+ # Direct save without speed modification
105
+ tts = gTTS(text=text, lang=lang, slow=self.slow)
106
+ tts.save(str(out_path))
107
+
108
+ return out_path
109
+
110
+ def _synthesize_with_speed(self, text: str, lang: str, speed: float):
111
+ """Synthesize with speed control using pydub.
112
+
113
+ Args:
114
+ text: Text to synthesize.
115
+ lang: Language code.
116
+ speed: Speed multiplier (>1.0 faster, <1.0 slower).
117
+
118
+ Returns:
119
+ AudioSegment with adjusted speed.
120
+ """
121
+ try:
122
+ from gtts import gTTS
123
+ from pydub import AudioSegment
124
+ except ImportError as e:
125
+ raise ImportError(
126
+ "pydub package required for speed control. "
127
+ "Install with: pip install pydub"
128
+ ) from e
129
+
130
+ # Generate speech to memory buffer
131
+ with io.BytesIO() as buffer:
132
+ gTTS(text=text, lang=lang, slow=self.slow).write_to_fp(buffer)
133
+ buffer.seek(0)
134
+ sound = AudioSegment.from_file(buffer, format="mp3")
135
+
136
+ # Apply speed adjustment
137
+ if speed > 1.0:
138
+ # speedup() for faster playback
139
+ sound = sound.speedup(
140
+ playback_speed=speed,
141
+ chunk_size=150,
142
+ crossfade=25
143
+ )
144
+ elif speed < 1.0:
145
+ # For slower playback, adjust frame rate
146
+ new_frame_rate = int(sound.frame_rate * speed)
147
+ sound = sound._spawn(
148
+ sound.raw_data,
149
+ overrides={"frame_rate": new_frame_rate}
150
+ ).set_frame_rate(sound.frame_rate)
151
+
152
+ return sound
153
+
154
+ def get_voices(self) -> List[dict]:
155
+ """Get available languages as 'voices'."""
156
+ return [
157
+ {"name": name, "id": code, "type": "language"}
158
+ for code, name in self.LANGUAGES.items()
159
+ ]
160
+
161
+
162
+ # EOF
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # Timestamp: "2025-12-11 (ywatanabe)"
4
+ # File: /home/ywatanabe/proj/scitex-code/src/scitex/audio/engines/pyttsx3_engine.py
5
+ # ----------------------------------------
6
+
7
+ """
8
+ System TTS backend using pyttsx3 - Offline, uses system voices.
9
+
10
+ Requirements:
11
+ - pip install pyttsx3
12
+ - Linux: sudo apt install espeak-ng libespeak1
13
+ - Windows: Uses SAPI5 (built-in)
14
+ - macOS: Uses NSSpeechSynthesizer (built-in)
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from pathlib import Path
20
+ from typing import List, Optional
21
+
22
+ from .base import BaseTTS
23
+
24
+ __all__ = ["SystemTTS"]
25
+
26
+
27
+ class SystemTTS(BaseTTS):
28
+ """System TTS backend using pyttsx3.
29
+
30
+ Works offline using system's built-in TTS engine.
31
+ Quality varies by platform and available voices.
32
+
33
+ Platforms:
34
+ - Linux: espeak/espeak-ng
35
+ - Windows: SAPI5
36
+ - macOS: NSSpeechSynthesizer
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ rate: int = 150, # Words per minute
42
+ volume: float = 1.0, # 0.0 to 1.0
43
+ voice: Optional[str] = None,
44
+ **kwargs,
45
+ ):
46
+ super().__init__(**kwargs)
47
+ self.rate = rate
48
+ self.volume = volume
49
+ self.voice = voice
50
+ self._engine = None
51
+
52
+ @property
53
+ def name(self) -> str:
54
+ return "pyttsx3"
55
+
56
+ @property
57
+ def engine(self):
58
+ """Lazy-load pyttsx3 engine."""
59
+ if self._engine is None:
60
+ try:
61
+ import pyttsx3
62
+
63
+ self._engine = pyttsx3.init()
64
+ self._engine.setProperty("rate", self.rate)
65
+ self._engine.setProperty("volume", self.volume)
66
+
67
+ if self.voice:
68
+ self._set_voice(self.voice)
69
+ except ImportError:
70
+ raise ImportError(
71
+ "pyttsx3 package not installed. "
72
+ "Install with: pip install pyttsx3\n"
73
+ "Linux also requires: sudo apt install espeak-ng libespeak1"
74
+ )
75
+ except RuntimeError as e:
76
+ if "eSpeak" in str(e):
77
+ raise RuntimeError(
78
+ "espeak not installed. "
79
+ "Install with: sudo apt install espeak-ng libespeak1"
80
+ )
81
+ raise
82
+ return self._engine
83
+
84
+ def _set_voice(self, voice_name: str):
85
+ """Set voice by name or ID."""
86
+ voices = self.engine.getProperty("voices")
87
+ for v in voices:
88
+ if voice_name.lower() in v.name.lower() or voice_name == v.id:
89
+ self.engine.setProperty("voice", v.id)
90
+ return
91
+ # If not found, keep default
92
+
93
+ def synthesize(self, text: str, output_path: str) -> Path:
94
+ """Synthesize text using system TTS."""
95
+ # Set voice if specified in config
96
+ voice = self.config.get("voice")
97
+ if voice:
98
+ self._set_voice(voice)
99
+
100
+ out_path = Path(output_path)
101
+
102
+ # pyttsx3 can save to file
103
+ self.engine.save_to_file(text, str(out_path))
104
+ self.engine.runAndWait()
105
+
106
+ return out_path
107
+
108
+ def speak_direct(self, text: str):
109
+ """Speak directly without saving to file (faster)."""
110
+ voice = self.config.get("voice")
111
+ if voice:
112
+ self._set_voice(voice)
113
+
114
+ self.engine.say(text)
115
+ self.engine.runAndWait()
116
+
117
+ def get_voices(self) -> List[dict]:
118
+ """Get available system voices."""
119
+ voices = self.engine.getProperty("voices")
120
+ return [
121
+ {
122
+ "name": v.name,
123
+ "id": v.id,
124
+ "type": "system",
125
+ "languages": getattr(v, "languages", []),
126
+ }
127
+ for v in voices
128
+ ]
129
+
130
+
131
+ # EOF