Skip to main content

Peako Studio

Peako Studio is a professional video editing platform. Edit, export, and manage video workflows with a modern React-based interface powered by Remotion's compositing engine.

Live at: https://studio.shin0x.space
API at: https://peako.shin0x.space
Docs: This file + /docs/ folder

What's Inside

  • Studio UI — React + Next.js app at /studio/ — login, dashboard, editor, settings, team management
  • API Backend — Fastify server at /src/ — video ops (trim/merge/mute/add-audio/subtitle/blur/speed-ramp), effects catalog, job queue
  • Remotion — Headless video composition engine at /remotion/ — renders video operations frame-by-frame
  • Queue — BullMQ + Redis (peako-redis container) — async job processing, status polling

Quick Start

Development (Local)

# Install dependencies
npm install

# Start backend (API server + job queue)
npm run dev

# In another terminal: start Studio frontend
npm run dev:studio

# Backend runs on http://localhost:3000
# Studio runs on http://localhost:3001

Production (Docker)

docker-compose up -d

# API: https://peako.shin0x.space (port 3000)
# Studio: https://studio.shin0x.space (port 3001)

Architecture

Frontend (/studio/src/)

Core Editor State: EditorCoreProvider + PeakoEditorCore singleton

  • CommandManager — undo/redo stack (Cmd+Z / Cmd+Shift+Z)
  • TimelineManager — track + clip mutations (all wrapped as reversible Commands)
  • PlaybackManager — Remotion Player integration (play/pause/scrub)
  • MediaManager — asset upload/download (POST /api/assets/upload)
  • SaveManager — 2-second debounced auto-save (POST /api/templates/:id) + status indicator
  • SelectionManager — multi-select clip state + UI sync

Pages:

  • app/login/ — Google OAuth via PKCE flow
  • app/dashboard/ — recent templates, create new, team overview
  • app/edit/ — full editor (3-panel: left menu | center preview | right controls + bottom timeline)
  • app/settings/ — user API keys, password reset, etc.
  • app/teams/ — create team, manage members, permissions
  • app/teams/join/[token]/ — invite link flow

UI Design: Paper+black color scheme

  • Background: #F5F0E8 (cream paper)
  • Text: #0A0A0A (deep black)
  • Accent: #7A5C00 (dark amber)
  • Shell: #0A0A0A (black)

Backend (/src/)

Video Operations (Remotion-based)

  • POST /api/trim — trim video by time range
  • POST /api/merge — concatenate multiple clips
  • POST /api/mute — silence audio track or regions
  • POST /api/add-audio — mix in audio track or music
  • POST /api/subtitle — burn-in subtitles (SRT format)
  • POST /api/blur — blur regions of video
  • POST /api/speed-ramp — apply speed keyframes (FFmpeg, not Remotion)

Catalogs

  • GET /api/effects/catalog — all available effects with previews + params
  • GET /api/transitions/catalog — transition library

Assets + Templates

  • POST /api/assets/upload — multipart video/audio upload, return { url, filename, mimeType }
  • GET /api/templates/:id — fetch template JSON (design state)
  • POST /api/templates/:id — save template state (auto-save)
  • POST /api/templates/:id/render — async job submission (returns jobId, 202)
  • POST /api/templates/:id/preview — sync preview frame render

Job Queue

  • GET /api/job/:jobId — poll job status (queued | active | done | failed)
  • DELETE /api/job/:jobId — cancel queued/delayed job

Auth

  • GET /auth/google — OAuth initiate (state + PKCE code_challenge → Redis)
  • GET /auth/google/callback — OAuth complete (exchange code + verifier, set peako_session cookie)
  • POST /auth/logout — clear session

Health

  • GET /health — live API + queue status

Deployment

Docker

# Build images
docker build -t peako-api:latest .
docker build -t peako-studio:latest -f studio.Dockerfile .

# Run with docker-compose
docker-compose up -d

# Logs
docker-compose logs -f peako-api
docker-compose logs -f peako-studio
docker-compose logs -f peako-redis

Environment Variables

# .env or credentials.env

# Server
PORT=3000
STUDIO_ORIGIN=https://studio.shin0x.space
PEAKO_ORIGIN=https://peako.shin0x.space
CORS_ORIGIN=https://studio.shin0x.space,https://peako.shin0x.space

# Google OAuth
GOOGLE_CLIENT_ID=<your-gcp-client-id>
GOOGLE_CLIENT_SECRET=<your-gcp-client-secret>
OAUTH_REDIRECT_URI=https://peako.shin0x.space/auth/google/callback

