@codingfactory/mediables-vue 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. package/dist/PixiFrameExporter-BTU38EVl.cjs +2 -0
  2. package/dist/PixiFrameExporter-BTU38EVl.cjs.map +1 -0
  3. package/dist/PixiFrameExporter-Bb3QNWP-.js +199 -0
  4. package/dist/PixiFrameExporter-Bb3QNWP-.js.map +1 -0
  5. package/dist/adapters/MediablesAdapter.d.ts +19 -0
  6. package/dist/adapters/SpatieAdapter.d.ts +18 -0
  7. package/dist/adapters/index.d.ts +18 -0
  8. package/dist/components/AdminMediaBrowser.vue.d.ts +11 -0
  9. package/dist/components/AdminMediaBrowserExample.vue.d.ts +2 -0
  10. package/dist/components/AdminMediaBulkActionsToolbar.vue.d.ts +2 -0
  11. package/dist/components/AdminMediaGrid.vue.d.ts +17 -0
  12. package/dist/components/AdminMediaListItem.vue.d.ts +10 -0
  13. package/dist/components/AdminMediaManager.vue.d.ts +25 -0
  14. package/dist/components/AdminMediaUploader.vue.d.ts +11 -0
  15. package/dist/components/AlbumBrowser.vue.d.ts +17 -0
  16. package/dist/components/AlbumManager.vue.d.ts +16 -0
  17. package/dist/components/AlbumMediaGrid.vue.d.ts +28 -0
  18. package/dist/components/AlbumTree.vue.d.ts +35 -0
  19. package/dist/components/BulkActionsToolbar.vue.d.ts +2 -0
  20. package/dist/components/ConversionProgressIndicator.vue.d.ts +2 -0
  21. package/dist/components/Editor.vue.d.ts +29 -0
  22. package/dist/components/ExampleGridAndList.vue.d.ts +2 -0
  23. package/dist/components/ExampleUsage.vue.d.ts +2 -0
  24. package/dist/components/Grid.vue.d.ts +2 -0
  25. package/dist/components/ImageEditor/ImageEditor.vue.d.ts +3 -0
  26. package/dist/components/ImageEditorModal.vue.d.ts +16 -0
  27. package/dist/components/ImagePicker.vue.d.ts +32 -0
  28. package/dist/components/ImageUploadZone.vue.d.ts +7 -0
  29. package/dist/components/Item.vue.d.ts +2 -0
  30. package/dist/components/Library.vue.d.ts +2 -0
  31. package/dist/components/ManagedMediaGallery.vue.d.ts +12 -0
  32. package/dist/components/MediaAttacher.vue.d.ts +21 -0
  33. package/dist/components/MediaBrowser.vue.d.ts +2 -0
  34. package/dist/components/MediaCard.vue.d.ts +2 -0
  35. package/dist/components/MediaFilters.vue.d.ts +2 -0
  36. package/dist/components/MediaGrid.vue.d.ts +31 -0
  37. package/dist/components/MediaInfoEditor.vue.d.ts +7 -0
  38. package/dist/components/MediaManager.vue.d.ts +2 -0
  39. package/dist/components/MediaUploadWithProgress.vue.d.ts +2 -0
  40. package/dist/components/MediaUploader.vue.d.ts +2 -0
  41. package/dist/components/MediaWorkspace.vue.d.ts +19 -0
  42. package/dist/components/Modal.vue.d.ts +2 -0
  43. package/dist/components/ModelMediaManager.vue.d.ts +80 -0
  44. package/dist/components/Pagination.vue.d.ts +2 -0
  45. package/dist/components/Search.vue.d.ts +2 -0
  46. package/dist/components/VideoEditorSimple.vue.d.ts +2 -0
  47. package/dist/components/VideoExportPanel.vue.d.ts +2 -0
  48. package/dist/components/VideoTimeline.vue.d.ts +2 -0
  49. package/dist/components/VideoTimelineSimple.vue.d.ts +2 -0
  50. package/dist/components/VideoToolsPanel.vue.d.ts +2 -0
  51. package/dist/components/albums/AlbumTreeNode.vue.d.ts +23 -0
  52. package/dist/components/attachment/MediaAttachment.vue.d.ts +23 -0
  53. package/dist/components/attachment/index.d.ts +4 -0
  54. package/dist/components/collection/MediaCollection.vue.d.ts +27 -0
  55. package/dist/components/collection/MediaCollectionDropzone.vue.d.ts +18 -0
  56. package/dist/components/collection/MediaCollectionItem.vue.d.ts +2 -0
  57. package/dist/components/collection/index.d.ts +6 -0
  58. package/dist/components/form/MediaHiddenFields.vue.d.ts +2 -0
  59. package/dist/components/form/index.d.ts +4 -0
  60. package/dist/components/image/ImageEditor.vue.d.ts +2 -0
  61. package/dist/components/image/ImageItem.vue.d.ts +2 -0
  62. package/dist/components/renderless/MediaAttachmentProvider.vue.d.ts +12 -0
  63. package/dist/components/renderless/MediaCollectionProvider.vue.d.ts +12 -0
  64. package/dist/components/renderless/index.d.ts +7 -0
  65. package/dist/components/timeline/TimeRuler.vue.d.ts +2 -0
  66. package/dist/components/timeline/VideoTrack.vue.d.ts +2 -0
  67. package/dist/components/tools/VideoFiltersPanel.vue.d.ts +7 -0
  68. package/dist/components/tools/VideoTextPanel.vue.d.ts +2 -0
  69. package/dist/components/video/AudioTrackManager.vue.d.ts +2 -0
  70. package/dist/components/video/EditorControls.vue.d.ts +2 -0
  71. package/dist/components/video/ExportPanel.vue.d.ts +2 -0
  72. package/dist/components/video/FilterSelector.vue.d.ts +2 -0
  73. package/dist/components/video/LiveStreamManager.vue.d.ts +2 -0
  74. package/dist/components/video/StreamCredentials.vue.d.ts +2 -0
  75. package/dist/components/video/StreamStatus.vue.d.ts +2 -0
  76. package/dist/components/video/TextOverlayPanel.vue.d.ts +2 -0
  77. package/dist/components/video/ThumbnailPicker.vue.d.ts +2 -0
  78. package/dist/components/video/TimelineClip.vue.d.ts +2 -0
  79. package/dist/components/video/TimelineControls.vue.d.ts +2 -0
  80. package/dist/components/video/TransitionSelector.vue.d.ts +2 -0
  81. package/dist/components/video/VideoControls.vue.d.ts +2 -0
  82. package/dist/components/video/VideoEditor.vue.d.ts +8 -0
  83. package/dist/components/video/VideoEditorDialog.vue.d.ts +12 -0
  84. package/dist/components/video/VideoFilterCarousel.vue.d.ts +2 -0
  85. package/dist/components/video/VideoFilterPreview.vue.d.ts +18 -0
  86. package/dist/components/video/VideoPlayer.vue.d.ts +2 -0
  87. package/dist/components/video/VideoPreview.vue.d.ts +3 -0
  88. package/dist/components/video/VideoPreviewCSS.vue.d.ts +2 -0
  89. package/dist/components/video/VideoPreviewEngine.vue.d.ts +3 -0
  90. package/dist/components/video/VideoTimeline.vue.d.ts +2 -0
  91. package/dist/components/video/VideoUploadProgress.vue.d.ts +2 -0
  92. package/dist/components/video/VideoUploader.vue.d.ts +29 -0
  93. package/dist/components/video/index.d.ts +19 -0
  94. package/dist/composables/useAccordion.d.ts +138 -0
  95. package/dist/composables/useAlbumDragDrop.d.ts +24 -0
  96. package/dist/composables/useAlbums.d.ts +17 -0
  97. package/dist/composables/useFloatingPills.d.ts +111 -0
  98. package/dist/composables/useHaptic.d.ts +10 -0
  99. package/dist/composables/useImageEditorModal.d.ts +277 -0
  100. package/dist/composables/useLiveStream.d.ts +66 -0
  101. package/dist/composables/useMediaAttachment.d.ts +105 -0
  102. package/dist/composables/useMediaCollection.d.ts +122 -0
  103. package/dist/composables/useMediaConversionProgress.d.ts +31 -0
  104. package/dist/composables/useMediaDragSort.d.ts +56 -0
  105. package/dist/composables/useMediaSelection.d.ts +27 -0
  106. package/dist/composables/useMediaUploadQueue.d.ts +61 -0
  107. package/dist/composables/useMediaValidation.d.ts +59 -0
  108. package/dist/composables/useRadialMenu.d.ts +116 -0
  109. package/dist/composables/useSanctumClient.d.ts +31 -0
  110. package/dist/composables/useTheme.d.ts +7 -0
  111. package/dist/composables/useToast.d.ts +25 -0
  112. package/dist/composables/useVideoEditor.d.ts +127 -0
  113. package/dist/composables/useVideoFilters.d.ts +176 -0
  114. package/dist/composables/useVideoPlayer.d.ts +50 -0
  115. package/dist/composables/useVideoUpload.d.ts +134 -0
  116. package/dist/filters/controlMapping.d.ts +31 -0
  117. package/dist/filters/css-registry.d.ts +83 -0
  118. package/dist/filters/definitions/adjustment.d.ts +2 -0
  119. package/dist/filters/definitions/adjustmentAdvanced.d.ts +2 -0
  120. package/dist/filters/definitions/advancedBloom.d.ts +2 -0
  121. package/dist/filters/definitions/alpha.d.ts +2 -0
  122. package/dist/filters/definitions/ascii.d.ts +2 -0
  123. package/dist/filters/definitions/backdropBlur.d.ts +2 -0
  124. package/dist/filters/definitions/bevel.d.ts +2 -0
  125. package/dist/filters/definitions/bloom.d.ts +2 -0
  126. package/dist/filters/definitions/blur.d.ts +2 -0
  127. package/dist/filters/definitions/bulgePinch.d.ts +2 -0
  128. package/dist/filters/definitions/colorGradient.d.ts +2 -0
  129. package/dist/filters/definitions/colorMap.d.ts +2 -0
  130. package/dist/filters/definitions/colorMatrix.d.ts +2 -0
  131. package/dist/filters/definitions/colorOverlay.d.ts +2 -0
  132. package/dist/filters/definitions/colorReplace.d.ts +2 -0
  133. package/dist/filters/definitions/convolution.d.ts +2 -0
  134. package/dist/filters/definitions/crossHatch.d.ts +2 -0
  135. package/dist/filters/definitions/crt.d.ts +2 -0
  136. package/dist/filters/definitions/displacement.d.ts +2 -0
  137. package/dist/filters/definitions/dot.d.ts +2 -0
  138. package/dist/filters/definitions/dropShadow.d.ts +2 -0
  139. package/dist/filters/definitions/emboss.d.ts +2 -0
  140. package/dist/filters/definitions/glitch.d.ts +2 -0
  141. package/dist/filters/definitions/glow.d.ts +2 -0
  142. package/dist/filters/definitions/godray.d.ts +2 -0
  143. package/dist/filters/definitions/grayscale.d.ts +2 -0
  144. package/dist/filters/definitions/hslAdjustment.d.ts +2 -0
  145. package/dist/filters/definitions/kawaseBlur.d.ts +2 -0
  146. package/dist/filters/definitions/lightmap.d.ts +2 -0
  147. package/dist/filters/definitions/motionBlur.d.ts +2 -0
  148. package/dist/filters/definitions/multiColorReplace.d.ts +2 -0
  149. package/dist/filters/definitions/noise.d.ts +2 -0
  150. package/dist/filters/definitions/oldFilm.d.ts +2 -0
  151. package/dist/filters/definitions/outline.d.ts +2 -0
  152. package/dist/filters/definitions/pixelate.d.ts +2 -0
  153. package/dist/filters/definitions/radialBlur.d.ts +2 -0
  154. package/dist/filters/definitions/reflection.d.ts +2 -0
  155. package/dist/filters/definitions/rgbSplit.d.ts +2 -0
  156. package/dist/filters/definitions/shockwave.d.ts +2 -0
  157. package/dist/filters/definitions/simplexNoise.d.ts +2 -0
  158. package/dist/filters/definitions/tiltShift.d.ts +2 -0
  159. package/dist/filters/definitions/twist.d.ts +2 -0
  160. package/dist/filters/definitions/vignette.d.ts +2 -0
  161. package/dist/filters/definitions/zoomBlur.d.ts +2 -0
  162. package/dist/filters/factory.d.ts +38 -0
  163. package/dist/filters/filters/controlMapping.d.ts +31 -0
  164. package/dist/filters/filters/definitions/adjustment.d.ts +2 -0
  165. package/dist/filters/filters/definitions/adjustmentAdvanced.d.ts +2 -0
  166. package/dist/filters/filters/definitions/advancedBloom.d.ts +2 -0
  167. package/dist/filters/filters/definitions/alpha.d.ts +2 -0
  168. package/dist/filters/filters/definitions/ascii.d.ts +2 -0
  169. package/dist/filters/filters/definitions/backdropBlur.d.ts +2 -0
  170. package/dist/filters/filters/definitions/bevel.d.ts +2 -0
  171. package/dist/filters/filters/definitions/bloom.d.ts +2 -0
  172. package/dist/filters/filters/definitions/blur.d.ts +2 -0
  173. package/dist/filters/filters/definitions/bulgePinch.d.ts +2 -0
  174. package/dist/filters/filters/definitions/colorGradient.d.ts +2 -0
  175. package/dist/filters/filters/definitions/colorMap.d.ts +2 -0
  176. package/dist/filters/filters/definitions/colorMatrix.d.ts +2 -0
  177. package/dist/filters/filters/definitions/colorOverlay.d.ts +2 -0
  178. package/dist/filters/filters/definitions/colorReplace.d.ts +2 -0
  179. package/dist/filters/filters/definitions/convolution.d.ts +2 -0
  180. package/dist/filters/filters/definitions/crossHatch.d.ts +2 -0
  181. package/dist/filters/filters/definitions/crt.d.ts +2 -0
  182. package/dist/filters/filters/definitions/displacement.d.ts +2 -0
  183. package/dist/filters/filters/definitions/dot.d.ts +2 -0
  184. package/dist/filters/filters/definitions/dropShadow.d.ts +2 -0
  185. package/dist/filters/filters/definitions/emboss.d.ts +2 -0
  186. package/dist/filters/filters/definitions/glitch.d.ts +2 -0
  187. package/dist/filters/filters/definitions/glow.d.ts +2 -0
  188. package/dist/filters/filters/definitions/godray.d.ts +2 -0
  189. package/dist/filters/filters/definitions/grayscale.d.ts +2 -0
  190. package/dist/filters/filters/definitions/hslAdjustment.d.ts +2 -0
  191. package/dist/filters/filters/definitions/kawaseBlur.d.ts +2 -0
  192. package/dist/filters/filters/definitions/lightmap.d.ts +2 -0
  193. package/dist/filters/filters/definitions/motionBlur.d.ts +2 -0
  194. package/dist/filters/filters/definitions/multiColorReplace.d.ts +2 -0
  195. package/dist/filters/filters/definitions/noise.d.ts +2 -0
  196. package/dist/filters/filters/definitions/oldFilm.d.ts +2 -0
  197. package/dist/filters/filters/definitions/outline.d.ts +2 -0
  198. package/dist/filters/filters/definitions/pixelate.d.ts +2 -0
  199. package/dist/filters/filters/definitions/radialBlur.d.ts +2 -0
  200. package/dist/filters/filters/definitions/reflection.d.ts +2 -0
  201. package/dist/filters/filters/definitions/rgbSplit.d.ts +2 -0
  202. package/dist/filters/filters/definitions/shockwave.d.ts +2 -0
  203. package/dist/filters/filters/definitions/simplexNoise.d.ts +2 -0
  204. package/dist/filters/filters/definitions/tiltShift.d.ts +2 -0
  205. package/dist/filters/filters/definitions/twist.d.ts +2 -0
  206. package/dist/filters/filters/definitions/vignette.d.ts +2 -0
  207. package/dist/filters/filters/definitions/zoomBlur.d.ts +2 -0
  208. package/dist/filters/filters/factory.d.ts +36 -0
  209. package/dist/filters/filters/index.d.ts +93 -0
  210. package/dist/filters/filters/registry.d.ts +89 -0
  211. package/dist/filters/index.d.ts +93 -0
  212. package/dist/filters/registry.d.ts +89 -0
  213. package/dist/filters/video-compatible.d.ts +77 -0
  214. package/dist/filters/video-css-filters.d.ts +153 -0
  215. package/dist/index-6yUGA--H.cjs +42 -0
  216. package/dist/index-6yUGA--H.cjs.map +1 -0
  217. package/dist/index-CcGWfCCV.js +7799 -0
  218. package/dist/index-CcGWfCCV.js.map +1 -0
  219. package/dist/index-DTUgsw7J.cjs +76 -0
  220. package/dist/index-DTUgsw7J.cjs.map +1 -0
  221. package/dist/index-VrUG0lmk.js +28655 -0
  222. package/dist/index-VrUG0lmk.js.map +1 -0
  223. package/dist/index.d.ts +62 -0
  224. package/dist/js/workers/material-color-extractor.js +215 -0
  225. package/dist/mediables-vanilla.cjs +2 -0
  226. package/dist/mediables-vanilla.cjs.map +1 -0
  227. package/dist/mediables-vanilla.mjs +12 -0
  228. package/dist/mediables-vanilla.mjs.map +1 -0
  229. package/dist/mediables-vue.cjs +2 -0
  230. package/dist/mediables-vue.cjs.map +1 -0
  231. package/dist/mediables-vue.mjs +67 -0
  232. package/dist/mediables-vue.mjs.map +1 -0
  233. package/dist/render-page/assets/index-hBfvGPpt.js +48933 -0
  234. package/dist/render-page/index.html +18 -0
  235. package/dist/services/VideoJobClient.d.ts +79 -0
  236. package/dist/stores/albumStore.d.ts +4 -0
  237. package/dist/stores/mediaVariantStore.d.ts +1 -0
  238. package/dist/stores/useAdminMediaStore.d.ts +16 -0
  239. package/dist/stores/useMediaStore.d.ts +25 -0
  240. package/dist/stores/useVideoStore.d.ts +21 -0
  241. package/dist/stores/variantPollStore.d.ts +5 -0
  242. package/dist/stores/video.d.ts +1 -0
  243. package/dist/style.css +1 -0
  244. package/dist/types/adapter.d.ts +181 -0
  245. package/dist/types/album.d.ts +28 -0
  246. package/dist/types/api.d.ts +88 -0
  247. package/dist/types/collection.d.ts +306 -0
  248. package/dist/types/editor.d.ts +172 -0
  249. package/dist/types/image.d.ts +210 -0
  250. package/dist/types/index.d.ts +5 -0
  251. package/dist/types/media.d.ts +107 -0
  252. package/dist/types/types/address.d.ts +66 -0
  253. package/dist/types/types/admin/intelligent-po.d.ts +47 -0
  254. package/dist/types/types/admin/products/index.d.ts +17 -0
  255. package/dist/types/types/admin/purchase-order.d.ts +50 -0
  256. package/dist/types/types/admin/receipt.d.ts +86 -0
  257. package/dist/types/types/admin/vendor.d.ts +61 -0
  258. package/dist/types/types/ai.d.ts +63 -0
  259. package/dist/types/types/aiActions.d.ts +42 -0
  260. package/dist/types/types/aiDesigner.d.ts +77 -0
  261. package/dist/types/types/api-errors.d.ts +6 -0
  262. package/dist/types/types/api.d.ts +109 -0
  263. package/dist/types/types/bundle.d.ts +131 -0
  264. package/dist/types/types/bundles/analytics.d.ts +64 -0
  265. package/dist/types/types/bundles.d.ts +108 -0
  266. package/dist/types/types/cart.d.ts +81 -0
  267. package/dist/types/types/checkout.d.ts +40 -0
  268. package/dist/types/types/component-config.d.ts +26 -0
  269. package/dist/types/types/components.d.ts +32 -0
  270. package/dist/types/types/content.d.ts +138 -0
  271. package/dist/types/types/coupon.d.ts +32 -0
  272. package/dist/types/types/customer-product-history.d.ts +210 -0
  273. package/dist/types/types/drag-contracts.d.ts +40 -0
  274. package/dist/types/types/drag-drop.d.ts +19 -0
  275. package/dist/types/types/editor.d.ts +127 -0
  276. package/dist/types/types/errors.d.ts +36 -0
  277. package/dist/types/types/feedback.d.ts +122 -0
  278. package/dist/types/types/image.d.ts +210 -0
  279. package/dist/types/types/index.d.ts +62 -0
  280. package/dist/types/types/instagram.d.ts +86 -0
  281. package/dist/types/types/ionic-components.d.ts +152 -0
  282. package/dist/types/types/layout.d.ts +127 -0
  283. package/dist/types/types/media-gateway.d.ts +34 -0
  284. package/dist/types/types/media.d.ts +178 -0
  285. package/dist/types/types/notifications.d.ts +123 -0
  286. package/dist/types/types/order-management.d.ts +245 -0
  287. package/dist/types/types/pageBuilder/block.d.ts +34 -0
  288. package/dist/types/types/pageBuilder/blocks.d.ts +82 -0
  289. package/dist/types/types/pageBuilder/cache.d.ts +33 -0
  290. package/dist/types/types/pageBuilder/editor.d.ts +15 -0
  291. package/dist/types/types/pageBuilder/field.d.ts +11 -0
  292. package/dist/types/types/pageBuilder/index.d.ts +24 -0
  293. package/dist/types/types/pageBuilder/revisions.d.ts +40 -0
  294. package/dist/types/types/pageBuilder/templates.d.ts +62 -0
  295. package/dist/types/types/pattern.d.ts +40 -0
  296. package/dist/types/types/payment.d.ts +21 -0
  297. package/dist/types/types/payments.d.ts +10 -0
  298. package/dist/types/types/pipeline.d.ts +12 -0
  299. package/dist/types/types/pixi/filter-args.d.ts +274 -0
  300. package/dist/types/types/pixi/filters-extended.d.ts +157 -0
  301. package/dist/types/types/pixi/filters.d.ts +38 -0
  302. package/dist/types/types/preview.d.ts +36 -0
  303. package/dist/types/types/pricing.d.ts +31 -0
  304. package/dist/types/types/quickbooks.d.ts +43 -0
  305. package/dist/types/types/receipt.d.ts +121 -0
  306. package/dist/types/types/rewards.d.ts +110 -0
  307. package/dist/types/types/saved-cart.d.ts +51 -0
  308. package/dist/types/types/settings.d.ts +63 -0
  309. package/dist/types/types/shipment.d.ts +62 -0
  310. package/dist/types/types/shipping.d.ts +98 -0
  311. package/dist/types/types/sidebar-variations.d.ts +226 -0
  312. package/dist/types/types/slots.d.ts +2 -0
  313. package/dist/types/types/specification-types.d.ts +70 -0
  314. package/dist/types/types/specifications.d.ts +163 -0
  315. package/dist/types/types/store.d.ts +64 -0
  316. package/dist/types/types/template.d.ts +8 -0
  317. package/dist/types/types/user.d.ts +47 -0
  318. package/dist/types/types/variant-groups.d.ts +158 -0
  319. package/dist/types/types/wishlist.d.ts +73 -0
  320. package/dist/types/types/workflow-wizard.d.ts +12 -0
  321. package/dist/types/video.d.ts +449 -0
  322. package/dist/utils/category-tree-constants.d.ts +42 -0
  323. package/dist/utils/cookies.d.ts +3 -0
  324. package/dist/utils/crypto-polyfill.d.ts +4 -0
  325. package/dist/utils/datetime.d.ts +43 -0
  326. package/dist/utils/debounce.d.ts +10 -0
  327. package/dist/utils/debugConsole.d.ts +69 -0
  328. package/dist/utils/editor/argHelpers.d.ts +6 -0
  329. package/dist/utils/formatters.d.ts +105 -0
  330. package/dist/utils/isPresignedAwsUrl.d.ts +67 -0
  331. package/dist/utils/media-helpers.d.ts +34 -0
  332. package/dist/utils/normalisePricing.d.ts +11 -0
  333. package/dist/utils/recipe-generator.d.ts +34 -0
  334. package/dist/utils/string.d.ts +29 -0
  335. package/dist/utils/unwrapApiResponse.d.ts +5 -0
  336. package/dist/utils/uuid.d.ts +30 -0
  337. package/dist/utils/validators.d.ts +28 -0
  338. package/dist/utils/video-export.d.ts +60 -0
  339. package/dist/v3-ionic-1-demo.html +440 -0
  340. package/dist/video-engine/VideoEngine.d.ts +267 -0
  341. package/dist/video-engine/adapters/AudioManager.d.ts +106 -0
  342. package/dist/video-engine/adapters/CSSFilterAdapter.d.ts +106 -0
  343. package/dist/video-engine/adapters/ExportManager.d.ts +88 -0
  344. package/dist/video-engine/adapters/FilterBridge.d.ts +96 -0
  345. package/dist/video-engine/adapters/MediablesCompositionAdapter.d.ts +56 -0
  346. package/dist/video-engine/adapters/PixiFrameExporter.d.ts +52 -0
  347. package/dist/video-engine/adapters/RenderQueue.d.ts +119 -0
  348. package/dist/video-engine/adapters/TextOverlayManager.d.ts +93 -0
  349. package/dist/video-engine/adapters/TimelineAdapter.d.ts +58 -0
  350. package/dist/video-engine/adapters/TransitionManager.d.ts +76 -0
  351. package/dist/video-engine/adapters/WebCodecsExport.d.ts +36 -0
  352. package/dist/video-engine/compositions/examples/example.d.ts +2 -0
  353. package/dist/video-engine/filters/CSSFilterSystem.d.ts +213 -0
  354. package/dist/video-engine/index.d.ts +14 -0
  355. package/dist/video-engine/presets/ExportPresets.d.ts +70 -0
  356. package/dist/video-engine/types/index.d.ts +96 -0
  357. package/dist/video-engine/types.d.ts +1 -0
  358. package/dist/video-engine/utils/EventEmitter.d.ts +12 -0
  359. package/dist/video-engine/utils/MediaSourceResolver.d.ts +9 -0
  360. package/dist/video-engine/utils/error-reporter.d.ts +159 -0
  361. package/dist/video-engine/utils/keyboard-shortcuts.d.ts +120 -0
  362. package/dist/video-engine/utils/pixi-video-fallback.d.ts +2 -0
  363. package/docs/video-subsystem/README.md +490 -0
  364. package/docs/video-subsystem/api-reference.md +747 -0
  365. package/docs/video-subsystem/component-examples.md +1477 -0
  366. package/docs/video-subsystem/integration-guide.md +1021 -0
  367. package/package.json +102 -0
