Skip to main content

generateOpenTimelineComposition()v4.0.542

Converts an OpenTimelineIO (.otio) timeline into editable Remotion TSX. Each clip becomes a separate JSX node with its own timing. To also register the component in a project, use addOpenTimelineComposition().

warning

Draft API: This API is experimental and may change.

import-timeline.ts
const result = generateOpenTimelineComposition({ timeline: otioJson, componentName: 'ImportedTimeline', fps: 30, width: 1920, height: 1080, }); if (result.source !== null) { console.log(result.source, result.metadata); } else { console.error(result.diagnostics); }

The function is synchronous and does not read files, fetch URLs, probe media, or install packages. The generated component uses remotion and, when needed, @remotion/media. Keep these packages at the same version as @remotion/codemods.

Options​

timeline​

An OTIO JSON string or parsed object with a Timeline.1 root. Convert other interchange formats, such as AAF, EDL, FCPXML, .otioz, or .otiod, to OTIO JSON first.

componentName​

The generated named export. Must begin with an uppercase ASCII letter and contain only letters, digits, underscores, or dollar signs.

fps​

The composition frame rate, as a positive finite number. Source timing is converted to this rate. Individual clip boundaries retain fractional frames; the composition duration is rounded up to a whole frame.

width​

The composition width, as a positive safe integer in pixels.

height​

The composition height, as a positive safe integer in pixels. Width, height, and frame rate must be supplied because OTIO does not define the output composition settings.

resolveMedia?​

A synchronous function that maps media references to browser-accessible assets. By default, supported remote URLs are used directly and public-relative paths use staticFile(). Absolute paths and file: URLs require a resolver. Assets are not copied or downloaded.

resolve-media.ts
const result = generateOpenTimelineComposition({ timeline: otioJson, componentName: 'Interview', fps: 30, width: 1920, height: 1080, resolveMedia: ({targetUrl}) => { if (targetUrl === 'file:///edit/interview.mov') { return {src: 'interview.mp4', source: 'public', kind: 'video'}; } return null; }, });

The resolver receives an object with the following fields.

reference​

The OTIO media reference as a read-only record, including its schema and metadata.

targetUrl​

The reference's URL, or null when absent. For an image sequence, this is its directory base.

path​

The path of the source clip in the OTIO input.

trackKind​

'Video' or 'Audio'.

Return {src, source, kind}, where source is 'url' or 'public' and kind is 'video', 'audio', or 'image'. Return null to use default resolution. A thrown error becomes an error diagnostic.

For image sequences, src is a directory base; file naming, numbering, rate, and frame step still come from the OTIO reference. Supply converted browser-decodable images under those filenames when necessary.

Return value​

source​

Generated TSX, or null if an error prevents importing. Unsupported effects are ignored with warnings.

metadata​

{width, height, fps, durationInFrames}, or null if the timeline or output settings are invalid. Metadata remains available when media resolution fails. Only register the generated component as a composition when source is not null.

diagnostics​

An ordered array of {code, severity, path, message} objects. severity is 'error', 'warning', or 'info'. path identifies the affected part of the input or options. Any error blocks source generation.

assets​

An array of resolved {src, source, kind, path} objects. source is 'url' or 'public'; kind is 'video', 'audio', 'image', or 'image-sequence'. path identifies the source clip. Media availability and codec support are not verified.

annotations​

An array of {path, metadata, markers} records. metadata is a record or null, and markers is an array of retained OTIO marker objects. These do not become visible overlays or effects.

globalStartTime​

The original timeline start timecode as {value, rate}, or null. Composition playback starts at frame zero; no leading gap is inserted for this timecode.

Supported timelines​

FeatureBehavior
Tracks, stacks, and nestingPreserves sequential timing, overlapping layers, and nested source ranges.
Clips and gapsSupports Clip.1, Clip.2, gaps, and legacy sequences/fillers. Disabled items retain their duration.
Source trims and mixed frame ratesPreserves source ranges and accounts for media start timecode.
Forward clip retiming and freezesSupports positive LinearTimeWarp.1 and FreezeFrame.1.
Other active effectsIgnored with a warning that includes the effect's name when available.
Internal SMPTE_Dissolve transitionsGenerates visual and audio fades between neighboring clips or gaps.
Image sequencesSupports browser-decodable images with frame numbering, padding, and frame steps. Missing-frame policy must be error.
Metadata, markers, and global start timeRetained in the result without rendered behavior.

Reverse playback, retimed tracks/stacks, unsupported combinations of time effects, custom transitions, transitions at a track boundary, and transitions adjacent to nested compositions produce errors. Unknown item schemas or versions also produce errors.

Missing media and application-specific generators require resolveMedia. PNG, JPG, JPEG, SVG, and BMP are detected as still images by default. Ambiguous formats such as GIF, WebP, and AVIF require an explicit resolver choice. Convert formats such as EXR, DPX, and TIFF to browser-decodable media first.

Video tracks render visuals with embedded audio muted. Include an audio track to import sound. Images use objectFit="contain"; application-specific crop, scale, color, and effect metadata is not interpreted.

Importing in Studio​

In a connected Remotion Studio or Browser Studio, choose File → Import OpenTimeline... and select an .otio file. Local Studio uses a native file picker on macOS and Windows; Browser Studio uses the browser's picker. Choose the composition name, dimensions, and destination folder, then add the composition. Duration comes from the imported timeline.

Studio preserves the rate of global_start_time when present, or the common rate of the timeline's time ranges. The detected FPS and calculated duration are shown as non-editable values. If no single rate can be determined, choose the FPS before importing.

The dialog checks the timeline and its media before importing. In a connected local Studio, referenced local media is copied into the public folder and the generated component uses staticFile() paths. Shared media is copied once per import; existing public assets and browser-accessible URLs are reused. Image sequences keep their filenames and numbering.

If a local media reference has no available_range, Studio reads its duration and embedded video timecode to calculate file-relative trims. Explicit available_range values take precedence. When using the codemod directly, provide available_range for media whose source timecode does not start at zero.

Absolute paths and file: URLs are resolved on the Studio server. The native picker provides the timeline's folder, which is used to resolve relative media paths. Use Locate media... if the referenced files are stored elsewhere. The browser file picker does not provide the original file's folder.

Browser Studio can use URLs and existing public assets, but cannot read files from your computer through a Studio server. The action is unavailable in read-only or disconnected Studios.

Compatibility​

BrowsersServersEnvironments
Chrome
Firefox
Safari
Node.js
Bun
Serverless Functions

See also​