@thanhvn14/csvibe 0.1.3 → 0.1.5

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 (395) hide show
  1. package/.github/agents/schemas/base-output.schema.json +88 -0
  2. package/.github/agents/schemas/brainstorm-output.schema.json +88 -0
  3. package/.github/agents/schemas/scout-output.schema.json +60 -0
  4. package/.github/agents/scripts/fetch-copilot-tools.js +245 -0
  5. package/.github/agents/scripts/lib/parse-agent-file.js +275 -0
  6. package/.github/agents/scripts/package-lock.json +78 -0
  7. package/.github/agents/scripts/package.json +22 -0
  8. package/.github/agents/scripts/schemas/agent-frontmatter.schema.json +83 -0
  9. package/.github/agents/scripts/validate-agent-all.js +157 -0
  10. package/.github/agents/scripts/validate-agent-frontmatter.js +96 -0
  11. package/.github/agents/scripts/validate-agent-handoffs.js +169 -0
  12. package/.github/agents/scripts/validate-agent-output.js +157 -0
  13. package/.github/agents/scripts/validate-agent-tools.js +278 -0
  14. package/.github/skills/.env.example +100 -0
  15. package/.github/skills/.install-state.json +23 -0
  16. package/.github/skills/README.md +149 -0
  17. package/.github/skills/ai-multimodal/.env.example +204 -0
  18. package/.github/skills/ai-multimodal/scripts/.coverage +0 -0
  19. package/.github/skills/ai-multimodal/scripts/check_setup.py +305 -0
  20. package/.github/skills/ai-multimodal/scripts/document_converter.py +395 -0
  21. package/.github/skills/ai-multimodal/scripts/gemini_batch_process.py +1184 -0
  22. package/.github/skills/ai-multimodal/scripts/media_optimizer.py +506 -0
  23. package/.github/skills/ai-multimodal/scripts/requirements.txt +26 -0
  24. package/.github/skills/better-auth/scripts/.coverage +0 -0
  25. package/.github/skills/better-auth/scripts/better_auth_init.py +521 -0
  26. package/.github/skills/better-auth/scripts/requirements.txt +15 -0
  27. package/.github/skills/chrome-devtools/scripts/README.md +272 -0
  28. package/.github/skills/chrome-devtools/scripts/__tests__/selector.test.js +210 -0
  29. package/.github/skills/chrome-devtools/scripts/aria-snapshot.js +362 -0
  30. package/.github/skills/chrome-devtools/scripts/click.js +83 -0
  31. package/.github/skills/chrome-devtools/scripts/console.js +79 -0
  32. package/.github/skills/chrome-devtools/scripts/evaluate.js +53 -0
  33. package/.github/skills/chrome-devtools/scripts/fill.js +76 -0
  34. package/.github/skills/chrome-devtools/scripts/inject-auth.js +229 -0
  35. package/.github/skills/chrome-devtools/scripts/install-deps.sh +181 -0
  36. package/.github/skills/chrome-devtools/scripts/install.sh +83 -0
  37. package/.github/skills/chrome-devtools/scripts/lib/browser.js +318 -0
  38. package/.github/skills/chrome-devtools/scripts/lib/selector.js +178 -0
  39. package/.github/skills/chrome-devtools/scripts/navigate.js +54 -0
  40. package/.github/skills/chrome-devtools/scripts/network.js +106 -0
  41. package/.github/skills/chrome-devtools/scripts/package-lock.json +1589 -0
  42. package/.github/skills/chrome-devtools/scripts/package.json +16 -0
  43. package/.github/skills/chrome-devtools/scripts/performance.js +149 -0
  44. package/.github/skills/chrome-devtools/scripts/screenshot.js +198 -0
  45. package/.github/skills/chrome-devtools/scripts/select-ref.js +131 -0
  46. package/.github/skills/chrome-devtools/scripts/snapshot.js +135 -0
  47. package/.github/skills/common/README.md +120 -0
  48. package/.github/skills/common/api_key_helper.py +411 -0
  49. package/.github/skills/common/api_key_rotator.py +248 -0
  50. package/.github/skills/databases/scripts/.coverage +0 -0
  51. package/.github/skills/databases/scripts/db_backup.py +502 -0
  52. package/.github/skills/databases/scripts/db_migrate.py +425 -0
  53. package/.github/skills/databases/scripts/db_performance_check.py +456 -0
  54. package/.github/skills/databases/scripts/requirements.txt +20 -0
  55. package/.github/skills/debugging/scripts/find-polluter.sh +63 -0
  56. package/.github/skills/devops/.env.example +76 -0
  57. package/.github/skills/devops/scripts/cloudflare_deploy.py +269 -0
  58. package/.github/skills/devops/scripts/docker_optimize.py +331 -0
  59. package/.github/skills/devops/scripts/requirements.txt +20 -0
  60. package/.github/skills/docs-seeker/.env.example +15 -0
  61. package/.github/skills/docs-seeker/package.json +25 -0
  62. package/.github/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
  63. package/.github/skills/docs-seeker/scripts/detect-topic.js +172 -0
  64. package/.github/skills/docs-seeker/scripts/fetch-docs.js +213 -0
  65. package/.github/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
  66. package/.github/skills/document-skills/docx/LICENSE.txt +30 -0
  67. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  68. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  69. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  70. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  71. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  72. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  73. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  74. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  75. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  76. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  77. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  78. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  79. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  80. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  81. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  82. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  83. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  84. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  85. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  86. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  87. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  88. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  89. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  90. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  91. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  92. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  93. package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  94. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  95. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  96. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  97. package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  98. package/.github/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  99. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  100. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  101. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  102. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  103. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  104. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  105. package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  106. package/.github/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
  107. package/.github/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
  108. package/.github/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
  109. package/.github/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  110. package/.github/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
  111. package/.github/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
  112. package/.github/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  113. package/.github/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  114. package/.github/skills/document-skills/docx/scripts/__init__.py +1 -0
  115. package/.github/skills/document-skills/docx/scripts/document.py +1276 -0
  116. package/.github/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
  117. package/.github/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
  118. package/.github/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  119. package/.github/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
  120. package/.github/skills/document-skills/docx/scripts/templates/people.xml +3 -0
  121. package/.github/skills/document-skills/docx/scripts/utilities.py +374 -0
  122. package/.github/skills/document-skills/pdf/LICENSE.txt +30 -0
  123. package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
  124. package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  125. package/.github/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
  126. package/.github/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  127. package/.github/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
  128. package/.github/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
  129. package/.github/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
  130. package/.github/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  131. package/.github/skills/document-skills/pptx/LICENSE.txt +30 -0
  132. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  133. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  134. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  135. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  136. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  137. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  138. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  139. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  140. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  141. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  142. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  143. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  144. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  145. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  146. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  147. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  148. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  149. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  150. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  151. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  152. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  153. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  154. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  155. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  156. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  157. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  158. package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  159. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  160. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  161. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  162. package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  163. package/.github/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  164. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  165. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  166. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  167. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  168. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  169. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  170. package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  171. package/.github/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
  172. package/.github/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
  173. package/.github/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
  174. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  175. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
  176. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  177. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  178. package/.github/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  179. package/.github/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
  180. package/.github/skills/document-skills/pptx/scripts/inventory.py +1020 -0
  181. package/.github/skills/document-skills/pptx/scripts/rearrange.py +231 -0
  182. package/.github/skills/document-skills/pptx/scripts/replace.py +385 -0
  183. package/.github/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
  184. package/.github/skills/document-skills/xlsx/LICENSE.txt +30 -0
  185. package/.github/skills/document-skills/xlsx/recalc.py +190 -0
  186. package/.github/skills/install.ps1 +1220 -0
  187. package/.github/skills/install.sh +1032 -0
  188. package/.github/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
  189. package/.github/skills/markdown-novel-viewer/assets/favicon.png +0 -0
  190. package/.github/skills/markdown-novel-viewer/assets/novel-theme.css +818 -0
  191. package/.github/skills/markdown-novel-viewer/assets/reader.js +262 -0
  192. package/.github/skills/markdown-novel-viewer/assets/template.html +80 -0
  193. package/.github/skills/markdown-novel-viewer/package-lock.json +146 -0
  194. package/.github/skills/markdown-novel-viewer/package.json +15 -0
  195. package/.github/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
  196. package/.github/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +272 -0
  197. package/.github/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
  198. package/.github/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
  199. package/.github/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
  200. package/.github/skills/markdown-novel-viewer/scripts/server.cjs +411 -0
  201. package/.github/skills/mcp-builder/LICENSE.txt +202 -0
  202. package/.github/skills/mcp-builder/scripts/connections.py +151 -0
  203. package/.github/skills/mcp-builder/scripts/evaluation.py +373 -0
  204. package/.github/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  205. package/.github/skills/mcp-builder/scripts/requirements.txt +2 -0
  206. package/.github/skills/mcp-management/README.md +219 -0
  207. package/.github/skills/mcp-management/assets/tools.json +3146 -0
  208. package/.github/skills/mcp-management/package-lock.json +6 -0
  209. package/.github/skills/mcp-management/scripts/.env.example +10 -0
  210. package/.github/skills/mcp-management/scripts/cli.ts +195 -0
  211. package/.github/skills/mcp-management/scripts/dist/analyze-tools.js +70 -0
  212. package/.github/skills/mcp-management/scripts/dist/cli.js +160 -0
  213. package/.github/skills/mcp-management/scripts/dist/mcp-client.js +183 -0
  214. package/.github/skills/mcp-management/scripts/mcp-client.ts +230 -0
  215. package/.github/skills/mcp-management/scripts/package.json +20 -0
  216. package/.github/skills/media-processing/scripts/README.md +111 -0
  217. package/.github/skills/media-processing/scripts/batch-remove-background.sh +124 -0
  218. package/.github/skills/media-processing/scripts/batch_resize.py +342 -0
  219. package/.github/skills/media-processing/scripts/media_convert.py +311 -0
  220. package/.github/skills/media-processing/scripts/remove-background.sh +96 -0
  221. package/.github/skills/media-processing/scripts/remove-bg-node.js +158 -0
  222. package/.github/skills/media-processing/scripts/requirements.txt +24 -0
  223. package/.github/skills/media-processing/scripts/video_optimize.py +414 -0
  224. package/.github/skills/payment-integration/README.md +185 -0
  225. package/.github/skills/payment-integration/scripts/.env.example +20 -0
  226. package/.github/skills/payment-integration/scripts/checkout-helper.js +244 -0
  227. package/.github/skills/payment-integration/scripts/package.json +17 -0
  228. package/.github/skills/payment-integration/scripts/polar-webhook-verify.js +202 -0
  229. package/.github/skills/payment-integration/scripts/sepay-webhook-verify.js +193 -0
  230. package/.github/skills/payment-integration/scripts/test-scripts.js +237 -0
  231. package/.github/skills/plans-kanban/assets/dashboard-template.html +119 -0
  232. package/.github/skills/plans-kanban/assets/dashboard.css +1594 -0
  233. package/.github/skills/plans-kanban/assets/dashboard.js +596 -0
  234. package/.github/skills/plans-kanban/assets/favicon.png +0 -0
  235. package/.github/skills/plans-kanban/package-lock.json +123 -0
  236. package/.github/skills/plans-kanban/package.json +13 -0
  237. package/.github/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +884 -0
  238. package/.github/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
  239. package/.github/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
  240. package/.github/skills/plans-kanban/scripts/lib/plan-parser.cjs +175 -0
  241. package/.github/skills/plans-kanban/scripts/lib/plan-scanner.cjs +272 -0
  242. package/.github/skills/plans-kanban/scripts/lib/port-finder.cjs +48 -0
  243. package/.github/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
  244. package/.github/skills/plans-kanban/scripts/server.cjs +260 -0
  245. package/.github/skills/repomix/scripts/.coverage +0 -0
  246. package/.github/skills/repomix/scripts/README.md +179 -0
  247. package/.github/skills/repomix/scripts/repomix_batch.py +455 -0
  248. package/.github/skills/repomix/scripts/repos.example.json +15 -0
  249. package/.github/skills/repomix/scripts/requirements.txt +15 -0
  250. package/.github/skills/scout-validation/scripts/lib/broad-pattern-detector.cjs +124 -0
  251. package/.github/skills/scout-validation/scripts/lib/path-checker.cjs +66 -0
  252. package/.github/skills/scout-validation/scripts/lib/schema-validator.cjs +45 -0
  253. package/.github/skills/scout-validation/scripts/package.json +11 -0
  254. package/.github/skills/scout-validation/scripts/validate-scout-output.cjs +219 -0
  255. package/.github/skills/scout-validation/test/broad-pattern-output.json +18 -0
  256. package/.github/skills/scout-validation/test/invalid-path-output.json +18 -0
  257. package/.github/skills/scout-validation/test/valid-scout-output.json +26 -0
  258. package/.github/skills/sequential-thinking/.env.example +8 -0
  259. package/.github/skills/sequential-thinking/README.md +183 -0
  260. package/.github/skills/sequential-thinking/package.json +31 -0
  261. package/.github/skills/sequential-thinking/scripts/format-thought.js +159 -0
  262. package/.github/skills/sequential-thinking/scripts/process-thought.js +236 -0
  263. package/.github/skills/shopify/README.md +66 -0
  264. package/.github/skills/shopify/scripts/.coverage +0 -0
  265. package/.github/skills/shopify/scripts/requirements.txt +19 -0
  266. package/.github/skills/shopify/scripts/shopify_init.py +423 -0
  267. package/.github/skills/skill-creator/LICENSE.txt +202 -0
  268. package/.github/skills/skill-creator/scripts/init_skill.py +303 -0
  269. package/.github/skills/skill-creator/scripts/package_skill.py +110 -0
  270. package/.github/skills/skill-creator/scripts/quick_validate.py +65 -0
  271. package/.github/skills/ui-styling/LICENSE.txt +202 -0
  272. package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  273. package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  274. package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  275. package/.github/skills/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  276. package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  277. package/.github/skills/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  278. package/.github/skills/ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  279. package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  280. package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  281. package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  282. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  283. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  284. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  285. package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  286. package/.github/skills/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  287. package/.github/skills/ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  288. package/.github/skills/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  289. package/.github/skills/ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  290. package/.github/skills/ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  291. package/.github/skills/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  292. package/.github/skills/ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  293. package/.github/skills/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  294. package/.github/skills/ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  295. package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  296. package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  297. package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  298. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  299. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  300. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  301. package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  302. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  303. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  304. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  305. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  306. package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  307. package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  308. package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  309. package/.github/skills/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  310. package/.github/skills/ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  311. package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  312. package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  313. package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  314. package/.github/skills/ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  315. package/.github/skills/ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  316. package/.github/skills/ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  317. package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  318. package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  319. package/.github/skills/ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  320. package/.github/skills/ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  321. package/.github/skills/ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  322. package/.github/skills/ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  323. package/.github/skills/ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  324. package/.github/skills/ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  325. package/.github/skills/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  326. package/.github/skills/ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  327. package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  328. package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  329. package/.github/skills/ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  330. package/.github/skills/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  331. package/.github/skills/ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  332. package/.github/skills/ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  333. package/.github/skills/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  334. package/.github/skills/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  335. package/.github/skills/ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  336. package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  337. package/.github/skills/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  338. package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  339. package/.github/skills/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  340. package/.github/skills/ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  341. package/.github/skills/ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  342. package/.github/skills/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  343. package/.github/skills/ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  344. package/.github/skills/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  345. package/.github/skills/ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  346. package/.github/skills/ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  347. package/.github/skills/ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  348. package/.github/skills/ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  349. package/.github/skills/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  350. package/.github/skills/ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  351. package/.github/skills/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  352. package/.github/skills/ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  353. package/.github/skills/ui-styling/scripts/.coverage +0 -0
  354. package/.github/skills/ui-styling/scripts/requirements.txt +17 -0
  355. package/.github/skills/ui-styling/scripts/shadcn_add.py +292 -0
  356. package/.github/skills/ui-styling/scripts/tailwind_config_gen.py +456 -0
  357. package/.github/skills/ui-ux-pro-max/data/charts.csv +26 -0
  358. package/.github/skills/ui-ux-pro-max/data/colors.csv +97 -0
  359. package/.github/skills/ui-ux-pro-max/data/landing.csv +31 -0
  360. package/.github/skills/ui-ux-pro-max/data/products.csv +97 -0
  361. package/.github/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  362. package/.github/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  363. package/.github/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +51 -0
  364. package/.github/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  365. package/.github/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  366. package/.github/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  367. package/.github/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  368. package/.github/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  369. package/.github/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  370. package/.github/skills/ui-ux-pro-max/data/styles.csv +59 -0
  371. package/.github/skills/ui-ux-pro-max/data/typography.csv +58 -0
  372. package/.github/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  373. package/.github/skills/ui-ux-pro-max/scripts/core.py +236 -0
  374. package/.github/skills/ui-ux-pro-max/scripts/search.py +76 -0
  375. package/.github/skills/web-frameworks/scripts/.coverage +0 -0
  376. package/.github/skills/web-frameworks/scripts/__init__.py +0 -0
  377. package/.github/skills/web-frameworks/scripts/nextjs_init.py +547 -0
  378. package/.github/skills/web-frameworks/scripts/requirements.txt +16 -0
  379. package/.github/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
  380. package/dist/config/constants.d.ts +3 -0
  381. package/dist/config/constants.d.ts.map +1 -1
  382. package/dist/config/constants.js +5 -1
  383. package/dist/config/constants.js.map +1 -1
  384. package/dist/domains/github/github-client.d.ts +5 -0
  385. package/dist/domains/github/github-client.d.ts.map +1 -1
  386. package/dist/domains/github/github-client.js +44 -0
  387. package/dist/domains/github/github-client.js.map +1 -1
  388. package/dist/utils/downloader.d.ts +3 -1
  389. package/dist/utils/downloader.d.ts.map +1 -1
  390. package/dist/utils/downloader.js +48 -11
  391. package/dist/utils/downloader.js.map +1 -1
  392. package/dist/utils/scaffolder.d.ts.map +1 -1
  393. package/dist/utils/scaffolder.js +2 -0
  394. package/dist/utils/scaffolder.js.map +1 -1
  395. package/package.json +3 -1
