davinci-resolve-mcp 2.57.4 → 2.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/AGENTS.md +20 -0
  2. package/CHANGELOG.md +197 -2
  3. package/LICENSE +1 -1
  4. package/README.md +73 -1
  5. package/bin/davinci-resolve-advanced-mcp.mjs +20 -0
  6. package/docs/README.md +19 -0
  7. package/docs/SKILL.md +62 -1
  8. package/docs/contributing.md +1 -1
  9. package/docs/guides/control-panel.md +9 -0
  10. package/docs/kernels/README.md +21 -0
  11. package/docs/kernels/audio-fairlight-kernel.md +22 -0
  12. package/docs/kernels/color-grade-kernel.md +51 -0
  13. package/docs/kernels/fusion-composition-kernel.md +17 -0
  14. package/docs/kernels/media-pool-ingest-kernel.md +20 -0
  15. package/docs/kernels/render-deliver-kernel.md +32 -0
  16. package/docs/kernels/timeline-conform-interchange-kernel.md +39 -0
  17. package/docs/kernels/timeline-edit-kernel.md +17 -0
  18. package/docs/process/release-process.md +29 -7
  19. package/docs/reference/api-coverage.md +1 -1
  20. package/docs/reference/api-limitations.md +38 -1
  21. package/install.py +27 -4
  22. package/package.json +23 -2
  23. package/resolve-advanced/README.md +194 -0
  24. package/resolve-advanced/package.json +50 -0
  25. package/resolve-advanced/server/black-balance.mjs +92 -0
  26. package/resolve-advanced/server/capabilities.mjs +86 -0
  27. package/resolve-advanced/server/cdl-io.mjs +76 -0
  28. package/resolve-advanced/server/contrast-normalize.mjs +180 -0
  29. package/resolve-advanced/server/db-patch.mjs +91 -0
  30. package/resolve-advanced/server/deliverable-entities.mjs +86 -0
  31. package/resolve-advanced/server/deliverable-qc.mjs +270 -0
  32. package/resolve-advanced/server/editorial.mjs +370 -0
  33. package/resolve-advanced/server/exposure-level.mjs +129 -0
  34. package/resolve-advanced/server/extract-frames.mjs +196 -0
  35. package/resolve-advanced/server/ffprobe-media.mjs +88 -0
  36. package/resolve-advanced/server/gamut-legal.mjs +112 -0
  37. package/resolve-advanced/server/grade-body-patch.mjs +246 -0
  38. package/resolve-advanced/server/grade-transfer.mjs +66 -0
  39. package/resolve-advanced/server/group-grade-read.mjs +137 -0
  40. package/resolve-advanced/server/index.mjs +105 -0
  41. package/resolve-advanced/server/lib.mjs +84 -0
  42. package/resolve-advanced/server/libs.mjs +65 -0
  43. package/resolve-advanced/server/lineage-db.mjs +479 -0
  44. package/resolve-advanced/server/lut-apply.mjs +61 -0
  45. package/resolve-advanced/server/match-to-reference.mjs +173 -0
  46. package/resolve-advanced/server/media-inventory.mjs +169 -0
  47. package/resolve-advanced/server/media-ops.mjs +243 -0
  48. package/resolve-advanced/server/node-meta-db.mjs +62 -0
  49. package/resolve-advanced/server/node-provenance.mjs +102 -0
  50. package/resolve-advanced/server/offline-ref-db.mjs +420 -0
  51. package/resolve-advanced/server/offline-ref.mjs +179 -0
  52. package/resolve-advanced/server/project-db.mjs +233 -0
  53. package/resolve-advanced/server/provenance-audit.mjs +210 -0
  54. package/resolve-advanced/server/qc-frame.mjs +224 -0
  55. package/resolve-advanced/server/qc-sampler.mjs +67 -0
  56. package/resolve-advanced/server/readback.mjs +77 -0
  57. package/resolve-advanced/server/render-manifest.mjs +93 -0
  58. package/resolve-advanced/server/reverse-clip-db.mjs +270 -0
  59. package/resolve-advanced/server/runner-apply-contract.mjs +64 -0
  60. package/resolve-advanced/server/runner.mjs +244 -0
  61. package/resolve-advanced/server/saturation-match.mjs +108 -0
  62. package/resolve-advanced/server/scope-read.mjs +257 -0
  63. package/resolve-advanced/server/season-look.mjs +96 -0
  64. package/resolve-advanced/server/shot-intent.mjs +82 -0
  65. package/resolve-advanced/server/shot-match.mjs +147 -0
  66. package/resolve-advanced/server/skin-match.mjs +205 -0
  67. package/resolve-advanced/server/spec-compile.mjs +217 -0
  68. package/resolve-advanced/server/tone-curve-transfer.mjs +184 -0
  69. package/resolve-advanced/server/tool-catalog.mjs +265 -0
  70. package/resolve-advanced/server/tools/audio.mjs +54 -0
  71. package/resolve-advanced/server/tools/audio_plan.mjs +58 -0
  72. package/resolve-advanced/server/tools/capabilities.mjs +16 -0
  73. package/resolve-advanced/server/tools/color_trace.mjs +165 -0
  74. package/resolve-advanced/server/tools/conform.mjs +291 -0
  75. package/resolve-advanced/server/tools/deliverable.mjs +105 -0
  76. package/resolve-advanced/server/tools/drp.mjs +232 -0
  77. package/resolve-advanced/server/tools/drt.mjs +200 -0
  78. package/resolve-advanced/server/tools/drx.mjs +943 -0
  79. package/resolve-advanced/server/tools/editorial.mjs +69 -0
  80. package/resolve-advanced/server/tools/fairlight.mjs +108 -0
  81. package/resolve-advanced/server/tools/fusion.mjs +64 -0
  82. package/resolve-advanced/server/tools/media.mjs +102 -0
  83. package/resolve-advanced/server/tools/offline_ref.mjs +123 -0
  84. package/resolve-advanced/server/tools/pipeline.mjs +137 -0
  85. package/resolve-advanced/server/tools/project_db.mjs +200 -0
  86. package/resolve-advanced/server/tools/project_read.mjs +212 -0
  87. package/resolve-advanced/server/tools/provenance.mjs +73 -0
  88. package/resolve-advanced/server/verify-grade.mjs +113 -0
  89. package/resolve-advanced/server/white-balance-match.mjs +122 -0
  90. package/resolve-advanced/vendor/audio/format-converter.js +330 -0
  91. package/resolve-advanced/vendor/audio/split.js +173 -0
  92. package/resolve-advanced/vendor/audio/trim.js +188 -0
  93. package/resolve-advanced/vendor/audio-fairlight/index.js +391 -0
  94. package/resolve-advanced/vendor/conform-qc/adapters/frame-sampler.js +56 -0
  95. package/resolve-advanced/vendor/conform-qc/adapters/local-ffmpeg-sampler.js +65 -0
  96. package/resolve-advanced/vendor/conform-qc/adapters/rendernode-ffmpeg-sampler.js +50 -0
  97. package/resolve-advanced/vendor/conform-qc/adapters/resolve/driver.py +176 -0
  98. package/resolve-advanced/vendor/conform-qc/adapters/resolve-driver.js +61 -0
  99. package/resolve-advanced/vendor/conform-qc/adapters/resolve-headless-driver.js +86 -0
  100. package/resolve-advanced/vendor/conform-qc/adapters/vision-validator.js +75 -0
  101. package/resolve-advanced/vendor/conform-qc/cli.js +63 -0
  102. package/resolve-advanced/vendor/conform-qc/compare/advisory.js +106 -0
  103. package/resolve-advanced/vendor/conform-qc/compare/decode.js +36 -0
  104. package/resolve-advanced/vendor/conform-qc/compare/index.js +61 -0
  105. package/resolve-advanced/vendor/conform-qc/compare/locate.js +70 -0
  106. package/resolve-advanced/vendor/conform-qc/compare/metrics.js +409 -0
  107. package/resolve-advanced/vendor/conform-qc/docs/runbook.md +72 -0
  108. package/resolve-advanced/vendor/conform-qc/index.js +49 -0
  109. package/resolve-advanced/vendor/conform-qc/knowledge/index.js +110 -0
  110. package/resolve-advanced/vendor/conform-qc/ops/conform-core.js +137 -0
  111. package/resolve-advanced/vendor/conform-qc/ops/conform-diff.js +109 -0
  112. package/resolve-advanced/vendor/conform-qc/ops/insert.js +108 -0
  113. package/resolve-advanced/vendor/conform-qc/ops/local-conform.js +61 -0
  114. package/resolve-advanced/vendor/conform-qc/ops/patch.js +80 -0
  115. package/resolve-advanced/vendor/conform-qc/ops/trigger.js +32 -0
  116. package/resolve-advanced/vendor/conform-qc/ops/verify.js +105 -0
  117. package/resolve-advanced/vendor/conform-qc/ops/workflow.js +30 -0
  118. package/resolve-advanced/vendor/conform-qc/oracle/emulate.js +155 -0
  119. package/resolve-advanced/vendor/conform-qc/oracle/index.js +38 -0
  120. package/resolve-advanced/vendor/conform-qc/oracle/resolve.js +196 -0
  121. package/resolve-advanced/vendor/conform-qc/package.json +16 -0
  122. package/resolve-advanced/vendor/conform-qc/packaging/emit-aaf.js +30 -0
  123. package/resolve-advanced/vendor/conform-qc/packaging/emit-fcp7.js +64 -0
  124. package/resolve-advanced/vendor/conform-qc/packaging/index.js +169 -0
  125. package/resolve-advanced/vendor/conform-qc/packaging/media-ops.js +56 -0
  126. package/resolve-advanced/vendor/conform-qc/packaging/otio.js +50 -0
  127. package/resolve-advanced/vendor/conform-qc/packaging/relink.js +50 -0
  128. package/resolve-advanced/vendor/conform-qc/packaging/surgical-relink.js +195 -0
  129. package/resolve-advanced/vendor/conform-qc/parse/index.js +54 -0
  130. package/resolve-advanced/vendor/conform-qc/parse/merge-dto.js +27 -0
  131. package/resolve-advanced/vendor/conform-qc/parse/xmeml-geometry.js +256 -0
  132. package/resolve-advanced/vendor/conform-qc/reference/burnin-ocr.js +100 -0
  133. package/resolve-advanced/vendor/conform-qc/reference/sidecar.js +37 -0
  134. package/resolve-advanced/vendor/conform-qc/repair/analysis.js +62 -0
  135. package/resolve-advanced/vendor/conform-qc/repair/index.js +78 -0
  136. package/resolve-advanced/vendor/conform-qc/repair/media-analysis.js +139 -0
  137. package/resolve-advanced/vendor/conform-qc/repair/media-index.js +135 -0
  138. package/resolve-advanced/vendor/conform-qc/repair/strategies.js +250 -0
  139. package/resolve-advanced/vendor/conform-qc/report/index.js +133 -0
  140. package/resolve-advanced/vendor/conform-qc/roles/index.js +96 -0
  141. package/resolve-advanced/vendor/conform-qc/synthetic/generate.js +233 -0
  142. package/resolve-advanced/vendor/conform-qc/test/advisory.test.js +85 -0
  143. package/resolve-advanced/vendor/conform-qc/test/cli.test.js +39 -0
  144. package/resolve-advanced/vendor/conform-qc/test/compare.test.js +152 -0
  145. package/resolve-advanced/vendor/conform-qc/test/conform-diff.test.js +70 -0
  146. package/resolve-advanced/vendor/conform-qc/test/emulate.test.js +51 -0
  147. package/resolve-advanced/vendor/conform-qc/test/frame-sampler.test.js +30 -0
  148. package/resolve-advanced/vendor/conform-qc/test/geometry.test.js +112 -0
  149. package/resolve-advanced/vendor/conform-qc/test/knowledge.test.js +56 -0
  150. package/resolve-advanced/vendor/conform-qc/test/lifecycle.test.js +110 -0
  151. package/resolve-advanced/vendor/conform-qc/test/local-ffmpeg-sampler.test.js +66 -0
  152. package/resolve-advanced/vendor/conform-qc/test/locate.test.js +63 -0
  153. package/resolve-advanced/vendor/conform-qc/test/media-analysis.test.js +63 -0
  154. package/resolve-advanced/vendor/conform-qc/test/media-index-normalized.test.js +65 -0
  155. package/resolve-advanced/vendor/conform-qc/test/media-index-origin.test.js +53 -0
  156. package/resolve-advanced/vendor/conform-qc/test/metrics-fast.test.js +91 -0
  157. package/resolve-advanced/vendor/conform-qc/test/oracle-reverse.test.js +86 -0
  158. package/resolve-advanced/vendor/conform-qc/test/oracle.test.js +136 -0
  159. package/resolve-advanced/vendor/conform-qc/test/p0-acceptance.test.js +60 -0
  160. package/resolve-advanced/vendor/conform-qc/test/p1-acceptance.test.js +75 -0
  161. package/resolve-advanced/vendor/conform-qc/test/p45-patch-acceptance.test.js +102 -0
  162. package/resolve-advanced/vendor/conform-qc/test/packaging.test.js +133 -0
  163. package/resolve-advanced/vendor/conform-qc/test/parse-stubs.test.js +28 -0
  164. package/resolve-advanced/vendor/conform-qc/test/repair-strategies.test.js +128 -0
  165. package/resolve-advanced/vendor/conform-qc/test/repair.test.js +84 -0
  166. package/resolve-advanced/vendor/conform-qc/test/report.test.js +52 -0
  167. package/resolve-advanced/vendor/conform-qc/test/resolve-readback.test.js +71 -0
  168. package/resolve-advanced/vendor/conform-qc/test/roles.test.js +107 -0
  169. package/resolve-advanced/vendor/conform-qc/test/runbook.test.js +30 -0
  170. package/resolve-advanced/vendor/conform-qc/test/scale-residual.test.js +40 -0
  171. package/resolve-advanced/vendor/conform-qc/test/sidecar.test.js +51 -0
  172. package/resolve-advanced/vendor/conform-qc/test/smoke.test.js +87 -0
  173. package/resolve-advanced/vendor/conform-qc/test/surgical-relink.test.js +73 -0
  174. package/resolve-advanced/vendor/conform-qc/test/synthetic.test.js +98 -0
  175. package/resolve-advanced/vendor/conform-qc/test/verify.test.js +93 -0
  176. package/resolve-advanced/vendor/conform-qc/test/vision-validator.test.js +43 -0
  177. package/resolve-advanced/vendor/conform-qc/test/workflow-driver.test.js +46 -0
  178. package/resolve-advanced/vendor/conform-qc/toolset/index.js +53 -0
  179. package/resolve-advanced/vendor/drp-format/README.md +116 -0
  180. package/resolve-advanced/vendor/drp-format/__tests__/_resolve-verify.js +39 -0
  181. package/resolve-advanced/vendor/drp-format/__tests__/add-media-clip.test.js +30 -0
  182. package/resolve-advanced/vendor/drp-format/__tests__/assemble-timeline.test.js +68 -0
  183. package/resolve-advanced/vendor/drp-format/__tests__/author-project.test.js +57 -0
  184. package/resolve-advanced/vendor/drp-format/__tests__/composition-text.test.js +98 -0
  185. package/resolve-advanced/vendor/drp-format/__tests__/diff.test.js +272 -0
  186. package/resolve-advanced/vendor/drp-format/__tests__/effect-filters-compressed.test.js +143 -0
  187. package/resolve-advanced/vendor/drp-format/__tests__/fixtures/p0-3-session30-empty-effectfilters.drp +0 -0
  188. package/resolve-advanced/vendor/drp-format/__tests__/fixtures/retimed-timemap-50pct.hex +1 -0
  189. package/resolve-advanced/vendor/drp-format/__tests__/fixtures/retimed-timemap-dynamic.hex +1 -0
  190. package/resolve-advanced/vendor/drp-format/__tests__/inject-grades.test.js +238 -0
  191. package/resolve-advanced/vendor/drp-format/__tests__/keyed-dict.test.js +85 -0
  192. package/resolve-advanced/vendor/drp-format/__tests__/lut-refs.test.js +119 -0
  193. package/resolve-advanced/vendor/drp-format/__tests__/media-blobs.test.js +25 -0
  194. package/resolve-advanced/vendor/drp-format/__tests__/media-timemap.test.js +119 -0
  195. package/resolve-advanced/vendor/drp-format/__tests__/place-fusion-title.test.js +52 -0
  196. package/resolve-advanced/vendor/drp-format/__tests__/place-generator.test.js +40 -0
  197. package/resolve-advanced/vendor/drp-format/__tests__/place-transition.test.js +48 -0
  198. package/resolve-advanced/vendor/drp-format/__tests__/protobuf-wire.test.js +64 -0
  199. package/resolve-advanced/vendor/drp-format/__tests__/relink-media.test.js +106 -0
  200. package/resolve-advanced/vendor/drp-format/__tests__/splice-clips.test.js +256 -0
  201. package/resolve-advanced/vendor/drp-format/assemble-timeline.js +65 -0
  202. package/resolve-advanced/vendor/drp-format/author-project.js +118 -0
  203. package/resolve-advanced/vendor/drp-format/composition-text.js +213 -0
  204. package/resolve-advanced/vendor/drp-format/curves-encoder.js +763 -0
  205. package/resolve-advanced/vendor/drp-format/diff.js +310 -0
  206. package/resolve-advanced/vendor/drp-format/drp-packager.js +201 -0
  207. package/resolve-advanced/vendor/drp-format/drp-validator.js +809 -0
  208. package/resolve-advanced/vendor/drp-format/effect-encoder.js +640 -0
  209. package/resolve-advanced/vendor/drp-format/extract-lut-refs.js +119 -0
  210. package/resolve-advanced/vendor/drp-format/grade-encoder.example.js +133 -0
  211. package/resolve-advanced/vendor/drp-format/grade-encoder.js +401 -0
  212. package/resolve-advanced/vendor/drp-format/grade-encoder.test.js +171 -0
  213. package/resolve-advanced/vendor/drp-format/grade-encoder.verify.js +249 -0
  214. package/resolve-advanced/vendor/drp-format/grade-node-extractor.js +495 -0
  215. package/resolve-advanced/vendor/drp-format/grade-parameter-decoder.js +774 -0
  216. package/resolve-advanced/vendor/drp-format/index.js +174 -0
  217. package/resolve-advanced/vendor/drp-format/inject-grades.js +219 -0
  218. package/resolve-advanced/vendor/drp-format/keyed-dict.js +227 -0
  219. package/resolve-advanced/vendor/drp-format/marker-encoder.js +532 -0
  220. package/resolve-advanced/vendor/drp-format/media-blobs.js +53 -0
  221. package/resolve-advanced/vendor/drp-format/media-timemap.js +164 -0
  222. package/resolve-advanced/vendor/drp-format/mp-folder-builder.js +293 -0
  223. package/resolve-advanced/vendor/drp-format/node-tree-encoder.js +1246 -0
  224. package/resolve-advanced/vendor/drp-format/package.json +18 -0
  225. package/resolve-advanced/vendor/drp-format/place-fusion-title.js +131 -0
  226. package/resolve-advanced/vendor/drp-format/place-generator.js +77 -0
  227. package/resolve-advanced/vendor/drp-format/place-transition.js +91 -0
  228. package/resolve-advanced/vendor/drp-format/power-window-encoder.js +776 -0
  229. package/resolve-advanced/vendor/drp-format/protobuf-wire.js +111 -0
  230. package/resolve-advanced/vendor/drp-format/qualifier-encoder.js +706 -0
  231. package/resolve-advanced/vendor/drp-format/relink-media.js +218 -0
  232. package/resolve-advanced/vendor/drp-format/rich-title-encoder.js +447 -0
  233. package/resolve-advanced/vendor/drp-format/seq-container-builder.js +572 -0
  234. package/resolve-advanced/vendor/drp-format/seq-surgery.js +155 -0
  235. package/resolve-advanced/vendor/drp-format/splice-clips.js +445 -0
  236. package/resolve-advanced/vendor/drp-format/templates/empty-project.drp +0 -0
  237. package/resolve-advanced/vendor/drp-format/templates/fusion-title.xml +56 -0
  238. package/resolve-advanced/vendor/drp-format/templates/generator-solid-color.xml +21 -0
  239. package/resolve-advanced/vendor/drp-format/templates/media-clip-h264.drp +0 -0
  240. package/resolve-advanced/vendor/drp-format/templates/transition-cross-dissolve.xml +22 -0
  241. package/resolve-advanced/vendor/drp-format/tool-registry.descriptor.js +80 -0
  242. package/resolve-advanced/vendor/drp-format/utils/safe-archive.js +54 -0
  243. package/resolve-advanced/vendor/drp-format/xml-builder.js +759 -0
  244. package/resolve-advanced/vendor/drt-format/__tests__/_resolve-verify.js +21 -0
  245. package/resolve-advanced/vendor/drt-format/__tests__/build.test.js +113 -0
  246. package/resolve-advanced/vendor/drt-format/__tests__/multi-format.test.js +93 -0
  247. package/resolve-advanced/vendor/drt-format/__tests__/parse-real-resolve21.test.js +51 -0
  248. package/resolve-advanced/vendor/drt-format/__tests__/parse.test.js +134 -0
  249. package/resolve-advanced/vendor/drt-format/__tests__/resolve-versions.test.js +120 -0
  250. package/resolve-advanced/vendor/drt-format/__tests__/schema-fingerprint.test.js +62 -0
  251. package/resolve-advanced/vendor/drt-format/__tests__/smoke.test.js +27 -0
  252. package/resolve-advanced/vendor/drt-format/__tests__/validate.test.js +109 -0
  253. package/resolve-advanced/vendor/drt-format/capabilities.js +69 -0
  254. package/resolve-advanced/vendor/drt-format/capability-domains.js +56 -0
  255. package/resolve-advanced/vendor/drt-format/drt-builder.js +42 -0
  256. package/resolve-advanced/vendor/drt-format/drt-parser.js +164 -0
  257. package/resolve-advanced/vendor/drt-format/drt-validator.js +98 -0
  258. package/resolve-advanced/vendor/drt-format/index.js +45 -0
  259. package/resolve-advanced/vendor/drt-format/package.json +17 -0
  260. package/resolve-advanced/vendor/drt-format/resolve-versions.js +153 -0
  261. package/resolve-advanced/vendor/drt-format/schema-fingerprint.js +74 -0
  262. package/resolve-advanced/vendor/drt-format/templates/drt-project-shell.xml +124 -0
  263. package/resolve-advanced/vendor/drx-codec/__tests__/curves-roundtrip.test.js +148 -0
  264. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-face-refinement.drx +58 -0
  265. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-filmgrain.drx +58 -0
  266. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-glow.drx +58 -0
  267. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-1-lens-flare.drx +58 -0
  268. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-3-beauty-25.drx +58 -0
  269. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p2-3-beauty-75.drx +58 -0
  270. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p5-1-node-no-lut.drx +58 -0
  271. package/resolve-advanced/vendor/drx-codec/__tests__/fixtures/p5-1-node-with-lut.drx +58 -0
  272. package/resolve-advanced/vendor/drx-codec/__tests__/hsl-curves-roundtrip.test.js +117 -0
  273. package/resolve-advanced/vendor/drx-codec/__tests__/lut-refs-roundtrip.test.js +112 -0
  274. package/resolve-advanced/vendor/drx-codec/__tests__/matte-roundtrip.test.js +167 -0
  275. package/resolve-advanced/vendor/drx-codec/__tests__/ofx-roundtrip.test.js +215 -0
  276. package/resolve-advanced/vendor/drx-codec/__tests__/ofx-slugs-discovery.test.js +149 -0
  277. package/resolve-advanced/vendor/drx-codec/__tests__/power-window-roundtrip.test.js +230 -0
  278. package/resolve-advanced/vendor/drx-codec/__tests__/qualifier-roundtrip.test.js +226 -0
  279. package/resolve-advanced/vendor/drx-codec/cdl-exporter.js +470 -0
  280. package/resolve-advanced/vendor/drx-codec/color-nlp-parser.js +833 -0
  281. package/resolve-advanced/vendor/drx-codec/data/color-nlp-action-mappings.json +2232 -0
  282. package/resolve-advanced/vendor/drx-codec/drx-generator.js +4123 -0
  283. package/resolve-advanced/vendor/drx-codec/drx-merger.js +320 -0
  284. package/resolve-advanced/vendor/drx-codec/drx-parser.js +1808 -0
  285. package/resolve-advanced/vendor/drx-codec/extract-custom-curves.js +215 -0
  286. package/resolve-advanced/vendor/drx-codec/extract-hsl-curves.js +180 -0
  287. package/resolve-advanced/vendor/drx-codec/extract-lut-refs.js +158 -0
  288. package/resolve-advanced/vendor/drx-codec/extract-matte-finesse.js +83 -0
  289. package/resolve-advanced/vendor/drx-codec/extract-ofx-params.js +226 -0
  290. package/resolve-advanced/vendor/drx-codec/extract-power-window.js +184 -0
  291. package/resolve-advanced/vendor/drx-codec/extract-qualifier.js +99 -0
  292. package/resolve-advanced/vendor/drx-codec/index.js +109 -0
  293. package/resolve-advanced/vendor/drx-codec/node-layout.js +249 -0
  294. package/resolve-advanced/vendor/drx-codec/resolved-drx-generator.js +393 -0
  295. package/resolve-advanced/vendor/drx-codec/tool-resolver.js +974 -0
  296. package/resolve-advanced/vendor/drx-codec/training-examples.js +548 -0
  297. package/resolve-advanced/vendor/drx-codec/vocabulary-intents.js +539 -0
  298. package/resolve-advanced/vendor/drx-parameters/CALIBRATION-STATUS.md +319 -0
  299. package/resolve-advanced/vendor/drx-parameters/DRX-VALUE-SCALING.md +251 -0
  300. package/resolve-advanced/vendor/drx-parameters/calibrated-ranges.json +17737 -0
  301. package/resolve-advanced/vendor/drx-parameters/corrector-types.js +120 -0
  302. package/resolve-advanced/vendor/drx-parameters/index.js +193 -0
  303. package/resolve-advanced/vendor/drx-parameters/parameter-codec.js +451 -0
  304. package/resolve-advanced/vendor/drx-parameters/parameter-ids.js +1292 -0
  305. package/resolve-advanced/vendor/drx-parameters/parameter-ranges.js +570 -0
  306. package/resolve-advanced/vendor/drx-parameters/parameter-validator.js +392 -0
  307. package/resolve-advanced/vendor/drx-parameters/resolvefx-registry.json +14973 -0
  308. package/resolve-advanced/vendor/drx-parameters/tool-registry.descriptor.js +38 -0
  309. package/resolve-advanced/vendor/drx-parameters/tools/drx-analyzer.js +371 -0
  310. package/resolve-advanced/vendor/fairlight/index.js +833 -0
  311. package/resolve-advanced/vendor/fusion-codec/composition-generator.js +401 -0
  312. package/resolve-advanced/vendor/fusion-codec/templates/blur-region.js +103 -0
  313. package/resolve-advanced/vendor/fusion-codec/templates/color-correct.js +87 -0
  314. package/resolve-advanced/vendor/fusion-codec/templates/film-grain.js +106 -0
  315. package/resolve-advanced/vendor/fusion-codec/templates/lower-third.js +241 -0
  316. package/resolve-advanced/vendor/fusion-codec/templates/picture-in-picture.js +188 -0
  317. package/resolve-advanced/vendor/fusion-codec/templates/text-overlay.js +161 -0
  318. package/resolve-advanced/vendor/fusion-codec/templates/title-card.js +184 -0
  319. package/resolve-advanced/vendor/fusion-codec/templates/vignette.js +107 -0
  320. package/resolve-advanced/vendor/fusion-codec/templates/watermark.js +101 -0
  321. package/scripts/agent-rules/README.md +68 -0
  322. package/src/analysis_dashboard.py +233 -1
  323. package/src/granular/common.py +1 -1
  324. package/src/server.py +479 -29
  325. package/src/utils/api_truth.py +117 -0
  326. package/src/utils/cut_ir.py +1 -1
  327. package/src/utils/failure_tracker.py +0 -2
  328. package/src/utils/timeline_xml.py +405 -0
