# Notification closing animation

Frames 14–18 are rendered entirely in Remotion, with no AI video generation. The composition is 1080 × 2340, 30 fps, 52 seconds, H.264. This is a silent picture draft; poem narration and pings can be added later.

The source uses the exact storyboard wallpaper and independent SVG controls and notifications in `public/`. Timeline durations are 8, 14, 7, 14 and 9 seconds. Notification arrivals fade in over eight frames with a 12-point vertical settling motion. `NotificationClosingReduced` keeps only the opacity changes. Neither preview autoplays.

To render a portable copy, install the pinned dependencies in a project terminal, then run `npm run render`. In the shared music-lab workspace, installation must use a Herdr pane. This local project currently reuses the existing installed Remotion dependency directory through a symlink; dependencies are not bundled in the ZIP.

`prepare.cjs` refreshes the assets from the parent storyboard project. A portable ZIP already contains the prepared assets and timeline, so it can render without running that preparation script. Refresh the source assets when changing the closing notification text.

## Full 18-frame film

`NotificationFull` assembles the entire storyboard at 1080×2340 and 30 fps. `NotificationFullReduced` uses short fades with no zoom, vertical swipes or notification movement. Both original closing compositions remain available.

Run `node prepare-full.cjs` after editing the storyboard or adding narration. It reads `../editor-data.json`, `../scenes.json`, and `../source.json`, then prepares separate wallpaper, application interface and notification layers in `public/full/`. Every notification title/body uses an exact poem excerpt. Frame 02 keeps frame 01's first notification, and the opening wallpaper continues in 07–09 and 14–18.

Narration comes from `../production/voiceover-manifest.json`:

```json
{"frames":[{"frame":1,"file":"production/audio/frame-01.mp3","durationSeconds":5.2,"text":"Surrounded by a city\nof all these worries\nand just need a break?"}]}
```

Files resolve from `notification/`; absolute paths also work. Each `text` must exactly equal its frame's poem stanza or preparation fails. `ffprobe` measures the actual audio, so `durationSeconds` is advisory. Each voice starts 0.4 seconds after the scene begins; scene duration is the greater of the original storyboard timing and audio duration plus 0.8 seconds. No generated speech or audio tags are added by this project.

Run `node check-full.cjs --require-audio` before the narrated export. It checks full verbatim poem coverage, all 18 audio files and transcripts, scene timing, notification bounds, shared characters, and lock-screen wallpaper continuity.

The prepared `public/full-timeline.json` is loaded by Remotion's `calculateMetadata` before rendering. The matching `src/full-timeline.json` supplies initial preview data. All 18 generated audio files should be present before a final narrated render. Preparation without an audio manifest creates a silent visual draft.

Optional generated clips can be inserted through a `clips` array in the same manifest:

```json
{"clips":[{"frame":3,"file":"production/videos/frame-03.mp4"}]}
```

Each clip is muted, loops if shorter than its narration, and sits below the separate phone interface. Missing clips use the current storyboard image. A clip file listed in the manifest must exist. The current draft uses images for every scene.

Render with the installed local browser:

```sh
node prepare-full.cjs
node node_modules/@remotion/cli/remotion-cli.js render src/index.tsx NotificationFull ../video/notification-full-storyboard.mp4 --public-dir=public --concurrency=2 --crf=23 --browser-executable=/home/cdxker/.cache/puppeteer/chrome-headless-shell/linux-150.0.7871.24/chrome-headless-shell-linux64/chrome-headless-shell
```

The install path above is machine specific; pass another compatible Chrome executable elsewhere. Dependencies are currently supplied by the workspace's existing `node_modules` symlink. No new dependency installation is needed here.

Remotion references: [dynamic metadata](https://www.remotion.dev/docs/calculate-metadata), [audio](https://www.remotion.dev/docs/html5-audio), [muted video layers](https://www.remotion.dev/docs/offthreadvideo).
