Skip to content

Saving projects ​

The timeline's state is plain data, so you can save it as JSON, in a database or alongside your own project format.

To save a whole session as one file, audio and plugins included, or to exchange it with REAPER, see Project files and REAPER.

ts
interface TimelineState {
  tracks: Track[];
  clips: Clip[];
}

interface Track {
  id: string;
  name: string;
  color?: string;
  height?: number; // row height in pixels, set by dragging its edge
  data?: unknown; // anything your app keeps with the track
}

interface Clip {
  id: string;
  track: string; // the track it sits on
  source: string; // the audio it plays
  start: number; // seconds on the timeline
  offset: number; // seconds into the audio
  duration: number; // seconds
  gain: number; // 1 is unchanged
  fadeIn: number; // seconds
  fadeOut: number; // seconds
  name?: string;
  color?: string;
}

A clip's source is any id you choose, such as a file id or a URL. Several clips can play the same source, which is what a split produces.

Saving on change ​

ts
timeline.on('change', ({ state, label, final }) => {
  if (!final) return; // a drag is still going

  saveSoon(state);
});

label names the edit (Move, Trim, Split, Undo Move…). Loading a project with load() also emits change with the label Load.

Loading ​

ts
timeline.load(await fetchProject(id));

load replaces everything without adding an undo step. Call timeline.history.clear() as well if the undo list shouldn't reach back into the previous project.

Released under the MIT License.