# Security
JWT_SECRET=<256-bit-random-string>
SESSION_SECRET=<random-string>

# Storage
STORAGE_TYPE=local|s3
BUNNY_API_KEY=<your-bunny-cdn-key>
BUNNY_ZONE_NAME=<your-zone>

# Redis
REDIS_URL=redis://peako-redis:6379

# Database
DATABASE_URL=sqlite:./db/peako.db

# Remotion
REMOTION_BUNDLE_PATH=/app/dist/index.js

API Response Models

Job Status

{
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"status": "active|queued|done|failed",
"progress": 45,
"outputUrl": "https://cdn.bunny.net/peako/550e8400.mp4",
"error": null,
"createdAt": 1708852843000,
"updatedAt": 1708852890000
}

Asset Upload

{
"url": "https://peako-bucket.s3.us-east-1.amazonaws.com/assets/file.mp4",
"filename": "file.mp4",
"mimeType": "video/mp4",
"size": 5242880,
"duration": 120
}

Effects Catalog

{
"id": "fade-in",
"name": "Fade In",
"category": "appear",
"description": "Fades the clip up from black over the opening seconds.",
"preview": "https://..../fade-in.png",
"params": [
{
"name": "duration",
"type": "number",
"default": 0.5,
"min": 0.1,
"max": 5.0,
"description": "Fade duration in seconds"
}
],
"tags": ["fade", "appear", "intro"]
}

Security

  • Auth: Google OAuth 2.0 with PKCE (RFC 7636) — code_challenge_method=S256
  • Session: peako_session cookie (httpOnly, Secure, SameSite=Lax, Domain=.shin0x.space)
  • API Keys: Hashed + salted, stored in DB, rotated via /api/user/key/rotate
  • CORS: Origins whitelist (studio.shin0x.space, peako.shin0x.space)
  • SSRF Protection: assertPublicUrl() on all URL inputs (trim src_url, add-audio src_url, etc.)
  • Path Traversal: Filenames validated as basename-only, no directory components
  • Rate Limiting: 100 req/min global, 20-job per-user queue depth cap

Testing

E2E Tests (Playwright)

npm test                          # Run all tests
npm run test:track-f # Just QA Track F (ops + auth)
PLAYWRIGHT_BROWSERS_PATH=/opt/nops-labs/openclaw-main/config/workspace/tools/browsers npm test

Manual Testing

  1. Login: Go to https://studio.shin0x.space, click "Sign in with Google"
  2. Upload: Dashboard → New Project → Upload a video
  3. Edit: Drag clip to timeline, trim/cut, apply effect, add text
  4. Export: Click Export, choose quality (HD/4K), format (MP4/WebM), delivery (Response/CDN)
  5. Monitor: Jobs Dashboard shows status in real-time

Directory Structure

peako-studio/
├── src/ # Fastify backend
│ ├── routes/
│ │ ├── ops/ # /api/trim, /merge, /mute, etc.
│ │ ├── auth.ts # OAuth + session
│ │ ├── catalog.ts # Effects/transitions
│ │ ├── template.ts # Render + preview (deprecated)
│ │ ├── templates.ts # CRUD templates
│ │ ├── jobs.ts # Status + cancel
│ │ └── assets.ts # Upload endpoint
│ ├── services/
│ │ ├── remotion.ts # Remotion renderer
│ │ ├── ffmpeg.ts # FFmpeg operations
│ │ ├── storage.ts # S3/CDN uploads
│ │ ├── redis.ts # Redis client
│ │ ├── auth.ts # OAuth + JWT
│ │ └── db.ts # SQLite + schema
│ ├── effects/ # Effect registry
│ ├── queues/ # BullMQ job queues
│ ├── middleware/ # Auth + CORS
│ └── server.ts # Fastify app entry
├── studio/src/ # Next.js frontend
│ ├── app/ # Pages (login, dashboard, edit, teams)
│ ├── components/ # UI components
│ ├── core/ # PeakoEditorCore + managers
│ ├── features/ # Feature modules (editor, etc.)
│ ├── store/ # Zustand stores
│ ├── types/ # TypeScript types
│ └── lib/ # Utilities
├── remotion/ # Compositions
│ └── compositions/ops/ # TrimComp, MergeComp, etc.
├── Dockerfile # Multi-stage build (backend)
└── package.json

Contributing

  1. Read the API Reference
  2. Read the Studio User Guide
  3. Make your changes, test locally
  4. Push to nOpsLabs/Peako-Studio main
  5. Tag <@U0AF8CRD8DV> (PM Phil) in your PR

License

Proprietary — nOps Labs