# video.haus

`video.haus` is a modular, web-based video tools suite built on Next.js App Router with a dark cinematic interface.

The project is designed as a product foundation, not a one-off demo:

- registry-driven tools dashboard
- reusable UI building blocks across tools
- shared FFmpeg/ffprobe processing layer
- safe local temp-file lifecycle
- clean expansion path for future tools

## Project Overview

Current suite includes 8 production-ready tools:

1. **Clip Frame Extractor**
2. **Extract Audio**
3. **Video Thumbnail Creator**
4. **Video Format Converter**
5. **Instagram Video Downloader**
6. **Twitter/X Video Downloader**
7. **YouTube Video Downloader**
8. **TikTok Video Downloader**

Core routes:

- `/` dashboard
- `/tools/[slug]` dynamic tool route
- `/api/tools/...` tool-specific processing endpoints

## Stack Choices

- **Framework:** Next.js (App Router)
- **Language:** TypeScript (strict)
- **Styling:** Tailwind CSS
- **UI primitives:** shadcn/ui + Base UI
- **Icons:** Lucide React
- **Media processing:** FFmpeg + ffprobe (server-side)
- **Social media fetching:** `youtube-dl-exec` (yt-dlp wrapper for public URL extraction/download)
- **Storage (phase scope):** local temp filesystem for uploads/outputs

## Why This Architecture

The architecture is centered around maintainability and expansion:

- **Registry-first tool model**
  - tool metadata is centralized in [`lib/tools-registry.ts`](./lib/tools-registry.ts)
  - routes, dashboard tiles, and metadata derive from one source
- **Route-to-component decoupling**
  - UI component wiring is isolated in [`lib/tool-page-components.ts`](./lib/tool-page-components.ts)
- **Shared media processing layer**
  - FFmpeg/ffprobe wrappers, metadata, extraction, conversion helpers in `lib/media-processing/*`
- **Shared client/server helper patterns**
  - API parsing helpers in [`lib/client/api-utils.ts`](./lib/client/api-utils.ts)
  - metadata route helper in [`lib/server/tool-routes.ts`](./lib/server/tool-routes.ts)
- **Composable UI system**
  - reusable components under `components/media/*` and `components/shared/*`

This keeps tool pages focused on orchestration while shared layers own repeated logic.

## Local Setup

### 1) Install dependencies

```bash
npm install
```

### 2) Run development server

```bash
npm run dev
```

### 3) Production checks

```bash
npm run typecheck
npm run lint
npm run build
```

### 4) Create a Drop-In Hosting Bundle

```powershell
powershell -ExecutionPolicy Bypass -File scripts/create-dropin-bundle.ps1
```

This generates:

- `dist/video-haus-dropin/` (runtime folder)
- `dist/video-haus-dropin.zip` (upload-ready archive)

## FFmpeg Installation Notes

`video.haus` resolves media binaries in this order:

1. `FFMPEG_PATH` / `FFPROBE_PATH` env vars
2. bundled binaries from `ffmpeg-static` / `ffprobe-static`
3. system PATH
4. common Windows install paths (Chocolatey/Scoop/default FFmpeg folders)

So the app works out-of-the-box after `npm install` in most local environments, while still allowing explicit overrides.

### macOS

- Install via Homebrew:
  - `brew install ffmpeg`

### Ubuntu/Debian

- Install via apt:
  - `sudo apt update && sudo apt install ffmpeg`

### Windows

- Install FFmpeg build and add `ffmpeg.exe` / `ffprobe.exe` to PATH
- Or set absolute paths via env vars below

### Optional Environment Variables

Defined in [`lib/server/media-config.ts`](./lib/server/media-config.ts):

- `FFMPEG_PATH` (default: `ffmpeg`)
- `FFPROBE_PATH` (default: `ffprobe`)
- `VIDEO_HAUS_TEMP_ROOT` (default: `<project>/.tmp/media`)
- `VIDEO_HAUS_MAX_UPLOAD_SIZE_BYTES` (default: `1000000000`)
- `VIDEO_HAUS_COMMAND_TIMEOUT_MS` (default: `120000`)
- `VIDEO_HAUS_CLEANUP_MAX_AGE_MS` (default: `1800000`)
- `YT_DLP_PATH` (optional override for yt-dlp binary path)
- `YT_DLP_COOKIES_PATH` (optional global `cookies.txt` path for authenticated yt-dlp requests)
- `INSTAGRAM_COOKIES_PATH` (optional Instagram-specific `cookies.txt`; overrides global value)
- `YT_DLP_PYTHON` (optional override for Python executable used by bundled yt-dlp launcher on Linux hosts)
- `NEXT_PUBLIC_SITE_URL` (recommended for SEO canonical/sitemap host, e.g. `https://video.haus`)
- `SITE_URL` (server-side fallback if `NEXT_PUBLIC_SITE_URL` is unset)

## Temp Upload/Output Lifecycle

Uploads and outputs are stored under:

