remotion icon indicating copy to clipboard operation
remotion copied to clipboard

Inconsistent serialization between `render` and `studio` of the `calculateMetadata` result

Open andrasferenczi opened this issue 1 year ago • 3 comments

Bug Report 🐛

I created the following composition:

    <Composition
      fps={30}
      id="NoSerializeComposition"
      height={720}
      width={1280}
      durationInFrames={10}
      calculateMetadata={() => {
        return {
          props: {
            calculated: new Vector2(10, 10),
          },
        }
      }}
      defaultProps={{
        calculated: undefined,
      }}
      component={({ calculated }: { calculated?: Vector2 }) => {
        const value = `${calculated}`

        console.log(value)

        return (
          <AbsoluteFill>
            <h1>{value}</h1>
          </AbsoluteFill>
        )
      }}
    />


export class Vector2 {
  readonly x: number
  readonly y: number

  constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }

  toString(): string {
    return `Vector2 [X: ${this.x}, Y: ${this.y}]`
  }
}

Key points from this example:

  • The calculateMetadata returns a non-serializable class, Vector2
  • The studio displays the following string: Vector2 [X: 10, Y: 10]
  • The render displays the following string: [object Object], which means it is no longer the Vector2 class

I think this is a bug, because:

Is there a way to undo this serialization?

Thank you!

andrasferenczi avatar Jun 22 '24 19:06 andrasferenczi

Thanks for reporting!

Objects are being passed between browser and Node.js and there is no useful way of undoing serialization of classes. We'll fix this by updating the docs to explicitly disallow non-JSON-serializable values.

JonnyBurger avatar Jun 24 '24 09:06 JonnyBurger

To still improve it, in the next version the serialization will be consistent and in the Studio it will also turn into an object, to catch this earlier in the developer journey.

JonnyBurger avatar Jun 24 '24 10:06 JonnyBurger

Makes sense, thanks. Based on your comments I got a better understanding of how Remotion works.

Couple minor doc comments I feel is missing from calculateMetadata is that:

  • it runs a single time, independent of the worker count (or concurrency defined in renderMedia)
  • it runs in a separate node process when rendering, executed whenever selectComposition is called

andrasferenczi avatar Jun 24 '24 21:06 andrasferenczi