431 lines
13 KiB
Markdown
431 lines
13 KiB
Markdown
|
|
# GlitchPlayer Integration Insights For GnommoEditor
|
||
|
|
|
||
|
|
This note is based on reading the current GnommoEditor frontend and backend, and comparing it to the current GlitchPlayer public API and data contracts.
|
||
|
|
|
||
|
|
## Short Version
|
||
|
|
|
||
|
|
GnommoEditor and GlitchPlayer are already close enough to integrate cleanly, but there are two different integration cases and they should not be solved with the exact same component:
|
||
|
|
|
||
|
|
1. Full presentation playback / slide-targeted preview inside the editor
|
||
|
|
2. Lightweight slide thumbnails inside the slide list and editing UI
|
||
|
|
|
||
|
|
The full player case is almost ready now.
|
||
|
|
|
||
|
|
The thumbnail case should get its own dedicated exported component from GlitchPlayer instead of embedding the full video player at tiny sizes.
|
||
|
|
|
||
|
|
## What Already Lines Up Well
|
||
|
|
|
||
|
|
### On the editor side
|
||
|
|
|
||
|
|
These files already create a strong seam for player integration:
|
||
|
|
|
||
|
|
- [src/pages/VideoEditorPage.jsx](/Users/jenstandstad/Projects/gnommoeditor/src/pages/VideoEditorPage.jsx)
|
||
|
|
- [backend/src/routes/videos.js](/Users/jenstandstad/Projects/gnommoeditor/backend/src/routes/videos.js)
|
||
|
|
- [backend/src/routes/slides.js](/Users/jenstandstad/Projects/gnommoeditor/backend/src/routes/slides.js)
|
||
|
|
- [backend/migrations/002_create_slides.cjs](/Users/jenstandstad/Projects/gnommoeditor/backend/migrations/002_create_slides.cjs)
|
||
|
|
|
||
|
|
The editor already stores:
|
||
|
|
|
||
|
|
- `component_key`
|
||
|
|
- `props`
|
||
|
|
- `display_mode`
|
||
|
|
- `presenter_notes`
|
||
|
|
- `start_time_sec`
|
||
|
|
- `end_time_sec`
|
||
|
|
- ordered narration segments
|
||
|
|
|
||
|
|
That is fundamentally the right shape.
|
||
|
|
|
||
|
|
### On the player side
|
||
|
|
|
||
|
|
These files define the reusable runtime surface:
|
||
|
|
|
||
|
|
- [src/player/index.ts](/Users/jenstandstad/Projects/gnommoplayer/src/player/index.ts)
|
||
|
|
- [src/components/LecturePlayer.tsx](/Users/jenstandstad/Projects/gnommoplayer/src/components/LecturePlayer.tsx)
|
||
|
|
- [src/types/lecture.ts](/Users/jenstandstad/Projects/gnommoplayer/src/types/lecture.ts)
|
||
|
|
- [packages/slide-contracts/src/templates.ts](/Users/jenstandstad/Projects/gnommoplayer/packages/slide-contracts/src/templates.ts)
|
||
|
|
|
||
|
|
The player already supports:
|
||
|
|
|
||
|
|
- full playback mode
|
||
|
|
- `mode="slide-preview"`
|
||
|
|
- `targetSlideId`
|
||
|
|
- shared slide contract types
|
||
|
|
- registry-driven slide rendering
|
||
|
|
|
||
|
|
That means the full preview case is mostly a data-shaping and packaging task, not a product rethink.
|
||
|
|
|
||
|
|
## Main Mismatches Right Now
|
||
|
|
|
||
|
|
### 1. Editor template keys do not match player template keys
|
||
|
|
|
||
|
|
The editor currently uses older local template definitions in [src/data/slideTemplates.js](/Users/jenstandstad/Projects/gnommoeditor/src/data/slideTemplates.js), including keys like:
|
||
|
|
|
||
|
|
- `TitleSlide`
|
||
|
|
- `ContentSlide`
|
||
|
|
- `BulletSlide`
|
||
|
|
- `ImageSlide`
|
||
|
|
- `QuoteSlide`
|
||
|
|
|
||
|
|
The player currently uses shared contract keys from [packages/slide-contracts/src/templates.ts](/Users/jenstandstad/Projects/gnommoplayer/packages/slide-contracts/src/templates.ts):
|
||
|
|
|
||
|
|
- `SquareYellow`
|
||
|
|
- `FullscreenSplit`
|
||
|
|
- `EquationFocus`
|
||
|
|
- `QuoteImage`
|
||
|
|
- `ChartSingle`
|
||
|
|
- `ProcessFlow`
|
||
|
|
- `DefinitionCard`
|
||
|
|
|
||
|
|
This is the most important mismatch to fix first.
|
||
|
|
|
||
|
|
### 2. The editor export route is close, but not rich enough yet
|
||
|
|
|
||
|
|
The current export route in [backend/src/routes/videos.js](/Users/jenstandstad/Projects/gnommoeditor/backend/src/routes/videos.js) at `GET /api/videos/:id/export` already builds a GlitchPlayer-style payload, but it is still missing some fields the player will want for deeper integration:
|
||
|
|
|
||
|
|
- slide `id`
|
||
|
|
- segment `id`
|
||
|
|
- glitch slide `id`
|
||
|
|
- orientation
|
||
|
|
- variant arrays beyond a single score-1 candidate
|
||
|
|
- `latexString` on equation slides as first-class data
|
||
|
|
|
||
|
|
Right now the route mostly emits one synthetic candidate per slide:
|
||
|
|
|
||
|
|
- `componentKey: s.component_key`
|
||
|
|
- `props: s.props || {}`
|
||
|
|
- `score: 1`
|
||
|
|
|
||
|
|
That is enough for a first playback integration, but not enough for a mature editor + player loop.
|
||
|
|
|
||
|
|
### 3. The thumbnail use case is not the same thing as slide preview mode
|
||
|
|
|
||
|
|
`mode="slide-preview"` in GlitchPlayer is useful for previewing a chosen slide in context, but it is still fundamentally a player runtime with:
|
||
|
|
|
||
|
|
- stage layout
|
||
|
|
- video region
|
||
|
|
- scrubber and chrome behavior
|
||
|
|
- gesture state
|
||
|
|
|
||
|
|
For editor thumbnails, that is too heavy.
|
||
|
|
|
||
|
|
What the editor really needs is a dedicated slide-only renderer.
|
||
|
|
|
||
|
|
## Recommended Integration Model
|
||
|
|
|
||
|
|
## Case 1: Full player integration inside GnommoEditor
|
||
|
|
|
||
|
|
### Recommended use
|
||
|
|
|
||
|
|
Use GlitchPlayer inside the editor for:
|
||
|
|
|
||
|
|
- a presentation preview panel
|
||
|
|
- a slide-targeted preview panel
|
||
|
|
- a “play current presentation” mode
|
||
|
|
- a “jump to this slide in player” editing workflow
|
||
|
|
|
||
|
|
### Recommended host surface
|
||
|
|
|
||
|
|
In GnommoEditor, add a React wrapper component such as:
|
||
|
|
|
||
|
|
- `src/components/GlitchPlayerPanel.jsx`
|
||
|
|
|
||
|
|
That wrapper should:
|
||
|
|
|
||
|
|
- fetch a player-ready presentation JSON object from the backend
|
||
|
|
- pass the presentation into `GlitchPlayer`
|
||
|
|
- supply the default slide registry
|
||
|
|
- own any editor-specific surrounding chrome
|
||
|
|
|
||
|
|
### Recommended backend route
|
||
|
|
|
||
|
|
Keep the current export route as the starting point, but rename or mirror it to a more intentional player route:
|
||
|
|
|
||
|
|
- `GET /api/presentations/:presentationId`
|
||
|
|
|
||
|
|
or
|
||
|
|
|
||
|
|
- `GET /api/videos/:id/player`
|
||
|
|
|
||
|
|
That keeps the seam aligned with GlitchPlayer naming and makes later migration into GnommoWeb or other runtimes easier.
|
||
|
|
|
||
|
|
### Required payload upgrades
|
||
|
|
|
||
|
|
The backend route should emit this minimum shape consistently:
|
||
|
|
|
||
|
|
```ts
|
||
|
|
{
|
||
|
|
id: string;
|
||
|
|
title: string;
|
||
|
|
version: string;
|
||
|
|
durationSec: number;
|
||
|
|
segments: Array<{
|
||
|
|
id: string;
|
||
|
|
src: string;
|
||
|
|
startTimeSec: number;
|
||
|
|
durationSec: number;
|
||
|
|
}>;
|
||
|
|
slides: Array<{
|
||
|
|
id: string;
|
||
|
|
startTimeSec: number;
|
||
|
|
endTimeSec?: number;
|
||
|
|
displayMode: "square" | "fullscreen";
|
||
|
|
glitchSlides: Array<{
|
||
|
|
id: string;
|
||
|
|
score: number;
|
||
|
|
componentKey: SlideTemplateKey;
|
||
|
|
props: SlideTemplateProps;
|
||
|
|
latexString?: string;
|
||
|
|
orientation?: "any" | "mobile-portrait" | "mobile-landscape" | "desktop";
|
||
|
|
}>;
|
||
|
|
}>;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Important detail: stable ids
|
||
|
|
|
||
|
|
For editor integration, stable ids matter more than they do in the demo app.
|
||
|
|
|
||
|
|
Use:
|
||
|
|
|
||
|
|
- presentation `id`: `videos.gnommo_id` if available
|
||
|
|
- slide `id`: ideally `slides.gnommo_slide_id`
|
||
|
|
- glitch slide `id`: for now `${slide_id}:default`
|
||
|
|
- segment `id`: `narration_segments.segment_key`
|
||
|
|
|
||
|
|
The current export route does not include those stable ids yet. It should.
|
||
|
|
|
||
|
|
### Best first embedding point in the editor
|
||
|
|
|
||
|
|
The best initial place to integrate GlitchPlayer is [src/pages/VideoEditorPage.jsx](/Users/jenstandstad/Projects/gnommoeditor/src/pages/VideoEditorPage.jsx).
|
||
|
|
|
||
|
|
Why:
|
||
|
|
|
||
|
|
- it already loads the video, slides, and narration segments
|
||
|
|
- it is where slide timing and component selection happen
|
||
|
|
- it is where “preview current slide” is most useful
|
||
|
|
|
||
|
|
### Concrete editor workflow
|
||
|
|
|
||
|
|
Recommended behavior:
|
||
|
|
|
||
|
|
1. User edits slides in the left/main editor UI
|
||
|
|
2. Editor fetches player-ready presentation JSON
|
||
|
|
3. Right-side preview panel mounts `GlitchPlayer`
|
||
|
|
4. Clicking a slide card sets `targetSlideId`
|
||
|
|
5. The preview panel mounts:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
<GlitchPlayer
|
||
|
|
presentation={presentation}
|
||
|
|
slideRegistry={defaultSlideRegistry}
|
||
|
|
mode="slide-preview"
|
||
|
|
targetSlideId={selectedSlideId}
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
This gives the editor a live preview of the exact runtime, not an approximation.
|
||
|
|
|
||
|
|
## Case 2: Slide thumbnails inside GnommoEditor
|
||
|
|
|
||
|
|
### Recommendation
|
||
|
|
|
||
|
|
Do not use the full `GlitchPlayer` for thumbnails.
|
||
|
|
|
||
|
|
Instead, add a dedicated GlitchPlayer export such as:
|
||
|
|
|
||
|
|
- `GlitchSlideThumbnail`
|
||
|
|
|
||
|
|
or
|
||
|
|
|
||
|
|
- `GlitchSlideRenderer`
|
||
|
|
|
||
|
|
### Why this should be separate
|
||
|
|
|
||
|
|
Thumbnails need to be:
|
||
|
|
|
||
|
|
- cheap to render
|
||
|
|
- deterministic
|
||
|
|
- slide-only
|
||
|
|
- independent from video playback
|
||
|
|
- easy to render many times in a list
|
||
|
|
|
||
|
|
The full player is optimized for:
|
||
|
|
|
||
|
|
- timeline playback
|
||
|
|
- stitched video
|
||
|
|
- gestures
|
||
|
|
- pause states
|
||
|
|
- scrubber chrome
|
||
|
|
|
||
|
|
That makes it the wrong abstraction for a slide list with 20 to 100 items.
|
||
|
|
|
||
|
|
### Suggested thumbnail component API
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
<GlitchSlideThumbnail
|
||
|
|
slide={slide}
|
||
|
|
slideRegistry={defaultSlideRegistry}
|
||
|
|
viewportMode="desktop"
|
||
|
|
preferredGlitchSlideId={optionalSelectedVariantId}
|
||
|
|
aspectRatio="square"
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
or more generally:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
<GlitchSlideRenderer
|
||
|
|
slide={slide}
|
||
|
|
slideRegistry={defaultSlideRegistry}
|
||
|
|
viewportMode="desktop"
|
||
|
|
renderMode="thumbnail"
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
### What the thumbnail component should do
|
||
|
|
|
||
|
|
- resolve the correct active glitch slide for a viewport
|
||
|
|
- render only the chosen slide surface
|
||
|
|
- render no video
|
||
|
|
- render no scrubber
|
||
|
|
- render no play/pause chrome
|
||
|
|
- render no vote UI
|
||
|
|
- avoid autoplay and interaction state
|
||
|
|
|
||
|
|
### Where thumbnails should be used in the editor
|
||
|
|
|
||
|
|
The first places:
|
||
|
|
|
||
|
|
- slide list cards in [src/pages/VideoEditorPage.jsx](/Users/jenstandstad/Projects/gnommoeditor/src/pages/VideoEditorPage.jsx)
|
||
|
|
- video detail slide table in [src/pages/VideoDetailPage.jsx](/Users/jenstandstad/Projects/gnommoeditor/src/pages/VideoDetailPage.jsx)
|
||
|
|
- template picker previews in [src/data/slideTemplates.js](/Users/jenstandstad/Projects/gnommoeditor/src/data/slideTemplates.js) or its replacement
|
||
|
|
|
||
|
|
### Data source for thumbnails
|
||
|
|
|
||
|
|
The editor does not need the full presentation to render thumbnails.
|
||
|
|
|
||
|
|
It only needs:
|
||
|
|
|
||
|
|
- the slide data
|
||
|
|
- the chosen or default glitch slide
|
||
|
|
- the desired viewport mode
|
||
|
|
|
||
|
|
So the thumbnail renderer can use the same slide contracts, but with a much smaller data dependency than the full player.
|
||
|
|
|
||
|
|
## Shared Contract Strategy
|
||
|
|
|
||
|
|
This should be the foundation of the integration.
|
||
|
|
|
||
|
|
### Recommended rule
|
||
|
|
|
||
|
|
GnommoEditor should stop owning its own slide template definitions as freeform local config.
|
||
|
|
|
||
|
|
Instead:
|
||
|
|
|
||
|
|
- `@gnommo/slide-contracts` becomes the single source of truth
|
||
|
|
- both repos import template keys and payload interfaces from it
|
||
|
|
- editor field forms are generated from contract metadata
|
||
|
|
- player rendering trusts the same contract
|
||
|
|
|
||
|
|
### Practical consequence
|
||
|
|
|
||
|
|
[src/data/slideTemplates.js](/Users/jenstandstad/Projects/gnommoeditor/src/data/slideTemplates.js) should eventually be replaced by a shared metadata layer derived from the contract package.
|
||
|
|
|
||
|
|
That shared metadata should include:
|
||
|
|
|
||
|
|
- `componentKey`
|
||
|
|
- display mode
|
||
|
|
- field definitions
|
||
|
|
- content budgets
|
||
|
|
- editor labels
|
||
|
|
- placeholders
|
||
|
|
|
||
|
|
That gives one definition of each slide type for:
|
||
|
|
|
||
|
|
- AI generation
|
||
|
|
- editor forms
|
||
|
|
- backend validation
|
||
|
|
- player rendering
|
||
|
|
|
||
|
|
## Recommended Implementation Plan
|
||
|
|
|
||
|
|
## Phase 1: Full preview integration
|
||
|
|
|
||
|
|
Goal: mount GlitchPlayer in GnommoEditor with minimal risk.
|
||
|
|
|
||
|
|
1. Add GlitchPlayer as a local workspace dependency or sibling package dependency
|
||
|
|
2. Add `@gnommo/slide-contracts` to the editor too
|
||
|
|
3. Upgrade `GET /api/videos/:id/export` to include stable ids and player-complete fields
|
||
|
|
4. Add a preview panel to [src/pages/VideoEditorPage.jsx](/Users/jenstandstad/Projects/gnommoeditor/src/pages/VideoEditorPage.jsx)
|
||
|
|
5. Wire slide-card click to `targetSlideId`
|
||
|
|
|
||
|
|
This gives immediate value with very little duplicated logic.
|
||
|
|
|
||
|
|
## Phase 2: Shared slide schema adoption
|
||
|
|
|
||
|
|
Goal: make editor and player speak exactly the same slide language.
|
||
|
|
|
||
|
|
1. Replace local editor template keys with shared keys
|
||
|
|
2. Add per-template form metadata to the shared contracts package
|
||
|
|
3. Make editor slide creation and editing use shared contract names
|
||
|
|
4. Validate slide payloads before save
|
||
|
|
|
||
|
|
This is the phase that prevents long-term drift.
|
||
|
|
|
||
|
|
## Phase 3: Thumbnail renderer
|
||
|
|
|
||
|
|
Goal: make the slide list visually accurate and lightweight.
|
||
|
|
|
||
|
|
1. Export `GlitchSlideThumbnail` or `GlitchSlideRenderer` from GlitchPlayer
|
||
|
|
2. Reuse player slide registry and resolution logic
|
||
|
|
3. Render only the slide surface
|
||
|
|
4. Drop all playback chrome and video dependencies
|
||
|
|
5. Use it in the editor slide list and detail pages
|
||
|
|
|
||
|
|
This will make the editor feel much more aligned with the actual player runtime.
|
||
|
|
|
||
|
|
## Phase 4: Variant-aware editing
|
||
|
|
|
||
|
|
Goal: prepare for many candidate glitch slides per logical slide.
|
||
|
|
|
||
|
|
1. Extend editor data model from “one `component_key` + `props` per slide” to:
|
||
|
|
- one logical slide
|
||
|
|
- many glitch slide variants
|
||
|
|
2. Add `score`, `orientation`, and `variant id`
|
||
|
|
3. Let thumbnails preview the highest-scoring or selected variant
|
||
|
|
4. Let full player preview the exact runtime behavior
|
||
|
|
|
||
|
|
This is where GlitchPlayer and GnommoEditor become a true shared system.
|
||
|
|
|
||
|
|
## My Strong Recommendations
|
||
|
|
|
||
|
|
### Recommendation 1
|
||
|
|
|
||
|
|
Treat full player preview and slide thumbnails as two separate exported surfaces.
|
||
|
|
|
||
|
|
That keeps both integrations simple and prevents the editor from trying to use a playback runtime as a list cell.
|
||
|
|
|
||
|
|
### Recommendation 2
|
||
|
|
|
||
|
|
Use the editor backend export route as the canonical bridge, but strengthen it.
|
||
|
|
|
||
|
|
The route in [backend/src/routes/videos.js](/Users/jenstandstad/Projects/gnommoeditor/backend/src/routes/videos.js) is already the right place to centralize this mapping.
|
||
|
|
|
||
|
|
### Recommendation 3
|
||
|
|
|
||
|
|
Replace local editor slide template config with shared contract-driven metadata as soon as possible.
|
||
|
|
|
||
|
|
That is the most important architectural step if you want AI agents, human editors, and GlitchPlayer to all agree on what a slide is.
|
||
|
|
|
||
|
|
## Suggested Next Tasks
|
||
|
|
|
||
|
|
If we want to execute this plan incrementally, I would do these next in order:
|
||
|
|
|
||
|
|
1. Upgrade the editor export route to emit stable ids and proper glitch slide objects
|
||
|
|
2. Mount GlitchPlayer in `VideoEditorPage` as a slide-targeted preview panel
|
||
|
|
3. Add a new exported `GlitchSlideThumbnail` component in GnommoPlayer
|
||
|
|
4. Replace editor-local slide template definitions with shared metadata from `@gnommo/slide-contracts`
|
||
|
|
|
||
|
|
That sequence gives fast value first, while keeping the long-term architecture clean.
|