@fungi.computer/darkroom 0.0.0-stage → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +315 -2
- package/dist/app-media-contracts.d.ts +499 -0
- package/dist/app-media-contracts.js +98 -0
- package/dist/browser-failure.d.ts +40 -0
- package/dist/browser-failure.js +39 -0
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +1 -0
- package/dist/cloudflare/provider.d.ts +13 -0
- package/dist/cloudflare/provider.js +140 -0
- package/dist/cloudflare/reference-images.d.ts +42 -0
- package/dist/cloudflare/reference-images.js +102 -0
- package/dist/cloudflare.d.ts +6 -0
- package/dist/cloudflare.js +4 -0
- package/dist/cost-estimate.d.ts +22 -0
- package/dist/cost-estimate.js +76 -0
- package/dist/effect.d.ts +2 -0
- package/dist/effect.js +2 -0
- package/dist/execution-error.d.ts +54 -0
- package/dist/execution-error.js +62 -0
- package/dist/failure.d.ts +2 -0
- package/dist/failure.js +8 -0
- package/dist/gateway-models.d.ts +23 -0
- package/dist/gateway-models.js +77 -0
- package/dist/gateway-wire.d.ts +16 -0
- package/dist/gateway-wire.js +22 -0
- package/dist/index.d.ts +361 -0
- package/dist/index.js +611 -0
- package/dist/media-binding.d.ts +291 -0
- package/dist/media-binding.js +146 -0
- package/dist/media-generation.d.ts +10 -0
- package/dist/media-generation.js +110 -0
- package/dist/media-operation-contract.d.ts +104 -0
- package/dist/media-operation-contract.js +29 -0
- package/dist/media-operation-do.d.ts +55 -0
- package/dist/media-operation-do.js +105 -0
- package/dist/media-operation-owner.d.ts +301 -0
- package/dist/media-operation-owner.js +903 -0
- package/dist/media-operation-storage.d.ts +81 -0
- package/dist/media-operation-storage.js +1 -0
- package/dist/media-operation.d.ts +33 -0
- package/dist/media-operation.js +230 -0
- package/dist/model-catalog.d.ts +456 -0
- package/dist/model-catalog.js +565 -0
- package/dist/neurons.d.ts +4 -0
- package/dist/neurons.js +4 -0
- package/dist/provenance-bytes.d.ts +3 -0
- package/dist/provenance-bytes.js +15 -0
- package/dist/provenance-export.d.ts +23 -0
- package/dist/provenance-export.js +103 -0
- package/dist/provenance-jpeg.d.ts +3 -0
- package/dist/provenance-jpeg.js +76 -0
- package/dist/provenance-png.d.ts +1 -0
- package/dist/provenance-png.js +21 -0
- package/dist/provenance-xmp.d.ts +2 -0
- package/dist/provenance-xmp.js +54 -0
- package/dist/provenance.d.ts +20 -0
- package/dist/provenance.js +58 -0
- package/dist/server.d.ts +158 -0
- package/dist/server.js +207 -0
- package/dist/video-providers/index.d.ts +14 -0
- package/dist/video-providers/index.js +14 -0
- package/dist/video-providers/minimax.d.ts +25 -0
- package/dist/video-providers/minimax.js +63 -0
- package/dist/video-providers/reference-encoding.d.ts +4 -0
- package/dist/video-providers/reference-encoding.js +11 -0
- package/dist/video-providers/types.d.ts +28 -0
- package/dist/video-providers/types.js +1 -0
- package/dist/video-providers/unified.d.ts +18 -0
- package/dist/video-providers/unified.js +52 -0
- package/docs/api/README.md +16 -0
- package/docs/api/app-media-contracts.md +507 -0
- package/docs/api/browser.md +126 -0
- package/docs/api/cloudflare.md +678 -0
- package/docs/api/effect.md +39 -0
- package/docs/api/index.md +1775 -0
- package/docs/api/modules.md +19 -0
- package/docs/api/provenance-export.md +114 -0
- package/docs/api/server.md +1672 -0
- package/package.json +110 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jamstack Consulting LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,316 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Darkroom
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Generate an image, keep the output, and retry a failed save without paying for
|
|
4
|
+
another generation. Your host supplies identity, permissions, a provider and a
|
|
5
|
+
place to put the file.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @fungi.computer/darkroom
|
|
11
|
+
npm install --save-dev wrangler @cloudflare/workers-types
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The root catalog and `server` work without a Workers runtime. The `cloudflare`
|
|
15
|
+
adapter runs on workerd, celld and Cloudflare with SQLite Durable Objects and
|
|
16
|
+
R2.
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
Save this as `worker.ts`. TypeScript hosts use
|
|
21
|
+
`lib: ["ES2023", "ESNext.Disposable"]` and
|
|
22
|
+
`types: ["@cloudflare/workers-types/experimental"]` in their compiler options.
|
|
23
|
+
This local example uses a fixed provider that returns a one-pixel GIF, so you
|
|
24
|
+
can try the save and retry path without a model account. Replace `provider` with
|
|
25
|
+
your own `MediaProvider` for real generation.
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
/// <reference types="@cloudflare/workers-types/experimental" resolution-mode="require" />
|
|
29
|
+
import { listMediaModels } from "@fungi.computer/darkroom";
|
|
30
|
+
import { createMediaService } from "@fungi.computer/darkroom/server";
|
|
31
|
+
import { MediaOperationDO } from "@fungi.computer/darkroom/cloudflare";
|
|
32
|
+
|
|
33
|
+
export { MediaOperationDO };
|
|
34
|
+
|
|
35
|
+
type Bindings = {
|
|
36
|
+
MEDIA_OPERATION: DurableObjectNamespace<MediaOperationDO>;
|
|
37
|
+
APP_ARTIFACTS: R2Bucket;
|
|
38
|
+
OUTPUTS: R2Bucket;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
async fetch(request: Request, env: Bindings): Promise<Response> {
|
|
43
|
+
const service = createMediaService({
|
|
44
|
+
scope: {
|
|
45
|
+
actorId: "local-owner",
|
|
46
|
+
namespace: "studio",
|
|
47
|
+
owner: "illustrator",
|
|
48
|
+
destinationId: "outputs",
|
|
49
|
+
},
|
|
50
|
+
operations: env.MEDIA_OPERATION,
|
|
51
|
+
provider: async () => ({
|
|
52
|
+
bytes: Uint8Array.from(
|
|
53
|
+
atob("R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"),
|
|
54
|
+
(character) => character.charCodeAt(0),
|
|
55
|
+
),
|
|
56
|
+
format: "gif",
|
|
57
|
+
}),
|
|
58
|
+
metering: "unmetered",
|
|
59
|
+
destination: {
|
|
60
|
+
authorize: async () => {},
|
|
61
|
+
write: async (path, bytes) => {
|
|
62
|
+
await env.OUTPUTS.put(path, bytes);
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
if (new URL(request.url).pathname === "/catalog")
|
|
67
|
+
return Response.json(listMediaModels());
|
|
68
|
+
return service.fetch(request);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Save this as `wrangler.json`:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"name": "darkroom-example",
|
|
78
|
+
"main": "worker.ts",
|
|
79
|
+
"compatibility_date": "2026-09-02",
|
|
80
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
81
|
+
"durable_objects": {
|
|
82
|
+
"bindings": [
|
|
83
|
+
{ "name": "MEDIA_OPERATION", "class_name": "MediaOperationDO" }
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MediaOperationDO"] }],
|
|
87
|
+
"r2_buckets": [
|
|
88
|
+
{ "binding": "APP_ARTIFACTS", "bucket_name": "darkroom-retained" },
|
|
89
|
+
{ "binding": "OUTPUTS", "bucket_name": "darkroom-output" }
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Run `npx wrangler dev --local`, then:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
curl http://localhost:8787/models
|
|
98
|
+
curl http://localhost:8787/generate \
|
|
99
|
+
-H 'Content-Type: application/json' -H 'X-Request-Id: first-picture' \
|
|
100
|
+
-d '{"path":"picture.gif","settings":{"model":"@cf/black-forest-labs/flux-1-schnell","prompt":"a quiet greenhouse","width":1024,"height":768}}'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Repeat the same request to replay its saved result. Change the input with the
|
|
104
|
+
same ID and the service returns 409. This example admits one local owner. Add
|
|
105
|
+
your host's authentication and destination authorization before serving others.
|
|
106
|
+
|
|
107
|
+
## Core concepts
|
|
108
|
+
|
|
109
|
+
The host chooses `actorId`, `namespace`, `owner` and `destinationId`. Request
|
|
110
|
+
bodies cannot choose that authority. A durable operation captures its identity
|
|
111
|
+
and input, retains provider bytes before saving, and reuses those bytes when a
|
|
112
|
+
save fails. An ambiguous provider execution is never silently dispatched again.
|
|
113
|
+
|
|
114
|
+
Declare `metering: "unmetered"` when your host pays its provider directly. A
|
|
115
|
+
metered host supplies idempotent `admit` and `settle` functions plus its own
|
|
116
|
+
`refusalMessages` for insufficient credit, daily limits and denied spending.
|
|
117
|
+
Quotes are estimates. Your metering owner decides the customer price and
|
|
118
|
+
settlement.
|
|
119
|
+
|
|
120
|
+
A recognized provider safety refusal returns HTTP 400 with
|
|
121
|
+
`code: "SAFETY_FILTER_REFUSED"`, `stage: "provider"`, and `retryable: false`.
|
|
122
|
+
The public message asks you to reword the prompt; provider details stay
|
|
123
|
+
redacted. Nothing is saved or charged. The owner retains only the bounded
|
|
124
|
+
refusal reason, so same-ID replay and background video polling preserve that
|
|
125
|
+
verdict without calling the provider again. Workers AI's observed NSFW-input
|
|
126
|
+
refusal and
|
|
127
|
+
[Veo's documented input-policy refusal](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/video/responsible-ai-and-usage-guidelines)
|
|
128
|
+
are classified; an error number by itself is not a safety verdict.
|
|
129
|
+
|
|
130
|
+
Pre-launch operation stores must use the current fresh schema. Hosts reset old
|
|
131
|
+
disposable stores; Darkroom does not migrate or repair their missing refusal
|
|
132
|
+
fact.
|
|
133
|
+
|
|
134
|
+
Video generation runs through the operation's alarm. A 202 response tells you to
|
|
135
|
+
retry the same request ID after the supplied `Retry-After` delay.
|
|
136
|
+
|
|
137
|
+
## API reference
|
|
138
|
+
|
|
139
|
+
| Import | Purpose |
|
|
140
|
+
| ---------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
141
|
+
| `@fungi.computer/darkroom` | Model catalog, settings, references, provider wire shapes and cost estimates. |
|
|
142
|
+
| `@fungi.computer/darkroom/app-media-contracts` | Runtime-neutral App catalog, destination and completed-generation schemas. |
|
|
143
|
+
| `@fungi.computer/darkroom/server` | Hono service, typed generation, metering and the portable SQL operation owner. |
|
|
144
|
+
| `@fungi.computer/darkroom/cloudflare` | Native operation DO, Workers AI provider and Images fitters. |
|
|
145
|
+
| `@fungi.computer/darkroom/provenance` | Lossless public image downloads with private metadata removed. |
|
|
146
|
+
|
|
147
|
+
The App-facing JSON protocol and page handles live in
|
|
148
|
+
`@fungi.computer/agar/media-json`. Darkroom owns host execution and its
|
|
149
|
+
`@fungi.computer/darkroom/browser` HTTP failure decoder.
|
|
150
|
+
|
|
151
|
+
The App contract entry exports `mediaModelsSchema`, `destinationSchema` and
|
|
152
|
+
`appMediaGenerationResultSchema`. The catalog bound is the maintained model
|
|
153
|
+
count; the host still filters models after decoding. Pending App replies use
|
|
154
|
+
Agar's public `pendingSchema`. `appMediaModelsOutcomeSchema` and
|
|
155
|
+
`appMediaGenerationOutcomeSchema` include the broker's emitted refusal payloads:
|
|
156
|
+
closed admission codes, the Media attachment-budget refusal, the existing
|
|
157
|
+
`agentAppMediaLibraryFailureSchema`, and `appMediaBrokerFailureSchema`. The
|
|
158
|
+
latter preserves the broker projection: HTTP `code` becomes `error`, HTTP
|
|
159
|
+
`error` becomes `message`, and `stage` and `retryable` stay unchanged. HTTP
|
|
160
|
+
failures and transport envelopes are separate representations and do not decode
|
|
161
|
+
as these outcomes.
|
|
162
|
+
|
|
163
|
+
See the [generated API](docs/api/README.md) for signatures and host ports. The
|
|
164
|
+
Cloudflare entry needs the native Workers type declarations in a TypeScript
|
|
165
|
+
host. The other entries use ordinary platform web types.
|
|
166
|
+
|
|
167
|
+
## Examples
|
|
168
|
+
|
|
169
|
+
For Workers AI, use `createWorkersAiMediaProvider(env.AI)` from `cloudflare` and
|
|
170
|
+
add an `AI` binding to your host. `createImagesReferenceFitter` prepares bounded
|
|
171
|
+
reference images through an Images binding. Your host authorizes each reference
|
|
172
|
+
read.
|
|
173
|
+
|
|
174
|
+
`stripPrivateProvenance(bytes)` from `provenance` removes prompt and lineage
|
|
175
|
+
metadata while preserving the AI marker, print ID and image encoding. It returns
|
|
176
|
+
bytes, MIME type and filename extension. The public XMP format uses
|
|
177
|
+
`https://fungi.computer/ns/provenance/1.0/`.
|
|
178
|
+
|
|
179
|
+
## Limits
|
|
180
|
+
|
|
181
|
+
References are bounded to four files, 512 pixels per side and 8 MiB per image.
|
|
182
|
+
Still-image output and public downloads are bounded to 32 MiB. Catalog models
|
|
183
|
+
may impose tighter limits. Video output has its own 64 MiB provider bound.
|
|
184
|
+
|
|
185
|
+
Private-provenance export supports PNG, JPEG and WebP. GIF without XMP remains
|
|
186
|
+
index-only. Signed, malformed and unsupported images return a typed refusal. The
|
|
187
|
+
original file is never changed.
|
|
188
|
+
|
|
189
|
+
## Contribute and license
|
|
190
|
+
|
|
191
|
+
MIT. See [LICENSE](LICENSE).
|
|
192
|
+
|
|
193
|
+
The `server` export provides the Promise `generateMedia(host, request, signal?)`
|
|
194
|
+
boundary and the relative HTTP service. Hosts composing Effect programs import
|
|
195
|
+
`runMediaGeneration` from `@fungi.computer/darkroom/effect`. Its advanced
|
|
196
|
+
declarations require the host's Effect environment; ordinary Workers consumers
|
|
197
|
+
need only the native Workers declarations.
|
|
198
|
+
|
|
199
|
+
## Video selections
|
|
200
|
+
|
|
201
|
+
The root export owns `mediaVideoSelectionSchema`, `validateMediaVideoSelection`,
|
|
202
|
+
`MediaVideoSelectionInput` and `MediaVideoSelection`. Apps select paths; their
|
|
203
|
+
host supplies reference authority and the MP4 destination. For example:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import {
|
|
207
|
+
estimateVideoMilliunits,
|
|
208
|
+
validateMediaVideoSelection,
|
|
209
|
+
} from "@fungi.computer/darkroom";
|
|
210
|
+
|
|
211
|
+
const selection = validateMediaVideoSelection({
|
|
212
|
+
model: "bytedance/seedance-2.0-mini",
|
|
213
|
+
prompt: "Fern fronds unfolding in morning light",
|
|
214
|
+
resolution: "720p",
|
|
215
|
+
aspectRatio: "16:9",
|
|
216
|
+
durationSeconds: 5,
|
|
217
|
+
references: [{ path: "fern.png", role: "first-frame" }],
|
|
218
|
+
});
|
|
219
|
+
const providerCostMilliunits = estimateVideoMilliunits(selection);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The strict input fields are `model`, `prompt`, optional `resolution`,
|
|
223
|
+
`aspectRatio`, `durationSeconds`, `generateAudio`, and optional `references`.
|
|
224
|
+
Each reference is `{path, role}`; role is `first-frame`, `last-frame`, or
|
|
225
|
+
`reference`. Normalization returns nominal `width`/`height`, explicit
|
|
226
|
+
resolution, aspect and duration, and the same path-only references. The host
|
|
227
|
+
adds its admitted `computerId` before calling the existing service. A single
|
|
228
|
+
untagged reference in that host service is first-frame mode, preserving the
|
|
229
|
+
existing Workflow caller. Unsupported combinations throw `MediaSettingsError`;
|
|
230
|
+
the service returns `400 INVALID_ARGUMENT` before billing admission or dispatch.
|
|
231
|
+
|
|
232
|
+
The sole model catalog describes these verified Unified AI contracts: Seedance
|
|
233
|
+
and Veo checked 2026-10-11, MiniMax H3 Max checked 2026-10-14. They run through
|
|
234
|
+
Workers `AI.run` with unprefixed IDs. Cloudflare's Workers AI `@cf/` catalog
|
|
235
|
+
does not supply these video IDs.
|
|
236
|
+
|
|
237
|
+
| Model | Resolution | Duration | Reference modes | Provider USD / output second |
|
|
238
|
+
| --------------------------------------------------------------------------------------------- | ------------------------ | ---------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------- |
|
|
239
|
+
| [Seedance 2.0](https://developers.cloudflare.com/ai/models/bytedance/seedance-2.0/) | 480p / 720p / 1080p / 4k | integers 4–12; default 5 | first frame; first + last; 1–4 reference images except at 1080p | .07 / .15 / .37 / .78 |
|
|
240
|
+
| [Seedance 2.0 Fast](https://developers.cloudflare.com/ai/models/bytedance/seedance-2.0-fast/) | 480p / 720p | integers 4–12; default 5 | first frame; first + last; 1–4 reference images | .06 / .12 |
|
|
241
|
+
| [Seedance 2.0 Mini](https://developers.cloudflare.com/ai/models/bytedance/seedance-2.0-mini/) | 480p / 720p | integers 4–12; default 5 | first frame; first + last; 1–4 reference images | .04 / .09 |
|
|
242
|
+
| [Veo 3.1](https://developers.cloudflare.com/ai/models/google/veo-3.1/) | 720p / 1080p | exactly 4 / 6 / 8; default 6 | one first image | .20 silent / .40 audio at either resolution |
|
|
243
|
+
| [Veo 3.1 Fast](https://developers.cloudflare.com/ai/models/google/veo-3.1-fast/) | 720p / 1080p | exactly 4 / 6 / 8; default 6 | one first image | 720p .08 silent / .10 audio; 1080p .10 silent / .12 audio |
|
|
244
|
+
| [MiniMax H3 Max](https://developers.cloudflare.com/ai/models/minimax/h3-max/) | 480p / 768p | integers 5–15; default 5 | first frame; first + last; 1–4 reference images, either resolution | .05 / .08 (no documented audio surcharge) |
|
|
245
|
+
|
|
246
|
+
Seedance and Veo default to 720p and 16:9; MiniMax H3 Max defaults to 768p and
|
|
247
|
+
16:9. Seedance aspects are 16:9, 4:3, 1:1, 3:4, 9:16, 21:9, and 9:21, with fixed
|
|
248
|
+
24 FPS. Veo aspects are 16:9, 9:16 and 1:1. MiniMax H3 Max aspects are 16:9,
|
|
249
|
+
4:3, 1:1, 3:4, 9:16 and 21:9 (no 9:21; its documented `adaptive` selector, which
|
|
250
|
+
follows the input image's own aspect instead of a fixed box, has no nominal
|
|
251
|
+
pixel size and is not exposed by this catalog). Seedance prompts are at most
|
|
252
|
+
2,000 characters; Veo uses Darkroom's retained 2,048-character host limit
|
|
253
|
+
because the provider page states no prompt maximum; MiniMax H3 Max's own limit
|
|
254
|
+
is 7,000 but Darkroom's 2,048-character host cap binds first. Paths are trimmed,
|
|
255
|
+
nonblank and at most 4,096 characters; references are bounded at four overall
|
|
256
|
+
and refined per model (MiniMax H3 Max's own page documents up to nine, which
|
|
257
|
+
this four-reference host ceiling cannot reach). Last frame requires exactly one
|
|
258
|
+
first frame. Frame mode cannot mix with reference-image mode. Seedance's first
|
|
259
|
+
image can override the requested aspect; returned width/height are nominal
|
|
260
|
+
selectors, not measured MP4 dimensions.
|
|
261
|
+
|
|
262
|
+
Veo audio defaults to true and is always explicit in the provider request and
|
|
263
|
+
quote. Seedance leaves `generate_audio` unset when `generateAudio` is omitted,
|
|
264
|
+
because its audio default is undocumented; its non-video-input rates are the
|
|
265
|
+
same for either audio choice. MiniMax H3 Max has no audio field at all: its
|
|
266
|
+
catalog entry carries the same silent and audio rate, and `gatewayInput` throws
|
|
267
|
+
`MediaSettingsError` if a caller sets `generateAudio` explicitly, rather than
|
|
268
|
+
silently dropping the choice. `estimateVideoMilliunits` and the gateway
|
|
269
|
+
estimator read the catalog prices: 1 USD = 100,000 milliunits, 1 cent = 1,000.
|
|
270
|
+
`mediaUnits` returns `{unit: "video_second", units: durationSeconds}`. The host
|
|
271
|
+
still owns admission, settlement, markup and refusal copy.
|
|
272
|
+
|
|
273
|
+
Reference limits follow the explicit Seedance parameter section's four-image
|
|
274
|
+
grammar; its overview's larger counts remain unsupported. Veo 4k pricing does
|
|
275
|
+
not establish a supported 4k input, and Seedance 2.5's duration grammar remains
|
|
276
|
+
unverified. Video/audio references and undocumented options are refused, never
|
|
277
|
+
silently dropped. Seedance frames and references become data URIs; Veo's
|
|
278
|
+
`image_input` is plain base64; MiniMax H3 Max's are data URIs inside a
|
|
279
|
+
multimodal `content[]` array (`{type: "image_url", image_url: {url}, role}`),
|
|
280
|
+
alongside the leading `{type: "text", text: prompt}` entry — a different
|
|
281
|
+
provider body than Seedance or Veo's flat `prompt`/`image` fields, documented
|
|
282
|
+
only by the raw request/response JSON schemas the Cloudflare page links, not its
|
|
283
|
+
prose parameter list. MiniMax H3 Max also sends its resolution selector
|
|
284
|
+
uppercase (`480P`/`768P`) where every other model sends it lowercase. Every
|
|
285
|
+
admitted image is translated, preserving its role. All successful responses use
|
|
286
|
+
the existing bounded HTTPS MP4 fetch and retention path (64 MiB maximum).
|
|
287
|
+
Seedance and Veo answer with the Unified gateway's normalized
|
|
288
|
+
`{state: "Completed", result: {video}}`; MiniMax H3 Max instead answers with its
|
|
289
|
+
own documented `{task: {status, content: {url}}}` wrapper, decoded separately
|
|
290
|
+
and treated as failed unless `status` is exactly `"succeeded"`. The provider
|
|
291
|
+
returns `{bytes, format: "mp4"}`; the service returns
|
|
292
|
+
`{bytes, costMilliunits, path, format, height, model, width}` on completion.
|
|
293
|
+
While the alarm is running, HTTP returns 202 with
|
|
294
|
+
`{status: "pending", retryAfterSeconds: 5}`. Retry the same request ID,
|
|
295
|
+
destination and settings to recover the retained result. The host chooses the
|
|
296
|
+
output path, such as `prints-<requestId>.mp4`; Darkroom adds no output-naming
|
|
297
|
+
rule or human-review gate.
|
|
298
|
+
|
|
299
|
+
### App MEDIA binding
|
|
300
|
+
|
|
301
|
+
The shared `@fungi.computer/darkroom/server` binding grammar and reply decoder
|
|
302
|
+
are used by Hub and standalone Oyster. The internal generation command carries
|
|
303
|
+
its image/video kind, stable request ID and App-owned library folder. Hosts
|
|
304
|
+
attach the admitted Computer to reference paths, read and fit those references,
|
|
305
|
+
and use `createMediaService` for generation, retention, replay and saving.
|
|
306
|
+
Guests cannot supply a principal or reference Computer ID.
|
|
307
|
+
|
|
308
|
+
Image encoding is model-native when `outputFormat` is omitted. An explicit PNG,
|
|
309
|
+
JPEG or WebP pin must be supported by the model; the saved result reports its
|
|
310
|
+
actual encoding. Catalogs retain reference support declared by the model and
|
|
311
|
+
available through that host. Unsupported reference selections are typed
|
|
312
|
+
`INVALID_ARGUMENT` settings refusals before dispatch.
|
|
313
|
+
|
|
314
|
+
Runtime-neutral App definitions import the shared binding schemas from
|
|
315
|
+
`@fungi.computer/darkroom/media-binding`; the server entry also re-exports them
|
|
316
|
+
for host composition.
|