@remotion-studio/sdk
v0.1.4
Published
Official Remotion Studio package for generating, editing, playing, and rendering AI-powered Remotion compositions.
Maintainers
Readme
@remotion-studio/sdk
Official SDK for the hosted Remotion Studio API.
This package includes:
@remotion-studio/sdkfor calling the API@remotion-studio/sdk/runtimefor rendering returned artifacts inside Remotion or@remotion/player
Install
npm install @remotion-studio/sdkpnpm add @remotion-studio/sdkbun add @remotion-studio/sdkAuthentication
Create a personal API token in the Remotion Studio web app, then use it as a bearer token.
import { createRemotionStudioClient } from "@remotion-studio/sdk";
const client = createRemotionStudioClient({
baseUrl: "https://remotionstudio.io",
headers: {
Authorization: `Bearer ${process.env.REMOTIONSTUDIO_API_TOKEN}`,
},
});The plaintext token is shown only once when it is created.
Client Options
createRemotionStudioClient() accepts:
baseUrl?: stringheaders?: HeadersInitfetch?: typeof fetch
baseUrl should be the Remotion Studio origin, for example https://remotionstudio.io, not https://remotionstudio.io/api.
SDK Methods
| Method | HTTP | Endpoint | Purpose |
| ---------------------- | ------ | ---------------------------- | ----------------------------------------------- |
| generate() | POST | /api/generate | Generate a composition |
| generateStream() | POST | /api/generate | Stream generation output with streaming: true |
| edit() | POST | /api/edit | Edit existing code |
| generateAsync() | POST | /api/generate/async | Queue a generation job |
| getGenerationJob() | GET | /api/generate/async/:jobId | Read generation job state |
| pollGenerationJob() | GET | /api/generate/async/:jobId | Wait for generation completion |
| editAsync() | POST | /api/edit/async | Queue an edit job |
| getEditJob() | GET | /api/edit/async/:jobId | Read edit job state |
| pollEditJob() | GET | /api/edit/async/:jobId | Wait for edit completion |
| render() | POST | /api/render/render | Start a Remotion Lambda render |
| getRenderProgress() | POST | /api/render/progress | Fetch render progress |
| pollRenderProgress() | POST | /api/render/progress | Wait for render completion |
Generate
const generated = await client.generate({
prompt: "A cinematic product hero reveal with dramatic lighting",
reasoningEffort: "none",
});Request fields:
prompt: stringpresetId?: stringreasoningEffort?: "none" | "low" | "medium" | "high" | "xhigh"frameImages?: string[]
Edit
const edited = await client.edit({
prompt: "Make it faster, cleaner, and more typography-driven",
currentCode: generated.code,
threadId: generated.thread?.id,
});Common request fields:
prompt: stringcurrentCode: stringthreadId?: stringconversationHistory?: { role: "user" | "assistant"; content: string; attachedImages?: string[] }[]hasManualEdits?: booleanerrorCorrection?: { error: string; source?: "compilation" | "runtime" | "generation"; attemptNumber: number; maxAttempts: number; failedEdit?: { description: string; old_string: string; new_string: string; lineNumber?: number } }previouslyUsedSkills?: string[]frameImages?: string[]reasoningEffort?: "none" | "low" | "medium" | "high" | "xhigh"
Stream Generation
const result = await client.generateStream(
{
prompt: "A kinetic typography intro",
},
{
onMetadata: (metadata) => {
console.log(metadata);
},
onReasoningStart: () => {
console.log("reasoning started");
},
onReasoning: (reasoning) => {
console.log(reasoning);
},
onTextStart: () => {
console.log("code started");
},
onCode: (partialCode) => {
console.log(partialCode);
},
},
);Async Jobs
Use async methods for long-running generations or edits.
Queue A Generation
const job = await client.generateAsync({
prompt: "A premium SaaS launch video opener",
reasoningEffort: "high",
webhook: {
url: "https://your-app.example.com/remotionstudio/webhook",
headers: {
Authorization: "Bearer your-app-owned-callback-token",
},
},
});
const generated = await client.pollGenerationJob(job.id, {
intervalMs: 2000,
timeoutMs: 10 * 60 * 1000,
});Read A Generation Job
const jobState = await client.getGenerationJob(job.id);Queue An Edit
const editJob = await client.editAsync({
prompt: "Add more contrast and speed up the transitions",
currentCode: generated.code,
threadId: generated.thread?.id,
});
const edited = await client.pollEditJob(editJob.id);Read An Edit Job
const editJobState = await client.getEditJob(editJob.id);Webhook headers are caller-owned. Remotion Studio forwards them when delivering the callback.
Render
Start a render:
const render = await client.render({
inputProps: {
code: generated.code,
durationInFrames: generated.artifact.composition.durationInFrames,
fps: generated.artifact.composition.fps,
},
threadId: generated.thread?.id,
});Check progress once:
const progress = await client.getRenderProgress({
id: render.renderId,
bucketName: render.bucketName,
});Poll until done:
const completed = await client.pollRenderProgress(
{
id: render.renderId,
bucketName: render.bucketName,
},
{
intervalMs: 2000,
timeoutMs: 10 * 60 * 1000,
},
);
console.log(completed.url);Responses
generate() and edit() return:
codesummarymetadataartifactthread?
The artifact is the stable runtime contract for playback and rendering.
Runtime
@remotion-studio/sdk/runtime exports:
MotionGraphicsSlotMotionGraphicsCompositioncalculateMotionGraphicsMetadatacompileMotionGraphicsArtifact
The runtime executes generated code inside your app process. Treat returned artifacts as trusted code only.
Render Inside An Existing Composition
Use MotionGraphicsSlot when you want to place a generated artifact inside your own composition tree.
import { AbsoluteFill } from "remotion";
import {
MotionGraphicsSlot,
type MotionGraphicsArtifact,
} from "@remotion-studio/sdk/runtime";
export const MyComposition = ({
artifact,
}: {
artifact: MotionGraphicsArtifact;
}) => {
return (
<AbsoluteFill>
<MotionGraphicsSlot artifact={artifact} />
</AbsoluteFill>
);
};Render In @remotion/player
import { Player } from "@remotion/player";
import {
MotionGraphicsComposition,
type MotionGraphicsArtifact,
} from "@remotion-studio/sdk/runtime";
export const ArtifactPlayer = ({
artifact,
}: {
artifact: MotionGraphicsArtifact;
}) => {
return (
<Player
component={MotionGraphicsComposition}
inputProps={{ artifact }}
durationInFrames={artifact.composition.durationInFrames}
fps={artifact.composition.fps}
compositionWidth={artifact.composition.width}
compositionHeight={artifact.composition.height}
controls
/>
);
};Register As A Remotion Composition
Use MotionGraphicsComposition with calculateMotionGraphicsMetadata when the artifact should define the composition dimensions and timing.
import { Composition } from "remotion";
import {
MotionGraphicsComposition,
calculateMotionGraphicsMetadata,
type MotionGraphicsCompositionProps,
} from "@remotion-studio/sdk/runtime";
export const RemotionRoot = ({ artifact }: MotionGraphicsCompositionProps) => {
return (
<Composition
id="GeneratedComposition"
component={MotionGraphicsComposition}
defaultProps={{ artifact }}
durationInFrames={180}
fps={30}
width={1920}
height={1080}
calculateMetadata={calculateMotionGraphicsMetadata}
/>
);
};Runtime Props
Both MotionGraphicsSlot and MotionGraphicsComposition accept:
artifact: MotionGraphicsArtifactcomponentProps?: Record<string, unknown>
componentProps is forwarded to the generated component at runtime.
Runtime Dependencies
If you only use the API client from @remotion-studio/sdk, you do not need any runtime dependencies.
If you use @remotion-studio/sdk/runtime, the package installs its runtime helper dependencies for you.
You still need to use it inside a normal React + Remotion app, and install @remotion/player separately if you want to use the player example above.
Errors
API failures throw RemotionStudioError.
Useful fields:
messagetypestatus?failedEdit?availableCredits?requiredCredits?
API Docs
- Hosted API reference: remotionstudio.io/api-docs
Package Exports
import {
createRemotionStudioClient,
RemotionStudioError,
} from "@remotion-studio/sdk";
import {
MotionGraphicsSlot,
MotionGraphicsComposition,
calculateMotionGraphicsMetadata,
compileMotionGraphicsArtifact,
} from "@remotion-studio/sdk/runtime";