@@ -0,0 +1,532 @@
1
+ /**
2
+ * DaVinci Resolve Timeline Marker Encoder/Decoder
3
+ *
4
+ * Encodes and decodes timeline markers into DaVinci Resolve's
5
+ * compressed protobuf format stored in Sm2SequenceLockableBlob.FieldsBlob.
6
+ *
7
+ * Format Overview:
8
+ * - FieldsBlob header (Big-Endian): version, field count, "BlobData" field
9
+ * - ZSTD compressed protobuf (magic: 0x28b52ffd)
10
+ * - Nested protobuf with frame, color, name, ref_id, description
11
+ *
12
+ * @module marker-encoder
13
+ */
14
+
15
+ const zlib = require('zlib');
16
+
17
+ /**
18
+ * DaVinci Resolve marker color codes
19
+ * Colors are represented as bit positions, not sequential values
20
+ */
21
+ const MARKER_COLORS = {
22
+ BLUE: 2, // 0x00002 - Default marker color
23
+ YELLOW: 8, // 0x00008
24
+ RED: 32, // 0x00020
25
+ PURPLE: 131072, // 0x20000 (Lavender)
26
+ // Additional colors to be reverse-engineered
27
+ };
28
+
29
+ /**
30
+ * Encode a positive integer as a protobuf varint
31
+ * @param {number} value - Non-negative integer to encode
32
+ * @returns {Buffer} Encoded varint bytes
33
+ */
34
+ function encodeVarint(value) {
35
+ const bytes = [];
36
+ let remaining = value;
37
+
38
+ while (remaining > 0x7f) {
39
+ bytes.push((remaining & 0x7f) | 0x80);
40
+ remaining = Math.floor(remaining / 128);
41
+ }
42
+ bytes.push(remaining & 0x7f);
43
+
44
+ return Buffer.from(bytes);
45
+ }
46
+
47
+ /**
48
+ * Decode a varint from buffer
49
+ * @param {Buffer} data - Buffer containing varint
50
+ * @param {number} offset - Start offset
51
+ * @returns {{value: number, bytesRead: number}} Decoded value and bytes consumed
52
+ */
53
+ function decodeVarint(data, offset = 0) {
54
+ let value = 0;
55
+ let shift = 0;
56
+ let bytesRead = 0;
57
+
58
+ while (offset + bytesRead < data.length) {
59
+ const byte = data[offset + bytesRead];
60
+ value |= (byte & 0x7f) << shift;
61
+ bytesRead++;
62
+
63
+ if ((byte & 0x80) === 0) {
64
+ break;
65
+ }
66
+ shift += 7;
67
+ }
68
+
69
+ return { value, bytesRead };
70
+ }
71
+
72
+ /**
73
+ * Encode a protobuf field tag
74
+ * @param {number} fieldNumber - Field number
75
+ * @param {number} wireType - Wire type (0=varint, 2=length-delimited)
76
+ * @returns {Buffer} Encoded tag
77
+ */
78
+ function encodeTag(fieldNumber, wireType) {
79
+ const tag = (fieldNumber << 3) | wireType;
80
+ return encodeVarint(tag);
81
+ }
82
+
83
+ /**
84
+ * Encode a string as a length-delimited protobuf field
85
+ * @param {number} fieldNumber - Field number
86
+ * @param {string} value - String value
87
+ * @returns {Buffer} Encoded field
88
+ */
89
+ function encodeString(fieldNumber, value) {
90
+ const tag = encodeTag(fieldNumber, 2);
91
+ const strBytes = Buffer.from(value, 'utf-8');
92
+ const length = encodeVarint(strBytes.length);
93
+ return Buffer.concat([tag, length, strBytes]);
94
+ }
95
+
96
+ /**
97
+ * Encode a varint field
98
+ * @param {number} fieldNumber - Field number
99
+ * @param {number} value - Integer value
100
+ * @returns {Buffer} Encoded field
101
+ */
102
+ function encodeVarintField(fieldNumber, value) {
103
+ const tag = encodeTag(fieldNumber, 0);
104
+ const valueBytes = encodeVarint(value);
105
+ return Buffer.concat([tag, valueBytes]);
106
+ }
107
+
108
+ /**
109
+ * Encode a length-delimited bytes field
110
+ * @param {number} fieldNumber - Field number
111
+ * @param {Buffer} value - Bytes value
112
+ * @returns {Buffer} Encoded field
113
+ */
114
+ function encodeBytesField(fieldNumber, value) {
115
+ const tag = encodeTag(fieldNumber, 2);
116
+ const length = encodeVarint(value.length);
117
+ return Buffer.concat([tag, length, value]);
118
+ }
119
+
120
+ /**
121
+ * Encode the innermost marker content
122
+ * @param {Object} marker - Marker data
123
+ * @param {number} marker.color - Color code
124
+ * @param {string} [marker.name=''] - Marker name
125
+ * @param {string} marker.refId - Reference ID
126
+ * @param {string} marker.note - Marker description/note
127
+ * @returns {Buffer} Encoded content
128
+ */
129
+ function encodeMarkerContent(marker) {
130
+ const parts = [];
131
+
132
+ // Field 1 (varint): color code
133
+ parts.push(encodeVarintField(1, marker.color || MARKER_COLORS.BLUE));
134
+
135
+ // Field 3 (string): name (usually empty)
136
+ parts.push(encodeString(3, marker.name || ''));
137
+
138
+ // Field 3 (string): reference ID
139
+ parts.push(encodeString(3, marker.refId || ''));
140
+
141
+ // Field 3 (string): description/note
142
+ parts.push(encodeString(3, marker.note || ''));
143
+
144
+ return Buffer.concat(parts);
145
+ }
146
+
147
+ /**
148
+ * Encode inner protobuf wrapper for marker data
149
+ * @param {Object} marker - Marker data
150
+ * @returns {Buffer} Encoded inner protobuf
151
+ */
152
+ function encodeMarkerInner(marker) {
153
+ const content = encodeMarkerContent(marker);
154
+ // Wrap content in Field 1 (nested message)
155
+ return encodeBytesField(1, content);
156
+ }
157
+
158
+ /**
159
+ * Encode complete marker data with 8-byte header
160
+ * @param {Object} marker - Marker data
161
+ * @returns {Buffer} Encoded marker data
162
+ */
163
+ function encodeMarkerData(marker) {
164
+ const inner = encodeMarkerInner(marker);
165
+
166
+ // 8-byte header (Big-Endian):
167
+ // - 4 bytes: Type = 2
168
+ // - 4 bytes: Inner protobuf length
169
+ const header = Buffer.alloc(8);
170
+ header.writeUInt32BE(2, 0);
171
+ header.writeUInt32BE(inner.length, 4);
172
+
173
+ return Buffer.concat([header, inner]);
174
+ }
175
+
176
+ /**
177
+ * Encode a complete marker entry
178
+ * @param {Object} marker - Marker data
179
+ * @param {number} marker.frame - Frame number
180
+ * @param {number} marker.color - Color code
181
+ * @param {string} marker.refId - Reference ID
182
+ * @param {string} marker.note - Description
183
+ * @returns {Buffer} Encoded marker entry
184
+ */
185
+ function encodeMarkerEntry(marker) {
186
+ const parts = [];
187
+
188
+ // Field 1 (varint): frame number
189
+ parts.push(encodeVarintField(1, marker.frame));
190
+
191
+ // Field 2 (bytes): marker data
192
+ const markerData = encodeMarkerData(marker);
193
+ parts.push(encodeBytesField(2, markerData));
194
+
195
+ return Buffer.concat(parts);
196
+ }
197
+
198
+ /**
199
+ * Encode all markers into container
200
+ * @param {Object[]} markers - Array of marker objects
201
+ * @returns {Buffer} Encoded container
202
+ */
203
+ function encodeMarkerContainer(markers) {
204
+ const parts = [];
205
+
206
+ for (const marker of markers) {
207
+ const entry = encodeMarkerEntry(marker);
208
+ // Each entry wrapped in Field 1 (repeated)
209
+ parts.push(encodeBytesField(1, entry));
210
+ }
211
+
212
+ return Buffer.concat(parts);
213
+ }
214
+
215
+ /**
216
+ * Encode markers to complete protobuf
217
+ * @param {Object[]} markers - Array of marker objects
218
+ * @returns {Buffer} Encoded protobuf
219
+ */
220
+ function encodeMarkersProtobuf(markers) {
221
+ const container = encodeMarkerContainer(markers);
222
+ // Wrap in Field 2
223
+ return encodeBytesField(2, container);
224
+ }
225
+
226
+ /**
227
+ * Compress markers protobuf with ZSTD
228
+ * Note: Node.js doesn't have native ZSTD, uses zlib deflate as fallback
229
+ * For production, use 'zstd-codec' or 'node-zstandard' npm package
230
+ *
231
+ * @param {Object[]} markers - Array of marker objects
232
+ * @returns {Buffer} Compressed data
233
+ */
234
+ function compressMarkers(markers) {
235
+ const protobuf = encodeMarkersProtobuf(markers);
236
+
237
+ // For full DRP compatibility, use ZSTD compression
238
+ // This requires installing: npm install @pxtrn/zstd or similar
239
+ // For now, return uncompressed with a note
240
+ console.warn('Note: For full DRP compatibility, use ZSTD compression');
241
+
242
+ // Return protobuf as-is (would need ZSTD for actual DRP files)
243
+ return protobuf;
244
+ }
245
+
246
+ /**
247
+ * Decode markers from compressed protobuf
248
+ * @param {Buffer} compressed - ZSTD compressed data
249
+ * @returns {Object[]} Array of decoded markers
250
+ */
251
+ function decodeMarkers(compressed) {
252
+ // For ZSTD decompression, use 'zstd-codec' npm package
253
+ // This is a simplified implementation assuming uncompressed data
254
+ const protobuf = compressed;
255
+
256
+ const markers = [];
257
+ let offset = 0;
258
+
259
+ // Skip Field 2 container tag
260
+ const { bytesRead: tagBytes } = decodeVarint(protobuf, 0);
261
+ offset = tagBytes;
262
+ const { value: containerLen, bytesRead: lenBytes } = decodeVarint(protobuf, offset);
263
+ offset += lenBytes;
264
+
265
+ const container = protobuf.slice(offset, offset + containerLen);
266
+
267
+ // Parse each marker entry
268
+ let containerOffset = 0;
269
+ while (containerOffset < container.length) {
270
+ const tag = container[containerOffset];
271
+ if ((tag & 0x7) !== 2) break;
272
+
273
+ const { value: entryLen, bytesRead } = decodeVarint(container, containerOffset + 1);
274
+ containerOffset += 1 + bytesRead;
275
+
276
+ const entry = container.slice(containerOffset, containerOffset + entryLen);
277
+ containerOffset += entryLen;
278
+
279
+ const marker = parseMarkerEntry(entry);
280
+ markers.push(marker);
281
+ }
282
+
283
+ return markers;
284
+ }
285
+
286
+ /**
287
+ * Parse a single marker entry
288
+ * @param {Buffer} entry - Marker entry bytes
289
+ * @returns {Object} Parsed marker
290
+ */
291
+ function parseMarkerEntry(entry) {
292
+ const marker = {
293
+ frame: 0,
294
+ color: MARKER_COLORS.BLUE,
295
+ name: '',
296
+ refId: '',
297
+ note: '',
298
+ };
299
+
300
+ let offset = 0;
301
+ while (offset < entry.length) {
302
+ const tag = entry[offset];
303
+ const fieldNum = tag >> 3;
304
+ const wireType = tag & 0x7;
305
+ offset++;
306
+
307
+ if (wireType === 0) {
308
+ // Varint
309
+ const { value, bytesRead } = decodeVarint(entry, offset);
310
+ offset += bytesRead;
311
+ if (fieldNum === 1) {
312
+ marker.frame = value;
313
+ }
314
+ } else if (wireType === 2) {
315
+ // Length-delimited
316
+ const { value: len, bytesRead } = decodeVarint(entry, offset);
317
+ offset += bytesRead;
318
+ const data = entry.slice(offset, offset + len);
319
+ offset += len;
320
+
321
+ if (fieldNum === 2 && data.length > 8) {
322
+ // Skip 8-byte header, parse inner protobuf
323
+ const inner = data.slice(8);
324
+ parseMarkerInner(inner, marker);
325
+ }
326
+ }
327
+ }
328
+
329
+ return marker;
330
+ }
331
+
332
+ /**
333
+ * Parse inner marker protobuf
334
+ * @param {Buffer} inner - Inner protobuf bytes
335
+ * @param {Object} marker - Marker object to populate
336
+ */
337
+ function parseMarkerInner(inner, marker) {
338
+ let offset = 0;
339
+ while (offset < inner.length) {
340
+ const tag = inner[offset];
341
+ const fieldNum = tag >> 3;
342
+ const wireType = tag & 0x7;
343
+ offset++;
344
+
345
+ if (wireType === 2) {
346
+ const { value: len, bytesRead } = decodeVarint(inner, offset);
347
+ offset += bytesRead;
348
+ const content = inner.slice(offset, offset + len);
349
+ offset += len;
350
+
351
+ // Parse content
352
+ parseMarkerContent(content, marker);
353
+ }
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Parse marker content fields
359
+ * @param {Buffer} content - Content bytes
360
+ * @param {Object} marker - Marker object to populate
361
+ */
362
+ function parseMarkerContent(content, marker) {
363
+ let offset = 0;
364
+ let stringIndex = 0;
365
+
366
+ while (offset < content.length) {
367
+ const tag = content[offset];
368
+ const fieldNum = tag >> 3;
369
+ const wireType = tag & 0x7;
370
+ offset++;
371
+
372
+ if (wireType === 0) {
373
+ // Varint
374
+ const { value, bytesRead } = decodeVarint(content, offset);
375
+ offset += bytesRead;
376
+ marker.color = value;
377
+ } else if (wireType === 2) {
378
+ // String
379
+ const { value: len, bytesRead } = decodeVarint(content, offset);
380
+ offset += bytesRead;
381
+ const str = content.slice(offset, offset + len).toString('utf-8');
382
+ offset += len;
383
+
384
+ if (stringIndex === 0) {
385
+ marker.name = str;
386
+ } else if (stringIndex === 1) {
387
+ marker.refId = str;
388
+ } else if (stringIndex === 2) {
389
+ marker.note = str;
390
+ }
391
+ stringIndex++;
392
+ }
393
+ }
394
+ }
395
+
396
+ /**
397
+ * Create FieldsBlob header for markers
398
+ * @param {Buffer} compressedData - ZSTD compressed protobuf
399
+ * @returns {Buffer} Complete FieldsBlob with header
400
+ */
401
+ function createFieldsBlob(compressedData) {
402
+ const parts = [];
403
+
404
+ // Version (4 bytes BE)
405
+ const version = Buffer.alloc(4);
406
+ version.writeUInt32BE(1, 0);
407
+ parts.push(version);
408
+
409
+ // Field count (4 bytes BE)
410
+ const fieldCount = Buffer.alloc(4);
411
+ fieldCount.writeUInt32BE(1, 0);
412
+ parts.push(fieldCount);
413
+
414
+ // Field name: "BlobData" (UTF-16BE)
415
+ const fieldName = Buffer.from('BlobData', 'utf16le').swap16();
416
+ const nameLen = Buffer.alloc(4);
417
+ nameLen.writeUInt32BE(fieldName.length, 0);
418
+ parts.push(nameLen);
419
+ parts.push(fieldName);
420
+
421
+ // Data length (12 bytes for BlobData metadata)
422
+ const dataLen = Buffer.alloc(4);
423
+ dataLen.writeUInt32BE(12, 0);
424
+ parts.push(dataLen);
425
+
426
+ // BlobData value (12 bytes metadata)
427
+ const blobDataValue = Buffer.alloc(12);
428
+ blobDataValue.writeUInt32BE(2, 0); // Type
429
+ // Remaining bytes can be calculated based on compressed size
430
+ parts.push(blobDataValue);
431
+
432
+ // Magic prefix before ZSTD
433
+ parts.push(Buffer.from([0xad, 0x81]));
434
+
435
+ // Compressed data
436
+ parts.push(compressedData);
437
+
438
+ return Buffer.concat(parts);
439
+ }
440
+
441
+ /**
442
+ * Convert timecode string to frame number
443
+ * @param {string} timecode - Timecode in HH:MM:SS:FF format
444
+ * @param {number} frameRate - Frame rate (default 23.976)
445
+ * @returns {number} Frame number
446
+ */
447
+ function timecodeToFrame(timecode, frameRate = 23.976) {
448
+ const parts = timecode.split(':').map(Number);
449
+ if (parts.length !== 4) {
450
+ throw new Error('Invalid timecode format. Use HH:MM:SS:FF');
451
+ }
452
+
453
+ const [hours, minutes, seconds, frames] = parts;
454
+ const totalSeconds = hours * 3600 + minutes * 60 + seconds;
455
+ return Math.round(totalSeconds * frameRate) + frames;
456
+ }
457
+
458
+ /**
459
+ * Convert frame number to timecode string
460
+ * @param {number} frame - Frame number
461
+ * @param {number} frameRate - Frame rate (default 23.976)
462
+ * @returns {string} Timecode in HH:MM:SS:FF format
463
+ */
464
+ function frameToTimecode(frame, frameRate = 23.976) {
465
+ const totalSeconds = frame / frameRate;
466
+ const hours = Math.floor(totalSeconds / 3600);
467
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
468
+ const seconds = Math.floor(totalSeconds % 60);
469
+ const frames = Math.round((totalSeconds % 1) * frameRate);
470
+
471
+ return [hours, minutes, seconds, frames]
472
+ .map((v) => v.toString().padStart(2, '0'))
473
+ .join(':');
474
+ }
475
+
476
+ /**
477
+ * Create a marker object with default values
478
+ * @param {Object} options - Marker options
479
+ * @param {number|string} options.position - Frame number or timecode string
480
+ * @param {string} [options.note=''] - Marker description
481
+ * @param {string} [options.refId=''] - Reference ID
482
+ * @param {number|string} [options.color='blue'] - Color code or name
483
+ * @param {string} [options.name=''] - Marker name
484
+ * @param {number} [options.frameRate=23.976] - Frame rate for timecode conversion
485
+ * @returns {Object} Marker object ready for encoding
486
+ */
487
+ function createMarker(options) {
488
+ let frame = options.position;
489
+ if (typeof frame === 'string') {
490
+ frame = timecodeToFrame(frame, options.frameRate || 23.976);
491
+ }
492
+
493
+ let color = options.color || MARKER_COLORS.BLUE;
494
+ if (typeof color === 'string') {
495
+ const colorName = color.toUpperCase();
496
+ color = MARKER_COLORS[colorName] || MARKER_COLORS.BLUE;
497
+ }
498
+
499
+ return {
500
+ frame,
501
+ color,
502
+ name: options.name || '',
503
+ refId: options.refId || '',
504
+ note: options.note || '',
505
+ };
506
+ }
507
+
508
+ module.exports = {
509
+ // Main encoding/decoding functions
510
+ encodeMarkersProtobuf,
511
+ decodeMarkers,
512
+ compressMarkers,
513
+ createFieldsBlob,
514
+
515
+ // Marker creation helpers
516
+ createMarker,
517
+ timecodeToFrame,
518
+ frameToTimecode,
519
+
520
+ // Low-level utilities
521
+ encodeVarint,
522
+ decodeVarint,
523
+ encodeTag,
524
+ encodeString,
525
+ encodeVarintField,
526
+ encodeBytesField,
527
+ encodeMarkerEntry,
528
+ parseMarkerEntry,
529
+
530
+ // Constants
531
+ MARKER_COLORS,
532
+ };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * media-blobs — decode/encode the simple fixed-size 16-byte Media Pool / timeline metadata blobs.
3
+ * Mapped + verified against real Resolve 21 exports (see knowledge/blob-map.md).
4
+ *
5
+ * Resolution = [u32 0][u32 width][u32 0][u32 height] (big-endian)
6
+ * FrameRate = [double fps][double 0] (little-endian) — timeline fps
7
+ * MediaFrameRate = [double fps][double 0] (little-endian) — clip source fps
8
+ * MediaExtents = [double startSeconds][double durationSeconds] (little-endian)
9
+ *
10
+ * @module drp-format/media-blobs
11
+ */
12
+
13
+ function decodeResolutionBlob(hex) {
14
+ const b = Buffer.from(hex, 'hex');
15
+ if (b.length !== 16) return null;
16
+ return { width: b.readUInt32BE(4), height: b.readUInt32BE(12) };
17
+ }
18
+ function encodeResolutionBlob({ width, height }) {
19
+ const b = Buffer.alloc(16);
20
+ b.writeUInt32BE(width >>> 0, 4);
21
+ b.writeUInt32BE(height >>> 0, 12);
22
+ return b.toString('hex');
23
+ }
24
+
25
+ // FrameRate / MediaFrameRate share the same [double fps][double 0] shape.
26
+ function decodeRateBlob(hex) {
27
+ const b = Buffer.from(hex, 'hex');
28
+ if (b.length !== 16) return null;
29
+ return b.readDoubleLE(0);
30
+ }
31
+ function encodeRateBlob(fps) {
32
+ const b = Buffer.alloc(16);
33
+ b.writeDoubleLE(fps, 0);
34
+ return b.toString('hex');
35
+ }
36
+
37
+ function decodeMediaExtentsBlob(hex) {
38
+ const b = Buffer.from(hex, 'hex');
39
+ if (b.length !== 16) return null;
40
+ return { startSeconds: b.readDoubleLE(0), durationSeconds: b.readDoubleLE(8) };
41
+ }
42
+ function encodeMediaExtentsBlob({ startSeconds, durationSeconds }) {
43
+ const b = Buffer.alloc(16);
44
+ b.writeDoubleLE(startSeconds, 0);
45
+ b.writeDoubleLE(durationSeconds, 8);
46
+ return b.toString('hex');
47
+ }
48
+
49
+ module.exports = {
50
+ decodeResolutionBlob, encodeResolutionBlob,
51
+ decodeRateBlob, encodeRateBlob,
52
+ decodeMediaExtentsBlob, encodeMediaExtentsBlob,
53
+ };