HTTP transport to the Kdenlive scripting fork — the JVM boundary.
Strata: Pure routes/request (kdenlive.routes, portable) Port IKdenlive — call a catalog route, get data back Boundary HttpKdenlive — java.net.http, JSON wire Seam kdenlive — read at call time; rebind in tests
The wire encoding is JSON. Requests carry the route's :body as a JSON
object, built by ->json here.
Responses are NOT decoded. -call answers
{:ok {:status int :body "<raw JSON string>"}}, because this namespace has
no JSON reader: ->json writes, and nothing reads. A caller that needs a
field out of the answer (hive-creator's :finish binds [:ids 0] and [:id]
to thread ids between steps) therefore cannot use this transport yet; the
headless document transport answers parsed data and is what such callers
run against today. This docstring previously claimed responses came back
"decoded to Clojure data with keyword keys", which was never true.
Tracked as a card: give this transport a JSON reader, and with it the :timeline/insert-clip trim, which the fork cannot do in one call (its scriptInsertClip binds binId/trackId/position only) and which therefore needs a following :clip/resize to match what the headless transport does.
HTTP transport to the Kdenlive scripting fork — the JVM boundary.
Strata:
Pure routes/request (kdenlive.routes, portable)
Port IKdenlive — call a catalog route, get data back
Boundary HttpKdenlive — java.net.http, JSON wire
Seam *kdenlive* — read at call time; rebind in tests
The wire encoding is JSON. Requests carry the route's :body as a JSON
object, built by `->json` here.
Responses are NOT decoded. `-call` answers
{:ok {:status int :body "<raw JSON string>"}}, because this namespace has
no JSON reader: `->json` writes, and nothing reads. A caller that needs a
field out of the answer (hive-creator's :finish binds [:ids 0] and [:id]
to thread ids between steps) therefore cannot use this transport yet; the
headless document transport answers parsed data and is what such callers
run against today. This docstring previously claimed responses came back
"decoded to Clojure data with keyword keys", which was never true.
Tracked as a card: give this transport a JSON reader, and with it the
:timeline/insert-clip trim, which the fork cannot do in one call (its
scriptInsertClip binds binId/trackId/position only) and which therefore
needs a following :clip/resize to match what the headless transport does.The :document transport: IKdenlive over a project file, with no Kdenlive.
http-kdenlive sends a catalog route to the scripting fork. This adapter
answers the same route ids against a timeline kept on disk as EDN
(hive-kdenlive.mlt.timeline), and after every edit writes the MLT document
melt renders beside it:
edit.hkd.edn the timeline, the source of truth edit.mlt its MLT rendering, rewritten on every change
:render/start renders that document with melt. Media is probed with
melt <file> -consumer xml, the same engine the render uses, so a length
the timeline trusts is a length the render will agree with.
Routes with no meaning off a running application (playback, render jobs) answer :document/unsupported-route, naming the routes that are supported.
The :document transport: IKdenlive over a project file, with no Kdenlive. `http-kdenlive` sends a catalog route to the scripting fork. This adapter answers the same route ids against a timeline kept on disk as EDN (hive-kdenlive.mlt.timeline), and after every edit writes the MLT document melt renders beside it: edit.hkd.edn the timeline, the source of truth edit.mlt its MLT rendering, rewritten on every change :render/start renders that document with melt. Media is probed with `melt <file> -consumer xml`, the same engine the render uses, so a length the timeline trusts is a length the render will agree with. Routes with no meaning off a running application (playback, render jobs) answer :document/unsupported-route, naming the routes that are supported.
JSON, both directions, with no dependency.
hive-kdenlive deliberately carries no JSON library, and until 2026-09-20 it
showed: the encoder handled a FLAT map of scalars and rendered anything
else with str, so :paths ["a.mp4" "b.mp3"] went out as the Clojure
literal ["a.mp4" "b.mp3"] (no commas) and :params {:duration 5} as
{:duration 5}. Both are the shapes hive-creator's :finish actually sends,
to :media/import and :clip/append-effect. There was no decoder at all, so
every answer came back as a raw string and a caller that needed an id out
of it got nothing.
Neither had been noticed because the HTTP transport was never exercised end to end; the headless document transport was.
write and read live together so a round trip can be property-tested,
which is the only way a hand-written codec stays honest.
Portable: clojure.core and clojure.string, and no host interop. There is no
StringBuilder here and no (int \c), because neither exists on cljw or
cljrs.
read answers Clojure data with STRING keys, exactly as the wire spells
them, because the route catalog's :result names a wire field.
JSON, both directions, with no dependency.
hive-kdenlive deliberately carries no JSON library, and until 2026-09-20 it
showed: the encoder handled a FLAT map of scalars and rendered anything
else with `str`, so `:paths ["a.mp4" "b.mp3"]` went out as the Clojure
literal `["a.mp4" "b.mp3"]` (no commas) and `:params {:duration 5}` as
`{:duration 5}`. Both are the shapes hive-creator's :finish actually sends,
to :media/import and :clip/append-effect. There was no decoder at all, so
every answer came back as a raw string and a caller that needed an id out
of it got nothing.
Neither had been noticed because the HTTP transport was never exercised end
to end; the headless document transport was.
`write` and `read` live together so a round trip can be property-tested,
which is the only way a hand-written codec stays honest.
Portable: clojure.core and clojure.string, and no host interop. There is no
StringBuilder here and no `(int \c)`, because neither exists on cljw or
cljrs.
`read` answers Clojure data with STRING keys, exactly as the wire spells
them, because the route catalog's :result names a wire field.Route catalog for the Kdenlive scripting fork's HTTP transport — pure data.
The catalog is the single source: each route names its id, HTTP method, path template, and required/optional params. The client boundary walks this data; adding an endpoint is a catalog entry, never new client code.
Portable: core + string only.
Route catalog for the Kdenlive scripting fork's HTTP transport — pure data. The catalog is the single source: each route names its id, HTTP method, path template, and required/optional params. The client boundary walks this data; adding an endpoint is a catalog entry, never new client code. Portable: core + string only.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |