Uh oh!
There was an error while loading. Please reload this page.
Compositions documentation - #278
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new beta Smelter Cloud documentation section to the Docusaurus site, including concept docs, how-to guides, and a published OpenAPI/Scalar REST API reference.
Changes:
- Introduces new
docs/smelter/docs tree (overview, quick start, scenes, how-tos, API reference) and sidebar categories. - Publishes Smelter Cloud REST API docs via Scalar at
/api/smelter-cloud, backed by a committed OpenAPI JSON spec. - Updates tooling to fetch/copy the Smelter Cloud spec from a new submodule and links the local
@fishjam-cloud/compositionpackage for type-checkable examples.
Reviewed changes
Copilot reviewed 16 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Adds workspace link entry for @fishjam-cloud/composition. |
| static/api/smelter-cloud-openapi.json | Adds committed Smelter Cloud OpenAPI 3.1 JSON spec for publishing. |
| spelling.txt | Adds rtmp to spellcheck allowlist. |
| scripts/update_api.sh | Adds branch-based submodule checkout and JSON spec sanitization/copy step. |
| package.json | Adds linked dependency on @fishjam-cloud/composition for examples/typechecking. |
| docusaurus.config.ts | Adds a Scalar instance to render the Smelter Cloud REST API reference page. |
| docs/smelter/what-is-smelter-cloud.mdx | Adds Smelter Cloud concept overview and navigation pointers. |
| docs/smelter/scenes.mdx | Documents video/audio scene model and live updates. |
| docs/smelter/quick-start.mdx | Adds end-to-end tutorial for creating/registering inputs/outputs and publishing. |
| docs/smelter/how-to/write-and-deploy-a-template.mdx | Adds template authoring/build/deploy guide including multipart upload endpoint. |
| docs/smelter/how-to/inputs-and-outputs.mdx | Summarizes supported input/output protocols and key fields. |
| docs/smelter/how-to/drive-a-template-with-events.mdx | Documents event delivery to templates via /event endpoint and eventBus. |
| docs/smelter/how-to/compose-a-fishjam-room.mdx | Documents linking a Fishjam room and templating room-driven layouts. |
| docs/smelter/how-to/category.json | Adds How-to Guides generated index under Smelter Cloud section. |
| docs/smelter/api-reference.mdx | Adds entry-point page for REST API, WebSocket auth, and error format. |
| docs/smelter/category.json | Adds top-level “Smelter Cloud” sidebar category at position 1. |
| .gitmodules | Adds api/smelter-cloud submodule entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 16 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (7)
docs/how-to/compositions/compose-a-fishjam-room.mdx:114
- This curl example uses a placeholder
Authorization: ******header, which is not a valid HTTP Authorization value and omits the requiredBearerprefix for the Management Token.
-H "Authorization: Bearer $TOKEN" \
docusaurus.config.ts:390
- The
/api/restScalar config declares asourcesentry for the Composition API, but the page-levelauthentication.preferredSecuritySchemeis set tomanagement_token, which does not exist incomposition-openapi.json(it usesBearerAuth). This can break or misconfigure the auth UI when switching to the Composition source, and it’s also redundant given the dedicated/api/compositionsScalar page below.
title: "Composition API",
slug: "composition",
url: "/docs/api/composition-openapi.json",
},
],
docs/how-to/compositions/compose-a-fishjam-room.mdx:97
- This curl example uses a placeholder
Authorization: ******header, which is not a valid HTTP Authorization value and omits the requiredBearerprefix for the Management Token.
-H "Authorization: Bearer $TOKEN" \
docs/how-to/compositions/compose-a-fishjam-room.mdx:125
- This curl example uses a placeholder
Authorization: ******header, which is not a valid HTTP Authorization value and omits the requiredBearerprefix for the Management Token.
-H "Authorization: Bearer $TOKEN"
docs/how-to/compositions/compose-a-fishjam-room.mdx:136
- This curl example uses a placeholder
Authorization: ******header, which is not a valid HTTP Authorization value and omits the requiredBearerprefix for the Management Token.
-H "Authorization: Bearer $TOKEN"
docs/api/reference.md:93
- The Composition authentication table contains broken/placeholder header values (e.g. missing
Bearer, missing closing backticks) which will render incorrectly and gives an invalid auth example.
| Control-plane calls (composition, inputs, outputs, renderers, events, room) | `Authorization: Bearer <token>`: your Fishjam **Management Token**, the same token used across Fishjam. |
| Publishing to an input (`/whip/{input_id}`) | The **input's** own bearer token, returned when you register a `whip_server` input (or the one you supplied). This is distinct from your account token. |
| Playing back an output (`/whep/{output_id}`) | Optional. Public playback is allowed; add a Bearer token only if you want to require one. |
docs/how-to/compositions/compose-a-fishjam-room.mdx:88
- This curl example uses a placeholder
Authorization: ******header, which is not a valid HTTP Authorization value and omits the requiredBearerprefix for the Management Token.
This issue also appears in the following locations of the same file:
- line 97
- line 114
- line 125
- line 136
-H "Authorization: Bearer $TOKEN" \
PiotrWodecki
left a comment
There was a problem hiding this comment.
postponing review until internal things are live
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Updated with new composition api openapi after fixes and other improvements |
PiotrWodecki
left a comment
There was a problem hiding this comment.
Mostly seems to match the current/future behavior, only stylistic changes are left
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
New top-level docs section for the hosted composition service: concept overview (disambiguated from the client-side Smelter library), quick start, template authoring with the composition SDK and CLI, room composition, runtime events, an input/output guide, a scene-model explainer, and an API reference. The REST reference renders a sanitized preview OpenAPI spec via Scalar; the auth model and WebSocket event stream are documented in prose.
Replace the hand-written preview spec with one generated from the
service source, copied by scripts/update_api.sh (the source repo is
private, so it is cloned on demand instead of being a submodule) and
sanitized of internal-only fields. The committed spec comes from the
template-workers branch with the oneOf variant-title improvement
applied, matching what main will contain after the pending merge.
Align the docs with the actual API surface: templated outputs are
registered in a single multipart request to POST
.../output/{output_id}/template (config + template), not registered
first and uploaded after; rescaler takes a single child. Template code
samples are now type-checked by the build, with
@fishjam-cloud/composition linked from the js-server-sdk submodule.CI's SUBMODULES_TOKEN covers the private source repo (same as the fishjam and room-manager submodules), so clone-on-demand is not needed. The repo has no semver release tags yet, so the submodule is checked out at a branch instead of the latest tag.
Guard the jq dependency in update_api.sh, use optional chaining on peer metadata in the template example, and fix quick-start wording: a whip_client output publishes to a WHIP endpoint; playback is WHEP on the receiving service.
"GPU-backed rendering session" and "bills for GPU time" pinned the docs to an implementation detail that buys the reader nothing: what they act on is that a composition bills continuously while it exists, not what it runs on. It also committed us to one composition per GPU, which we would have to keep true. The claim about being the most expensive thing in Fishjam went too, since pricing belongs on the pricing page and that sentence ages badly. The idle-cleanup warning was repeated almost verbatim in two how-tos and carried the five minute figure, which also appears in two more files. It is now one shared snippet, so the number has one home.
Outputs were described as pushing, and as where the result is sent, which is accurate but leaves the reader looking for the URL to watch a composition on. There isn't one. The concept page now states that a composition produces video rather than serving it, and the how-to leads with the missing URL and shows where viewers actually connect instead.
Saying the output pushes somewhere else, and that viewers connect to that somewhere else, restated the problem rather than answering it. The two destinations are a Fishjam livestream watched over WHEP and an RTMP service such as YouTube, so the diagram and the prose name them.
The shared cleanup warning repeated the paragraph it sat under in both how-tos, so it is now only the part those paragraphs do not say: nothing will delete this composition for you. Both how-tos created a composition and then used $COMPOSITION without ever capturing it, and two of them used $COMPOSITION_URL and $TOKEN with nothing defining them, so following either from the top produced requests to an empty URL. Both now save the id, and both carry the same environment block the tutorial uses. Also: the room how-to now says where to get the livestream URL and token it asks you to paste, its two links to the Server API agree with each other, the reference states that unknown fields are rejected rather than ignored, and the intro no longer says the composed stream can be published anywhere when the point is that it goes to one destination you choose.
The tutorial used inset as a verb once and then as a name for the layout twice, 170 lines later, without ever introducing that name. Step 4 meanwhile described the same thing as a rounded box and as tucked into the corner. It is a corner overlay everywhere now.
The tutorial described the layout twice, once in prose and once as a box drawing, and neither showed what the composition actually produces. The clip is the real thing: smelter rendering the Step 4 scene from the same two mp4 inputs, then the Step 6 update switching to tiles, captured through an mp4 output rather than a screen recording.
baseUrl is /docs, so a bare /video/... src pointed outside the site and the element loaded nothing. useBaseUrl emits /docs/video/... instead.
The clip ran through the Step 6 layout switch and the caption announced it, which gave away the step before the reader gets there. It is now ten seconds of the corner overlay alone, and the caption describes just that.
The livestream is scaffolding here, not the subject, so getting one should be as short as possible. One unauthenticated call now returns both the streamer token and the stream id, replacing two authenticated calls. It also means the result can be watched in the livestreaming demo instead of sending readers to a third-party WHEP player, since that demo takes exactly the room name used here. A note says the Sandbox API is for prototyping and production creates livestreams through the Server API, and cleanup still goes that way because the Sandbox API only creates.
This reverts commit 2f8fdc0.
The clip above already shows the layout, so naming it again after the playback instructions repeats what the reader has just watched.
Restores the Sandbox API flow reverted in d69e4b9, with the one change that made it fail: the livestream is created with public=false. The room-manager keys its in-memory room lookup on the whole room config, and public is part of that config, so a livestream created as public is stored under a different key than the one the viewer path looks for. getSandboxViewerToken in the client SDK sends no public parameter, so it always looks for the unlisted variant and a public livestream is invisible to it. Verified end to end against production: the create call returns a streamer token, and the viewer token call the demo makes returns 200 for the same room name.
The inputs table already lists what a whip_server input accepts, from a phone camera to a hardware encoder, so pointing at a third-party publisher on top added nothing. OBS stays, it ships WHIP output. The template how-to also promised that the tutorial's livestream plays back in any WHEP player without a token. Since the tutorial now creates it unlisted through the Sandbox API, that is no longer true.
The composition pages tell you to copy your Management Token and then ask you to paste it into YOUR_FISHJAM_TOKEN. Everywhere else in the docs it is the Management Token, so the placeholder now says so too.
The page handed the reader a template and then jumped straight to sending events, with no route from one to the other. It now names the multipart deploy request and the livestream the output needs, each linked to the page that covers it.
Two pages sent readers to an empty URL. The template how-to publishes with $STREAMER_TOKEN and deletes $STREAM without setting either, and the inputs and outputs guide uses $COMPOSITION_URL, $TOKEN and $COMPOSITION with no environment block at all. Both now define what they use, and say which tutorial step produces the composition, the livestream and its token.
Doing it in the preamble meant both sat idle through scaffolding, writing and building the template, and a composition with no input media deletes itself after five minutes, so the reader would reach the deploy step with nothing to deploy to. The environment block now lives in the deploy section. The inputs and outputs guide keeps no environment block: it is a reference for picking types, not a walkthrough.
The Sandbox API URL is a separate credential that can be regenerated and revoked on its own, so it cannot be derived by appending /room-manager to the Fishjam URL. The tutorial exports it like every other value it needs, and Step 5 points back at the same one rather than describing how to build it.
It was created in the preamble and then sat through the whole template example, which is the one thing the page warns about two paragraphs later. Creation now happens in the deploy section, next to the output it needs.
The route is /api/composition/{composition_id}/whip/{input_id}. Posting to
rtc.fishjam.io/whip/... answers 400 missing field composition_id, so the
shortened form sent publishers nowhere.With cleanup_without_inputs off, cleanup still runs, it just waits for the outputs to go quiet as well as the inputs. Claiming nothing will clean it up, or that an idle one survives indefinitely, promised more than the code does: is_inactive returns inputs_inactive && outputs_inactive in that mode, so an idle composition is still collected. What survives is one whose output keeps publishing.
main now requires url on the mp4 input and no longer has an hls input at all, so the spec asset, the input table and every prose list of supported protocols follow. The submodule points at main again, the way update-api leaves it.
- regenerate static/api/composition-openapi.json from foundry main and move the submodule with it - rtmp_server now takes only stream_key, app is gone from the schema - oneOf variants arrive as plain $refs instead of allOf wrappers
58f1870 to
ddf5459CompareUh oh!
There was an error while loading. Please reload this page.
Closes FCE-2924, FCE-2925 and FCE-3137 by publishing the API specification here.
Documents compositions as a core Fishjam feature, integrated into the existing docs structure instead of a standalone section:
explanation/compositions(what compositions are, core concepts, the scene model).tutorials/compositions(create a composition end to end with curl).how-to/compositions/(write and deploy a template, compose a Fishjam room, drive a template with events, choose inputs and outputs).api/reference): a Compositions section covering REST, the WebSocket event stream, authentication, and errors.