Adding handoff functionality for reviews
This commit is contained in:
@@ -0,0 +1,362 @@
|
||||
# Gnommo
|
||||
|
||||
Gnommo is ADHD friendly video-editor for coders.
|
||||
|
||||
1. Design the presentation in keynote
|
||||
2. Set up the greenscreen and audio settings once
|
||||
3. Automatically times slides and videos to your voice.
|
||||
4. Limited options means you waste less time on stuff that isn't important.
|
||||
|
||||
A code-first video editing pipeline for creating narrated presentations with slides, video overlays, and synchronized audio.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Create a project
|
||||
gnommo -p myproject init
|
||||
|
||||
# Import slides and presenter notes from Keynote file
|
||||
gnommo -p myproject import
|
||||
|
||||
# Process the narration videos with video and audio filters
|
||||
gnommo -p myproject pre
|
||||
|
||||
# Stitch together the narration segments to one full length narration.
|
||||
gnommo -p myproject stitch
|
||||
|
||||
# Transcribe the actual narrated content
|
||||
gnommo -p myproject transcribe
|
||||
|
||||
# Generate the final video
|
||||
gnommo -p myproject render
|
||||
|
||||
# Generate the final youtube assets. Manuscript file, description
|
||||
gnommo -p myproject youtubeready
|
||||
|
||||
# Free up disk space locally by saving your project to an external drive
|
||||
gnommo -p myproject archive
|
||||
```
|
||||
|
||||
## Proxying
|
||||
Using the --proxy keyword makes everything faster because it creates some smaller files.
|
||||
```
|
||||
gnommo -p myproject pre --proxy
|
||||
gnommo -p myproject stitch --proxy
|
||||
gnommo -p myproject render --proxy
|
||||
```
|
||||
|
||||
## Lowres
|
||||
Renders the final video in a low-res mode, for faster iteration
|
||||
```
|
||||
gnommo -p myproject render --res low
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
myproject/
|
||||
├── project.json # Project configuration
|
||||
├── manuscript.txt # Narration script with [markers]
|
||||
├── media/
|
||||
│ ├── slides/
|
||||
│ │ ├── slides.json # Slide definitions
|
||||
│ │ └── *.png # Slide images
|
||||
│ ├── videos/
|
||||
│ │ ├── videos.json # Video source definitions
|
||||
│ │ └── *.mov # Video files
|
||||
│ ├── narration/
|
||||
│ │ ├── narration.json # Narration segment definitions
|
||||
│ │ └── *.mov # Raw narration recordings
|
||||
│ └── audio/
|
||||
│ ├── audio.json # Audio effect definitions
|
||||
│ └── *.mp3 # Sound effects
|
||||
└── output/
|
||||
└── final.mp4 # Rendered output
|
||||
└── preview.mp4 # Preview (lower resolution, faster render)
|
||||
```
|
||||
|
||||
## The Five Stages
|
||||
|
||||
Gnommo uses a five-stage pipeline for processing video projects:
|
||||
|
||||
### Stage 1: Init
|
||||
|
||||
Creates a folder and a default project.json file inside it.
|
||||
```bash
|
||||
gnommo -p myproject init
|
||||
```
|
||||
|
||||
### Stage 2: Import
|
||||
First : Place the myproject.key Keynote presentation in the myproject folder.
|
||||
Place videos, audio and narration you want to use in their respective folders in side myproject/media
|
||||
Then : This command media scans directories and generates JSON definition files.
|
||||
|
||||
```bash
|
||||
gnommo -p myproject import
|
||||
```
|
||||
|
||||
**What it does:**
|
||||
- Opens the keynote presentation and exports all slides a PNG images into media/slides/
|
||||
- Scans `media/slides/` for images → generates `slides.json`
|
||||
- Scans `media/videos/` for video files → generates `videos.json`
|
||||
- Scans `media/narration/` for recordings → generates `narration.json`
|
||||
- Scans `media/audio/` for sound effects → generates `audio.json`
|
||||
|
||||
**When to use:** After adding new media files to populate the JSON definitions with the actual files in the folders
|
||||
|
||||
---
|
||||
|
||||
### Stage 3: Preprocess
|
||||
|
||||
Applies video filters (chroma key, scaling, etc.) to narration segments.
|
||||
|
||||
```bash
|
||||
gnommo -p myproject pre
|
||||
```
|
||||
|
||||
**What it does:**
|
||||
- Reads filter definitions from `project.json` and `narration.json`
|
||||
- Processes each narration segment with its configured filters
|
||||
- Outputs processed files (e.g., `segment1_processed.mov`)
|
||||
|
||||
**When to use:** After recording narration that needs background removal, sound normalization or other processing.
|
||||
|
||||
---
|
||||
|
||||
### Stage 4: stitch
|
||||
First : Go through the source videos, and add trim settings to `begin` and `end` parameters in `narration.json`
|
||||
|
||||
Then : Run command to sticth the usable parts of narration segments into a single continuous video
|
||||
|
||||
```bash
|
||||
gnommo -p myproject stitch
|
||||
```
|
||||
|
||||
**What it does:**
|
||||
- Reads segments from `narration.json`
|
||||
- Concatenates them in order, respecting `begin`/`end` trim points
|
||||
- Outputs `narration_combined.mov` in `media/videos/`
|
||||
- Adds `narration_combined` entry to `videos.json` with volume settings
|
||||
- Generates word-level timestamps from the narration using Whisper speech recognition.
|
||||
|
||||
**When to use:** After preprocessing, or adjusting trim settings, to create the main narration scaffolding.
|
||||
|
||||
### Stage 5: Render
|
||||
|
||||
Composites all elements into the final video.
|
||||
|
||||
```bash
|
||||
gnommo -p myproject render
|
||||
```
|
||||
|
||||
**What it does:**
|
||||
- Parses `manuscript.txt` for slide/video markers
|
||||
- Aligns markers to transcription timestamps
|
||||
- Composites background, narration, slides, and video overlays
|
||||
- Outputs `final.mp4`
|
||||
|
||||
**Options:**
|
||||
```bash
|
||||
gnommo -p myproject render --dry-run # Show FFmpeg command without running
|
||||
gnommo -p myproject render --slides S1:S10 # Render only slides S1 through S10
|
||||
gnommo -p myproject render --proxy # Fast preview at reduced resolution
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Shortcut: All Stages
|
||||
|
||||
Run all stages 2-5 and render in one command:
|
||||
|
||||
```bash
|
||||
gnommo -p myproject all
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Manuscript Format
|
||||
|
||||
The manuscript is plain text with embedded markers:
|
||||
|
||||
```
|
||||
[S1] Welcome to this presentation.
|
||||
|
||||
[S2] Let me show you how this works.
|
||||
|
||||
[video:demo] Here's a quick demonstration.
|
||||
|
||||
[Zoom1] Notice this important detail.
|
||||
|
||||
[Reset] And that concludes our overview.
|
||||
```
|
||||
|
||||
**Marker types:**
|
||||
- `[S1]`, `[S2]` - Slide markers (reference slides.json)
|
||||
- `[video:id]` - Triggered video overlay
|
||||
- `[narration:id]` - Start continuous narration video
|
||||
- `[Zoom1]`, `[Reset]` - Camera presets
|
||||
- `[Awoosh]` - Audio effect trigger
|
||||
|
||||
---
|
||||
|
||||
## External Storage (GnommoCache)
|
||||
|
||||
For large projects, gnommo supports transparent external storage fallback.
|
||||
|
||||
**Setup:** Create `~/.gnommo.conf`:
|
||||
```ini
|
||||
[cache]
|
||||
path = /Volumes/ExternalDrive/gnommo
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
- Files are first looked up locally in the project directory
|
||||
- If not found, gnommo checks `{cache_path}/{project_name}/...`
|
||||
- The 📁 indicator shows files loaded from external storage
|
||||
|
||||
**Archive to external storage:**
|
||||
```bash
|
||||
gnommo -p myproject archive # Sync project to cache
|
||||
gnommo -p myproject archive --dry-run # Preview what would sync
|
||||
```
|
||||
|
||||
This allows you to move large preprocessed files to external storage while keeping the project functional.
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### New Project Setup
|
||||
```bash
|
||||
# 1. Create project structure and add media files
|
||||
mkdir -p myproject/media/{slides,videos,narration,audio}
|
||||
|
||||
# 2. Create project.json with basic config
|
||||
|
||||
# 3. Import media to generate JSON definitions
|
||||
gnommo -p myproject import
|
||||
|
||||
# 4. Edit JSON files to configure filters, trim points, etc.
|
||||
|
||||
# 5. Run full pipeline
|
||||
gnommo -p myproject all
|
||||
```
|
||||
|
||||
### Re-render After Editing Manuscript
|
||||
```bash
|
||||
gnommo -p myproject render
|
||||
```
|
||||
|
||||
### Re-process After Recording New Narration
|
||||
```bash
|
||||
gnommo -p myproject pre
|
||||
gnommo -p myproject stitch
|
||||
gnommo -p myproject transcribe
|
||||
gnommo -p myproject render
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Additional Commands
|
||||
|
||||
```bash
|
||||
gnommo -p myproject validate # Check for errors without rendering
|
||||
gnommo -p myproject description # Generate YouTube description with chapters
|
||||
gnommo -p myproject transcribe --final # Transcribe final.mp4 for subtitles
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Glitch University — Server Sync
|
||||
|
||||
Gnommo can push project metadata and short scripts to a gnommoweb server,
|
||||
and pull changes back. This keeps the platform database in sync with your
|
||||
local project files without manual copy-paste.
|
||||
|
||||
**Setup** — add to `gnommo/.env`:
|
||||
```ini
|
||||
GNOMMOWEB_URL=http://localhost:3001
|
||||
GNOMMOWEB_API_KEY=your_content_api_key
|
||||
```
|
||||
|
||||
### Push
|
||||
|
||||
Registers the project on the server and syncs all defined shorts (including
|
||||
their scripts). Creates a filming task for each new short.
|
||||
|
||||
```bash
|
||||
gnommo -p myproject push # push local → server
|
||||
gnommo -p myproject push --force # overwrite server even if it has newer changes
|
||||
```
|
||||
|
||||
On the first push, gnommo creates:
|
||||
- A stub video record in the platform database
|
||||
- One short record per entry in `project.json["shorts"]`
|
||||
- One task per new short ("Film short: …")
|
||||
|
||||
Re-running push is safe — existing records are updated, no duplicate tasks.
|
||||
Scripts are only overwritten on the server if the local file has changed;
|
||||
edits made in the staff UI are preserved.
|
||||
|
||||
### Pull
|
||||
|
||||
Fetches the current project state from the server and merges the `shorts`
|
||||
array back into `project.json`. Useful after editing short titles or hooks
|
||||
in the web interface.
|
||||
|
||||
```bash
|
||||
gnommo -p myproject pull # pull server → local
|
||||
gnommo -p myproject pull --force # overwrite local even if it has unsaved changes
|
||||
```
|
||||
|
||||
Pull preserves local `script` file paths — it won't overwrite your `.md`
|
||||
script files.
|
||||
|
||||
### Conflict guards
|
||||
|
||||
Both commands check for conflicts before writing:
|
||||
|
||||
| Situation | Push behaviour | Pull behaviour |
|
||||
|---|---|---|
|
||||
| Server has changes you haven't pulled | Blocked — pull first | Proceeds (that's the point) |
|
||||
| Local has changes you haven't pushed | Proceeds (that's the point) | Blocked — push first |
|
||||
| `--force` flag | Overrides | Overrides |
|
||||
|
||||
Sync state is stored in `<project>/.gnommo_sync.json` (tracked by git,
|
||||
so collaborators share the same reference point).
|
||||
|
||||
### Defining shorts in `project.json`
|
||||
|
||||
Add a `shorts` array to your project:
|
||||
|
||||
```json
|
||||
"shorts": [
|
||||
{
|
||||
"id": "short_pixelated_universe",
|
||||
"title": "Is the universe pixelated?",
|
||||
"hook": "What if space is made of tiny blocks?",
|
||||
"script": "shorts/short_pixelated_universe.md",
|
||||
"platform_targets": ["youtube"]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
- `id` — unique slug within the project, used as the upsert key
|
||||
- `script` — relative path to a markdown file with the full short narration
|
||||
- `hook` — opening line / thumbnail caption
|
||||
- `platform_targets` — list of platforms (currently `["youtube"]`)
|
||||
|
||||
Scripts are plain markdown with the same `[SLIDE: name]` markers and
|
||||
`{word}` whisper timestamp tags used elsewhere in gnommo.
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.10+
|
||||
- FFmpeg
|
||||
- OpenAI Whisper (for transcription)
|
||||
|
||||
```bash
|
||||
pip install openai-whisper
|
||||
```
|
||||
Reference in New Issue
Block a user