@prestyj/editor 0.7.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.
- package/LICENSE +21 -0
- package/README.md +457 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +278 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/ass.d.ts +75 -0
- package/dist/core/ass.d.ts.map +1 -0
- package/dist/core/ass.js +128 -0
- package/dist/core/ass.js.map +1 -0
- package/dist/core/ass.test.d.ts +2 -0
- package/dist/core/ass.test.d.ts.map +1 -0
- package/dist/core/ass.test.js +112 -0
- package/dist/core/ass.test.js.map +1 -0
- package/dist/core/audio-cleanup.d.ts +16 -0
- package/dist/core/audio-cleanup.d.ts.map +1 -0
- package/dist/core/audio-cleanup.js +79 -0
- package/dist/core/audio-cleanup.js.map +1 -0
- package/dist/core/audio-cleanup.test.d.ts +2 -0
- package/dist/core/audio-cleanup.test.d.ts.map +1 -0
- package/dist/core/audio-cleanup.test.js +41 -0
- package/dist/core/audio-cleanup.test.js.map +1 -0
- package/dist/core/audio-mix.d.ts +89 -0
- package/dist/core/audio-mix.d.ts.map +1 -0
- package/dist/core/audio-mix.js +163 -0
- package/dist/core/audio-mix.js.map +1 -0
- package/dist/core/audio-mix.test.d.ts +2 -0
- package/dist/core/audio-mix.test.d.ts.map +1 -0
- package/dist/core/audio-mix.test.js +91 -0
- package/dist/core/audio-mix.test.js.map +1 -0
- package/dist/core/auth/api-keys.d.ts +18 -0
- package/dist/core/auth/api-keys.d.ts.map +1 -0
- package/dist/core/auth/api-keys.js +73 -0
- package/dist/core/auth/api-keys.js.map +1 -0
- package/dist/core/auth/index.d.ts +20 -0
- package/dist/core/auth/index.d.ts.map +1 -0
- package/dist/core/auth/index.js +18 -0
- package/dist/core/auth/index.js.map +1 -0
- package/dist/core/auth/login.d.ts +13 -0
- package/dist/core/auth/login.d.ts.map +1 -0
- package/dist/core/auth/login.js +176 -0
- package/dist/core/auth/login.js.map +1 -0
- package/dist/core/auth/types.d.ts +22 -0
- package/dist/core/auth/types.d.ts.map +1 -0
- package/dist/core/auth/types.js +12 -0
- package/dist/core/auth/types.js.map +1 -0
- package/dist/core/beats.d.ts +59 -0
- package/dist/core/beats.d.ts.map +1 -0
- package/dist/core/beats.js +122 -0
- package/dist/core/beats.js.map +1 -0
- package/dist/core/beats.test.d.ts +2 -0
- package/dist/core/beats.test.d.ts.map +1 -0
- package/dist/core/beats.test.js +86 -0
- package/dist/core/beats.test.js.map +1 -0
- package/dist/core/brand-kit.d.ts +80 -0
- package/dist/core/brand-kit.d.ts.map +1 -0
- package/dist/core/brand-kit.js +96 -0
- package/dist/core/brand-kit.js.map +1 -0
- package/dist/core/brand-kit.test.d.ts +2 -0
- package/dist/core/brand-kit.test.d.ts.map +1 -0
- package/dist/core/brand-kit.test.js +76 -0
- package/dist/core/brand-kit.test.js.map +1 -0
- package/dist/core/bundled-sfx.d.ts +64 -0
- package/dist/core/bundled-sfx.d.ts.map +1 -0
- package/dist/core/bundled-sfx.js +218 -0
- package/dist/core/bundled-sfx.js.map +1 -0
- package/dist/core/bundled-sfx.test.d.ts +2 -0
- package/dist/core/bundled-sfx.test.d.ts.map +1 -0
- package/dist/core/bundled-sfx.test.js +81 -0
- package/dist/core/bundled-sfx.test.js.map +1 -0
- package/dist/core/child-abort.d.ts +57 -0
- package/dist/core/child-abort.d.ts.map +1 -0
- package/dist/core/child-abort.js +95 -0
- package/dist/core/child-abort.js.map +1 -0
- package/dist/core/child-abort.test.d.ts +2 -0
- package/dist/core/child-abort.test.d.ts.map +1 -0
- package/dist/core/child-abort.test.js +88 -0
- package/dist/core/child-abort.test.js.map +1 -0
- package/dist/core/cli-banner.d.ts +16 -0
- package/dist/core/cli-banner.d.ts.map +1 -0
- package/dist/core/cli-banner.js +75 -0
- package/dist/core/cli-banner.js.map +1 -0
- package/dist/core/clip-scoring.d.ts +44 -0
- package/dist/core/clip-scoring.d.ts.map +1 -0
- package/dist/core/clip-scoring.js +165 -0
- package/dist/core/clip-scoring.js.map +1 -0
- package/dist/core/clip-scoring.test.d.ts +2 -0
- package/dist/core/clip-scoring.test.d.ts.map +1 -0
- package/dist/core/clip-scoring.test.js +113 -0
- package/dist/core/clip-scoring.test.js.map +1 -0
- package/dist/core/clustering.d.ts +52 -0
- package/dist/core/clustering.d.ts.map +1 -0
- package/dist/core/clustering.js +163 -0
- package/dist/core/clustering.js.map +1 -0
- package/dist/core/clustering.test.d.ts +2 -0
- package/dist/core/clustering.test.d.ts.map +1 -0
- package/dist/core/clustering.test.js +112 -0
- package/dist/core/clustering.test.js.map +1 -0
- package/dist/core/color-match.d.ts +19 -0
- package/dist/core/color-match.d.ts.map +1 -0
- package/dist/core/color-match.js +119 -0
- package/dist/core/color-match.js.map +1 -0
- package/dist/core/color-match.test.d.ts +2 -0
- package/dist/core/color-match.test.d.ts.map +1 -0
- package/dist/core/color-match.test.js +40 -0
- package/dist/core/color-match.test.js.map +1 -0
- package/dist/core/doctor-render.d.ts +9 -0
- package/dist/core/doctor-render.d.ts.map +1 -0
- package/dist/core/doctor-render.js +145 -0
- package/dist/core/doctor-render.js.map +1 -0
- package/dist/core/doctor-render.test.d.ts +2 -0
- package/dist/core/doctor-render.test.d.ts.map +1 -0
- package/dist/core/doctor-render.test.js +151 -0
- package/dist/core/doctor-render.test.js.map +1 -0
- package/dist/core/doctor-runner.d.ts +17 -0
- package/dist/core/doctor-runner.d.ts.map +1 -0
- package/dist/core/doctor-runner.js +419 -0
- package/dist/core/doctor-runner.js.map +1 -0
- package/dist/core/doctor.d.ts +120 -0
- package/dist/core/doctor.d.ts.map +1 -0
- package/dist/core/doctor.js +413 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/doctor.test.d.ts +2 -0
- package/dist/core/doctor.test.d.ts.map +1 -0
- package/dist/core/doctor.test.js +131 -0
- package/dist/core/doctor.test.js.map +1 -0
- package/dist/core/ducking.d.ts +37 -0
- package/dist/core/ducking.d.ts.map +1 -0
- package/dist/core/ducking.js +71 -0
- package/dist/core/ducking.js.map +1 -0
- package/dist/core/ducking.test.d.ts +2 -0
- package/dist/core/ducking.test.d.ts.map +1 -0
- package/dist/core/ducking.test.js +38 -0
- package/dist/core/ducking.test.js.map +1 -0
- package/dist/core/edl-roundtrip.test.d.ts +2 -0
- package/dist/core/edl-roundtrip.test.d.ts.map +1 -0
- package/dist/core/edl-roundtrip.test.js +171 -0
- package/dist/core/edl-roundtrip.test.js.map +1 -0
- package/dist/core/edl.d.ts +41 -0
- package/dist/core/edl.d.ts.map +1 -0
- package/dist/core/edl.js +56 -0
- package/dist/core/edl.js.map +1 -0
- package/dist/core/edl.test.d.ts +2 -0
- package/dist/core/edl.test.d.ts.map +1 -0
- package/dist/core/edl.test.js +62 -0
- package/dist/core/edl.test.js.map +1 -0
- package/dist/core/emoji-captions.d.ts +45 -0
- package/dist/core/emoji-captions.d.ts.map +1 -0
- package/dist/core/emoji-captions.js +121 -0
- package/dist/core/emoji-captions.js.map +1 -0
- package/dist/core/envelope-sync.d.ts +52 -0
- package/dist/core/envelope-sync.d.ts.map +1 -0
- package/dist/core/envelope-sync.js +169 -0
- package/dist/core/envelope-sync.js.map +1 -0
- package/dist/core/envelope-sync.test.d.ts +2 -0
- package/dist/core/envelope-sync.test.d.ts.map +1 -0
- package/dist/core/envelope-sync.test.js +70 -0
- package/dist/core/envelope-sync.test.js.map +1 -0
- package/dist/core/face-reframe.d.ts +91 -0
- package/dist/core/face-reframe.d.ts.map +1 -0
- package/dist/core/face-reframe.js +141 -0
- package/dist/core/face-reframe.js.map +1 -0
- package/dist/core/face-reframe.test.d.ts +2 -0
- package/dist/core/face-reframe.test.d.ts.map +1 -0
- package/dist/core/face-reframe.test.js +171 -0
- package/dist/core/face-reframe.test.js.map +1 -0
- package/dist/core/fcpxml-roundtrip.test.d.ts +2 -0
- package/dist/core/fcpxml-roundtrip.test.d.ts.map +1 -0
- package/dist/core/fcpxml-roundtrip.test.js +251 -0
- package/dist/core/fcpxml-roundtrip.test.js.map +1 -0
- package/dist/core/fcpxml.d.ts +172 -0
- package/dist/core/fcpxml.d.ts.map +1 -0
- package/dist/core/fcpxml.js +406 -0
- package/dist/core/fcpxml.js.map +1 -0
- package/dist/core/fcpxml.test.d.ts +2 -0
- package/dist/core/fcpxml.test.d.ts.map +1 -0
- package/dist/core/fcpxml.test.js +360 -0
- package/dist/core/fcpxml.test.js.map +1 -0
- package/dist/core/filler-words.d.ts +155 -0
- package/dist/core/filler-words.d.ts.map +1 -0
- package/dist/core/filler-words.js +273 -0
- package/dist/core/filler-words.js.map +1 -0
- package/dist/core/filler-words.test.d.ts +2 -0
- package/dist/core/filler-words.test.d.ts.map +1 -0
- package/dist/core/filler-words.test.js +251 -0
- package/dist/core/filler-words.test.js.map +1 -0
- package/dist/core/format.d.ts +36 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +57 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/format.test.d.ts +2 -0
- package/dist/core/format.test.d.ts.map +1 -0
- package/dist/core/format.test.js +81 -0
- package/dist/core/format.test.js.map +1 -0
- package/dist/core/frames.d.ts +35 -0
- package/dist/core/frames.d.ts.map +1 -0
- package/dist/core/frames.js +64 -0
- package/dist/core/frames.js.map +1 -0
- package/dist/core/hook-analysis.d.ts +90 -0
- package/dist/core/hook-analysis.d.ts.map +1 -0
- package/dist/core/hook-analysis.js +223 -0
- package/dist/core/hook-analysis.js.map +1 -0
- package/dist/core/hook-analysis.test.d.ts +2 -0
- package/dist/core/hook-analysis.test.d.ts.map +1 -0
- package/dist/core/hook-analysis.test.js +130 -0
- package/dist/core/hook-analysis.test.js.map +1 -0
- package/dist/core/hook-rewrite.d.ts +48 -0
- package/dist/core/hook-rewrite.d.ts.map +1 -0
- package/dist/core/hook-rewrite.js +151 -0
- package/dist/core/hook-rewrite.js.map +1 -0
- package/dist/core/hook-rewrite.test.d.ts +2 -0
- package/dist/core/hook-rewrite.test.d.ts.map +1 -0
- package/dist/core/hook-rewrite.test.js +58 -0
- package/dist/core/hook-rewrite.test.js.map +1 -0
- package/dist/core/hosts/detect.d.ts +17 -0
- package/dist/core/hosts/detect.d.ts.map +1 -0
- package/dist/core/hosts/detect.js +64 -0
- package/dist/core/hosts/detect.js.map +1 -0
- package/dist/core/hosts/detect.test.d.ts +2 -0
- package/dist/core/hosts/detect.test.d.ts.map +1 -0
- package/dist/core/hosts/detect.test.js +17 -0
- package/dist/core/hosts/detect.test.js.map +1 -0
- package/dist/core/hosts/index.d.ts +13 -0
- package/dist/core/hosts/index.d.ts.map +1 -0
- package/dist/core/hosts/index.js +30 -0
- package/dist/core/hosts/index.js.map +1 -0
- package/dist/core/hosts/lazy.d.ts +53 -0
- package/dist/core/hosts/lazy.d.ts.map +1 -0
- package/dist/core/hosts/lazy.js +143 -0
- package/dist/core/hosts/lazy.js.map +1 -0
- package/dist/core/hosts/lazy.test.d.ts +2 -0
- package/dist/core/hosts/lazy.test.d.ts.map +1 -0
- package/dist/core/hosts/lazy.test.js +117 -0
- package/dist/core/hosts/lazy.test.js.map +1 -0
- package/dist/core/hosts/none/adapter.d.ts +74 -0
- package/dist/core/hosts/none/adapter.d.ts.map +1 -0
- package/dist/core/hosts/none/adapter.js +99 -0
- package/dist/core/hosts/none/adapter.js.map +1 -0
- package/dist/core/hosts/premiere/adapter.d.ts +91 -0
- package/dist/core/hosts/premiere/adapter.d.ts.map +1 -0
- package/dist/core/hosts/premiere/adapter.js +219 -0
- package/dist/core/hosts/premiere/adapter.js.map +1 -0
- package/dist/core/hosts/premiere/bridge-source.d.ts +26 -0
- package/dist/core/hosts/premiere/bridge-source.d.ts.map +1 -0
- package/dist/core/hosts/premiere/bridge-source.js +374 -0
- package/dist/core/hosts/premiere/bridge-source.js.map +1 -0
- package/dist/core/hosts/premiere/bridge-source.test.d.ts +2 -0
- package/dist/core/hosts/premiere/bridge-source.test.d.ts.map +1 -0
- package/dist/core/hosts/premiere/bridge-source.test.js +36 -0
- package/dist/core/hosts/premiere/bridge-source.test.js.map +1 -0
- package/dist/core/hosts/premiere/bridge.d.ts +38 -0
- package/dist/core/hosts/premiere/bridge.d.ts.map +1 -0
- package/dist/core/hosts/premiere/bridge.js +238 -0
- package/dist/core/hosts/premiere/bridge.js.map +1 -0
- package/dist/core/hosts/premiere/http-bridge.d.ts +47 -0
- package/dist/core/hosts/premiere/http-bridge.d.ts.map +1 -0
- package/dist/core/hosts/premiere/http-bridge.js +82 -0
- package/dist/core/hosts/premiere/http-bridge.js.map +1 -0
- package/dist/core/hosts/premiere/http-bridge.test.d.ts +2 -0
- package/dist/core/hosts/premiere/http-bridge.test.d.ts.map +1 -0
- package/dist/core/hosts/premiere/http-bridge.test.js +113 -0
- package/dist/core/hosts/premiere/http-bridge.test.js.map +1 -0
- package/dist/core/hosts/premiere/ws-bridge.d.ts +91 -0
- package/dist/core/hosts/premiere/ws-bridge.d.ts.map +1 -0
- package/dist/core/hosts/premiere/ws-bridge.js +303 -0
- package/dist/core/hosts/premiere/ws-bridge.js.map +1 -0
- package/dist/core/hosts/premiere/ws-bridge.test.d.ts +2 -0
- package/dist/core/hosts/premiere/ws-bridge.test.d.ts.map +1 -0
- package/dist/core/hosts/premiere/ws-bridge.test.js +146 -0
- package/dist/core/hosts/premiere/ws-bridge.test.js.map +1 -0
- package/dist/core/hosts/resolve/adapter.d.ts +104 -0
- package/dist/core/hosts/resolve/adapter.d.ts.map +1 -0
- package/dist/core/hosts/resolve/adapter.js +195 -0
- package/dist/core/hosts/resolve/adapter.js.map +1 -0
- package/dist/core/hosts/resolve/bridge-source.d.ts +17 -0
- package/dist/core/hosts/resolve/bridge-source.d.ts.map +1 -0
- package/dist/core/hosts/resolve/bridge-source.js +1061 -0
- package/dist/core/hosts/resolve/bridge-source.js.map +1 -0
- package/dist/core/hosts/resolve/bridge.d.ts +52 -0
- package/dist/core/hosts/resolve/bridge.d.ts.map +1 -0
- package/dist/core/hosts/resolve/bridge.integration.test.d.ts +2 -0
- package/dist/core/hosts/resolve/bridge.integration.test.d.ts.map +1 -0
- package/dist/core/hosts/resolve/bridge.integration.test.js +810 -0
- package/dist/core/hosts/resolve/bridge.integration.test.js.map +1 -0
- package/dist/core/hosts/resolve/bridge.js +349 -0
- package/dist/core/hosts/resolve/bridge.js.map +1 -0
- package/dist/core/hosts/resolve/bridge.test.d.ts +2 -0
- package/dist/core/hosts/resolve/bridge.test.d.ts.map +1 -0
- package/dist/core/hosts/resolve/bridge.test.js +240 -0
- package/dist/core/hosts/resolve/bridge.test.js.map +1 -0
- package/dist/core/hosts/types.d.ts +254 -0
- package/dist/core/hosts/types.d.ts.map +1 -0
- package/dist/core/hosts/types.js +27 -0
- package/dist/core/hosts/types.js.map +1 -0
- package/dist/core/keyframes.d.ts +35 -0
- package/dist/core/keyframes.d.ts.map +1 -0
- package/dist/core/keyframes.js +90 -0
- package/dist/core/keyframes.js.map +1 -0
- package/dist/core/keyframes.test.d.ts +2 -0
- package/dist/core/keyframes.test.d.ts.map +1 -0
- package/dist/core/keyframes.test.js +73 -0
- package/dist/core/keyframes.test.js.map +1 -0
- package/dist/core/keyword-captions.d.ts +75 -0
- package/dist/core/keyword-captions.d.ts.map +1 -0
- package/dist/core/keyword-captions.js +285 -0
- package/dist/core/keyword-captions.js.map +1 -0
- package/dist/core/keyword-captions.test.d.ts +2 -0
- package/dist/core/keyword-captions.test.d.ts.map +1 -0
- package/dist/core/keyword-captions.test.js +90 -0
- package/dist/core/keyword-captions.test.js.map +1 -0
- package/dist/core/logger.d.ts +32 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +188 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/loop-match.d.ts +57 -0
- package/dist/core/loop-match.d.ts.map +1 -0
- package/dist/core/loop-match.js +91 -0
- package/dist/core/loop-match.js.map +1 -0
- package/dist/core/loudness.d.ts +52 -0
- package/dist/core/loudness.d.ts.map +1 -0
- package/dist/core/loudness.js +120 -0
- package/dist/core/loudness.js.map +1 -0
- package/dist/core/loudness.test.d.ts +2 -0
- package/dist/core/loudness.test.d.ts.map +1 -0
- package/dist/core/loudness.test.js +34 -0
- package/dist/core/loudness.test.js.map +1 -0
- package/dist/core/marker-colors.d.ts +39 -0
- package/dist/core/marker-colors.d.ts.map +1 -0
- package/dist/core/marker-colors.js +83 -0
- package/dist/core/marker-colors.js.map +1 -0
- package/dist/core/marker-colors.test.d.ts +2 -0
- package/dist/core/marker-colors.test.d.ts.map +1 -0
- package/dist/core/marker-colors.test.js +116 -0
- package/dist/core/marker-colors.test.js.map +1 -0
- package/dist/core/media/ffmpeg.d.ts +27 -0
- package/dist/core/media/ffmpeg.d.ts.map +1 -0
- package/dist/core/media/ffmpeg.js +64 -0
- package/dist/core/media/ffmpeg.js.map +1 -0
- package/dist/core/multi-format.d.ts +67 -0
- package/dist/core/multi-format.d.ts.map +1 -0
- package/dist/core/multi-format.js +127 -0
- package/dist/core/multi-format.js.map +1 -0
- package/dist/core/multi-format.test.d.ts +2 -0
- package/dist/core/multi-format.test.d.ts.map +1 -0
- package/dist/core/multi-format.test.js +151 -0
- package/dist/core/multi-format.test.js.map +1 -0
- package/dist/core/multicam.d.ts +40 -0
- package/dist/core/multicam.d.ts.map +1 -0
- package/dist/core/multicam.js +77 -0
- package/dist/core/multicam.js.map +1 -0
- package/dist/core/multicam.test.d.ts +2 -0
- package/dist/core/multicam.test.d.ts.map +1 -0
- package/dist/core/multicam.test.js +56 -0
- package/dist/core/multicam.test.js.map +1 -0
- package/dist/core/punch-in.d.ts +72 -0
- package/dist/core/punch-in.d.ts.map +1 -0
- package/dist/core/punch-in.js +133 -0
- package/dist/core/punch-in.js.map +1 -0
- package/dist/core/punch-in.test.d.ts +2 -0
- package/dist/core/punch-in.test.d.ts.map +1 -0
- package/dist/core/punch-in.test.js +118 -0
- package/dist/core/punch-in.test.js.map +1 -0
- package/dist/core/python/beats.py +61 -0
- package/dist/core/python/face_reframe.py +163 -0
- package/dist/core/python/sidecar-path.d.ts +13 -0
- package/dist/core/python/sidecar-path.d.ts.map +1 -0
- package/dist/core/python/sidecar-path.js +24 -0
- package/dist/core/python/sidecar-path.js.map +1 -0
- package/dist/core/python.d.ts +57 -0
- package/dist/core/python.d.ts.map +1 -0
- package/dist/core/python.js +107 -0
- package/dist/core/python.js.map +1 -0
- package/dist/core/python.test.d.ts +2 -0
- package/dist/core/python.test.d.ts.map +1 -0
- package/dist/core/python.test.js +129 -0
- package/dist/core/python.test.js.map +1 -0
- package/dist/core/reformat.d.ts +26 -0
- package/dist/core/reformat.d.ts.map +1 -0
- package/dist/core/reformat.js +31 -0
- package/dist/core/reformat.js.map +1 -0
- package/dist/core/reformat.test.d.ts +2 -0
- package/dist/core/reformat.test.d.ts.map +1 -0
- package/dist/core/reformat.test.js +29 -0
- package/dist/core/reformat.test.js.map +1 -0
- package/dist/core/reorder.d.ts +42 -0
- package/dist/core/reorder.d.ts.map +1 -0
- package/dist/core/reorder.js +80 -0
- package/dist/core/reorder.js.map +1 -0
- package/dist/core/reorder.test.d.ts +2 -0
- package/dist/core/reorder.test.d.ts.map +1 -0
- package/dist/core/reorder.test.js +88 -0
- package/dist/core/reorder.test.js.map +1 -0
- package/dist/core/retention-structure.d.ts +81 -0
- package/dist/core/retention-structure.d.ts.map +1 -0
- package/dist/core/retention-structure.js +206 -0
- package/dist/core/retention-structure.js.map +1 -0
- package/dist/core/retention-structure.test.d.ts +2 -0
- package/dist/core/retention-structure.test.d.ts.map +1 -0
- package/dist/core/retention-structure.test.js +88 -0
- package/dist/core/retention-structure.test.js.map +1 -0
- package/dist/core/review.d.ts +55 -0
- package/dist/core/review.d.ts.map +1 -0
- package/dist/core/review.js +124 -0
- package/dist/core/review.js.map +1 -0
- package/dist/core/review.test.d.ts +2 -0
- package/dist/core/review.test.d.ts.map +1 -0
- package/dist/core/review.test.js +76 -0
- package/dist/core/review.test.js.map +1 -0
- package/dist/core/safe-paths.d.ts +58 -0
- package/dist/core/safe-paths.d.ts.map +1 -0
- package/dist/core/safe-paths.js +118 -0
- package/dist/core/safe-paths.js.map +1 -0
- package/dist/core/safe-paths.test.d.ts +2 -0
- package/dist/core/safe-paths.test.d.ts.map +1 -0
- package/dist/core/safe-paths.test.js +92 -0
- package/dist/core/safe-paths.test.js.map +1 -0
- package/dist/core/sessions.d.ts +40 -0
- package/dist/core/sessions.d.ts.map +1 -0
- package/dist/core/sessions.js +61 -0
- package/dist/core/sessions.js.map +1 -0
- package/dist/core/sfx-on-cuts.d.ts +60 -0
- package/dist/core/sfx-on-cuts.d.ts.map +1 -0
- package/dist/core/sfx-on-cuts.js +90 -0
- package/dist/core/sfx-on-cuts.js.map +1 -0
- package/dist/core/sfx-on-cuts.test.d.ts +2 -0
- package/dist/core/sfx-on-cuts.test.d.ts.map +1 -0
- package/dist/core/sfx-on-cuts.test.js +53 -0
- package/dist/core/sfx-on-cuts.test.js.map +1 -0
- package/dist/core/silence.d.ts +41 -0
- package/dist/core/silence.d.ts.map +1 -0
- package/dist/core/silence.js +104 -0
- package/dist/core/silence.js.map +1 -0
- package/dist/core/silence.test.d.ts +2 -0
- package/dist/core/silence.test.d.ts.map +1 -0
- package/dist/core/silence.test.js +143 -0
- package/dist/core/silence.test.js.map +1 -0
- package/dist/core/skills-loader.d.ts +80 -0
- package/dist/core/skills-loader.d.ts.map +1 -0
- package/dist/core/skills-loader.js +161 -0
- package/dist/core/skills-loader.js.map +1 -0
- package/dist/core/skills-loader.test.d.ts +2 -0
- package/dist/core/skills-loader.test.d.ts.map +1 -0
- package/dist/core/skills-loader.test.js +130 -0
- package/dist/core/skills-loader.test.js.map +1 -0
- package/dist/core/skin-grade.d.ts +62 -0
- package/dist/core/skin-grade.d.ts.map +1 -0
- package/dist/core/skin-grade.js +271 -0
- package/dist/core/skin-grade.js.map +1 -0
- package/dist/core/skin-grade.test.d.ts +2 -0
- package/dist/core/skin-grade.test.d.ts.map +1 -0
- package/dist/core/skin-grade.test.js +182 -0
- package/dist/core/skin-grade.test.js.map +1 -0
- package/dist/core/speaker-changes.d.ts +30 -0
- package/dist/core/speaker-changes.d.ts.map +1 -0
- package/dist/core/speaker-changes.js +19 -0
- package/dist/core/speaker-changes.js.map +1 -0
- package/dist/core/speaker-changes.test.d.ts +2 -0
- package/dist/core/speaker-changes.test.d.ts.map +1 -0
- package/dist/core/speaker-changes.test.js +46 -0
- package/dist/core/speaker-changes.test.js.map +1 -0
- package/dist/core/speed-ramp.d.ts +60 -0
- package/dist/core/speed-ramp.d.ts.map +1 -0
- package/dist/core/speed-ramp.js +113 -0
- package/dist/core/speed-ramp.js.map +1 -0
- package/dist/core/speed-ramp.test.d.ts +2 -0
- package/dist/core/speed-ramp.test.d.ts.map +1 -0
- package/dist/core/speed-ramp.test.js +74 -0
- package/dist/core/speed-ramp.test.js.map +1 -0
- package/dist/core/srt.d.ts +91 -0
- package/dist/core/srt.d.ts.map +1 -0
- package/dist/core/srt.js +159 -0
- package/dist/core/srt.js.map +1 -0
- package/dist/core/srt.test.d.ts +2 -0
- package/dist/core/srt.test.d.ts.map +1 -0
- package/dist/core/srt.test.js +160 -0
- package/dist/core/srt.test.js.map +1 -0
- package/dist/core/stabilize.d.ts +15 -0
- package/dist/core/stabilize.d.ts.map +1 -0
- package/dist/core/stabilize.js +69 -0
- package/dist/core/stabilize.js.map +1 -0
- package/dist/core/styles-loader.d.ts +33 -0
- package/dist/core/styles-loader.d.ts.map +1 -0
- package/dist/core/styles-loader.js +67 -0
- package/dist/core/styles-loader.js.map +1 -0
- package/dist/core/styles-loader.test.d.ts +2 -0
- package/dist/core/styles-loader.test.d.ts.map +1 -0
- package/dist/core/styles-loader.test.js +72 -0
- package/dist/core/styles-loader.test.js.map +1 -0
- package/dist/core/text-overlay.d.ts +76 -0
- package/dist/core/text-overlay.d.ts.map +1 -0
- package/dist/core/text-overlay.js +233 -0
- package/dist/core/text-overlay.js.map +1 -0
- package/dist/core/text-overlay.test.d.ts +2 -0
- package/dist/core/text-overlay.test.d.ts.map +1 -0
- package/dist/core/text-overlay.test.js +103 -0
- package/dist/core/text-overlay.test.js.map +1 -0
- package/dist/core/thumbnail-compose.d.ts +58 -0
- package/dist/core/thumbnail-compose.d.ts.map +1 -0
- package/dist/core/thumbnail-compose.js +101 -0
- package/dist/core/thumbnail-compose.js.map +1 -0
- package/dist/core/thumbnail-promise.d.ts +46 -0
- package/dist/core/thumbnail-promise.d.ts.map +1 -0
- package/dist/core/thumbnail-promise.js +133 -0
- package/dist/core/thumbnail-promise.js.map +1 -0
- package/dist/core/thumbnail-promise.test.d.ts +2 -0
- package/dist/core/thumbnail-promise.test.d.ts.map +1 -0
- package/dist/core/thumbnail-promise.test.js +52 -0
- package/dist/core/thumbnail-promise.test.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +26 -0
- package/dist/core/version.js.map +1 -0
- package/dist/core/viral-moments.d.ts +70 -0
- package/dist/core/viral-moments.d.ts.map +1 -0
- package/dist/core/viral-moments.js +192 -0
- package/dist/core/viral-moments.js.map +1 -0
- package/dist/core/viral-moments.test.d.ts +2 -0
- package/dist/core/viral-moments.test.d.ts.map +1 -0
- package/dist/core/viral-moments.test.js +153 -0
- package/dist/core/viral-moments.test.js.map +1 -0
- package/dist/core/vision.d.ts +53 -0
- package/dist/core/vision.d.ts.map +1 -0
- package/dist/core/vision.js +151 -0
- package/dist/core/vision.js.map +1 -0
- package/dist/core/vision.test.d.ts +2 -0
- package/dist/core/vision.test.d.ts.map +1 -0
- package/dist/core/vision.test.js +76 -0
- package/dist/core/vision.test.js.map +1 -0
- package/dist/core/whisper.d.ts +204 -0
- package/dist/core/whisper.d.ts.map +1 -0
- package/dist/core/whisper.js +448 -0
- package/dist/core/whisper.js.map +1 -0
- package/dist/core/whisper.test.d.ts +2 -0
- package/dist/core/whisper.test.d.ts.map +1 -0
- package/dist/core/whisper.test.js +372 -0
- package/dist/core/whisper.test.js.map +1 -0
- package/dist/core/youtube-metadata.d.ts +44 -0
- package/dist/core/youtube-metadata.d.ts.map +1 -0
- package/dist/core/youtube-metadata.js +168 -0
- package/dist/core/youtube-metadata.js.map +1 -0
- package/dist/core/youtube-metadata.test.d.ts +2 -0
- package/dist/core/youtube-metadata.test.d.ts.map +1 -0
- package/dist/core/youtube-metadata.test.js +132 -0
- package/dist/core/youtube-metadata.test.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/prompt-commands.d.ts +24 -0
- package/dist/prompt-commands.d.ts.map +1 -0
- package/dist/prompt-commands.js +243 -0
- package/dist/prompt-commands.js.map +1 -0
- package/dist/prompt-commands.test.d.ts +2 -0
- package/dist/prompt-commands.test.d.ts.map +1 -0
- package/dist/prompt-commands.test.js +46 -0
- package/dist/prompt-commands.test.js.map +1 -0
- package/dist/skills.d.ts +18 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +1780 -0
- package/dist/skills.js.map +1 -0
- package/dist/system-prompt.d.ts +35 -0
- package/dist/system-prompt.d.ts.map +1 -0
- package/dist/system-prompt.js +618 -0
- package/dist/system-prompt.js.map +1 -0
- package/dist/system-prompt.test.d.ts +2 -0
- package/dist/system-prompt.test.d.ts.map +1 -0
- package/dist/system-prompt.test.js +87 -0
- package/dist/system-prompt.test.js.map +1 -0
- package/dist/tools/add-fades.d.ts +13 -0
- package/dist/tools/add-fades.d.ts.map +1 -0
- package/dist/tools/add-fades.js +89 -0
- package/dist/tools/add-fades.js.map +1 -0
- package/dist/tools/add-marker.d.ts +31 -0
- package/dist/tools/add-marker.d.ts.map +1 -0
- package/dist/tools/add-marker.js +56 -0
- package/dist/tools/add-marker.js.map +1 -0
- package/dist/tools/add-sfx-at-cuts.d.ts +24 -0
- package/dist/tools/add-sfx-at-cuts.d.ts.map +1 -0
- package/dist/tools/add-sfx-at-cuts.js +145 -0
- package/dist/tools/add-sfx-at-cuts.js.map +1 -0
- package/dist/tools/add-sfx-to-timeline.d.ts +34 -0
- package/dist/tools/add-sfx-to-timeline.d.ts.map +1 -0
- package/dist/tools/add-sfx-to-timeline.js +169 -0
- package/dist/tools/add-sfx-to-timeline.js.map +1 -0
- package/dist/tools/add-sfx-to-timeline.test.d.ts +2 -0
- package/dist/tools/add-sfx-to-timeline.test.d.ts.map +1 -0
- package/dist/tools/add-sfx-to-timeline.test.js +181 -0
- package/dist/tools/add-sfx-to-timeline.test.js.map +1 -0
- package/dist/tools/add-track.d.ts +13 -0
- package/dist/tools/add-track.d.ts.map +1 -0
- package/dist/tools/add-track.js +26 -0
- package/dist/tools/add-track.js.map +1 -0
- package/dist/tools/analyze-hook.d.ts +28 -0
- package/dist/tools/analyze-hook.d.ts.map +1 -0
- package/dist/tools/analyze-hook.js +126 -0
- package/dist/tools/analyze-hook.js.map +1 -0
- package/dist/tools/append-clip.d.ts +10 -0
- package/dist/tools/append-clip.d.ts.map +1 -0
- package/dist/tools/append-clip.js +27 -0
- package/dist/tools/append-clip.js.map +1 -0
- package/dist/tools/apply-lut.d.ts +11 -0
- package/dist/tools/apply-lut.d.ts.map +1 -0
- package/dist/tools/apply-lut.js +33 -0
- package/dist/tools/apply-lut.js.map +1 -0
- package/dist/tools/audit-first-frame.d.ts +36 -0
- package/dist/tools/audit-first-frame.d.ts.map +1 -0
- package/dist/tools/audit-first-frame.js +181 -0
- package/dist/tools/audit-first-frame.js.map +1 -0
- package/dist/tools/audit-retention-structure.d.ts +20 -0
- package/dist/tools/audit-retention-structure.d.ts.map +1 -0
- package/dist/tools/audit-retention-structure.js +95 -0
- package/dist/tools/audit-retention-structure.js.map +1 -0
- package/dist/tools/audit-retention-structure.test.d.ts +2 -0
- package/dist/tools/audit-retention-structure.test.d.ts.map +1 -0
- package/dist/tools/audit-retention-structure.test.js +93 -0
- package/dist/tools/audit-retention-structure.test.js.map +1 -0
- package/dist/tools/bleep-words.d.ts +59 -0
- package/dist/tools/bleep-words.d.ts.map +1 -0
- package/dist/tools/bleep-words.js +211 -0
- package/dist/tools/bleep-words.js.map +1 -0
- package/dist/tools/bleep-words.test.d.ts +2 -0
- package/dist/tools/bleep-words.test.d.ts.map +1 -0
- package/dist/tools/bleep-words.test.js +96 -0
- package/dist/tools/bleep-words.test.js.map +1 -0
- package/dist/tools/burn-subtitles.d.ts +28 -0
- package/dist/tools/burn-subtitles.d.ts.map +1 -0
- package/dist/tools/burn-subtitles.js +92 -0
- package/dist/tools/burn-subtitles.js.map +1 -0
- package/dist/tools/clean-audio.d.ts +18 -0
- package/dist/tools/clean-audio.d.ts.map +1 -0
- package/dist/tools/clean-audio.js +55 -0
- package/dist/tools/clean-audio.js.map +1 -0
- package/dist/tools/clone-timeline.d.ts +9 -0
- package/dist/tools/clone-timeline.d.ts.map +1 -0
- package/dist/tools/clone-timeline.js +28 -0
- package/dist/tools/clone-timeline.js.map +1 -0
- package/dist/tools/cluster-takes.d.ts +11 -0
- package/dist/tools/cluster-takes.d.ts.map +1 -0
- package/dist/tools/cluster-takes.js +72 -0
- package/dist/tools/cluster-takes.js.map +1 -0
- package/dist/tools/color-match.d.ts +16 -0
- package/dist/tools/color-match.d.ts.map +1 -0
- package/dist/tools/color-match.js +55 -0
- package/dist/tools/color-match.js.map +1 -0
- package/dist/tools/compose-layered.d.ts +47 -0
- package/dist/tools/compose-layered.d.ts.map +1 -0
- package/dist/tools/compose-layered.js +104 -0
- package/dist/tools/compose-layered.js.map +1 -0
- package/dist/tools/compose-thumbnail-variants.d.ts +70 -0
- package/dist/tools/compose-thumbnail-variants.d.ts.map +1 -0
- package/dist/tools/compose-thumbnail-variants.js +274 -0
- package/dist/tools/compose-thumbnail-variants.js.map +1 -0
- package/dist/tools/compose-thumbnail.d.ts +28 -0
- package/dist/tools/compose-thumbnail.d.ts.map +1 -0
- package/dist/tools/compose-thumbnail.js +101 -0
- package/dist/tools/compose-thumbnail.js.map +1 -0
- package/dist/tools/concat-videos.d.ts +18 -0
- package/dist/tools/concat-videos.d.ts.map +1 -0
- package/dist/tools/concat-videos.js +87 -0
- package/dist/tools/concat-videos.js.map +1 -0
- package/dist/tools/concat-videos.test.d.ts +2 -0
- package/dist/tools/concat-videos.test.d.ts.map +1 -0
- package/dist/tools/concat-videos.test.js +103 -0
- package/dist/tools/concat-videos.test.js.map +1 -0
- package/dist/tools/copy-grade.d.ts +10 -0
- package/dist/tools/copy-grade.d.ts.map +1 -0
- package/dist/tools/copy-grade.js +29 -0
- package/dist/tools/copy-grade.js.map +1 -0
- package/dist/tools/create-timeline.d.ts +12 -0
- package/dist/tools/create-timeline.d.ts.map +1 -0
- package/dist/tools/create-timeline.js +35 -0
- package/dist/tools/create-timeline.js.map +1 -0
- package/dist/tools/crossfade-videos.d.ts +49 -0
- package/dist/tools/crossfade-videos.d.ts.map +1 -0
- package/dist/tools/crossfade-videos.js +122 -0
- package/dist/tools/crossfade-videos.js.map +1 -0
- package/dist/tools/cut-at.d.ts +10 -0
- package/dist/tools/cut-at.d.ts.map +1 -0
- package/dist/tools/cut-at.js +24 -0
- package/dist/tools/cut-at.js.map +1 -0
- package/dist/tools/cut-filler-words.d.ts +27 -0
- package/dist/tools/cut-filler-words.d.ts.map +1 -0
- package/dist/tools/cut-filler-words.js +182 -0
- package/dist/tools/cut-filler-words.js.map +1 -0
- package/dist/tools/detect-silence.d.ts +13 -0
- package/dist/tools/detect-silence.d.ts.map +1 -0
- package/dist/tools/detect-silence.js +98 -0
- package/dist/tools/detect-silence.js.map +1 -0
- package/dist/tools/detect-speaker-changes.d.ts +9 -0
- package/dist/tools/detect-speaker-changes.d.ts.map +1 -0
- package/dist/tools/detect-speaker-changes.js +43 -0
- package/dist/tools/detect-speaker-changes.js.map +1 -0
- package/dist/tools/duck-audio.d.ts +16 -0
- package/dist/tools/duck-audio.d.ts.map +1 -0
- package/dist/tools/duck-audio.js +73 -0
- package/dist/tools/duck-audio.js.map +1 -0
- package/dist/tools/extract-audio.d.ts +10 -0
- package/dist/tools/extract-audio.d.ts.map +1 -0
- package/dist/tools/extract-audio.js +36 -0
- package/dist/tools/extract-audio.js.map +1 -0
- package/dist/tools/extract-frame.d.ts +12 -0
- package/dist/tools/extract-frame.d.ts.map +1 -0
- package/dist/tools/extract-frame.js +70 -0
- package/dist/tools/extract-frame.js.map +1 -0
- package/dist/tools/face-reframe.d.ts +30 -0
- package/dist/tools/face-reframe.d.ts.map +1 -0
- package/dist/tools/face-reframe.js +143 -0
- package/dist/tools/face-reframe.js.map +1 -0
- package/dist/tools/face-reframe.test.d.ts +2 -0
- package/dist/tools/face-reframe.test.d.ts.map +1 -0
- package/dist/tools/face-reframe.test.js +139 -0
- package/dist/tools/face-reframe.test.js.map +1 -0
- package/dist/tools/find-viral-moments.d.ts +23 -0
- package/dist/tools/find-viral-moments.d.ts.map +1 -0
- package/dist/tools/find-viral-moments.js +176 -0
- package/dist/tools/find-viral-moments.js.map +1 -0
- package/dist/tools/find-viral-moments.test.d.ts +2 -0
- package/dist/tools/find-viral-moments.test.d.ts.map +1 -0
- package/dist/tools/find-viral-moments.test.js +144 -0
- package/dist/tools/find-viral-moments.test.js.map +1 -0
- package/dist/tools/fusion-comp.d.ts +49 -0
- package/dist/tools/fusion-comp.d.ts.map +1 -0
- package/dist/tools/fusion-comp.js +129 -0
- package/dist/tools/fusion-comp.js.map +1 -0
- package/dist/tools/generate-gif.d.ts +13 -0
- package/dist/tools/generate-gif.d.ts.map +1 -0
- package/dist/tools/generate-gif.js +111 -0
- package/dist/tools/generate-gif.js.map +1 -0
- package/dist/tools/generate-gif.test.d.ts +2 -0
- package/dist/tools/generate-gif.test.d.ts.map +1 -0
- package/dist/tools/generate-gif.test.js +115 -0
- package/dist/tools/generate-gif.test.js.map +1 -0
- package/dist/tools/generate-outro.d.ts +18 -0
- package/dist/tools/generate-outro.d.ts.map +1 -0
- package/dist/tools/generate-outro.js +175 -0
- package/dist/tools/generate-outro.js.map +1 -0
- package/dist/tools/generate-youtube-metadata.d.ts +23 -0
- package/dist/tools/generate-youtube-metadata.d.ts.map +1 -0
- package/dist/tools/generate-youtube-metadata.js +103 -0
- package/dist/tools/generate-youtube-metadata.js.map +1 -0
- package/dist/tools/generate-youtube-metadata.test.d.ts +2 -0
- package/dist/tools/generate-youtube-metadata.test.d.ts.map +1 -0
- package/dist/tools/generate-youtube-metadata.test.js +118 -0
- package/dist/tools/generate-youtube-metadata.test.js.map +1 -0
- package/dist/tools/get-markers.d.ts +13 -0
- package/dist/tools/get-markers.d.ts.map +1 -0
- package/dist/tools/get-markers.js +71 -0
- package/dist/tools/get-markers.js.map +1 -0
- package/dist/tools/get-timeline.d.ts +9 -0
- package/dist/tools/get-timeline.d.ts.map +1 -0
- package/dist/tools/get-timeline.js +43 -0
- package/dist/tools/get-timeline.js.map +1 -0
- package/dist/tools/grade-skin-tones.d.ts +31 -0
- package/dist/tools/grade-skin-tones.d.ts.map +1 -0
- package/dist/tools/grade-skin-tones.js +92 -0
- package/dist/tools/grade-skin-tones.js.map +1 -0
- package/dist/tools/host-eval.d.ts +35 -0
- package/dist/tools/host-eval.d.ts.map +1 -0
- package/dist/tools/host-eval.js +70 -0
- package/dist/tools/host-eval.js.map +1 -0
- package/dist/tools/host-info.d.ts +7 -0
- package/dist/tools/host-info.d.ts.map +1 -0
- package/dist/tools/host-info.js +33 -0
- package/dist/tools/host-info.js.map +1 -0
- package/dist/tools/host-tools.test.d.ts +2 -0
- package/dist/tools/host-tools.test.d.ts.map +1 -0
- package/dist/tools/host-tools.test.js +125 -0
- package/dist/tools/host-tools.test.js.map +1 -0
- package/dist/tools/import-edl.d.ts +9 -0
- package/dist/tools/import-edl.d.ts.map +1 -0
- package/dist/tools/import-edl.js +25 -0
- package/dist/tools/import-edl.js.map +1 -0
- package/dist/tools/import-subtitles.d.ts +9 -0
- package/dist/tools/import-subtitles.d.ts.map +1 -0
- package/dist/tools/import-subtitles.js +31 -0
- package/dist/tools/import-subtitles.js.map +1 -0
- package/dist/tools/import-to-media-pool.d.ts +10 -0
- package/dist/tools/import-to-media-pool.d.ts.map +1 -0
- package/dist/tools/import-to-media-pool.js +27 -0
- package/dist/tools/import-to-media-pool.js.map +1 -0
- package/dist/tools/index.d.ts +110 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +380 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/index.test.d.ts +2 -0
- package/dist/tools/index.test.d.ts.map +1 -0
- package/dist/tools/index.test.js +158 -0
- package/dist/tools/index.test.js.map +1 -0
- package/dist/tools/insert-broll.d.ts +13 -0
- package/dist/tools/insert-broll.d.ts.map +1 -0
- package/dist/tools/insert-broll.js +56 -0
- package/dist/tools/insert-broll.js.map +1 -0
- package/dist/tools/ken-burns.d.ts +26 -0
- package/dist/tools/ken-burns.d.ts.map +1 -0
- package/dist/tools/ken-burns.js +126 -0
- package/dist/tools/ken-burns.js.map +1 -0
- package/dist/tools/list-render-presets.d.ts +7 -0
- package/dist/tools/list-render-presets.d.ts.map +1 -0
- package/dist/tools/list-render-presets.js +30 -0
- package/dist/tools/list-render-presets.js.map +1 -0
- package/dist/tools/loop-match-short.d.ts +22 -0
- package/dist/tools/loop-match-short.d.ts.map +1 -0
- package/dist/tools/loop-match-short.js +107 -0
- package/dist/tools/loop-match-short.js.map +1 -0
- package/dist/tools/match-clip-color.d.ts +29 -0
- package/dist/tools/match-clip-color.d.ts.map +1 -0
- package/dist/tools/match-clip-color.js +99 -0
- package/dist/tools/match-clip-color.js.map +1 -0
- package/dist/tools/measure-loudness.d.ts +8 -0
- package/dist/tools/measure-loudness.d.ts.map +1 -0
- package/dist/tools/measure-loudness.js +40 -0
- package/dist/tools/measure-loudness.js.map +1 -0
- package/dist/tools/mix-audio.d.ts +46 -0
- package/dist/tools/mix-audio.d.ts.map +1 -0
- package/dist/tools/mix-audio.js +102 -0
- package/dist/tools/mix-audio.js.map +1 -0
- package/dist/tools/multicam-sync.d.ts +14 -0
- package/dist/tools/multicam-sync.d.ts.map +1 -0
- package/dist/tools/multicam-sync.js +75 -0
- package/dist/tools/multicam-sync.js.map +1 -0
- package/dist/tools/new-tools.test.d.ts +2 -0
- package/dist/tools/new-tools.test.d.ts.map +1 -0
- package/dist/tools/new-tools.test.js +511 -0
- package/dist/tools/new-tools.test.js.map +1 -0
- package/dist/tools/normalize-loudness.d.ts +21 -0
- package/dist/tools/normalize-loudness.d.ts.map +1 -0
- package/dist/tools/normalize-loudness.js +95 -0
- package/dist/tools/normalize-loudness.js.map +1 -0
- package/dist/tools/open-page.d.ts +17 -0
- package/dist/tools/open-page.d.ts.map +1 -0
- package/dist/tools/open-page.js +27 -0
- package/dist/tools/open-page.js.map +1 -0
- package/dist/tools/overlay-watermark.d.ts +28 -0
- package/dist/tools/overlay-watermark.d.ts.map +1 -0
- package/dist/tools/overlay-watermark.js +99 -0
- package/dist/tools/overlay-watermark.js.map +1 -0
- package/dist/tools/path-traversal.test.d.ts +15 -0
- package/dist/tools/path-traversal.test.d.ts.map +1 -0
- package/dist/tools/path-traversal.test.js +223 -0
- package/dist/tools/path-traversal.test.js.map +1 -0
- package/dist/tools/pick-best-takes.d.ts +20 -0
- package/dist/tools/pick-best-takes.d.ts.map +1 -0
- package/dist/tools/pick-best-takes.js +148 -0
- package/dist/tools/pick-best-takes.js.map +1 -0
- package/dist/tools/post-tools.test.d.ts +2 -0
- package/dist/tools/post-tools.test.d.ts.map +1 -0
- package/dist/tools/post-tools.test.js +83 -0
- package/dist/tools/post-tools.test.js.map +1 -0
- package/dist/tools/pre-render-check.d.ts +23 -0
- package/dist/tools/pre-render-check.d.ts.map +1 -0
- package/dist/tools/pre-render-check.js +134 -0
- package/dist/tools/pre-render-check.js.map +1 -0
- package/dist/tools/probe-media.d.ts +8 -0
- package/dist/tools/probe-media.d.ts.map +1 -0
- package/dist/tools/probe-media.js +32 -0
- package/dist/tools/probe-media.js.map +1 -0
- package/dist/tools/punch-in.d.ts +30 -0
- package/dist/tools/punch-in.d.ts.map +1 -0
- package/dist/tools/punch-in.js +131 -0
- package/dist/tools/punch-in.js.map +1 -0
- package/dist/tools/read-skill.d.ts +9 -0
- package/dist/tools/read-skill.d.ts.map +1 -0
- package/dist/tools/read-skill.js +24 -0
- package/dist/tools/read-skill.js.map +1 -0
- package/dist/tools/read-transcript.d.ts +14 -0
- package/dist/tools/read-transcript.d.ts.map +1 -0
- package/dist/tools/read-transcript.js +86 -0
- package/dist/tools/read-transcript.js.map +1 -0
- package/dist/tools/read-transcript.test.d.ts +2 -0
- package/dist/tools/read-transcript.test.d.ts.map +1 -0
- package/dist/tools/read-transcript.test.js +136 -0
- package/dist/tools/read-transcript.test.js.map +1 -0
- package/dist/tools/reformat-timeline.d.ts +25 -0
- package/dist/tools/reformat-timeline.d.ts.map +1 -0
- package/dist/tools/reformat-timeline.js +61 -0
- package/dist/tools/reformat-timeline.js.map +1 -0
- package/dist/tools/render-multi-format.d.ts +35 -0
- package/dist/tools/render-multi-format.d.ts.map +1 -0
- package/dist/tools/render-multi-format.js +206 -0
- package/dist/tools/render-multi-format.js.map +1 -0
- package/dist/tools/render-multi-format.test.d.ts +2 -0
- package/dist/tools/render-multi-format.test.d.ts.map +1 -0
- package/dist/tools/render-multi-format.test.js +312 -0
- package/dist/tools/render-multi-format.test.js.map +1 -0
- package/dist/tools/render.d.ts +10 -0
- package/dist/tools/render.d.ts.map +1 -0
- package/dist/tools/render.js +26 -0
- package/dist/tools/render.js.map +1 -0
- package/dist/tools/reorder-timeline.d.ts +12 -0
- package/dist/tools/reorder-timeline.d.ts.map +1 -0
- package/dist/tools/reorder-timeline.js +66 -0
- package/dist/tools/reorder-timeline.js.map +1 -0
- package/dist/tools/replace-clip.d.ts +10 -0
- package/dist/tools/replace-clip.d.ts.map +1 -0
- package/dist/tools/replace-clip.js +28 -0
- package/dist/tools/replace-clip.js.map +1 -0
- package/dist/tools/review-edit.d.ts +23 -0
- package/dist/tools/review-edit.d.ts.map +1 -0
- package/dist/tools/review-edit.js +47 -0
- package/dist/tools/review-edit.js.map +1 -0
- package/dist/tools/rewrite-hook.d.ts +32 -0
- package/dist/tools/rewrite-hook.d.ts.map +1 -0
- package/dist/tools/rewrite-hook.js +65 -0
- package/dist/tools/rewrite-hook.js.map +1 -0
- package/dist/tools/ripple-delete.d.ts +11 -0
- package/dist/tools/ripple-delete.d.ts.map +1 -0
- package/dist/tools/ripple-delete.js +27 -0
- package/dist/tools/ripple-delete.js.map +1 -0
- package/dist/tools/save-project.d.ts +7 -0
- package/dist/tools/save-project.d.ts.map +1 -0
- package/dist/tools/save-project.js +22 -0
- package/dist/tools/save-project.js.map +1 -0
- package/dist/tools/score-clip.d.ts +30 -0
- package/dist/tools/score-clip.d.ts.map +1 -0
- package/dist/tools/score-clip.js +109 -0
- package/dist/tools/score-clip.js.map +1 -0
- package/dist/tools/score-clip.test.d.ts +2 -0
- package/dist/tools/score-clip.test.d.ts.map +1 -0
- package/dist/tools/score-clip.test.js +110 -0
- package/dist/tools/score-clip.test.js.map +1 -0
- package/dist/tools/score-shot.d.ts +18 -0
- package/dist/tools/score-shot.d.ts.map +1 -0
- package/dist/tools/score-shot.js +127 -0
- package/dist/tools/score-shot.js.map +1 -0
- package/dist/tools/search-tools.d.ts +34 -0
- package/dist/tools/search-tools.d.ts.map +1 -0
- package/dist/tools/search-tools.js +86 -0
- package/dist/tools/search-tools.js.map +1 -0
- package/dist/tools/search-tools.test.d.ts +2 -0
- package/dist/tools/search-tools.test.d.ts.map +1 -0
- package/dist/tools/search-tools.test.js +60 -0
- package/dist/tools/search-tools.test.js.map +1 -0
- package/dist/tools/set-clip-speed.d.ts +10 -0
- package/dist/tools/set-clip-speed.d.ts.map +1 -0
- package/dist/tools/set-clip-speed.js +28 -0
- package/dist/tools/set-clip-speed.js.map +1 -0
- package/dist/tools/set-clip-volume.d.ts +10 -0
- package/dist/tools/set-clip-volume.d.ts.map +1 -0
- package/dist/tools/set-clip-volume.js +33 -0
- package/dist/tools/set-clip-volume.js.map +1 -0
- package/dist/tools/set-primary-correction.d.ts +14 -0
- package/dist/tools/set-primary-correction.d.ts.map +1 -0
- package/dist/tools/set-primary-correction.js +45 -0
- package/dist/tools/set-primary-correction.js.map +1 -0
- package/dist/tools/smart-reframe.d.ts +22 -0
- package/dist/tools/smart-reframe.d.ts.map +1 -0
- package/dist/tools/smart-reframe.js +39 -0
- package/dist/tools/smart-reframe.js.map +1 -0
- package/dist/tools/snap-cuts-to-beats.d.ts +18 -0
- package/dist/tools/snap-cuts-to-beats.d.ts.map +1 -0
- package/dist/tools/snap-cuts-to-beats.js +110 -0
- package/dist/tools/snap-cuts-to-beats.js.map +1 -0
- package/dist/tools/snap-cuts-to-beats.test.d.ts +2 -0
- package/dist/tools/snap-cuts-to-beats.test.d.ts.map +1 -0
- package/dist/tools/snap-cuts-to-beats.test.js +99 -0
- package/dist/tools/snap-cuts-to-beats.test.js.map +1 -0
- package/dist/tools/speed-ramp.d.ts +14 -0
- package/dist/tools/speed-ramp.d.ts.map +1 -0
- package/dist/tools/speed-ramp.js +72 -0
- package/dist/tools/speed-ramp.js.map +1 -0
- package/dist/tools/stabilize-video.d.ts +12 -0
- package/dist/tools/stabilize-video.d.ts.map +1 -0
- package/dist/tools/stabilize-video.js +64 -0
- package/dist/tools/stabilize-video.js.map +1 -0
- package/dist/tools/suggest-broll.d.ts +34 -0
- package/dist/tools/suggest-broll.d.ts.map +1 -0
- package/dist/tools/suggest-broll.js +367 -0
- package/dist/tools/suggest-broll.js.map +1 -0
- package/dist/tools/suggest-broll.test.d.ts +2 -0
- package/dist/tools/suggest-broll.test.d.ts.map +1 -0
- package/dist/tools/suggest-broll.test.js +217 -0
- package/dist/tools/suggest-broll.test.js.map +1 -0
- package/dist/tools/text-based-cut.d.ts +33 -0
- package/dist/tools/text-based-cut.d.ts.map +1 -0
- package/dist/tools/text-based-cut.js +172 -0
- package/dist/tools/text-based-cut.js.map +1 -0
- package/dist/tools/text-based-cut.test.d.ts +2 -0
- package/dist/tools/text-based-cut.test.d.ts.map +1 -0
- package/dist/tools/text-based-cut.test.js +32 -0
- package/dist/tools/text-based-cut.test.js.map +1 -0
- package/dist/tools/transcribe.d.ts +29 -0
- package/dist/tools/transcribe.d.ts.map +1 -0
- package/dist/tools/transcribe.js +117 -0
- package/dist/tools/transcribe.js.map +1 -0
- package/dist/tools/transition-videos.d.ts +29 -0
- package/dist/tools/transition-videos.d.ts.map +1 -0
- package/dist/tools/transition-videos.js +130 -0
- package/dist/tools/transition-videos.js.map +1 -0
- package/dist/tools/trim-dead-air.d.ts +59 -0
- package/dist/tools/trim-dead-air.d.ts.map +1 -0
- package/dist/tools/trim-dead-air.js +215 -0
- package/dist/tools/trim-dead-air.js.map +1 -0
- package/dist/tools/trim-dead-air.test.d.ts +2 -0
- package/dist/tools/trim-dead-air.test.d.ts.map +1 -0
- package/dist/tools/trim-dead-air.test.js +75 -0
- package/dist/tools/trim-dead-air.test.js.map +1 -0
- package/dist/tools/verify-thumbnail-promise.d.ts +33 -0
- package/dist/tools/verify-thumbnail-promise.d.ts.map +1 -0
- package/dist/tools/verify-thumbnail-promise.js +112 -0
- package/dist/tools/verify-thumbnail-promise.js.map +1 -0
- package/dist/tools/verify-thumbnail-promise.test.d.ts +2 -0
- package/dist/tools/verify-thumbnail-promise.test.d.ts.map +1 -0
- package/dist/tools/verify-thumbnail-promise.test.js +38 -0
- package/dist/tools/verify-thumbnail-promise.test.js.map +1 -0
- package/dist/tools/write-ass.d.ts +34 -0
- package/dist/tools/write-ass.d.ts.map +1 -0
- package/dist/tools/write-ass.js +102 -0
- package/dist/tools/write-ass.js.map +1 -0
- package/dist/tools/write-edl.d.ts +24 -0
- package/dist/tools/write-edl.d.ts.map +1 -0
- package/dist/tools/write-edl.js +60 -0
- package/dist/tools/write-edl.js.map +1 -0
- package/dist/tools/write-fcpxml.d.ts +20 -0
- package/dist/tools/write-fcpxml.d.ts.map +1 -0
- package/dist/tools/write-fcpxml.js +53 -0
- package/dist/tools/write-fcpxml.js.map +1 -0
- package/dist/tools/write-keyword-captions.d.ts +43 -0
- package/dist/tools/write-keyword-captions.d.ts.map +1 -0
- package/dist/tools/write-keyword-captions.js +215 -0
- package/dist/tools/write-keyword-captions.js.map +1 -0
- package/dist/tools/write-lower-third.d.ts +34 -0
- package/dist/tools/write-lower-third.d.ts.map +1 -0
- package/dist/tools/write-lower-third.js +53 -0
- package/dist/tools/write-lower-third.js.map +1 -0
- package/dist/tools/write-srt.d.ts +20 -0
- package/dist/tools/write-srt.d.ts.map +1 -0
- package/dist/tools/write-srt.js +73 -0
- package/dist/tools/write-srt.js.map +1 -0
- package/dist/tools/write-title-card.d.ts +25 -0
- package/dist/tools/write-title-card.d.ts.map +1 -0
- package/dist/tools/write-title-card.js +58 -0
- package/dist/tools/write-title-card.js.map +1 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/App.d.ts +56 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +524 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/components/Banner.d.ts +13 -0
- package/dist/ui/components/Banner.d.ts.map +1 -0
- package/dist/ui/components/Banner.js +59 -0
- package/dist/ui/components/Banner.js.map +1 -0
- package/dist/ui/render.d.ts +9 -0
- package/dist/ui/render.d.ts.map +1 -0
- package/dist/ui/render.js +56 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/tool-formatters.d.ts +30 -0
- package/dist/ui/tool-formatters.d.ts.map +1 -0
- package/dist/ui/tool-formatters.js +461 -0
- package/dist/ui/tool-formatters.js.map +1 -0
- package/dist/ui/tool-formatters.test.d.ts +2 -0
- package/dist/ui/tool-formatters.test.d.ts.map +1 -0
- package/dist/ui/tool-formatters.test.js +143 -0
- package/dist/ui/tool-formatters.test.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,1061 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded Python source for the Resolve bridge. Written to a temp file at
|
|
3
|
+
* first launch and spawned with python3.
|
|
4
|
+
*
|
|
5
|
+
* Protocol: one JSON object per stdin line (request), one JSON object per
|
|
6
|
+
* stdout line (response). All Resolve API access is wrapped in try/except so
|
|
7
|
+
* a single failed call cannot kill the bridge.
|
|
8
|
+
*
|
|
9
|
+
* Request: {"id": "1", "method": "get_timeline", "params": {}}
|
|
10
|
+
* Response: {"id": "1", "ok": true, "result": {...}}
|
|
11
|
+
* {"id": "1", "ok": false, "error": "..."}
|
|
12
|
+
*
|
|
13
|
+
* The bridge keeps the resolve / project / timeline references fresh by
|
|
14
|
+
* re-fetching them per call (cheap, and handles the user switching projects).
|
|
15
|
+
*/
|
|
16
|
+
export const BRIDGE_PY = String.raw `#!/usr/bin/env python3
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
import sys
|
|
20
|
+
import traceback
|
|
21
|
+
|
|
22
|
+
# Resolve loads its scripting module from a non-standard path. The TS wrapper
|
|
23
|
+
# guarantees PYTHONPATH already contains the right Modules dir, but we double-
|
|
24
|
+
# check here so the error is clear if not.
|
|
25
|
+
try:
|
|
26
|
+
import DaVinciResolveScript as dvr # type: ignore
|
|
27
|
+
except ModuleNotFoundError as e:
|
|
28
|
+
sys.stdout.write(json.dumps({
|
|
29
|
+
"id": "_bootstrap",
|
|
30
|
+
"ok": False,
|
|
31
|
+
"error": "DaVinciResolveScript not importable. Set RESOLVE_SCRIPT_API and PYTHONPATH. " + str(e),
|
|
32
|
+
}) + "\n")
|
|
33
|
+
sys.stdout.flush()
|
|
34
|
+
sys.exit(2)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_resolve():
|
|
38
|
+
r = dvr.scriptapp("Resolve")
|
|
39
|
+
if r is None:
|
|
40
|
+
raise RuntimeError("Could not connect to Resolve. Is the app running and is external scripting enabled in Preferences?")
|
|
41
|
+
return r
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_project():
|
|
45
|
+
r = get_resolve()
|
|
46
|
+
pm = r.GetProjectManager()
|
|
47
|
+
p = pm.GetCurrentProject()
|
|
48
|
+
if p is None:
|
|
49
|
+
raise RuntimeError("No project open in Resolve.")
|
|
50
|
+
return p
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_timeline_obj():
|
|
54
|
+
p = get_project()
|
|
55
|
+
t = p.GetCurrentTimeline()
|
|
56
|
+
if t is None:
|
|
57
|
+
raise RuntimeError("No timeline open in Resolve.")
|
|
58
|
+
return t
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# ── Helpers ─────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _find_timeline_item(clip_id):
|
|
65
|
+
t = get_timeline_obj()
|
|
66
|
+
cid = str(clip_id)
|
|
67
|
+
for kind in ("video", "audio"):
|
|
68
|
+
try:
|
|
69
|
+
count = int(t.GetTrackCount(kind))
|
|
70
|
+
except Exception:
|
|
71
|
+
count = 0
|
|
72
|
+
for ti in range(1, count + 1):
|
|
73
|
+
for item in (t.GetItemListInTrack(kind, ti) or []):
|
|
74
|
+
try:
|
|
75
|
+
iid = str(item.GetUniqueId()) if hasattr(item, "GetUniqueId") else item.GetName()
|
|
76
|
+
except Exception:
|
|
77
|
+
iid = None
|
|
78
|
+
if iid == cid:
|
|
79
|
+
return item
|
|
80
|
+
raise RuntimeError(f"clip not found on timeline: {clip_id}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ── Method implementations ──────────────────────────────────
|
|
84
|
+
|
|
85
|
+
def m_ping(_params):
|
|
86
|
+
r = get_resolve()
|
|
87
|
+
return {"pong": True, "product": r.GetProductName(), "version": r.GetVersionString()}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def m_get_timeline(_params):
|
|
91
|
+
t = get_timeline_obj()
|
|
92
|
+
fr = float(t.GetSetting("timelineFrameRate") or 24.0)
|
|
93
|
+
start_frame = int(t.GetStartFrame())
|
|
94
|
+
end_frame = int(t.GetEndFrame())
|
|
95
|
+
|
|
96
|
+
clips = []
|
|
97
|
+
for kind in ("video", "audio"):
|
|
98
|
+
try:
|
|
99
|
+
count = int(t.GetTrackCount(kind))
|
|
100
|
+
except Exception:
|
|
101
|
+
count = 0
|
|
102
|
+
for ti in range(1, count + 1):
|
|
103
|
+
items = t.GetItemListInTrack(kind, ti) or []
|
|
104
|
+
for item in items:
|
|
105
|
+
try:
|
|
106
|
+
clips.append({
|
|
107
|
+
"id": str(item.GetUniqueId()) if hasattr(item, "GetUniqueId") else item.GetName(),
|
|
108
|
+
"track": ti,
|
|
109
|
+
"trackKind": kind,
|
|
110
|
+
"startFrame": int(item.GetStart()) - start_frame,
|
|
111
|
+
"endFrame": int(item.GetEnd()) - start_frame,
|
|
112
|
+
"name": item.GetName(),
|
|
113
|
+
})
|
|
114
|
+
except Exception:
|
|
115
|
+
# Skip clips we can't introspect (compound/timeline items)
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
markers_dict = t.GetMarkers() or {}
|
|
119
|
+
markers = []
|
|
120
|
+
for frame_id, info in markers_dict.items():
|
|
121
|
+
markers.append({
|
|
122
|
+
"frame": int(frame_id),
|
|
123
|
+
"note": info.get("note", "") or info.get("name", ""),
|
|
124
|
+
"color": info.get("color"),
|
|
125
|
+
"durationFrames": int(info.get("duration", 1)),
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
"name": t.GetName(),
|
|
130
|
+
"frameRate": fr,
|
|
131
|
+
"durationFrames": end_frame - start_frame,
|
|
132
|
+
"clips": clips,
|
|
133
|
+
"markers": markers,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def m_add_marker(params):
|
|
138
|
+
t = get_timeline_obj()
|
|
139
|
+
frame = int(params["frame"])
|
|
140
|
+
note = str(params.get("note", ""))
|
|
141
|
+
color = str(params.get("color", "Blue")).capitalize()
|
|
142
|
+
duration = int(params.get("durationFrames", 1) or 1)
|
|
143
|
+
# Resolve marker color names: Blue, Cyan, Green, Yellow, Red, Pink, Purple,
|
|
144
|
+
# Fuchsia, Rose, Lavender, Sky, Mint, Lemon, Sand, Cocoa, Cream
|
|
145
|
+
ok = t.AddMarker(frame, color, note[:60], note, duration, "")
|
|
146
|
+
if not ok:
|
|
147
|
+
raise RuntimeError("AddMarker returned False (frame may already have a marker, or be out of range).")
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def m_append_clip(params):
|
|
152
|
+
project = get_project()
|
|
153
|
+
media_pool = project.GetMediaPool()
|
|
154
|
+
media_path = params["mediaPath"]
|
|
155
|
+
track = int(params.get("track", 1))
|
|
156
|
+
|
|
157
|
+
# Import the file into the media pool first.
|
|
158
|
+
media_storage = get_resolve().GetMediaStorage()
|
|
159
|
+
items = media_storage.AddItemListToMediaPool([media_path]) or []
|
|
160
|
+
if not items:
|
|
161
|
+
raise RuntimeError(f"Failed to import {media_path} into the media pool.")
|
|
162
|
+
|
|
163
|
+
# AppendToTimeline appends to the end of whatever the current timeline is.
|
|
164
|
+
# Track index is honoured for audio-only / video-only items; for AV items
|
|
165
|
+
# the audio component goes to A1 by default.
|
|
166
|
+
appended = media_pool.AppendToTimeline(items) or []
|
|
167
|
+
if not appended:
|
|
168
|
+
raise RuntimeError("AppendToTimeline returned no items.")
|
|
169
|
+
|
|
170
|
+
item = appended[0]
|
|
171
|
+
t = get_timeline_obj()
|
|
172
|
+
start_frame = int(t.GetStartFrame())
|
|
173
|
+
return {
|
|
174
|
+
"id": str(item.GetUniqueId()) if hasattr(item, "GetUniqueId") else item.GetName(),
|
|
175
|
+
"track": track,
|
|
176
|
+
"trackKind": "video",
|
|
177
|
+
"startFrame": int(item.GetStart()) - start_frame,
|
|
178
|
+
"endFrame": int(item.GetEnd()) - start_frame,
|
|
179
|
+
"name": item.GetName(),
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def m_import_timeline(params):
|
|
184
|
+
project = get_project()
|
|
185
|
+
media_pool = project.GetMediaPool()
|
|
186
|
+
file_path = params["filePath"]
|
|
187
|
+
timeline = media_pool.ImportTimelineFromFile(file_path, {})
|
|
188
|
+
if timeline is None:
|
|
189
|
+
raise RuntimeError(f"ImportTimelineFromFile returned None for {file_path}.")
|
|
190
|
+
return {"name": timeline.GetName()}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def m_render(params):
|
|
194
|
+
project = get_project()
|
|
195
|
+
preset = params["preset"]
|
|
196
|
+
output_path = params["output"]
|
|
197
|
+
|
|
198
|
+
if not project.LoadRenderPreset(preset):
|
|
199
|
+
# Try as a built-in preset key. List available so the agent can recover.
|
|
200
|
+
available = project.GetRenderPresetList() or []
|
|
201
|
+
raise RuntimeError(f"Render preset not found: {preset}. Available: {available[:10]}")
|
|
202
|
+
|
|
203
|
+
out_dir = os.path.dirname(output_path) or "."
|
|
204
|
+
out_file = os.path.basename(output_path)
|
|
205
|
+
project.SetRenderSettings({
|
|
206
|
+
"TargetDir": out_dir,
|
|
207
|
+
"CustomName": os.path.splitext(out_file)[0],
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
job_id = project.AddRenderJob()
|
|
211
|
+
if not job_id:
|
|
212
|
+
raise RuntimeError("AddRenderJob failed.")
|
|
213
|
+
project.StartRendering([job_id], False)
|
|
214
|
+
|
|
215
|
+
# Block until done.
|
|
216
|
+
import time
|
|
217
|
+
while project.IsRenderingInProgress():
|
|
218
|
+
time.sleep(0.5)
|
|
219
|
+
|
|
220
|
+
return {"jobId": job_id, "output": output_path}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def m_get_markers(_params):
|
|
224
|
+
t = get_timeline_obj()
|
|
225
|
+
markers_dict = t.GetMarkers() or {}
|
|
226
|
+
out = []
|
|
227
|
+
for frame_id, info in markers_dict.items():
|
|
228
|
+
out.append({
|
|
229
|
+
"frame": int(frame_id),
|
|
230
|
+
"note": info.get("note", "") or info.get("name", ""),
|
|
231
|
+
"color": info.get("color"),
|
|
232
|
+
"durationFrames": int(info.get("duration", 1)),
|
|
233
|
+
})
|
|
234
|
+
return out
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def m_create_timeline(params):
|
|
238
|
+
project = get_project()
|
|
239
|
+
media_pool = project.GetMediaPool()
|
|
240
|
+
name = str(params["name"])
|
|
241
|
+
fps = params.get("fps")
|
|
242
|
+
width = params.get("width")
|
|
243
|
+
height = params.get("height")
|
|
244
|
+
|
|
245
|
+
# Project-level frame rate must be set BEFORE creating the timeline; once a
|
|
246
|
+
# project has timelines, the frame rate becomes locked. We try, and if it
|
|
247
|
+
# fails because timelines exist, the new timeline will inherit project fps.
|
|
248
|
+
if fps is not None:
|
|
249
|
+
try:
|
|
250
|
+
project.SetSetting("timelineFrameRate", str(float(fps)))
|
|
251
|
+
except Exception:
|
|
252
|
+
pass
|
|
253
|
+
|
|
254
|
+
timeline = media_pool.CreateEmptyTimeline(name)
|
|
255
|
+
if timeline is None:
|
|
256
|
+
raise RuntimeError("CreateEmptyTimeline returned None.")
|
|
257
|
+
|
|
258
|
+
if width is not None:
|
|
259
|
+
try:
|
|
260
|
+
timeline.SetSetting("useCustomSettings", "1")
|
|
261
|
+
timeline.SetSetting("timelineResolutionWidth", str(int(width)))
|
|
262
|
+
except Exception:
|
|
263
|
+
pass
|
|
264
|
+
if height is not None:
|
|
265
|
+
try:
|
|
266
|
+
timeline.SetSetting("timelineResolutionHeight", str(int(height)))
|
|
267
|
+
except Exception:
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
return {"name": timeline.GetName()}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def m_import_to_media_pool(params):
|
|
274
|
+
project = get_project()
|
|
275
|
+
media_pool = project.GetMediaPool()
|
|
276
|
+
paths = list(params.get("paths") or [])
|
|
277
|
+
bin_name = params.get("bin")
|
|
278
|
+
|
|
279
|
+
if bin_name:
|
|
280
|
+
# Walk top-level bins for a name match; create if absent.
|
|
281
|
+
root = media_pool.GetRootFolder()
|
|
282
|
+
target = None
|
|
283
|
+
for sub in root.GetSubFolderList() or []:
|
|
284
|
+
if sub.GetName() == bin_name:
|
|
285
|
+
target = sub
|
|
286
|
+
break
|
|
287
|
+
if target is None:
|
|
288
|
+
target = media_pool.AddSubFolder(root, bin_name)
|
|
289
|
+
if target is not None:
|
|
290
|
+
media_pool.SetCurrentFolder(target)
|
|
291
|
+
|
|
292
|
+
media_storage = get_resolve().GetMediaStorage()
|
|
293
|
+
items = media_storage.AddItemListToMediaPool(paths) or []
|
|
294
|
+
return {"imported": len(items)}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def m_open_page(params):
|
|
298
|
+
r = get_resolve()
|
|
299
|
+
name = str(params["name"]).lower()
|
|
300
|
+
valid = {"media", "cut", "edit", "fusion", "color", "fairlight", "deliver"}
|
|
301
|
+
if name not in valid:
|
|
302
|
+
raise RuntimeError(f"unknown page: {name}; valid: {sorted(valid)}")
|
|
303
|
+
ok = r.OpenPage(name)
|
|
304
|
+
if not ok:
|
|
305
|
+
raise RuntimeError(f"OpenPage('{name}') returned False.")
|
|
306
|
+
return None
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def m_set_clip_speed(params):
|
|
310
|
+
clip_id = str(params["clipId"])
|
|
311
|
+
speed = float(params["speed"])
|
|
312
|
+
if speed <= 0:
|
|
313
|
+
raise RuntimeError("speed must be > 0")
|
|
314
|
+
found = _find_timeline_item(clip_id)
|
|
315
|
+
|
|
316
|
+
last_err = None
|
|
317
|
+
# Try several APIs; Resolve versions differ.
|
|
318
|
+
for setter in (
|
|
319
|
+
lambda i: i.SetClipProperty("Speed", str(speed * 100.0)),
|
|
320
|
+
lambda i: i.SetProperty("Speed", speed),
|
|
321
|
+
lambda i: i.SetClipProperty("Speed", speed),
|
|
322
|
+
):
|
|
323
|
+
try:
|
|
324
|
+
ok = setter(found)
|
|
325
|
+
if ok:
|
|
326
|
+
return {"clipId": clip_id, "speed": speed}
|
|
327
|
+
except Exception as e:
|
|
328
|
+
last_err = e
|
|
329
|
+
raise RuntimeError(
|
|
330
|
+
f"Resolve refused all clip-speed setters for this version. Last error: {last_err}. "
|
|
331
|
+
f"fix: rebuild via FCPXML with explicit timeMap."
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def m_apply_lut(params):
|
|
336
|
+
import os as _os
|
|
337
|
+
clip_id = str(params["clipId"])
|
|
338
|
+
lut_path = str(params["lutPath"])
|
|
339
|
+
node_index = int(params.get("nodeIndex", 1) or 1)
|
|
340
|
+
if not _os.path.exists(lut_path):
|
|
341
|
+
raise RuntimeError(f"LUT file not found: {lut_path}")
|
|
342
|
+
item = _find_timeline_item(clip_id)
|
|
343
|
+
if not hasattr(item, "SetLUT"):
|
|
344
|
+
raise RuntimeError("this Resolve version's TimelineItem has no SetLUT")
|
|
345
|
+
ok = item.SetLUT(node_index, lut_path)
|
|
346
|
+
if not ok:
|
|
347
|
+
raise RuntimeError(
|
|
348
|
+
f"SetLUT returned False (node {node_index}, lut {lut_path}). "
|
|
349
|
+
f"fix: ensure node {node_index} exists; node 1 always does."
|
|
350
|
+
)
|
|
351
|
+
return {"clipId": clip_id, "lutPath": lut_path, "nodeIndex": node_index}
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _fmt3(triple):
|
|
355
|
+
return "%g %g %g" % (float(triple[0]), float(triple[1]), float(triple[2]))
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def _ensure_color_page():
|
|
359
|
+
"""Best-effort switch to the Color page when the current page isn't already
|
|
360
|
+
color. Returns True if we issued an OpenPage call, False otherwise. Used by
|
|
361
|
+
SetCDL / CopyGrades retry logic — those API calls silently no-op on the
|
|
362
|
+
wrong page even though the values land in the data model.
|
|
363
|
+
"""
|
|
364
|
+
try:
|
|
365
|
+
r = get_resolve()
|
|
366
|
+
cur = r.GetCurrentPage() if hasattr(r, "GetCurrentPage") else None
|
|
367
|
+
if cur == "color":
|
|
368
|
+
return False
|
|
369
|
+
r.OpenPage("color")
|
|
370
|
+
return True
|
|
371
|
+
except Exception:
|
|
372
|
+
return False
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def m_set_primary_correction(params):
|
|
376
|
+
clip_id = str(params["clipId"])
|
|
377
|
+
node_index = int(params.get("nodeIndex", 1) or 1)
|
|
378
|
+
item = _find_timeline_item(clip_id)
|
|
379
|
+
if not hasattr(item, "SetCDL"):
|
|
380
|
+
raise RuntimeError("this Resolve version's TimelineItem has no SetCDL")
|
|
381
|
+
cdl = {"NodeIndex": node_index}
|
|
382
|
+
if params.get("slope") is not None:
|
|
383
|
+
cdl["Slope"] = _fmt3(params["slope"])
|
|
384
|
+
if params.get("offset") is not None:
|
|
385
|
+
cdl["Offset"] = _fmt3(params["offset"])
|
|
386
|
+
if params.get("power") is not None:
|
|
387
|
+
cdl["Power"] = _fmt3(params["power"])
|
|
388
|
+
if params.get("saturation") is not None:
|
|
389
|
+
cdl["Saturation"] = "%g" % float(params["saturation"])
|
|
390
|
+
ok = item.SetCDL(cdl)
|
|
391
|
+
if not ok:
|
|
392
|
+
# Common cause: agent set CDL while user was on another page. Auto-
|
|
393
|
+
# switch to Color and retry once. If it fails again, the user/clip is
|
|
394
|
+
# genuinely the problem — surface the original message.
|
|
395
|
+
if _ensure_color_page():
|
|
396
|
+
ok = item.SetCDL(cdl)
|
|
397
|
+
if not ok:
|
|
398
|
+
raise RuntimeError(
|
|
399
|
+
f"SetCDL returned False for node {node_index}. "
|
|
400
|
+
f"fix: ensure the clip exists and the project's color page is reachable."
|
|
401
|
+
)
|
|
402
|
+
return {"clipId": clip_id, "nodeIndex": node_index}
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def m_copy_grade(params):
|
|
406
|
+
source_id = str(params["sourceClipId"])
|
|
407
|
+
target_ids = [str(x) for x in (params.get("targetClipIds") or [])]
|
|
408
|
+
if not target_ids:
|
|
409
|
+
raise RuntimeError("targetClipIds must be a non-empty list")
|
|
410
|
+
src = _find_timeline_item(source_id)
|
|
411
|
+
targets = [_find_timeline_item(tid) for tid in target_ids]
|
|
412
|
+
if not hasattr(src, "CopyGrades"):
|
|
413
|
+
raise RuntimeError("this Resolve version's TimelineItem has no CopyGrades")
|
|
414
|
+
ok = src.CopyGrades(targets)
|
|
415
|
+
if not ok:
|
|
416
|
+
if _ensure_color_page():
|
|
417
|
+
ok = src.CopyGrades(targets)
|
|
418
|
+
if not ok:
|
|
419
|
+
raise RuntimeError(
|
|
420
|
+
"CopyGrades returned False. fix: ensure source + targets are valid timeline items."
|
|
421
|
+
)
|
|
422
|
+
return {"sourceClipId": source_id, "copied": len(targets)}
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def m_list_render_presets(_params):
|
|
426
|
+
project = get_project()
|
|
427
|
+
presets = project.GetRenderPresetList() or []
|
|
428
|
+
return list(presets)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def m_replace_clip(params):
|
|
432
|
+
clip_id = str(params["clipId"])
|
|
433
|
+
media_path = str(params["mediaPath"])
|
|
434
|
+
item = _find_timeline_item(clip_id)
|
|
435
|
+
# Newer Resolve API: TimelineItem.ReplaceClip(media_path) or .ReplaceMedia.
|
|
436
|
+
last_err = None
|
|
437
|
+
for setter in (
|
|
438
|
+
lambda i: i.ReplaceClip(media_path) if hasattr(i, "ReplaceClip") else False,
|
|
439
|
+
lambda i: i.ReplaceMedia(media_path) if hasattr(i, "ReplaceMedia") else False,
|
|
440
|
+
):
|
|
441
|
+
try:
|
|
442
|
+
ok = setter(item)
|
|
443
|
+
if ok:
|
|
444
|
+
return {"clipId": clip_id, "mediaPath": media_path}
|
|
445
|
+
except Exception as e:
|
|
446
|
+
last_err = e
|
|
447
|
+
raise RuntimeError(
|
|
448
|
+
f"replace_clip not supported by this Resolve version. Last error: {last_err}. "
|
|
449
|
+
f"fix: rebuild the segment via FCPXML with the new media reference."
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def m_add_track(params):
|
|
454
|
+
t = get_timeline_obj()
|
|
455
|
+
kind = str(params.get("kind", "video"))
|
|
456
|
+
if kind not in ("video", "audio", "subtitle"):
|
|
457
|
+
raise RuntimeError(f"unknown track kind: {kind}")
|
|
458
|
+
if not hasattr(t, "AddTrack"):
|
|
459
|
+
raise RuntimeError("this Resolve version's Timeline has no AddTrack")
|
|
460
|
+
ok = t.AddTrack(kind)
|
|
461
|
+
if not ok:
|
|
462
|
+
raise RuntimeError(f"AddTrack({kind}) returned False")
|
|
463
|
+
try:
|
|
464
|
+
new_count = int(t.GetTrackCount(kind))
|
|
465
|
+
except Exception:
|
|
466
|
+
new_count = 0
|
|
467
|
+
return {"kind": kind, "track": new_count}
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def m_set_clip_volume(params):
|
|
471
|
+
clip_id = str(params["clipId"])
|
|
472
|
+
volume_db = float(params["volumeDb"])
|
|
473
|
+
item = _find_timeline_item(clip_id)
|
|
474
|
+
# Resolve audio clips expose Volume as a clip property in dB. Some versions
|
|
475
|
+
# accept dB directly; older versions need linear (10**(dB/20)). Try both.
|
|
476
|
+
last_err = None
|
|
477
|
+
for setter in (
|
|
478
|
+
lambda i: i.SetClipProperty("Volume", str(volume_db)),
|
|
479
|
+
lambda i: i.SetClipProperty("Volume", volume_db),
|
|
480
|
+
lambda i: i.SetClipProperty("Volume", str(10 ** (volume_db / 20.0))),
|
|
481
|
+
):
|
|
482
|
+
try:
|
|
483
|
+
ok = setter(item)
|
|
484
|
+
if ok:
|
|
485
|
+
return {"clipId": clip_id, "volumeDb": volume_db}
|
|
486
|
+
except Exception as e:
|
|
487
|
+
last_err = e
|
|
488
|
+
raise RuntimeError(
|
|
489
|
+
f"Resolve refused all volume setters. Last error: {last_err}. "
|
|
490
|
+
f"fix: adjust volume manually on the Fairlight page."
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def m_clone_timeline(params):
|
|
495
|
+
project = get_project()
|
|
496
|
+
pm = get_resolve().GetProjectManager()
|
|
497
|
+
src = project.GetCurrentTimeline()
|
|
498
|
+
if src is None:
|
|
499
|
+
raise RuntimeError("No active timeline to clone.")
|
|
500
|
+
new_name = str(params["newName"])
|
|
501
|
+
# Resolve API: TimelineItem dup is via Timeline.DuplicateTimeline(name).
|
|
502
|
+
if not hasattr(src, "DuplicateTimeline"):
|
|
503
|
+
raise RuntimeError("this Resolve version's Timeline has no DuplicateTimeline")
|
|
504
|
+
new_tl = src.DuplicateTimeline(new_name)
|
|
505
|
+
if new_tl is None:
|
|
506
|
+
raise RuntimeError("DuplicateTimeline returned None")
|
|
507
|
+
project.SetCurrentTimeline(new_tl)
|
|
508
|
+
pm.SaveProject()
|
|
509
|
+
return {"name": new_tl.GetName()}
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
def m_save_project(_params):
|
|
513
|
+
pm = get_resolve().GetProjectManager()
|
|
514
|
+
ok = pm.SaveProject()
|
|
515
|
+
if not ok:
|
|
516
|
+
raise RuntimeError("SaveProject returned False")
|
|
517
|
+
return None
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def m_insert_clip_on_track(params):
|
|
521
|
+
project = get_project()
|
|
522
|
+
media_pool = project.GetMediaPool()
|
|
523
|
+
media_path = str(params["mediaPath"])
|
|
524
|
+
track = int(params.get("track", 2))
|
|
525
|
+
record_frame = int(params["recordFrame"])
|
|
526
|
+
|
|
527
|
+
# Import media into the pool first.
|
|
528
|
+
media_storage = get_resolve().GetMediaStorage()
|
|
529
|
+
items = media_storage.AddItemListToMediaPool([media_path]) or []
|
|
530
|
+
if not items:
|
|
531
|
+
raise RuntimeError(f"failed to import {media_path} into media pool")
|
|
532
|
+
item = items[0]
|
|
533
|
+
|
|
534
|
+
# mediaKind selects video (1) or audio (2) timeline track. AppendToTimeline
|
|
535
|
+
# uses this to know which track family to operate on — critical for
|
|
536
|
+
# SFX/foley insertion onto Fairlight tracks (audio_only=2).
|
|
537
|
+
media_kind = str(params.get("mediaKind", "video")).lower()
|
|
538
|
+
media_type = 2 if media_kind == "audio" else 1
|
|
539
|
+
clip_info = {
|
|
540
|
+
"mediaPoolItem": item,
|
|
541
|
+
"mediaType": media_type,
|
|
542
|
+
"trackIndex": track,
|
|
543
|
+
"recordFrame": record_frame,
|
|
544
|
+
}
|
|
545
|
+
if params.get("sourceInFrame") is not None:
|
|
546
|
+
clip_info["startFrame"] = int(params["sourceInFrame"])
|
|
547
|
+
if params.get("sourceOutFrame") is not None:
|
|
548
|
+
clip_info["endFrame"] = int(params["sourceOutFrame"])
|
|
549
|
+
|
|
550
|
+
appended = media_pool.AppendToTimeline([clip_info]) or []
|
|
551
|
+
if not appended:
|
|
552
|
+
raise RuntimeError(
|
|
553
|
+
"AppendToTimeline returned no items; verify track index exists and recordFrame is within the timeline."
|
|
554
|
+
)
|
|
555
|
+
inserted = appended[0]
|
|
556
|
+
t = get_timeline_obj()
|
|
557
|
+
start_offset = int(t.GetStartFrame())
|
|
558
|
+
return {
|
|
559
|
+
"id": str(inserted.GetUniqueId()) if hasattr(inserted, "GetUniqueId") else inserted.GetName(),
|
|
560
|
+
"track": track,
|
|
561
|
+
"trackKind": "video",
|
|
562
|
+
"startFrame": int(inserted.GetStart()) - start_offset,
|
|
563
|
+
"endFrame": int(inserted.GetEnd()) - start_offset,
|
|
564
|
+
"name": inserted.GetName(),
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
def m_smart_reframe(params):
|
|
569
|
+
clip_id = str(params["clipId"])
|
|
570
|
+
aspect = str(params["aspect"])
|
|
571
|
+
frame_interest = str(params.get("frameInterest", "all"))
|
|
572
|
+
reference_frame = params.get("referenceFrame")
|
|
573
|
+
item = _find_timeline_item(clip_id)
|
|
574
|
+
if not hasattr(item, "SmartReframe"):
|
|
575
|
+
raise RuntimeError(
|
|
576
|
+
"this Resolve version's TimelineItem has no SmartReframe (Studio-only feature)"
|
|
577
|
+
)
|
|
578
|
+
# SmartReframe signature varies; pass aspect always, then optional kwargs.
|
|
579
|
+
try:
|
|
580
|
+
if reference_frame is not None and frame_interest == "reference-frame":
|
|
581
|
+
ok = item.SmartReframe(aspect, frame_interest, int(reference_frame))
|
|
582
|
+
else:
|
|
583
|
+
ok = item.SmartReframe(aspect, frame_interest)
|
|
584
|
+
except TypeError:
|
|
585
|
+
ok = item.SmartReframe(aspect)
|
|
586
|
+
if not ok:
|
|
587
|
+
raise RuntimeError(
|
|
588
|
+
"SmartReframe returned False. fix: ensure Resolve Studio (free version lacks AI), and the clip is on the active timeline."
|
|
589
|
+
)
|
|
590
|
+
return {"clipId": clip_id, "aspect": aspect}
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def m_import_subtitles(params):
|
|
594
|
+
project = get_project()
|
|
595
|
+
media_pool = project.GetMediaPool()
|
|
596
|
+
srt_path = params["srtPath"]
|
|
597
|
+
|
|
598
|
+
items = media_pool.ImportMedia([srt_path]) or []
|
|
599
|
+
if not items:
|
|
600
|
+
raise RuntimeError(
|
|
601
|
+
f"ImportMedia returned no items for {srt_path}. fix: import the SRT manually via File > Import Subtitle."
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
t = get_timeline_obj()
|
|
605
|
+
# Make sure at least one subtitle track exists.
|
|
606
|
+
try:
|
|
607
|
+
sub_count = int(t.GetTrackCount("subtitle"))
|
|
608
|
+
except Exception:
|
|
609
|
+
sub_count = 0
|
|
610
|
+
if sub_count < 1:
|
|
611
|
+
try:
|
|
612
|
+
t.AddTrack("subtitle")
|
|
613
|
+
except Exception:
|
|
614
|
+
pass
|
|
615
|
+
|
|
616
|
+
# Anchor the SRT at the timeline's start. AppendToTimeline(items) without
|
|
617
|
+
# a clip-info dict appends to the END of existing content on the chosen
|
|
618
|
+
# track — so if the subtitle track already has clips, OR Resolve picks the
|
|
619
|
+
# video track's tail, the SRT's 0s cue lands at frame N>0 and every cue
|
|
620
|
+
# past (timelineLength - N) seconds falls past the end of the video and
|
|
621
|
+
# never renders. Forcing recordFrame=GetStartFrame() pins the SRT to the
|
|
622
|
+
# start so its internal timecodes line up with the video.
|
|
623
|
+
start_frame = int(t.GetStartFrame())
|
|
624
|
+
clip_info = {
|
|
625
|
+
"mediaPoolItem": items[0],
|
|
626
|
+
"recordFrame": start_frame,
|
|
627
|
+
}
|
|
628
|
+
appended = media_pool.AppendToTimeline([clip_info]) or []
|
|
629
|
+
if not appended:
|
|
630
|
+
# Fallback to the legacy raw-items form. Some Resolve builds reject the
|
|
631
|
+
# dict form for subtitle media — if so, the user gets the same
|
|
632
|
+
# end-append behaviour as before but at least the SRT lands somewhere.
|
|
633
|
+
appended = media_pool.AppendToTimeline(items) or []
|
|
634
|
+
if not appended:
|
|
635
|
+
return {
|
|
636
|
+
"imported": True,
|
|
637
|
+
"attached": False,
|
|
638
|
+
"note": "SRT imported to media pool but auto-attach failed; drag onto subtitle track manually.",
|
|
639
|
+
}
|
|
640
|
+
return {
|
|
641
|
+
"imported": True,
|
|
642
|
+
"attached": True,
|
|
643
|
+
"note": "SRT attached at end of timeline (Resolve rejected recordFrame=0). Move the subtitle clip back to frame 0 manually if cues appear past the video end.",
|
|
644
|
+
}
|
|
645
|
+
return {"imported": True, "attached": True}
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
# ── Fusion ──────────────────────────────────────────────────
|
|
649
|
+
#
|
|
650
|
+
# Fusion compositions live either at the timeline-clip level (every
|
|
651
|
+
# TimelineItem can carry one or more 'Fusion comps') OR at the project level
|
|
652
|
+
# via the standalone Fusion page. The agent operates on whichever the user
|
|
653
|
+
# is currently focused on — we resolve the comp once per call:
|
|
654
|
+
#
|
|
655
|
+
# - clipId given: item.GetFusionCompByIndex(1) on that timeline item.
|
|
656
|
+
# - no clipId: fusion.GetCurrentComp() on the active Fusion page.
|
|
657
|
+
#
|
|
658
|
+
# We deliberately keep the surface narrow (8 actions, the Fusion-page tools
|
|
659
|
+
# every short-form workflow needs) instead of mirroring the entire Fusion
|
|
660
|
+
# Python API. Power users have m_execute_code for the rest.
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def _resolve_fusion_comp(clip_id):
|
|
664
|
+
if clip_id:
|
|
665
|
+
item = _find_timeline_item(clip_id)
|
|
666
|
+
if not hasattr(item, "GetFusionCompCount") or not hasattr(item, "GetFusionCompByIndex"):
|
|
667
|
+
raise RuntimeError("this Resolve version's TimelineItem has no Fusion comp accessors")
|
|
668
|
+
count = int(item.GetFusionCompCount() or 0)
|
|
669
|
+
if count < 1:
|
|
670
|
+
# Try to add one. Modern Resolve exposes AddFusionComp; older
|
|
671
|
+
# builds need the user to do it manually on the Fusion page.
|
|
672
|
+
if hasattr(item, "AddFusionComp"):
|
|
673
|
+
comp = item.AddFusionComp()
|
|
674
|
+
if comp is None:
|
|
675
|
+
raise RuntimeError(f"AddFusionComp returned None for clip {clip_id}")
|
|
676
|
+
return comp
|
|
677
|
+
raise RuntimeError(
|
|
678
|
+
f"clip {clip_id} has no Fusion comp; create one in Resolve (right-click → New Fusion Composition) first."
|
|
679
|
+
)
|
|
680
|
+
comp = item.GetFusionCompByIndex(1)
|
|
681
|
+
if comp is None:
|
|
682
|
+
raise RuntimeError(f"GetFusionCompByIndex(1) returned None for clip {clip_id}")
|
|
683
|
+
return comp
|
|
684
|
+
# No clip — use the active Fusion page comp.
|
|
685
|
+
r = get_resolve()
|
|
686
|
+
try:
|
|
687
|
+
fusion = r.Fusion()
|
|
688
|
+
except Exception as e:
|
|
689
|
+
raise RuntimeError(f"Resolve.Fusion() unavailable: {e}")
|
|
690
|
+
if fusion is None:
|
|
691
|
+
raise RuntimeError("Fusion is not available in this Resolve build")
|
|
692
|
+
comp = fusion.GetCurrentComp() if hasattr(fusion, "GetCurrentComp") else None
|
|
693
|
+
if comp is None:
|
|
694
|
+
raise RuntimeError(
|
|
695
|
+
"No active Fusion comp. fix: switch to the Fusion page (open_page('fusion')) on a clip with a comp, or pass clipId."
|
|
696
|
+
)
|
|
697
|
+
return comp
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
def _fusion_node_summary(node):
|
|
701
|
+
# Best-effort, never throws — the caller is reading a list of nodes.
|
|
702
|
+
try:
|
|
703
|
+
name = node.GetAttrs("TOOLS_Name") if hasattr(node, "GetAttrs") else None
|
|
704
|
+
except Exception:
|
|
705
|
+
name = None
|
|
706
|
+
try:
|
|
707
|
+
toolid = node.GetAttrs("TOOLS_RegID") if hasattr(node, "GetAttrs") else None
|
|
708
|
+
except Exception:
|
|
709
|
+
toolid = None
|
|
710
|
+
if not name and hasattr(node, "Name"):
|
|
711
|
+
try:
|
|
712
|
+
name = node.Name
|
|
713
|
+
except Exception:
|
|
714
|
+
pass
|
|
715
|
+
if not toolid and hasattr(node, "ID"):
|
|
716
|
+
try:
|
|
717
|
+
toolid = node.ID
|
|
718
|
+
except Exception:
|
|
719
|
+
pass
|
|
720
|
+
return {"name": name, "toolId": toolid}
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
def m_fusion_comp(params):
|
|
724
|
+
action = str(params.get("action") or "")
|
|
725
|
+
if not action:
|
|
726
|
+
raise RuntimeError("fusion_comp requires an 'action' field")
|
|
727
|
+
clip_id = params.get("clipId")
|
|
728
|
+
comp = _resolve_fusion_comp(str(clip_id) if clip_id else None)
|
|
729
|
+
|
|
730
|
+
if action == "list_nodes":
|
|
731
|
+
nodes = []
|
|
732
|
+
try:
|
|
733
|
+
tool_list = comp.GetToolList(False) or {}
|
|
734
|
+
except Exception as e:
|
|
735
|
+
raise RuntimeError(f"GetToolList failed: {e}")
|
|
736
|
+
# GetToolList returns a 1-indexed dict on some builds; iterate values.
|
|
737
|
+
try:
|
|
738
|
+
iterator = tool_list.values() if hasattr(tool_list, "values") else list(tool_list)
|
|
739
|
+
except Exception:
|
|
740
|
+
iterator = []
|
|
741
|
+
for node in iterator:
|
|
742
|
+
nodes.append(_fusion_node_summary(node))
|
|
743
|
+
return {"nodes": nodes, "count": len(nodes)}
|
|
744
|
+
|
|
745
|
+
if action == "add_node":
|
|
746
|
+
tool_id = str(params.get("toolId") or "")
|
|
747
|
+
if not tool_id:
|
|
748
|
+
raise RuntimeError("add_node requires 'toolId' (e.g. 'TextPlus', 'Background', 'Merge')")
|
|
749
|
+
if not hasattr(comp, "AddTool"):
|
|
750
|
+
raise RuntimeError("this Resolve build's Comp has no AddTool")
|
|
751
|
+
node = comp.AddTool(tool_id)
|
|
752
|
+
if node is None:
|
|
753
|
+
raise RuntimeError(f"AddTool('{tool_id}') returned None; verify the tool ID exists")
|
|
754
|
+
wanted_name = params.get("name")
|
|
755
|
+
if wanted_name and hasattr(node, "SetAttrs"):
|
|
756
|
+
try:
|
|
757
|
+
node.SetAttrs({"TOOLS_Name": str(wanted_name)})
|
|
758
|
+
except Exception:
|
|
759
|
+
pass
|
|
760
|
+
return _fusion_node_summary(node)
|
|
761
|
+
|
|
762
|
+
if action == "delete_node":
|
|
763
|
+
name = str(params.get("name") or "")
|
|
764
|
+
if not name:
|
|
765
|
+
raise RuntimeError("delete_node requires 'name'")
|
|
766
|
+
node = comp.FindTool(name) if hasattr(comp, "FindTool") else None
|
|
767
|
+
if node is None:
|
|
768
|
+
raise RuntimeError(f"node not found: {name}")
|
|
769
|
+
if not hasattr(node, "Delete"):
|
|
770
|
+
raise RuntimeError("this Resolve build's Tool has no Delete")
|
|
771
|
+
node.Delete()
|
|
772
|
+
return {"deleted": name}
|
|
773
|
+
|
|
774
|
+
if action == "connect":
|
|
775
|
+
from_name = str(params.get("fromNode") or "")
|
|
776
|
+
to_name = str(params.get("toNode") or "")
|
|
777
|
+
from_output = str(params.get("fromOutput") or "Output")
|
|
778
|
+
to_input = str(params.get("toInput") or "Input")
|
|
779
|
+
if not from_name or not to_name:
|
|
780
|
+
raise RuntimeError("connect requires 'fromNode' and 'toNode'")
|
|
781
|
+
a = comp.FindTool(from_name)
|
|
782
|
+
b = comp.FindTool(to_name)
|
|
783
|
+
if a is None or b is None:
|
|
784
|
+
raise RuntimeError(f"node not found (from={from_name}, to={to_name})")
|
|
785
|
+
try:
|
|
786
|
+
out = a.FindMainOutput(1) if from_output == "Output" else getattr(a, from_output, None)
|
|
787
|
+
except Exception:
|
|
788
|
+
out = None
|
|
789
|
+
if out is None:
|
|
790
|
+
raise RuntimeError(f"output '{from_output}' not found on {from_name}")
|
|
791
|
+
try:
|
|
792
|
+
inp = getattr(b, to_input, None)
|
|
793
|
+
if inp is None and hasattr(b, "FindMainInput"):
|
|
794
|
+
inp = b.FindMainInput(1)
|
|
795
|
+
except Exception:
|
|
796
|
+
inp = None
|
|
797
|
+
if inp is None:
|
|
798
|
+
raise RuntimeError(f"input '{to_input}' not found on {to_name}")
|
|
799
|
+
try:
|
|
800
|
+
inp.ConnectTo(out)
|
|
801
|
+
except Exception as e:
|
|
802
|
+
raise RuntimeError(f"ConnectTo failed: {e}")
|
|
803
|
+
return {"from": from_name, "to": to_name}
|
|
804
|
+
|
|
805
|
+
if action == "set_input":
|
|
806
|
+
name = str(params.get("node") or "")
|
|
807
|
+
input_name = str(params.get("input") or "")
|
|
808
|
+
if not name or not input_name:
|
|
809
|
+
raise RuntimeError("set_input requires 'node' and 'input'")
|
|
810
|
+
if "value" not in params:
|
|
811
|
+
raise RuntimeError("set_input requires 'value'")
|
|
812
|
+
node = comp.FindTool(name)
|
|
813
|
+
if node is None:
|
|
814
|
+
raise RuntimeError(f"node not found: {name}")
|
|
815
|
+
try:
|
|
816
|
+
attr = getattr(node, input_name)
|
|
817
|
+
except Exception:
|
|
818
|
+
raise RuntimeError(f"input '{input_name}' not found on {name}")
|
|
819
|
+
try:
|
|
820
|
+
# Fusion inputs accept assignment directly: node.Input = value.
|
|
821
|
+
setattr(node, input_name, params["value"])
|
|
822
|
+
except Exception as e:
|
|
823
|
+
raise RuntimeError(f"set_input failed: {e}")
|
|
824
|
+
return {"node": name, "input": input_name}
|
|
825
|
+
|
|
826
|
+
if action == "get_input":
|
|
827
|
+
name = str(params.get("node") or "")
|
|
828
|
+
input_name = str(params.get("input") or "")
|
|
829
|
+
if not name or not input_name:
|
|
830
|
+
raise RuntimeError("get_input requires 'node' and 'input'")
|
|
831
|
+
node = comp.FindTool(name)
|
|
832
|
+
if node is None:
|
|
833
|
+
raise RuntimeError(f"node not found: {name}")
|
|
834
|
+
try:
|
|
835
|
+
attr = getattr(node, input_name)
|
|
836
|
+
except Exception:
|
|
837
|
+
raise RuntimeError(f"input '{input_name}' not found on {name}")
|
|
838
|
+
value = None
|
|
839
|
+
try:
|
|
840
|
+
# Fusion inputs are callable for current-value access on some builds.
|
|
841
|
+
value = attr() if callable(attr) else attr
|
|
842
|
+
except Exception:
|
|
843
|
+
value = attr
|
|
844
|
+
try:
|
|
845
|
+
json.dumps(value)
|
|
846
|
+
except Exception:
|
|
847
|
+
value = repr(value)
|
|
848
|
+
return {"node": name, "input": input_name, "value": value}
|
|
849
|
+
|
|
850
|
+
if action == "set_keyframe":
|
|
851
|
+
name = str(params.get("node") or "")
|
|
852
|
+
input_name = str(params.get("input") or "")
|
|
853
|
+
frame = params.get("frame")
|
|
854
|
+
if frame is None or not name or not input_name or "value" not in params:
|
|
855
|
+
raise RuntimeError("set_keyframe requires 'node', 'input', 'frame', 'value'")
|
|
856
|
+
node = comp.FindTool(name)
|
|
857
|
+
if node is None:
|
|
858
|
+
raise RuntimeError(f"node not found: {name}")
|
|
859
|
+
try:
|
|
860
|
+
attr = getattr(node, input_name)
|
|
861
|
+
except Exception:
|
|
862
|
+
raise RuntimeError(f"input '{input_name}' not found on {name}")
|
|
863
|
+
try:
|
|
864
|
+
# Comp.SetKeyFrames is the canonical path; older builds use
|
|
865
|
+
# input.SetKeyFrames or .SetExpression. Try the modern one first.
|
|
866
|
+
ok = comp.SetKeyFrames({attr: {int(frame): params["value"]}})
|
|
867
|
+
except Exception:
|
|
868
|
+
ok = False
|
|
869
|
+
if not ok and hasattr(attr, "SetKeyFrames"):
|
|
870
|
+
try:
|
|
871
|
+
attr.SetKeyFrames({int(frame): params["value"]})
|
|
872
|
+
ok = True
|
|
873
|
+
except Exception:
|
|
874
|
+
ok = False
|
|
875
|
+
if not ok:
|
|
876
|
+
raise RuntimeError("could not set keyframe via Comp.SetKeyFrames or Input.SetKeyFrames")
|
|
877
|
+
return {"node": name, "input": input_name, "frame": int(frame)}
|
|
878
|
+
|
|
879
|
+
if action == "set_render_range":
|
|
880
|
+
start = params.get("start")
|
|
881
|
+
end = params.get("end")
|
|
882
|
+
if start is None or end is None:
|
|
883
|
+
raise RuntimeError("set_render_range requires 'start' and 'end'")
|
|
884
|
+
try:
|
|
885
|
+
comp.SetAttrs({"COMPN_RenderStart": int(start), "COMPN_RenderEnd": int(end)})
|
|
886
|
+
except Exception as e:
|
|
887
|
+
raise RuntimeError(f"SetAttrs failed: {e}")
|
|
888
|
+
return {"start": int(start), "end": int(end)}
|
|
889
|
+
|
|
890
|
+
raise RuntimeError(
|
|
891
|
+
f"unknown fusion_comp action: {action}; valid: list_nodes, add_node, delete_node, connect, set_input, get_input, set_keyframe, set_render_range"
|
|
892
|
+
)
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
def m_execute_code(params):
|
|
896
|
+
"""Escape hatch: run arbitrary user code with the Resolve API pre-bound.
|
|
897
|
+
|
|
898
|
+
Pre-bound globals available to the snippet:
|
|
899
|
+
resolve, project, projectManager, mediaPool, mediaStorage, timeline,
|
|
900
|
+
fusion (lazy — None if Fusion comp is unavailable), dvr (the
|
|
901
|
+
DaVinciResolveScript module itself).
|
|
902
|
+
|
|
903
|
+
Result delivery (in priority order):
|
|
904
|
+
1. Call set_result(value) — explicit, supports any JSON-serialisable value.
|
|
905
|
+
2. Assign to a top-level 'result' variable.
|
|
906
|
+
3. Otherwise: stdout text only.
|
|
907
|
+
|
|
908
|
+
stdout is captured and returned regardless. The snippet runs in the same
|
|
909
|
+
process as every other bridge call, so a crash here CAN take the bridge
|
|
910
|
+
down. We trap exceptions but a segfault in fusionscript.so cannot be caught.
|
|
911
|
+
"""
|
|
912
|
+
code = params.get("code")
|
|
913
|
+
if not isinstance(code, str) or not code.strip():
|
|
914
|
+
raise RuntimeError("execute_code requires a non-empty 'code' string.")
|
|
915
|
+
|
|
916
|
+
import io
|
|
917
|
+
import contextlib
|
|
918
|
+
|
|
919
|
+
resolve = get_resolve()
|
|
920
|
+
project_manager = resolve.GetProjectManager()
|
|
921
|
+
project = project_manager.GetCurrentProject() if project_manager else None
|
|
922
|
+
media_pool = project.GetMediaPool() if project else None
|
|
923
|
+
media_storage = resolve.GetMediaStorage()
|
|
924
|
+
try:
|
|
925
|
+
timeline = project.GetCurrentTimeline() if project else None
|
|
926
|
+
except Exception:
|
|
927
|
+
timeline = None
|
|
928
|
+
try:
|
|
929
|
+
fusion = resolve.Fusion()
|
|
930
|
+
except Exception:
|
|
931
|
+
fusion = None
|
|
932
|
+
|
|
933
|
+
# JSON-serialisability check that won't crash on Resolve API objects (which
|
|
934
|
+
# are PyRemoteObject and not JSON-able). Anything non-serialisable is
|
|
935
|
+
# coerced to its repr so the agent at least sees what came back.
|
|
936
|
+
def _safe(value):
|
|
937
|
+
try:
|
|
938
|
+
json.dumps(value)
|
|
939
|
+
return value
|
|
940
|
+
except Exception:
|
|
941
|
+
return repr(value)
|
|
942
|
+
|
|
943
|
+
holder = {"result": None, "set": False}
|
|
944
|
+
|
|
945
|
+
def set_result(value):
|
|
946
|
+
holder["result"] = _safe(value)
|
|
947
|
+
holder["set"] = True
|
|
948
|
+
|
|
949
|
+
g = {
|
|
950
|
+
"__builtins__": __builtins__,
|
|
951
|
+
"resolve": resolve,
|
|
952
|
+
"project": project,
|
|
953
|
+
"projectManager": project_manager,
|
|
954
|
+
"mediaPool": media_pool,
|
|
955
|
+
"mediaStorage": media_storage,
|
|
956
|
+
"timeline": timeline,
|
|
957
|
+
"fusion": fusion,
|
|
958
|
+
"dvr": dvr,
|
|
959
|
+
"set_result": set_result,
|
|
960
|
+
"json": json,
|
|
961
|
+
}
|
|
962
|
+
l = {}
|
|
963
|
+
|
|
964
|
+
buf = io.StringIO()
|
|
965
|
+
with contextlib.redirect_stdout(buf):
|
|
966
|
+
try:
|
|
967
|
+
exec(code, g, l)
|
|
968
|
+
except Exception as ex:
|
|
969
|
+
# Re-raise with the captured stdout attached so the agent gets both
|
|
970
|
+
# the print() output that ran before the crash AND the error.
|
|
971
|
+
stdout = buf.getvalue()
|
|
972
|
+
tail = ("\nstdout: " + stdout[-1500:]) if stdout else ""
|
|
973
|
+
raise RuntimeError(f"{ex.__class__.__name__}: {ex}{tail}") from ex
|
|
974
|
+
|
|
975
|
+
stdout = buf.getvalue()
|
|
976
|
+
|
|
977
|
+
# Result resolution: explicit set_result wins; else top-level 'result'.
|
|
978
|
+
if holder["set"]:
|
|
979
|
+
result_value = holder["result"]
|
|
980
|
+
elif "result" in l:
|
|
981
|
+
result_value = _safe(l["result"])
|
|
982
|
+
else:
|
|
983
|
+
result_value = None
|
|
984
|
+
|
|
985
|
+
out = {"result": result_value}
|
|
986
|
+
if stdout:
|
|
987
|
+
# Cap stdout to keep tool output token-economical.
|
|
988
|
+
if len(stdout) > 4000:
|
|
989
|
+
stdout = stdout[:2000] + "\n…[truncated]…\n" + stdout[-1500:]
|
|
990
|
+
out["stdout"] = stdout
|
|
991
|
+
return out
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
METHODS = {
|
|
995
|
+
"ping": m_ping,
|
|
996
|
+
"get_timeline": m_get_timeline,
|
|
997
|
+
"add_marker": m_add_marker,
|
|
998
|
+
"append_clip": m_append_clip,
|
|
999
|
+
"import_timeline": m_import_timeline,
|
|
1000
|
+
"render": m_render,
|
|
1001
|
+
"get_markers": m_get_markers,
|
|
1002
|
+
"create_timeline": m_create_timeline,
|
|
1003
|
+
"import_to_media_pool": m_import_to_media_pool,
|
|
1004
|
+
"open_page": m_open_page,
|
|
1005
|
+
"set_clip_speed": m_set_clip_speed,
|
|
1006
|
+
"apply_lut": m_apply_lut,
|
|
1007
|
+
"set_primary_correction": m_set_primary_correction,
|
|
1008
|
+
"copy_grade": m_copy_grade,
|
|
1009
|
+
"list_render_presets": m_list_render_presets,
|
|
1010
|
+
"replace_clip": m_replace_clip,
|
|
1011
|
+
"smart_reframe": m_smart_reframe,
|
|
1012
|
+
"insert_clip_on_track": m_insert_clip_on_track,
|
|
1013
|
+
"clone_timeline": m_clone_timeline,
|
|
1014
|
+
"save_project": m_save_project,
|
|
1015
|
+
"add_track": m_add_track,
|
|
1016
|
+
"set_clip_volume": m_set_clip_volume,
|
|
1017
|
+
"import_subtitles": m_import_subtitles,
|
|
1018
|
+
"fusion_comp": m_fusion_comp,
|
|
1019
|
+
"execute_code": m_execute_code,
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
def main():
|
|
1024
|
+
# Signal we're alive.
|
|
1025
|
+
sys.stdout.write(json.dumps({"id": "_ready", "ok": True, "result": {"ready": True}}) + "\n")
|
|
1026
|
+
sys.stdout.flush()
|
|
1027
|
+
|
|
1028
|
+
for line in sys.stdin:
|
|
1029
|
+
line = line.strip()
|
|
1030
|
+
if not line:
|
|
1031
|
+
continue
|
|
1032
|
+
try:
|
|
1033
|
+
req = json.loads(line)
|
|
1034
|
+
except json.JSONDecodeError as e:
|
|
1035
|
+
sys.stdout.write(json.dumps({"id": "_parse", "ok": False, "error": f"bad json: {e}"}) + "\n")
|
|
1036
|
+
sys.stdout.flush()
|
|
1037
|
+
continue
|
|
1038
|
+
|
|
1039
|
+
rid = req.get("id", "?")
|
|
1040
|
+
method = req.get("method", "")
|
|
1041
|
+
params = req.get("params", {}) or {}
|
|
1042
|
+
|
|
1043
|
+
fn = METHODS.get(method)
|
|
1044
|
+
if fn is None:
|
|
1045
|
+
sys.stdout.write(json.dumps({"id": rid, "ok": False, "error": f"unknown method: {method}"}) + "\n")
|
|
1046
|
+
sys.stdout.flush()
|
|
1047
|
+
continue
|
|
1048
|
+
|
|
1049
|
+
try:
|
|
1050
|
+
result = fn(params)
|
|
1051
|
+
sys.stdout.write(json.dumps({"id": rid, "ok": True, "result": result}) + "\n")
|
|
1052
|
+
except Exception as e:
|
|
1053
|
+
tb = traceback.format_exc(limit=2)
|
|
1054
|
+
sys.stdout.write(json.dumps({"id": rid, "ok": False, "error": f"{e.__class__.__name__}: {e}", "trace": tb}) + "\n")
|
|
1055
|
+
sys.stdout.flush()
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
if __name__ == "__main__":
|
|
1059
|
+
main()
|
|
1060
|
+
`;
|
|
1061
|
+
//# sourceMappingURL=bridge-source.js.map
|