- `.tmp/media/uploads`
- `.tmp/media/outputs`

Flow:

1. Upload is validated and written to temp.
2. Processing reads from temp upload and writes temp output.
3. Response is returned.
4. Temp files are cleaned in `finally` blocks.

Safety features:

- path boundary enforcement (`assertPathWithinRoot`)
- sanitized file names
- stale-file cleanup helper (`cleanupStaleTempFiles`)

## Tool Registry Pattern (Finalized)

Registry lives in [`lib/tools-registry.ts`](./lib/tools-registry.ts) and includes:

- `slug`
- `title`
- `description`
- `icon`
- `status`
- `accent`
- `route` (auto-derived from slug unless overridden)

Enhancements in finalized pattern:

- duplicate slug detection at registry creation
- derived `RegisteredToolSlug` type
- route metadata map export
- helper guards (`isRegisteredToolSlug`, `getToolBySlug`)

## How To Add A New Tool

Quick workflow:

1. Add tool definition in [`lib/tools-registry.ts`](./lib/tools-registry.ts)
2. Create UI component in `components/tools/<slug>-tool.tsx`
3. Register it in [`lib/tool-page-components.ts`](./lib/tool-page-components.ts)
4. Add API routes in `app/api/tools/<slug>/...` if processing is needed
5. Add shared processing helpers in `lib/media-processing/*` when reusable
6. Update README
7. Run validation commands

Detailed guide:

- [`docs/adding-a-tool.md`](./docs/adding-a-tool.md)

Starter references:

- [`lib/tools/new-tool-starter.ts`](./lib/tools/new-tool-starter.ts)

## How Each Initial Tool Works

### 1) Clip Frame Extractor

- Upload video
- Probe metadata server-side via ffprobe
- Scrub timeline + step frame-by-frame
- Export exact timestamp frame as PNG/JPG at source resolution

API routes:

- `POST /api/tools/clip-frame-extractor/metadata`
- `POST /api/tools/clip-frame-extractor/extract`

### 2) Extract Audio

- Upload video
- Extract full audio or selected range
- Dual-range controls + editable time inputs
- Export MP3/WAV/M4A
- Validates range boundaries and duration

API routes:

- `POST /api/tools/extract-audio/metadata`
- `POST /api/tools/extract-audio/extract`

### 3) Video Thumbnail Creator

- Upload video
- Generate and score 4 candidate thumbnails
- Heuristics include darkness rejection, duplicate suppression, detail/balance preference
- Optional toggles: sharpen, brightness/contrast boost, title-safe overlay
- Reroll uses deterministic seed progression for debuggable variation

API route:

- `POST /api/tools/video-thumbnail-creator/analyze`

### 4) Video Format Converter

- Upload video
- Convert to MP4/MOV/WebM/MKV/AVI
- Presets: High, Standard, Small file
- Preset definitions are centralized in:
  - [`lib/media-processing/conversion-presets.ts`](./lib/media-processing/conversion-presets.ts)
- Preserves aspect ratio and preserves audio when source contains audio

API routes:

- `POST /api/tools/video-format-converter/metadata`
- `POST /api/tools/video-format-converter/convert`

### 5) Instagram Video Downloader

- Paste a public Instagram post/reel URL
- Analyze metadata from a public link
- Download as MP4
- Includes a rights reminder for permitted-use downloads

API routes:

- `POST /api/tools/instagram-video-downloader/info`
- `POST /api/tools/instagram-video-downloader/download`

### 6) Twitter/X Video Downloader

- Paste a public X/Twitter status URL
- Analyze metadata and creator details from a public link
- Download as MP4
- Includes a rights reminder for permitted-use downloads

API routes:

- `POST /api/tools/twitter-video-downloader/info`
- `POST /api/tools/twitter-video-downloader/download`

### 7) YouTube Video Downloader

- Paste a public YouTube video URL (`youtube.com` or `youtu.be`)
- Analyze metadata and creator/channel details
- Download best available progressive format (MP4/WebM)
- Includes a rights reminder for permitted-use downloads

API routes:

- `POST /api/tools/youtube-video-downloader/info`
- `POST /api/tools/youtube-video-downloader/download`

## Future Tools

Planned for future phases:

- clip trimmer
- gif maker
- subtitle extractor
- speech-to-text
- silence remover
- scene splitter
- caption burn-in
- social resize presets
- transcript-based clip finder

## Expansion Workflow Notes

For new tools, prefer:

- adding reusable server logic to shared media layer first
- keeping tool component focused on orchestration and UX
- avoiding route-specific duplicated parsing/validation

Current shared helper patterns:

- client API parse helpers
- metadata route helper
- dashboard favorites/recents localStorage helpers
- registry + typed slug map

## Recommended Next Steps

1. Add background job model + progress events (for long-running media tasks).
2. Add integration tests per tool route and critical UI flows.
3. Add optional persistent storage (jobs/history/favorites) behind repository abstraction.
4. Add observability (request IDs, structured logs, error categorization) for production operations.