@@ -0,0 +1,96 @@
1
+ #!/bin/bash
2
+ # Background removal script using RMBG CLI
3
+ # Usage: ./remove-background.sh <input> [model] [output] [resolution]
4
+
5
+ set -e
6
+
7
+ # Colors for output
8
+ RED='\033[0;31m'
9
+ GREEN='\033[0;32m'
10
+ YELLOW='\033[1;33m'
11
+ NC='\033[0m' # No Color
12
+
13
+ # Default values
14
+ INPUT=""
15
+ MODEL="modnet"
16
+ OUTPUT=""
17
+ MAX_RESOLUTION="2048"
18
+
19
+ # Parse arguments
20
+ INPUT="$1"
21
+ if [ -n "$2" ]; then
22
+ MODEL="$2"
23
+ fi
24
+ if [ -n "$3" ]; then
25
+ OUTPUT="$3"
26
+ fi
27
+ if [ -n "$4" ]; then
28
+ MAX_RESOLUTION="$4"
29
+ fi
30
+
31
+ # Validate input
32
+ if [ -z "$INPUT" ]; then
33
+ echo -e "${RED}Error: Input file is required${NC}"
34
+ echo ""
35
+ echo "Usage: $0 <input> [model] [output] [resolution]"
36
+ echo ""
37
+ echo "Arguments:"
38
+ echo " input Input image file (required)"
39
+ echo " model Model name: u2netp, modnet, briaai, isnet-anime, silueta, u2net-cloth (default: modnet)"
40
+ echo " output Output file path (default: auto-generated)"
41
+ echo " resolution Max resolution in pixels (default: 2048)"
42
+ echo ""
43
+ echo "Examples:"
44
+ echo " $0 photo.jpg"
45
+ echo " $0 photo.jpg briaai"
46
+ echo " $0 photo.jpg briaai output.png"
47
+ echo " $0 photo.jpg briaai output.png 4096"
48
+ exit 1
49
+ fi
50
+
51
+ if [ ! -f "$INPUT" ]; then
52
+ echo -e "${RED}Error: Input file '$INPUT' not found${NC}"
53
+ exit 1
54
+ fi
55
+
56
+ # Check if rmbg-cli is installed
57
+ if ! command -v rmbg &> /dev/null; then
58
+ echo -e "${YELLOW}Warning: rmbg-cli not found${NC}"
59
+ echo "Installing rmbg-cli globally..."
60
+ npm install -g rmbg-cli
61
+ echo -e "${GREEN}✓ rmbg-cli installed${NC}"
62
+ fi
63
+
64
+ # Generate output filename if not provided
65
+ if [ -z "$OUTPUT" ]; then
66
+ BASENAME=$(basename "$INPUT" | sed 's/\.[^.]*$//')
67
+ OUTPUT="${BASENAME}-no-bg.png"
68
+ fi
69
+
70
+ # Display configuration
71
+ echo -e "${GREEN}Background Removal Configuration:${NC}"
72
+ echo " Input: $INPUT"
73
+ echo " Model: $MODEL"
74
+ echo " Output: $OUTPUT"
75
+ echo " Resolution: $MAX_RESOLUTION"
76
+ echo ""
77
+
78
+ # Remove background
79
+ echo "Processing..."
80
+ rmbg "$INPUT" -m "$MODEL" -o "$OUTPUT" -r "$MAX_RESOLUTION"
81
+
82
+ if [ $? -eq 0 ]; then
83
+ echo -e "${GREEN}✓ Background removed successfully${NC}"
84
+ echo " Output: $OUTPUT"
85
+
86
+ # Display file sizes
87
+ INPUT_SIZE=$(du -h "$INPUT" | cut -f1)
88
+ OUTPUT_SIZE=$(du -h "$OUTPUT" | cut -f1)
89
+ echo ""
90
+ echo "File sizes:"
91
+ echo " Input: $INPUT_SIZE"
92
+ echo " Output: $OUTPUT_SIZE"
93
+ else
94
+ echo -e "${RED}✗ Background removal failed${NC}"
95
+ exit 1
96
+ fi
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Node.js background removal script using RMBG SDK
5
+ * Usage: node remove-bg-node.js <input> [options]
6
+ */
7
+
8
+ const { rmbg, createBriaaiModel, createModnetModel, createU2netpModel } = require('rmbg')
9
+ const { readFileSync, writeFileSync, existsSync } = require('fs')
10
+ const { basename, extname } = require('path')
11
+
12
+ // Parse command line arguments
13
+ const args = process.argv.slice(2)
14
+
15
+ if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
16
+ console.log(`
17
+ Background Removal using RMBG SDK
18
+
19
+ Usage: node remove-bg-node.js <input> [options]
20
+
21
+ Arguments:
22
+ input Input image file path (required)
23
+
24
+ Options:
25
+ -o, --output <path> Output file path (default: auto-generated)
26
+ -m, --model <name> Model: briaai, modnet, u2netp (default: modnet)
27
+ -r, --resolution <n> Max resolution in pixels (default: 2048)
28
+ -p, --progress Show progress information
29
+ -h, --help Show this help message
30
+
31
+ Examples:
32
+ node remove-bg-node.js photo.jpg
33
+ node remove-bg-node.js photo.jpg -m briaai -o output.png
34
+ node remove-bg-node.js photo.jpg -r 4096 -p
35
+ `)
36
+ process.exit(0)
37
+ }
38
+
39
+ // Parse options
40
+ const input = args[0]
41
+ let output = null
42
+ let model = 'modnet'
43
+ let maxResolution = 2048
44
+ let showProgress = false
45
+
46
+ for (let i = 1; i < args.length; i++) {
47
+ const arg = args[i]
48
+ if (arg === '-o' || arg === '--output') {
49
+ output = args[++i]
50
+ } else if (arg === '-m' || arg === '--model') {
51
+ model = args[++i]
52
+ } else if (arg === '-r' || arg === '--resolution') {
53
+ maxResolution = parseInt(args[++i], 10)
54
+ } else if (arg === '-p' || arg === '--progress') {
55
+ showProgress = true
56
+ }
57
+ }
58
+
59
+ // Validate input
60
+ if (!input) {
61
+ console.error('Error: Input file is required')
62
+ process.exit(1)
63
+ }
64
+
65
+ if (!existsSync(input)) {
66
+ console.error(`Error: Input file '${input}' not found`)
67
+ process.exit(1)
68
+ }
69
+
70
+ // Generate output filename if not provided
71
+ if (!output) {
72
+ const name = basename(input, extname(input))
73
+ output = `${name}-no-bg.png`
74
+ }
75
+
76
+ // Select model
77
+ let modelInstance
78
+ switch (model.toLowerCase()) {
79
+ case 'briaai':
80
+ modelInstance = createBriaaiModel()
81
+ break
82
+ case 'u2netp':
83
+ modelInstance = createU2netpModel()
84
+ break
85
+ case 'modnet':
86
+ default:
87
+ modelInstance = createModnetModel()
88
+ break
89
+ }
90
+
91
+ // Display configuration
92
+ console.log('Background Removal Configuration:')
93
+ console.log(` Input: ${input}`)
94
+ console.log(` Model: ${model}`)
95
+ console.log(` Output: ${output}`)
96
+ console.log(` Resolution: ${maxResolution}`)
97
+ console.log('')
98
+
99
+ // Remove background
100
+ async function removeBackground() {
101
+ try {
102
+ console.log('Processing...')
103
+ const startTime = Date.now()
104
+
105
+ const options = {
106
+ model: modelInstance,
107
+ maxResolution,
108
+ output
109
+ }
110
+
111
+ if (showProgress) {
112
+ options.onProgress = (progress, download, process) => {
113
+ const percent = Math.round(progress * 100)
114
+ const downloadPercent = Math.round(download * 100)
115
+ const processPercent = Math.round(process * 100)
116
+
117
+ process.stdout.write(
118
+ `\rProgress: ${percent}% | Download: ${downloadPercent}% | Process: ${processPercent}%`
119
+ )
120
+ }
121
+ }
122
+
123
+ await rmbg(input, options)
124
+
125
+ const duration = ((Date.now() - startTime) / 1000).toFixed(2)
126
+
127
+ if (showProgress) {
128
+ console.log('') // New line after progress
129
+ }
130
+
131
+ console.log('✓ Background removed successfully')
132
+ console.log(` Output: ${output}`)
133
+ console.log(` Duration: ${duration}s`)
134
+
135
+ // Display file sizes
136
+ const inputStats = require('fs').statSync(input)
137
+ const outputStats = require('fs').statSync(output)
138
+
139
+ console.log('')
140
+ console.log('File sizes:')
141
+ console.log(` Input: ${formatBytes(inputStats.size)}`)
142
+ console.log(` Output: ${formatBytes(outputStats.size)}`)
143
+ } catch (error) {
144
+ console.error('✗ Background removal failed:', error.message)
145
+ process.exit(1)
146
+ }
147
+ }
148
+
149
+ function formatBytes(bytes) {
150
+ if (bytes === 0) return '0 Bytes'
151
+ const k = 1024
152
+ const sizes = ['Bytes', 'KB', 'MB', 'GB']
153
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
154
+ return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
155
+ }
156
+
157
+ // Run
158
+ removeBackground()
@@ -0,0 +1,24 @@
1
+ # Media Processing Skill Dependencies
2
+ # Python 3.10+ required
3
+
4
+ # No Python package dependencies - uses system binaries
5
+ # Required system tools (install separately):
6
+ # - FFmpeg (video/audio processing)
7
+ # - ImageMagick (image processing)
8
+
9
+ # Testing dependencies (dev)
10
+ pytest>=8.0.0
11
+ pytest-cov>=4.1.0
12
+ pytest-mock>=3.12.0
13
+
14
+ # Installation instructions:
15
+ #
16
+ # Ubuntu/Debian:
17
+ # sudo apt-get install ffmpeg imagemagick
18
+ #
19
+ # macOS (Homebrew):
20
+ # brew install ffmpeg imagemagick
21
+ #
22
+ # Windows:
23
+ # choco install ffmpeg imagemagick
24
+ # or download from official websites
@@ -0,0 +1,414 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Video size optimization with quality/size balance.
4
+
5
+ Supports resolution reduction, frame rate adjustment, audio bitrate optimization,
6
+ multi-pass encoding, and comparison metrics.
7
+ """
8
+
9
+ import argparse
10
+ import json
11
+ import subprocess
12
+ import sys
13
+ from dataclasses import dataclass
14
+ from pathlib import Path
15
+ from typing import Optional, Tuple
16
+
17
+
18
+ @dataclass
19
+ class VideoInfo:
20
+ """Video file information."""
21
+ path: Path
22
+ duration: float
23
+ width: int
24
+ height: int
25
+ bitrate: int
26
+ fps: float
27
+ size: int
28
+ codec: str
29
+ audio_codec: str
30
+ audio_bitrate: int
31
+
32
+
33
+ class VideoOptimizer:
34
+ """Handle video optimization operations using FFmpeg."""
35
+
36
+ def __init__(self, verbose: bool = False, dry_run: bool = False):
37
+ self.verbose = verbose
38
+ self.dry_run = dry_run
39
+
40
+ def check_ffmpeg(self) -> bool:
41
+ """Check if FFmpeg is available."""
42
+ try:
43
+ subprocess.run(
44
+ ['ffmpeg', '-version'],
45
+ stdout=subprocess.DEVNULL,
46
+ stderr=subprocess.DEVNULL,
47
+ check=True
48
+ )
49
+ return True
50
+ except (subprocess.CalledProcessError, FileNotFoundError):
51
+ return False
52
+
53
+ def get_video_info(self, input_path: Path) -> Optional[VideoInfo]:
54
+ """Extract video information using ffprobe."""
55
+ try:
56
+ cmd = [
57
+ 'ffprobe',
58
+ '-v', 'quiet',
59
+ '-print_format', 'json',
60
+ '-show_format',
61
+ '-show_streams',
62
+ str(input_path)
63
+ ]
64
+
65
+ result = subprocess.run(cmd, capture_output=True, check=True)
66
+ data = json.loads(result.stdout)
67
+
68
+ # Find video and audio streams
69
+ video_stream = None
70
+ audio_stream = None
71
+
72
+ for stream in data['streams']:
73
+ if stream['codec_type'] == 'video' and not video_stream:
74
+ video_stream = stream
75
+ elif stream['codec_type'] == 'audio' and not audio_stream:
76
+ audio_stream = stream
77
+
78
+ if not video_stream:
79
+ return None
80
+
81
+ # Parse frame rate
82
+ fps_parts = video_stream.get('r_frame_rate', '0/1').split('/')
83
+ fps = float(fps_parts[0]) / float(fps_parts[1]) if len(fps_parts) == 2 else 0
84
+
85
+ return VideoInfo(
86
+ path=input_path,
87
+ duration=float(data['format'].get('duration', 0)),
88
+ width=int(video_stream.get('width', 0)),
89
+ height=int(video_stream.get('height', 0)),
90
+ bitrate=int(data['format'].get('bit_rate', 0)),
91
+ fps=fps,
92
+ size=int(data['format'].get('size', 0)),
93
+ codec=video_stream.get('codec_name', 'unknown'),
94
+ audio_codec=audio_stream.get('codec_name', 'none') if audio_stream else 'none',
95
+ audio_bitrate=int(audio_stream.get('bit_rate', 0)) if audio_stream else 0
96
+ )
97
+
98
+ except Exception as e:
99
+ print(f"Error getting video info: {e}", file=sys.stderr)
100
+ return None
101
+
102
+ def calculate_target_resolution(
103
+ self,
104
+ width: int,
105
+ height: int,
106
+ max_width: Optional[int],
107
+ max_height: Optional[int]
108
+ ) -> Tuple[int, int]:
109
+ """Calculate target resolution maintaining aspect ratio."""
110
+ if not max_width and not max_height:
111
+ return width, height
112
+
113
+ aspect_ratio = width / height
114
+
115
+ if max_width and max_height:
116
+ # Fit within both constraints
117
+ if width > max_width or height > max_height:
118
+ if width / max_width > height / max_height:
119
+ new_width = max_width
120
+ new_height = int(max_width / aspect_ratio)
121
+ else:
122
+ new_height = max_height
123
+ new_width = int(max_height * aspect_ratio)
124
+ else:
125
+ new_width, new_height = width, height
126
+ elif max_width:
127
+ new_width = min(width, max_width)
128
+ new_height = int(new_width / aspect_ratio)
129
+ else:
130
+ new_height = min(height, max_height)
131
+ new_width = int(new_height * aspect_ratio)
132
+
133
+ # Ensure dimensions are even (required by some codecs)
134
+ new_width = new_width - (new_width % 2)
135
+ new_height = new_height - (new_height % 2)
136
+
137
+ return new_width, new_height
138
+
139
+ def optimize_video(
140
+ self,
141
+ input_path: Path,
142
+ output_path: Path,
143
+ max_width: Optional[int] = None,
144
+ max_height: Optional[int] = None,
145
+ target_fps: Optional[float] = None,
146
+ crf: int = 23,
147
+ audio_bitrate: str = '128k',
148
+ preset: str = 'medium',
149
+ two_pass: bool = False
150
+ ) -> bool:
151
+ """Optimize a video file."""
152
+ # Get input video info
153
+ info = self.get_video_info(input_path)
154
+ if not info:
155
+ print(f"Error: Could not read video info for {input_path}", file=sys.stderr)
156
+ return False
157
+
158
+ if self.verbose:
159
+ print(f"\nInput video info:")
160
+ print(f" Resolution: {info.width}x{info.height}")
161
+ print(f" FPS: {info.fps:.2f}")
162
+ print(f" Bitrate: {info.bitrate // 1000} kbps")
163
+ print(f" Size: {info.size / (1024*1024):.2f} MB")
164
+
165
+ # Calculate target resolution
166
+ target_width, target_height = self.calculate_target_resolution(
167
+ info.width, info.height, max_width, max_height
168
+ )
169
+
170
+ # Build FFmpeg command
171
+ cmd = ['ffmpeg', '-i', str(input_path)]
172
+
173
+ # Video filters
174
+ filters = []
175
+ if target_width != info.width or target_height != info.height:
176
+ filters.append(f'scale={target_width}:{target_height}')
177
+
178
+ if filters:
179
+ cmd.extend(['-vf', ','.join(filters)])
180
+
181
+ # Frame rate adjustment
182
+ if target_fps and target_fps < info.fps:
183
+ cmd.extend(['-r', str(target_fps)])
184
+
185
+ # Video encoding
186
+ if two_pass:
187
+ # Two-pass encoding for better quality
188
+ target_bitrate = int(info.bitrate * 0.7) # 30% reduction
189
+
190
+ # Pass 1
191
+ pass1_cmd = cmd + [
192
+ '-c:v', 'libx264',
193
+ '-preset', preset,
194
+ '-b:v', str(target_bitrate),
195
+ '-pass', '1',
196
+ '-an',
197
+ '-f', 'null',
198
+ '/dev/null' if sys.platform != 'win32' else 'NUL'
199
+ ]
200
+
201
+ if self.verbose or self.dry_run:
202
+ print(f"Pass 1: {' '.join(pass1_cmd)}")
203
+
204
+ if not self.dry_run:
205
+ try:
206
+ subprocess.run(pass1_cmd, check=True, capture_output=not self.verbose)
207
+ except subprocess.CalledProcessError as e:
208
+ print(f"Error in pass 1: {e}", file=sys.stderr)
209
+ return False
210
+
211
+ # Pass 2
212
+ cmd.extend([
213
+ '-c:v', 'libx264',
214
+ '-preset', preset,
215
+ '-b:v', str(target_bitrate),
216
+ '-pass', '2'
217
+ ])
218
+ else:
219
+ # Single-pass CRF encoding
220
+ cmd.extend([
221
+ '-c:v', 'libx264',
222
+ '-preset', preset,
223
+ '-crf', str(crf)
224
+ ])
225
+
226
+ # Audio encoding
227
+ cmd.extend([
228
+ '-c:a', 'aac',
229
+ '-b:a', audio_bitrate
230
+ ])
231
+
232
+ # Output
233
+ cmd.extend(['-movflags', '+faststart', '-y', str(output_path)])
234
+
235
+ if self.verbose or self.dry_run:
236
+ print(f"Command: {' '.join(cmd)}")
237
+
238
+ if self.dry_run:
239
+ return True
240
+
241
+ # Execute
242
+ try:
243
+ subprocess.run(cmd, check=True, capture_output=not self.verbose)
244
+
245
+ # Get output info
246
+ output_info = self.get_video_info(output_path)
247
+ if output_info and self.verbose:
248
+ print(f"\nOutput video info:")
249
+ print(f" Resolution: {output_info.width}x{output_info.height}")
250
+ print(f" FPS: {output_info.fps:.2f}")
251
+ print(f" Bitrate: {output_info.bitrate // 1000} kbps")
252
+ print(f" Size: {output_info.size / (1024*1024):.2f} MB")
253
+ reduction = (1 - output_info.size / info.size) * 100
254
+ print(f" Size reduction: {reduction:.1f}%")
255
+
256
+ return True
257
+
258
+ except subprocess.CalledProcessError as e:
259
+ print(f"Error optimizing video: {e}", file=sys.stderr)
260
+ return False
261
+ except Exception as e:
262
+ print(f"Error optimizing video: {e}", file=sys.stderr)
263
+ return False
264
+ finally:
265
+ # Clean up two-pass log files
266
+ if two_pass and not self.dry_run:
267
+ for log_file in Path('.').glob('ffmpeg2pass-*.log*'):
268
+ log_file.unlink(missing_ok=True)
269
+
270
+ def compare_videos(self, original: Path, optimized: Path) -> None:
271
+ """Compare original and optimized videos."""
272
+ orig_info = self.get_video_info(original)
273
+ opt_info = self.get_video_info(optimized)
274
+
275
+ if not orig_info or not opt_info:
276
+ print("Error: Could not compare videos", file=sys.stderr)
277
+ return
278
+
279
+ print(f"\n{'Metric':<20} {'Original':<20} {'Optimized':<20} {'Change':<15}")
280
+ print("-" * 75)
281
+
282
+ # Resolution
283
+ orig_res = f"{orig_info.width}x{orig_info.height}"
284
+ opt_res = f"{opt_info.width}x{opt_info.height}"
285
+ print(f"{'Resolution':<20} {orig_res:<20} {opt_res:<20}")
286
+
287
+ # FPS
288
+ fps_change = opt_info.fps - orig_info.fps
289
+ print(f"{'FPS':<20} {orig_info.fps:<20.2f} {opt_info.fps:<20.2f} {fps_change:+.2f}")
290
+
291
+ # Bitrate
292
+ orig_br = f"{orig_info.bitrate // 1000} kbps"
293
+ opt_br = f"{opt_info.bitrate // 1000} kbps"
294
+ br_change = ((opt_info.bitrate / orig_info.bitrate) - 1) * 100
295
+ print(f"{'Bitrate':<20} {orig_br:<20} {opt_br:<20} {br_change:+.1f}%")
296
+
297
+ # Size
298
+ orig_size = f"{orig_info.size / (1024*1024):.2f} MB"
299
+ opt_size = f"{opt_info.size / (1024*1024):.2f} MB"
300
+ size_reduction = (1 - opt_info.size / orig_info.size) * 100
301
+ print(f"{'Size':<20} {orig_size:<20} {opt_size:<20} {-size_reduction:.1f}%")
302
+
303
+
304
+ def main():
305
+ """Main entry point."""
306
+ parser = argparse.ArgumentParser(
307
+ description='Video size optimization with quality/size balance.'
308
+ )
309
+ parser.add_argument(
310
+ 'input',
311
+ type=Path,
312
+ help='Input video file'
313
+ )
314
+ parser.add_argument(
315
+ '-o', '--output',
316
+ type=Path,
317
+ required=True,
318
+ help='Output video file'
319
+ )
320
+ parser.add_argument(
321
+ '-w', '--max-width',
322
+ type=int,
323
+ help='Maximum width in pixels'
324
+ )
325
+ parser.add_argument(
326
+ '-H', '--max-height',
327
+ type=int,
328
+ help='Maximum height in pixels'
329
+ )
330
+ parser.add_argument(
331
+ '--fps',
332
+ type=float,
333
+ help='Target frame rate'
334
+ )
335
+ parser.add_argument(
336
+ '--crf',
337
+ type=int,
338
+ default=23,
339
+ help='CRF quality (18-28, lower=better, default: 23)'
340
+ )
341
+ parser.add_argument(
342
+ '--audio-bitrate',
343
+ default='128k',
344
+ help='Audio bitrate (default: 128k)'
345
+ )
346
+ parser.add_argument(
347
+ '--preset',
348
+ choices=['ultrafast', 'superfast', 'veryfast', 'faster', 'fast',
349
+ 'medium', 'slow', 'slower', 'veryslow'],
350
+ default='medium',
351
+ help='Encoding preset (default: medium)'
352
+ )
353
+ parser.add_argument(
354
+ '--two-pass',
355
+ action='store_true',
356
+ help='Use two-pass encoding (better quality)'
357
+ )
358
+ parser.add_argument(
359
+ '--compare',
360
+ action='store_true',
361
+ help='Compare original and optimized videos'
362
+ )
363
+ parser.add_argument(
364
+ '-n', '--dry-run',
365
+ action='store_true',
366
+ help='Show command without executing'
367
+ )
368
+ parser.add_argument(
369
+ '-v', '--verbose',
370
+ action='store_true',
371
+ help='Verbose output'
372
+ )
373
+
374
+ args = parser.parse_args()
375
+
376
+ # Validate input
377
+ if not args.input.exists():
378
+ print(f"Error: Input file not found: {args.input}", file=sys.stderr)
379
+ sys.exit(1)
380
+
381
+ # Initialize optimizer
382
+ optimizer = VideoOptimizer(verbose=args.verbose, dry_run=args.dry_run)
383
+
384
+ # Check dependencies
385
+ if not optimizer.check_ffmpeg():
386
+ print("Error: FFmpeg not found", file=sys.stderr)
387
+ sys.exit(1)
388
+
389
+ # Optimize video
390
+ print(f"Optimizing {args.input.name}...")
391
+ success = optimizer.optimize_video(
392
+ args.input,
393
+ args.output,
394
+ args.max_width,
395
+ args.max_height,
396
+ args.fps,
397
+ args.crf,
398
+ args.audio_bitrate,
399
+ args.preset,
400
+ args.two_pass
401
+ )
402
+
403
+ if not success:
404
+ sys.exit(1)
405
+
406
+ # Compare if requested
407
+ if args.compare and not args.dry_run:
408
+ optimizer.compare_videos(args.input, args.output)
409
+
410
+ print(f"\nOptimized video saved to: {args.output}")
411
+
412
+
413
+ if __name__ == '__main__':
414
+ main()