@@ -0,0 +1,1021 @@
1
+ # Video Subsystem Integration Guide
2
+
3
+ This guide provides step-by-step instructions for integrating the Mediables video subsystem into your Laravel application.
4
+
5
+ ## Table of Contents
6
+ 1. [Prerequisites](#prerequisites)
7
+ 2. [Installation](#installation)
8
+ 3. [Backend Setup](#backend-setup)
9
+ 4. [Frontend Integration](#frontend-integration)
10
+ 5. [Provider Configuration](#provider-configuration)
11
+ 6. [Queue Configuration](#queue-configuration)
12
+ 7. [Testing](#testing)
13
+ 8. [Production Deployment](#production-deployment)
14
+
15
+ ## Prerequisites
16
+
17
+ ### System Requirements
18
+ - PHP 8.1 or higher
19
+ - Laravel 11.x or 12.x
20
+ - PostgreSQL 13+ (with UUID support)
21
+ - Redis for queues
22
+ - FFmpeg 4.4+ (for video processing)
23
+ - Node.js 18+ and npm 9+
24
+
25
+ ### Required PHP Extensions
26
+ - `ext-gd` or `ext-imagick`
27
+ - `ext-redis`
28
+ - `ext-pcntl` (for queue workers)
29
+ - `ext-exif` (for media metadata)
30
+
31
+ ### FFmpeg Installation
32
+
33
+ **macOS**:
34
+ ```bash
35
+ brew install ffmpeg
36
+ ```
37
+
38
+ **Ubuntu/Debian**:
39
+ ```bash
40
+ sudo apt update
41
+ sudo apt install ffmpeg
42
+ ```
43
+
44
+ **CentOS/RHEL**:
45
+ ```bash
46
+ sudo yum install epel-release
47
+ sudo yum install ffmpeg
48
+ ```
49
+
50
+ Verify installation:
51
+ ```bash
52
+ ffmpeg -version
53
+ ```
54
+
55
+ ## Installation
56
+
57
+ ### Step 1: Install Package
58
+
59
+ ```bash
60
+ # Install via Composer
61
+ composer require mediables/mediables:^2.0
62
+
63
+ # Install Vue components
64
+ npm install @mediables/vue@^2.0
65
+ ```
66
+
67
+ ### Step 2: Publish Configuration
68
+
69
+ ```bash
70
+ # Publish config file
71
+ php artisan vendor:publish --provider="Mediables\MediablesServiceProvider" --tag="config"
72
+
73
+ # Publish migrations
74
+ php artisan vendor:publish --provider="Mediables\MediablesServiceProvider" --tag="migrations"
75
+ ```
76
+
77
+ ### Step 3: Run Migrations
78
+
79
+ ```bash
80
+ # Run the migrations
81
+ php artisan migrate
82
+ ```
83
+
84
+ ## Backend Setup
85
+
86
+ ### Step 1: Configure Bunny Provider (Built-In)
87
+
88
+ The Mediables package ships with a Bunny video provider. No custom provider class is required.
89
+
90
+ Add the following to your `.env`:
91
+
92
+ ```env
93
+ VIDEO_PROVIDER=bunny
94
+ BUNNY_VIDEO_API_KEY=your-api-key
95
+ BUNNY_VIDEO_LIBRARY_ID=your-library-id
96
+ BUNNY_VIDEO_CDN_HOSTNAME=your-cdn.b-cdn.net
97
+ BUNNY_VIDEO_WEBHOOK_SECRET=your-secret
98
+ ```
99
+
100
+ ### Step 2: (Optional) Override the Provider Binding
101
+
102
+ If you want to override the provider binding (e.g. for a custom provider), bind `Mediables\Contracts\VideoProviderInterface` in your application:
103
+
104
+ ```php
105
+ use Mediables\Contracts\VideoProviderInterface;
106
+ use Mediables\Services\Video\BunnyVideoProvider;
107
+
108
+ $this->app->singleton(VideoProviderInterface::class, function () {
109
+ return new BunnyVideoProvider();
110
+ });
111
+ ```
112
+
113
+ ### Step 3: Create API Controllers
114
+
115
+ Create `app/Http/Controllers/Api/V1/VideoUploadController.php`:
116
+
117
+ ```php
118
+ <?php
119
+
120
+ namespace App\Http\Controllers\Api\V1;
121
+
122
+ use App\Http\Controllers\Controller;
123
+ use App\Http\Requests\VideoUploadRequest;
124
+ use App\Services\Video\Contracts\VideoProviderInterface;
125
+ use Mediables\Facades\MediaService;
126
+ use Illuminate\Http\JsonResponse;
127
+
128
+ class VideoUploadController extends Controller
129
+ {
130
+ public function __construct(
131
+ private VideoProviderInterface $provider
132
+ ) {}
133
+
134
+ public function createUpload(VideoUploadRequest $request): JsonResponse
135
+ {
136
+ // Create pending media record
137
+ $media = MediaService::createFromRequest($request, [
138
+ 'collection' => $request->input('collection', 'videos'),
139
+ 'disk' => 'videos',
140
+ 'status' => 'pending',
141
+ 'meta' => [
142
+ 'original_name' => $request->input('filename'),
143
+ 'mime_type' => $request->input('mime_type'),
144
+ 'size' => $request->input('size')
145
+ ]
146
+ ]);
147
+
148
+ // Get upload URL from provider
149
+ $upload = $this->provider->createUploadUrl([
150
+ 'metadata' => [
151
+ 'media_uuid' => $media->uuid
152
+ ]
153
+ ]);
154
+
155
+ // Update media with upload info
156
+ $media->update([
157
+ 'upload_id' => $upload->uploadId,
158
+ 'upload_expires_at' => $upload->expiresAt
159
+ ]);
160
+
161
+ return response()->json([
162
+ 'upload_url' => $upload->uploadUrl,
163
+ 'upload_id' => $upload->uploadId,
164
+ 'media_uuid' => $media->uuid,
165
+ 'expires_at' => $upload->expiresAt->toIso8601String()
166
+ ], 201);
167
+ }
168
+
169
+ public function completeUpload(string $uuid): JsonResponse
170
+ {
171
+ $media = MediaService::findByUuid($uuid);
172
+
173
+ if (!$media) {
174
+ return response()->json(['error' => 'Media not found'], 404);
175
+ }
176
+
177
+ // Mark as processing
178
+ $media->update(['status' => 'processing']);
179
+
180
+ // Dispatch job to check processing status
181
+ ProcessVideoAsset::dispatch($media)->delay(now()->addSeconds(10));
182
+
183
+ return response()->json([
184
+ 'message' => 'Upload completed, processing started',
185
+ 'media' => $media
186
+ ]);
187
+ }
188
+ }
189
+ ```
190
+
191
+ ### Step 4: Create Webhook Handler
192
+
193
+ The Mediables package includes a built-in Bunny webhook endpoint:
194
+
195
+ - **Endpoint**: `POST /api/v1/video/webhooks/bunny`
196
+ - **Security**: `?secret=...` query parameter (recommended) or `X-Webhook-Signature` header (deployment-specific)
197
+
198
+ No additional controller is required unless you want custom behavior.
199
+
200
+ ### Step 5: Create Form Requests
201
+
202
+ Create `app/Http/Requests/VideoUploadRequest.php`:
203
+
204
+ ```php
205
+ <?php
206
+
207
+ namespace App\Http\Requests;
208
+
209
+ use Illuminate\Foundation\Http\FormRequest;
210
+
211
+ class VideoUploadRequest extends FormRequest
212
+ {
213
+ public function authorize(): bool
214
+ {
215
+ return true; // Add your authorization logic
216
+ }
217
+
218
+ public function rules(): array
219
+ {
220
+ return [
221
+ 'filename' => 'required|string|max:255',
222
+ 'size' => 'required|integer|min:1|max:5368709120', // 5GB max
223
+ 'mime_type' => 'required|string|in:video/mp4,video/quicktime,video/x-msvideo,video/x-matroska,video/webm',
224
+ 'collection' => 'nullable|string|max:50'
225
+ ];
226
+ }
227
+
228
+ public function messages(): array
229
+ {
230
+ return [
231
+ 'size.max' => 'Video file must not exceed 5GB',
232
+ 'mime_type.in' => 'Unsupported video format. Supported formats: MP4, MOV, AVI, MKV, WebM'
233
+ ];
234
+ }
235
+ }
236
+ ```
237
+
238
+ ## Frontend Integration
239
+
240
+ ### Step 1: Configure Vue Application
241
+
242
+ Update your Vue app's main file:
243
+
244
+ ```javascript
245
+ // main.js or main.ts
246
+ import { createApp } from 'vue'
247
+ import { createPinia } from 'pinia'
248
+ import { IonicVue } from '@ionic/vue'
249
+ import App from './App.vue'
250
+
251
+ // Import Mediables styles
252
+ import '@mediables/vue/dist/style.css'
253
+
254
+ const app = createApp(App)
255
+ const pinia = createPinia()
256
+
257
+ app.use(IonicVue)
258
+ app.use(pinia)
259
+
260
+ // Configure Mediables
261
+ import { configureMediables } from '@mediables/vue'
262
+
263
+ configureMediables({
264
+ apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:8000',
265
+ apiPrefix: '/api/v1',
266
+ storage: {
267
+ driver: 's3',
268
+ bucket: import.meta.env.VITE_S3_BUCKET,
269
+ region: import.meta.env.VITE_S3_REGION
270
+ },
271
+ video: {
272
+ provider: 'bunny',
273
+ maxUploadSize: 5 * 1024 * 1024 * 1024, // 5GB
274
+ allowedFormats: ['video/mp4', 'video/quicktime', 'video/webm'],
275
+ thumbnailQualities: ['poster', '2s', '5s', '10s']
276
+ }
277
+ })
278
+
279
+ app.mount('#app')
280
+ ```
281
+
282
+ ### Step 2: Create Video Upload Page
283
+
284
+ ```vue
285
+ <template>
286
+ <PageShell>
287
+ <template #header>
288
+ <IonHeader>
289
+ <IonToolbar>
290
+ <IonTitle>Upload Video</IonTitle>
291
+ </IonToolbar>
292
+ </IonHeader>
293
+ </template>
294
+
295
+ <div class="p-4">
296
+ <VideoUploader
297
+ :collection="'user-videos'"
298
+ :max-size="5 * 1024 * 1024 * 1024"
299
+ @uploaded="handleVideoUploaded"
300
+ @error="handleUploadError"
301
+ >
302
+ <template #trigger>
303
+ <IonButton expand="block" fill="outline">
304
+ <IonIcon :icon="videocamOutline" slot="start" />
305
+ Select Video
306
+ </IonButton>
307
+ </template>
308
+ </VideoUploader>
309
+
310
+ <div v-if="uploadedVideos.length > 0" class="mt-6">
311
+ <h3 class="text-lg font-semibold mb-4">Uploaded Videos</h3>
312
+
313
+ <div class="space-y-4">
314
+ <VideoCard
315
+ v-for="video in uploadedVideos"
316
+ :key="video.uuid"
317
+ :media="video"
318
+ @play="playVideo(video)"
319
+ @edit="editVideo(video)"
320
+ />
321
+ </div>
322
+ </div>
323
+ </div>
324
+ </PageShell>
325
+ </template>
326
+
327
+ <script setup lang="ts">
328
+ import { ref } from 'vue'
329
+ import { useRouter } from 'vue-router'
330
+ import {
331
+ IonHeader,
332
+ IonToolbar,
333
+ IonTitle,
334
+ IonButton,
335
+ IonIcon,
336
+ useIonToast
337
+ } from '@ionic/vue'
338
+ import { videocamOutline } from 'ionicons/icons'
339
+ import { VideoUploader, VideoCard } from '@mediables/vue'
340
+ import PageShell from '@/components/layout/PageShell.vue'
341
+
342
+ const router = useRouter()
343
+ const [presentToast] = useIonToast()
344
+ const uploadedVideos = ref([])
345
+
346
+ async function handleVideoUploaded(media) {
347
+ uploadedVideos.value.unshift(media)
348
+
349
+ await presentToast({
350
+ message: 'Video uploaded successfully!',
351
+ duration: 3000,
352
+ color: 'success'
353
+ })
354
+ }
355
+
356
+ async function handleUploadError(error) {
357
+ await presentToast({
358
+ message: error.message || 'Upload failed',
359
+ duration: 5000,
360
+ color: 'danger'
361
+ })
362
+ }
363
+
364
+ function playVideo(video) {
365
+ router.push(`/video/${video.uuid}/play`)
366
+ }
367
+
368
+ function editVideo(video) {
369
+ router.push(`/video/${video.uuid}/edit`)
370
+ }
371
+ </script>
372
+ ```
373
+
374
+ ### Step 3: Create Video Player Page
375
+
376
+ ```vue
377
+ <template>
378
+ <PageShell :use-content-wrapper="false">
379
+ <template #header>
380
+ <IonHeader>
381
+ <IonToolbar>
382
+ <IonButtons slot="start">
383
+ <IonBackButton />
384
+ </IonButtons>
385
+ <IonTitle>{{ media?.title || 'Video Player' }}</IonTitle>
386
+ </IonToolbar>
387
+ </IonHeader>
388
+ </template>
389
+
390
+ <div class="video-player-container">
391
+ <VideoPlayer
392
+ v-if="media"
393
+ :media="media"
394
+ :controls="true"
395
+ :autoplay="false"
396
+ @play="handlePlay"
397
+ @ended="handleEnded"
398
+ />
399
+
400
+ <div class="p-4">
401
+ <h2 class="text-xl font-semibold">{{ media?.title }}</h2>
402
+ <p class="text-gray-600 mt-2">{{ media?.description }}</p>
403
+
404
+ <div class="flex items-center gap-4 mt-4">
405
+ <span class="text-sm text-gray-500">
406
+ Duration: {{ formatDuration(media?.duration) }}
407
+ </span>
408
+ <span class="text-sm text-gray-500">
409
+ Size: {{ formatSize(media?.size) }}
410
+ </span>
411
+ </div>
412
+ </div>
413
+ </div>
414
+ </PageShell>
415
+ </template>
416
+
417
+ <script setup lang="ts">
418
+ import { ref, onMounted } from 'vue'
419
+ import { useRoute } from 'vue-router'
420
+ import {
421
+ IonHeader,
422
+ IonToolbar,
423
+ IonTitle,
424
+ IonButtons,
425
+ IonBackButton
426
+ } from '@ionic/vue'
427
+ import { VideoPlayer } from '@mediables/vue'
428
+ import PageShell from '@/components/layout/PageShell.vue'
429
+ import { useMediaStore } from '@/stores/media'
430
+
431
+ const route = useRoute()
432
+ const mediaStore = useMediaStore()
433
+ const media = ref(null)
434
+
435
+ onMounted(async () => {
436
+ const uuid = route.params.uuid
437
+ media.value = await mediaStore.fetchMedia(uuid)
438
+ })
439
+
440
+ function handlePlay() {
441
+ console.log('Video started playing')
442
+ }
443
+
444
+ function handleEnded() {
445
+ console.log('Video playback ended')
446
+ }
447
+
448
+ function formatDuration(seconds) {
449
+ if (!seconds) return 'N/A'
450
+ const mins = Math.floor(seconds / 60)
451
+ const secs = Math.floor(seconds % 60)
452
+ return `${mins}:${secs.toString().padStart(2, '0')}`
453
+ }
454
+
455
+ function formatSize(bytes) {
456
+ if (!bytes) return 'N/A'
457
+ const mb = bytes / (1024 * 1024)
458
+ return `${mb.toFixed(2)} MB`
459
+ }
460
+ </script>
461
+ ```
462
+
463
+ ### Step 4: Create Video Editor Page
464
+
465
+ ```vue
466
+ <template>
467
+ <PageShell :use-content-wrapper="false">
468
+ <VideoEditor
469
+ v-if="media"
470
+ :media-uuid="media.uuid"
471
+ @export="handleExport"
472
+ @save-draft="handleSaveDraft"
473
+ />
474
+
475
+ <IonLoading
476
+ :is-open="exporting"
477
+ message="Processing video..."
478
+ />
479
+ </PageShell>
480
+ </template>
481
+
482
+ <script setup lang="ts">
483
+ import { ref, onMounted } from 'vue'
484
+ import { useRoute, useRouter } from 'vue-router'
485
+ import { IonLoading, useIonToast } from '@ionic/vue'
486
+ import { VideoEditor } from '@mediables/vue'
487
+ import PageShell from '@/components/layout/PageShell.vue'
488
+ import { useMediaStore } from '@/stores/media'
489
+ import api from '@/services/api'
490
+
491
+ const route = useRoute()
492
+ const router = useRouter()
493
+ const [presentToast] = useIonToast()
494
+ const mediaStore = useMediaStore()
495
+
496
+ const media = ref(null)
497
+ const exporting = ref(false)
498
+
499
+ onMounted(async () => {
500
+ const uuid = route.params.uuid
501
+ media.value = await mediaStore.fetchMedia(uuid)
502
+ })
503
+
504
+ async function handleExport(recipe) {
505
+ exporting.value = true
506
+
507
+ try {
508
+ const response = await api.post(`/video/${media.value.uuid}/export`, {
509
+ recipe
510
+ })
511
+
512
+ await presentToast({
513
+ message: 'Export started! We\'ll notify you when it\'s ready.',
514
+ duration: 5000,
515
+ color: 'success'
516
+ })
517
+
518
+ // Navigate to export status page
519
+ router.push(`/video/export/${response.data.job_id}`)
520
+
521
+ } catch (error) {
522
+ await presentToast({
523
+ message: 'Export failed. Please try again.',
524
+ duration: 5000,
525
+ color: 'danger'
526
+ })
527
+ } finally {
528
+ exporting.value = false
529
+ }
530
+ }
531
+
532
+ async function handleSaveDraft(recipe) {
533
+ try {
534
+ await api.post(`/video/${media.value.uuid}/draft`, { recipe })
535
+
536
+ await presentToast({
537
+ message: 'Draft saved successfully',
538
+ duration: 3000,
539
+ color: 'success'
540
+ })
541
+ } catch (error) {
542
+ console.error('Failed to save draft:', error)
543
+ }
544
+ }
545
+ </script>
546
+ ```
547
+
548
+ ## Provider Configuration
549
+
550
+ ### Bunny Configuration
551
+
552
+ 1. **Create a Bunny Stream Video Library**:
553
+ - Get your `Video Library ID`
554
+ - Generate an API key
555
+
556
+ 2. **Configure webhooks**:
557
+ - Endpoint: `https://yourdomain.com/api/v1/video/webhooks/bunny?secret=your-secret`
558
+
559
+ 3. **RTMP ingest**:
560
+ - `rtmp://ingest.bunny.live/{stream-key}`
561
+
562
+ 4. **Environment variables**:
563
+ ```env
564
+ VIDEO_PROVIDER=bunny
565
+ BUNNY_VIDEO_API_KEY=your-api-key
566
+ BUNNY_VIDEO_LIBRARY_ID=your-library-id
567
+ BUNNY_VIDEO_CDN_HOSTNAME=your-cdn.b-cdn.net
568
+ BUNNY_VIDEO_WEBHOOK_SECRET=your-secret
569
+ ```
570
+
571
+ ### CloudFlare Stream Configuration
572
+
573
+ For CloudFlare Stream support, create a CloudFlareVideoProvider:
574
+
575
+ ```php
576
+ class CloudFlareVideoProvider implements VideoProviderInterface
577
+ {
578
+ // Implementation for CloudFlare Stream API
579
+ }
580
+ ```
581
+
582
+ ## Queue Configuration
583
+
584
+ ### Configure Queue Workers
585
+
586
+ Update `config/queue.php`:
587
+
588
+ ```php
589
+ 'connections' => [
590
+ 'redis' => [
591
+ 'driver' => 'redis',
592
+ 'connection' => 'default',
593
+ 'queue' => env('REDIS_QUEUE', 'default'),
594
+ 'retry_after' => 90,
595
+ 'block_for' => null,
596
+ 'after_commit' => false,
597
+ ],
598
+
599
+ 'video-processing' => [
600
+ 'driver' => 'redis',
601
+ 'connection' => 'default',
602
+ 'queue' => 'video-processing',
603
+ 'retry_after' => 7200, // 2 hours for long videos
604
+ 'block_for' => null,
605
+ 'after_commit' => false,
606
+ ],
607
+ ],
608
+ ```
609
+
610
+ ### Create Queue Jobs
611
+
612
+ Create `app/Jobs/ProcessVideoExport.php`:
613
+
614
+ ```php
615
+ <?php
616
+
617
+ namespace App\Jobs;
618
+
619
+ use Illuminate\Bus\Queueable;
620
+ use Illuminate\Contracts\Queue\ShouldQueue;
621
+ use Illuminate\Foundation\Bus\Dispatchable;
622
+ use Illuminate\Queue\InteractsWithQueue;
623
+ use Illuminate\Queue\SerializesModels;
624
+ use Mediables\Models\Media;
625
+ use FFMpeg\FFMpeg;
626
+ use FFMpeg\Format\Video\X264;
627
+
628
+ class ProcessVideoExport implements ShouldQueue
629
+ {
630
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
631
+
632
+ public $timeout = 7200; // 2 hours
633
+ public $tries = 3;
634
+
635
+ public function __construct(
636
+ public Media $media,
637
+ public array $recipe,
638
+ public string $jobId
639
+ ) {}
640
+
641
+ public function handle(): void
642
+ {
643
+ $ffmpeg = FFMpeg::create([
644
+ 'ffmpeg.binaries' => config('mediables.ffmpeg_path', '/usr/bin/ffmpeg'),
645
+ 'ffprobe.binaries' => config('mediables.ffprobe_path', '/usr/bin/ffprobe'),
646
+ 'timeout' => 3600,
647
+ 'ffmpeg.threads' => 12,
648
+ ]);
649
+
650
+ // Download source video
651
+ $sourcePath = $this->downloadSourceVideo();
652
+
653
+ // Open video
654
+ $video = $ffmpeg->open($sourcePath);
655
+
656
+ // Apply timeline edits
657
+ foreach ($this->recipe['timeline'] as $clip) {
658
+ $video->clip(
659
+ \FFMpeg\Coordinate\TimeCode::fromSeconds($clip['source_in']),
660
+ \FFMpeg\Coordinate\TimeCode::fromSeconds($clip['source_out'] - $clip['source_in'])
661
+ );
662
+ }
663
+
664
+ // Apply filters
665
+ foreach ($this->recipe['filters'] as $filter) {
666
+ $video->addFilter(new \FFMpeg\Filters\Video\CustomFilter($filter['ffmpeg']));
667
+ }
668
+
669
+ // Configure output format
670
+ $format = new X264();
671
+ $format->setKiloBitrate(4000)
672
+ ->setAudioCodec('aac')
673
+ ->setAudioKiloBitrate(128);
674
+
675
+ // Add progress listener
676
+ $format->on('progress', function ($video, $format, $percentage) {
677
+ $this->updateProgress($percentage);
678
+ });
679
+
680
+ // Export
681
+ $outputPath = storage_path("app/exports/{$this->jobId}.mp4");
682
+ $video->save($format, $outputPath);
683
+
684
+ // Upload to provider
685
+ $this->uploadToProvider($outputPath);
686
+
687
+ // Clean up
688
+ @unlink($sourcePath);
689
+ @unlink($outputPath);
690
+
691
+ // Update media status
692
+ $this->media->update([
693
+ 'export_status' => 'completed',
694
+ 'export_completed_at' => now()
695
+ ]);
696
+
697
+ // Fire event
698
+ event(new VideoExportCompleted($this->media, $this->jobId));
699
+ }
700
+
701
+ private function updateProgress(int $percentage): void
702
+ {
703
+ cache()->put("export:{$this->jobId}:progress", $percentage, 3600);
704
+ }
705
+ }
706
+ ```
707
+
708
+ ### Run Queue Workers
709
+
710
+ ```bash
711
+ # Development
712
+ php artisan queue:work --queue=video-processing
713
+
714
+ # Production with Supervisor
715
+ [program:video-worker]
716
+ process_name=%(program_name)s_%(process_num)02d
717
+ command=php /path/to/artisan queue:work redis --queue=video-processing --sleep=3 --tries=3 --max-time=3600
718
+ autostart=true
719
+ autorestart=true
720
+ stopasgroup=true
721
+ killasgroup=true
722
+ user=www-data
723
+ numprocs=4
724
+ redirect_stderr=true
725
+ stdout_logfile=/path/to/logs/video-worker.log
726
+ ```
727
+
728
+ ## Testing
729
+
730
+ ### Backend Testing
731
+
732
+ Create `tests/Feature/VideoUploadTest.php`:
733
+
734
+ ```php
735
+ <?php
736
+
737
+ namespace Tests\Feature;
738
+
739
+ use Tests\TestCase;
740
+ use Illuminate\Foundation\Testing\RefreshDatabase;
741
+ use App\Models\User;
742
+ use Mediables\Models\Media;
743
+
744
+ class VideoUploadTest extends TestCase
745
+ {
746
+ use RefreshDatabase;
747
+
748
+ public function test_can_request_upload_url(): void
749
+ {
750
+ $user = User::factory()->create();
751
+
752
+ $response = $this->actingAs($user)
753
+ ->postJson('/api/v1/video/upload', [
754
+ 'filename' => 'test-video.mp4',
755
+ 'size' => 1048576,
756
+ 'mime_type' => 'video/mp4',
757
+ 'collection' => 'videos'
758
+ ]);
759
+
760
+ $response->assertStatus(201)
761
+ ->assertJsonStructure([
762
+ 'upload_url',
763
+ 'upload_id',
764
+ 'media_uuid',
765
+ 'expires_at'
766
+ ]);
767
+
768
+ $this->assertDatabaseHas('media', [
769
+ 'uuid' => $response->json('media_uuid'),
770
+ 'status' => 'pending',
771
+ 'collection' => 'videos'
772
+ ]);
773
+ }
774
+
775
+ public function test_webhook_updates_media_status(): void
776
+ {
777
+ config()->set('mediables.video.bunny.webhook_secret', 'test-secret');
778
+
779
+ $media = Media::factory()->create([
780
+ 'provider' => 'bunny',
781
+ 'provider_asset_id' => 'video-guid-123',
782
+ 'status' => 'processing',
783
+ ]);
784
+
785
+ $payload = [
786
+ 'VideoLibraryId' => 12345,
787
+ 'VideoGuid' => 'video-guid-123',
788
+ 'Status' => 3,
789
+ ];
790
+
791
+ $response = $this->postJson('/api/v1/video/webhooks/bunny?secret=test-secret', $payload);
792
+
793
+ $response->assertOk();
794
+ }
795
+ }
796
+ ```
797
+
798
+ ### Frontend Testing
799
+
800
+ Create `tests/components/VideoUploader.spec.ts`:
801
+
802
+ ```typescript
803
+ import { describe, it, expect, vi } from 'vitest'
804
+ import { mount } from '@vue/test-utils'
805
+ import { VideoUploader } from '@mediables/vue'
806
+ import axios from 'axios'
807
+
808
+ vi.mock('axios')
809
+
810
+ describe('VideoUploader', () => {
811
+ it('requests upload URL on file selection', async () => {
812
+ const mockUploadResponse = {
813
+ data: {
814
+ upload_url: 'https://video.bunnycdn.com/library/test-library-id/videos/video-guid-123',
815
+ upload_id: 'upload-123',
816
+ media_uuid: 'media-456',
817
+ expires_at: new Date().toISOString()
818
+ }
819
+ }
820
+
821
+ axios.post.mockResolvedValueOnce(mockUploadResponse)
822
+
823
+ const wrapper = mount(VideoUploader, {
824
+ props: {
825
+ collection: 'videos'
826
+ }
827
+ })
828
+
829
+ // Simulate file selection
830
+ const file = new File(['video content'], 'test.mp4', { type: 'video/mp4' })
831
+ const input = wrapper.find('input[type="file"]')
832
+
833
+ Object.defineProperty(input.element, 'files', {
834
+ value: [file],
835
+ writable: false
836
+ })
837
+
838
+ await input.trigger('change')
839
+
840
+ expect(axios.post).toHaveBeenCalledWith('/api/v1/video/upload', {
841
+ filename: 'test.mp4',
842
+ size: file.size,
843
+ mime_type: 'video/mp4',
844
+ collection: 'videos'
845
+ })
846
+ })
847
+
848
+ it('shows upload progress', async () => {
849
+ const wrapper = mount(VideoUploader)
850
+
851
+ // Start upload
852
+ wrapper.vm.startUpload({
853
+ file: new File(['content'], 'test.mp4'),
854
+ uploadUrl: 'https://video.bunnycdn.com/library/test-library-id/videos/video-guid-123'
855
+ })
856
+
857
+ // Simulate progress
858
+ wrapper.vm.updateProgress(50)
859
+
860
+ await wrapper.vm.$nextTick()
861
+
862
+ expect(wrapper.find('.upload-progress').exists()).toBe(true)
863
+ expect(wrapper.text()).toContain('50%')
864
+ })
865
+ })
866
+ ```
867
+
868
+ ## Production Deployment
869
+
870
+ ### Server Requirements
871
+
872
+ - **CPU**: 4+ cores for video processing
873
+ - **RAM**: 8GB minimum, 16GB recommended
874
+ - **Storage**: SSD with sufficient space for temporary files
875
+ - **Network**: 100Mbps+ for video uploads/downloads
876
+
877
+ ### Deployment Checklist
878
+
879
+ 1. **Environment Configuration**:
880
+ ```bash
881
+ # Set production environment
882
+ APP_ENV=production
883
+ APP_DEBUG=false
884
+
885
+ # Configure queues
886
+ QUEUE_CONNECTION=redis
887
+ REDIS_HOST=your-redis-host
888
+
889
+ # Video provider settings
890
+ VIDEO_PROVIDER=bunny
891
+ BUNNY_VIDEO_API_KEY=production-api-key
892
+ BUNNY_VIDEO_LIBRARY_ID=production-library-id
893
+ BUNNY_VIDEO_CDN_HOSTNAME=production-cdn.b-cdn.net
894
+ BUNNY_VIDEO_WEBHOOK_SECRET=production-secret
895
+ ```
896
+
897
+ 2. **Optimize Application**:
898
+ ```bash
899
+ php artisan config:cache
900
+ php artisan route:cache
901
+ php artisan view:cache
902
+ php artisan event:cache
903
+ composer install --no-dev --optimize-autoloader
904
+ ```
905
+
906
+ 3. **Frontend Build**:
907
+ ```bash
908
+ npm run build
909
+ ```
910
+
911
+ 4. **Database Optimization**:
912
+ ```sql
913
+ -- Add indexes for video queries
914
+ CREATE INDEX idx_media_video_queries ON media(provider, processing_status, created_at);
915
+ CREATE INDEX idx_live_streams_active ON live_streams(status) WHERE status IN ('idle', 'live');
916
+ ```
917
+
918
+ 5. **Queue Worker Configuration**:
919
+ - Use Supervisor or systemd for process management
920
+ - Configure multiple workers for video processing
921
+ - Set appropriate memory limits
922
+
923
+ 6. **Monitoring**:
924
+ - Set up error tracking (Sentry, Bugsnag)
925
+ - Monitor queue lengths
926
+ - Track video processing times
927
+ - Alert on webhook failures
928
+
929
+ 7. **CDN Configuration**:
930
+ - Configure CDN for video thumbnail delivery
931
+ - Set appropriate cache headers
932
+ - Enable CORS for video playback
933
+
934
+ 8. **Security**:
935
+ - Enable rate limiting on upload endpoints
936
+ - Validate webhook signatures
937
+ - Use HTTPS everywhere
938
+ - Implement CSP headers
939
+
940
+ ### Performance Tuning
941
+
942
+ 1. **PHP Configuration**:
943
+ ```ini
944
+ ; php.ini
945
+ upload_max_filesize = 5G
946
+ post_max_size = 5G
947
+ max_execution_time = 0
948
+ memory_limit = 2G
949
+ ```
950
+
951
+ 2. **Nginx Configuration**:
952
+ ```nginx
953
+ # nginx.conf
954
+ client_max_body_size 5G;
955
+ client_body_timeout 3600;
956
+ proxy_read_timeout 3600;
957
+ proxy_connect_timeout 3600;
958
+ proxy_send_timeout 3600;
959
+ ```
960
+
961
+ 3. **Redis Configuration**:
962
+ ```conf
963
+ # redis.conf
964
+ maxmemory 2gb
965
+ maxmemory-policy allkeys-lru
966
+ ```
967
+
968
+ ## Troubleshooting Guide
969
+
970
+ ### Common Issues and Solutions
971
+
972
+ **Issue**: Upload fails with CORS error
973
+ ```javascript
974
+ // Solution: Configure CORS in Laravel
975
+ // config/cors.php
976
+ 'paths' => ['api/*'],
977
+ 'allowed_origins' => ['https://yourdomain.com'],
978
+ 'allowed_methods' => ['*'],
979
+ 'allowed_headers' => ['*'],
980
+ ```
981
+
982
+ **Issue**: Video processing never completes
983
+ ```bash
984
+ # Check queue workers
985
+ php artisan queue:failed
986
+
987
+ # Retry failed jobs
988
+ php artisan queue:retry all
989
+
990
+ # Check FFmpeg installation
991
+ ffmpeg -version
992
+ ```
993
+
994
+ **Issue**: Playback token expires during viewing
995
+ ```javascript
996
+ // Solution: Implement token refresh
997
+ const refreshInterval = setInterval(() => {
998
+ if (shouldRefreshToken()) {
999
+ refreshPlaybackToken()
1000
+ }
1001
+ }, 30000) // Check every 30 seconds
1002
+ ```
1003
+
1004
+ **Issue**: Memory exhausted during export
1005
+ ```php
1006
+ // Solution: Increase memory limit for export jobs
1007
+ public $timeout = 7200;
1008
+ public $memory = 2048; // MB
1009
+
1010
+ // Or in job handle method
1011
+ ini_set('memory_limit', '2G');
1012
+ ```
1013
+
1014
+ ## Support
1015
+
1016
+ For additional help:
1017
+
1018
+ - **Documentation**: https://mediables.dev/docs/video
1019
+ - **GitHub Issues**: https://github.com/mediables/mediables/issues
1020
+ - **Discord Community**: https://discord.gg/mediables
1021
+ - **Email Support**: video-support@mediables.dev