Skip to content

Image and Audio clips lost during loadFromJSON/exportToJSON round-trip #60

@guillempuche

Description

@guillempuche

Steps to reproduce

// Set up a project with Image, Audio, and Text clips
const project = {
  clips: [
    {
      id: "img-1",
      type: "Image",
      src: "/assets/bg.webp",
      display: { from: 0, to: 24000000 },
      duration: 24000000,
    },
    {
      id: "audio-1",
      type: "Audio",
      src: "/assets/narration.mp3",
      display: { from: 0, to: 3526500 },
      duration: 3526500,
    },
    {
      id: "text-1",
      type: "Text",
      src: "",
      text: "Hello world",
      display: { from: 0, to: 3526500 },
      duration: 3526500,
    },
  ],
  tracks: [
    { id: "t1", name: "Image 1", type: "image", clipIds: ["img-1"] },
    { id: "t2", name: "Audio 1", type: "audio", clipIds: ["audio-1"] },
    { id: "t3", name: "Text 1", type: "text", clipIds: ["text-1"] },
  ],
  settings: { size: { width: 1080, height: 1920 } },
};

await studio.loadFromJSON(project);
const exported = studio.exportToJSON();

// Expected: 3 clips (Image, Audio, Text)
// Actual:   1 clip  (Text only)
console.log(exported.clips.length);
console.log(exported.clips.map(c => c.type));

What happens

After loadFromJSON()exportToJSON(), only the Text clip survives. Image and Audio are gone.

We haven't pinpointed which side drops them:

  • loadFromJSON() might fail to instantiate them — we saw it log errors for Image clips with bad URLs, and it may silently skip Audio too. If the clips never enter the SDK's internal state, exportToJSON() correctly has nothing to export.
  • exportToJSON() might skip them during serialization — the clips could exist internally but not get included in the output.

Either way, the data is lost after the round-trip.

Impact

Our editor auto-saves by calling exportToJSON() and writing back to disk. Without a workaround, every save permanently deletes Image and Audio clips from the project. In our case: 25 clips go in, 10 come out (3 Image + 12 Audio lost).

Current workaround

  • Server-side: when the editor saves, the server merges missing clips back from its in-memory cache before writing to disk (project_store.ts)
  • Client-side: the timeline UI supplements the SDK export with clip data stored from the initial server load (use_studio_timeline.ts)

Discovered while working on #40.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions