Skip to content

Commit

Permalink
Add basic bring-your-own-encoder rendering
Browse files Browse the repository at this point in the history
This adds a basic encoder-agnostic rendering function to renin, so that
you can render your demos to video.

To use this, you need to add some boilerplate/integration code to your
demo project. In your project, you can for instance use mp4-wasm as the
encoder. Here is a quick guide on how to do that.

First, install mp4-wasm:

```bash
yarn add mp4-wasm
```

Then, add these imports to the top of your demo's `main.ts`:

```typescript
import loadMP4Module from "mp4-wasm";
import mp4wasm from "mp4-wasm/build/mp4.wasm?url";
```

And finally, comment out `renin.loop()` in `main.ts` and instead do
something like this:

```typescript
// commented out for rendering purposes
// renin.loop()

(async () => {
  const wasmBinary = await (await fetch(mp4wasm)).arrayBuffer();
  const MP4 = await loadMP4Module({ wasmBinary });
  const width = 1920;
  const height = 1080;
  const encoder = MP4.createWebCodecsEncoder({
    width,
    height,
    fps: 60,
    encoderOptions: {
      framerate: 60,
      bitrate: 24_000_000,
    },
  });
  render(renin, { encoder, width, height });
})();
```

Now, the demo should play automatically when you visit renin in the
browser, and at the end a render.mp4 will be automatically downloaded.

It is without sound though, so we can add the music using ffmpeg:

```bash
ffmpeg -i render.mp4 -i music.ogg -c:v copy -map 0:v -map 1:a -y output.mp4
```

Now you have a finished video file that you can upload to YouTube!

mp4-wasm doesn't play nice with building renin as a lib -- otherwise we
could have bundled it with renin to make things easier.
  • Loading branch information
sigvef committed Apr 10, 2023
1 parent b1853e8 commit 7ab0b94
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
3 changes: 2 additions & 1 deletion renin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"tslib": "^2.4.0",
"typescript": "^4.8.4",
"vite": "^3.1.8"
}
},
"dependencies": {}
}
52 changes: 52 additions & 0 deletions renin/src/render.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Renin } from './renin';
interface RenderOptions {
encoder: {
addFrame: (bitmap: ImageBitmap, frame: number) => Promise<void>;
end: () => Promise<ArrayBuffer>;
};
width: number;
height: number;
}

const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export async function render(renin: Renin, options: RenderOptions) {
const { width, height, encoder } = options;

renin.jumpToFrame(0);
renin.isFullscreen = true;
renin.resize(width, height);

/* Drive the UI a little bit to make sure all animations have settled :D */
for (let i = 0; i < 300; i++) {
await delay(1);
renin.uiTime = Date.now() / 1000;
renin.uiUpdate();
renin.uiRender();
}
window.innerWidth = width;
window.innerHeight = height;
renin.resize(width, height);
renin.renderer.setPixelRatio(1);

const extraPaddingAtTheEnd = 60;
const numberOfFramesToRender = renin.music.getDuration() * 60 + extraPaddingAtTheEnd;

for (let i = 0; i < numberOfFramesToRender; i++) {
await delay(1);
renin.jumpToFrame(i);
const bitmap = await createImageBitmap(renin.renderer.domElement);
await encoder.addFrame(bitmap, i);
}

const buffer = await encoder.end();
const url = URL.createObjectURL(new Blob([buffer], { type: 'video/mp4' }));

const a = document.createElement('a');
a.style.display = 'none';
document.body.appendChild(a);
a.href = url;
a.download = 'render.mp4';
a.click();
URL.revokeObjectURL(url);
}
1 change: 1 addition & 0 deletions renin/src/renin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { getSetting, setSetting } from './ui/storedSettings';
/* otherwise it won't be added to the build */
export * as vite from './ui/vite';
export * as ReninNode from './ReninNode';
export * as render from './render';

export const defaultVertexShader = defaultVert;

Expand Down

0 comments on commit 7ab0b94

Please sign in to comment.