The Problem

Web‑based video editors normally rely on server‑side rendering or proprietary SaaS APIs, exposing user media and API keys to third‑party services. Teams that need full privacy, offline capability, or fine‑grained cost tracking lack an open‑source, client‑only alternative that can still tap modern text‑to‑video, image‑to‑image and audio models.

What This Does

videosos delivers a full‑featured video editor that runs completely in the browser. The UI lives under src/app/ and src/components/, while model‑selection, pricing, and cost aggregation are implemented in src/lib/ (e.g., src/lib/fal.ts). Model metadata lives in data/fal_models_schemas.json. The project bundles FFmpeg‑wasm and Remotion for client‑side rendering, and stores everything in IndexedDB (src/app/api/uploadthing/ utilities).

Key files:

  • src/app/[locale]/page.tsx – entry page rendered by Next.js.
  • src/components/right-panel.tsx – UI hub that pulls pricing (src/lib/pricing.ts) and model lists.
  • src/lib/fal.ts – central façade for the fal.ai API; the largest source file (≈2 k lines).

How It Is Wired

  1. Startupnpm run dev (or docker compose up) launches the Next.js server defined by next.config.mjs. The first request hits src/app/layout.tsx, which injects global CSS (src/app/globals.css) and loads locale data from messages/*.json.
  2. Model Loadingsrc/components/right-panel.tsx imports src/lib/fal.ts. That module reads data/fal_models_schemas.json and exposes fetchModels() which calls the fal.ai endpoint (API key read from process.env.FAL_API_KEY).
  3. Cost Calculation – UI components (src/components/ui/*) pull pricing via src/lib/pricing.ts. This module is imported by only a handful of components (instability 0.9) but performs HTTP calls to the provider’s pricing API, then caches results in IndexedDB.
  4. Media Generation – When a user triggers generation, src/components/media-panel.tsx invokes src/lib/fal.ts’s generateMedia() which returns a streaming URL. The response is stored via the uploadthing helpers (src/app/api/uploadthing/core.ts) and displayed in the timeline (src/components/video-frame-selector.tsx).
  5. Export – The “Export” button calls src/components/export-dialog.tsx, which uses Remotion (remotion dependency) to compose the final video. Rendering happens in the browser via FFmpeg.wasm; the only external effect is a Blob download.

The import graph shows no circular dependencies and 95 internal modules with 82 edges. The most‑connected node is src/components/ui/button (10 inbound imports, 0 outbound), indicating a stable, low‑risk UI primitive. Conversely, src/components/right-panel imports 16 modules but is not imported elsewhere, giving it an instability of 1 – changes here have the widest blast radius.

How To Use It

# Clone the repo
git clone https://github.com/moses-y/videosos
cd videosos

# Install Node dependencies
npm ci           # uses package-lock.json

# Copy example env and add your API keys
cp .env.example .env
# edit .env → set FAL_API_KEY, RUNWARE_API_KEY, etc.

# Run locally (Docker optional)
npm run dev      # starts Next.js on http://localhost:3000

# Or containerised build
docker compose up --build   # builds docker/node/Dockerfile

The Makefile provides shortcuts (make lint, make test) that run the GitHub Actions lint workflow locally.

Real‑World Use

A marketing team can spin up the app on an internal workstation, load their private fal.ai key, and produce short promotional videos without any data leaving the device. The UI lets them select a model, preview cost (src/lib/pricing.ts), generate assets, arrange them on the timeline, and export a final MP4—all client‑side.

Code Health & Issues

  • HIGH – Oversized filessrc/lib/fal.ts, src/components/media-panel.tsx, src/components/right-panel.tsx each exceed 2 k lines; refactor into focused modules.
  • HIGH – Duplicated code – Repeated 6‑line blocks across 22 script files (scripts/*.ts); extract shared helpers.
  • HIGH – Deep nesting – Max indentation depth 11 in src/components/right-panel.tsx, tools/docs-scraper/scrape_models.py, src/components/left-panel.tsx; flatten with guard clauses.
  • MEDIUM – Broad exception handlingscripts/parse_fal_models.py uses bare except; replace with specific catches.
  • MEDIUM – High branching densitysrc/lib/pricing.ts and related scripts contain >70 branches; consider strategy tables.

Additional observations: CI is defined in .github/workflows/lint.yml, but only linting runs; no test suite execution despite a single test file present. The repository contains committed secrets (docs/fal/pages/real-time/secrets.md). License (MIT) and lockfiles are present.

The Bottom Line

videosos offers a functional, privacy‑first browser editor with a rich model catalog, but the codebase suffers from large monolithic files and duplicated script logic that will increase maintenance cost. It is suitable for teams comfortable with Next.js and willing to invest in refactoring for long‑term stability.