Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![CI](https://github.com/rennerdo30/WebEncode/actions/workflows/ci.yml/badge.svg)](https://github.com/rennerdo30/WebEncode/actions/workflows/ci.yml)
[![Go Version](https://img.shields.io/badge/Go-1.24+-00ADD8?logo=go)](https://go.dev/)
[![Go Version](https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go)](https://go.dev/)
[![Next.js](https://img.shields.io/badge/Next.js-16-black?logo=next.js)](https://nextjs.org/)

**Distributed, Plugin-Based Video Transcoding Platform**
Expand All @@ -17,25 +17,27 @@ WebEncode is a high-performance, distributed media processing engine designed fo

- **Hyper-Modular Architecture**: 5-Pillar Plugin System (Auth, Storage, Encoder, Live, Publisher)
- **Distributed Workers**: Scalable FFmpeg execution engine powered by NATS JetStream
- **Modern UI**: Next.js 16 Dashboard with real-time monitoring
- **Modern UI**: Next.js 16 dashboard with real-time monitoring, dark and light themes, and five UI languages
- **Live Streaming**: Zero-config RTMP ingest to HLS via MediaMTX integration
- **Production Ready**: Docker, Kubernetes, OpenTelemetry, and structured logging
- **Restreaming**: 1:N simulcasting to YouTube, Twitch, Kick, and Rumble with unified chat

## Technology Stack

### Backend
- **Language**: Go 1.24+
- **Language**: Go 1.25+
- **Framework**: Chi/v5 (HTTP), gRPC (plugins)
- **Database**: PostgreSQL 16 (pgx/v5)
- **Database**: PostgreSQL 17 (pgx/v5, SQLC)
- **Message Bus**: NATS JetStream 2.10+
- **Plugin System**: HashiCorp go-plugin

### Frontend
- **Framework**: Next.js 16 with React 19
- **UI Components**: Shadcn/ui, Radix UI
- **Styling**: Tailwind CSS 4
- **Framework**: Next.js 16 (App Router) with React 19
- **UI Components**: shadcn/ui, Radix UI, Lucide icons
- **Styling**: Tailwind CSS 4 with themed CSS custom properties (dark + light)
- **State Management**: TanStack React Query
- **Internationalisation**: next-intl (English, German, Spanish, French, Japanese)
- **Tests**: Vitest, Testing Library

### Infrastructure
- **Containerization**: Docker, Docker Compose
Expand All @@ -47,7 +49,7 @@ WebEncode is a high-performance, distributed media processing engine designed fo

### Prerequisites
- [Docker](https://docs.docker.com/get-docker/) and Docker Compose
- [Go 1.24+](https://go.dev/dl/) (for local development)
- [Go 1.25+](https://go.dev/dl/) (for local development)
- [Node.js 22+](https://nodejs.org/) (for UI development)

### Run with Docker
Expand Down Expand Up @@ -75,6 +77,23 @@ make test
make test-coverage
```

### Develop the Dashboard

The dashboard is a standalone Next.js app in `ui/` and talks to the kernel API.

```bash
cd ui
npm install
npm run dev # http://localhost:3000
npm run lint
npm run test:run
```

`/api/v1/*` is rewritten to the kernel; point `INTERNAL_API_URL` at it if it is
not listening on http://localhost:8090. The theme (dark by default, light
available from the header toggle) and the UI language are remembered per
browser; the language is also part of the URL, for example `/de/jobs`.

## Project Structure

```
Expand Down
60 changes: 38 additions & 22 deletions ui/README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,52 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
# WebEncode Dashboard

## Getting Started
The web UI for [WebEncode](../README.md): a Next.js 16 App Router app that
monitors jobs, workers, live streams and restreams against the kernel REST API.

First, run the development server:
## Getting Started

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
npm install
npm run dev # http://localhost:3000
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
Requests to `/api/v1/*` are rewritten to the kernel (see `next.config.ts`). Set
`INTERNAL_API_URL` if the kernel is not listening on `http://localhost:8090`.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Scripts

## Learn More
| Script | Purpose |
| --- | --- |
| `npm run dev` | Development server |
| `npm run build` | Production build (`output: "standalone"`) |
| `npm run start` | Serve a production build |
| `npm run lint` | ESLint (`eslint-config-next`) |
| `npm run test:run` | Vitest suite, single run |
| `npm run test:coverage` | Vitest with V8 coverage |

To learn more about Next.js, take a look at the following resources:
## Structure

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
```
src/
├── app/[locale]/ # Localised routes (dashboard, jobs, streams, ...)
├── components/ # App components; components/ui holds the shadcn primitives
├── i18n/ # next-intl routing and request config
├── lib/ # API client, providers, nav/theme/app metadata constants
└── app/globals.css # Theme tokens, component classes, utilities
messages/ # Translation bundles: en, de, es, fr, ja
```

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Theming

## Deploy on Vercel
Colours are CSS custom properties in `src/app/globals.css`. Both a dark (default)
and a light theme are defined; the active one is the presence of the `dark` class
on `<html>`, set before first paint by the init script in `src/lib/theme.ts` and
toggled from the header. Prefer the semantic tokens (`primary`, `brand`,
`success`, `warning`, `danger`, `info`, `muted`, `border`, ...) over fixed
palette utilities such as `text-violet-400`, which only work on one theme.

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
## Internationalisation

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
Text lives in `messages/<locale>.json` and is read with `next-intl`. Add new keys
to every bundle, and format dates and numbers with next-intl's `useFormatter`
rather than hardcoding a locale.
29 changes: 25 additions & 4 deletions ui/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@
"success": "Erfolg",
"live": "Live",
"offline": "Offline",
"admin": "Admin"
"admin": "Admin",
"viewAll": "Alle anzeigen",
"language": "Sprache",
"openNavigation": "Navigation öffnen",
"mainNavigation": "Hauptnavigation",
"skipToContent": "Zum Hauptinhalt springen",
"switchToDark": "Zu dunklem Design wechseln",
"switchToLight": "Zu hellem Design wechseln"
},
"dashboard": {
"welcome": "JWillkommen bei WebEncode",
"welcome": "Willkommen bei <span>WebEncode</span>",
"activeJobs": "Aktive Aufträge",
"workersOnline": "Worker Online",
"completedJobs": "Abgeschlossene Aufträge",
Expand Down Expand Up @@ -97,6 +104,20 @@
"stackTrace": "Stack-Trace",
"timestamp": "Zeitstempel",
"path": "Pfad",
"method": "Methode"
"method": "Methode",
"refresh": "Aktualisieren",
"filterBySource": "Nach Quelle filtern",
"allSources": "Alle Quellen",
"markResolved": "Als behoben markieren",
"copyDetails": "Fehlerdetails kopieren",
"noErrors": "Keine Fehler gefunden",
"systemHealthy": "System ist fehlerfrei",
"showStackTrace": "Stacktrace anzeigen"
},
"footer": {
"label": "Fußzeile",
"copyright": "© {year} {name}. Open Source unter der MIT-Lizenz.",
"documentation": "Dokumentation",
"api": "API"
}
}
}
27 changes: 24 additions & 3 deletions ui/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@
"success": "Success",
"live": "Live",
"offline": "Offline",
"admin": "Admin"
"admin": "Admin",
"viewAll": "View all",
"language": "Language",
"openNavigation": "Open navigation",
"mainNavigation": "Main navigation",
"skipToContent": "Skip to main content",
"switchToDark": "Switch to dark theme",
"switchToLight": "Switch to light theme"
},
"dashboard": {
"welcome": "Welcome to <span>WebEncode</span>",
Expand Down Expand Up @@ -97,6 +104,20 @@
"stackTrace": "Stack Trace",
"timestamp": "Timestamp",
"path": "Path",
"method": "Method"
"method": "Method",
"refresh": "Refresh",
"filterBySource": "Filter by source",
"allSources": "All sources",
"markResolved": "Mark as resolved",
"copyDetails": "Copy error details",
"noErrors": "No errors detected",
"systemHealthy": "System is healthy",
"showStackTrace": "Show stack trace"
},
"footer": {
"label": "Footer",
"copyright": "© {year} {name}. Open source under the MIT License.",
"documentation": "Documentation",
"api": "API"
}
}
}
29 changes: 25 additions & 4 deletions ui/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@
"success": "Éxito",
"live": "En vivo",
"offline": "Desconectado",
"admin": "Administrador"
"admin": "Administrador",
"viewAll": "Ver todo",
"language": "Idioma",
"openNavigation": "Abrir navegación",
"mainNavigation": "Navegación principal",
"skipToContent": "Saltar al contenido principal",
"switchToDark": "Cambiar al tema oscuro",
"switchToLight": "Cambiar al tema claro"
},
"dashboard": {
"welcome": "Bienvenido a WebEncode",
"welcome": "Bienvenido a <span>WebEncode</span>",
"activeJobs": "Trabajos Activos",
"workersOnline": "Trabajadores en Línea",
"completedJobs": "Trabajos Completados",
Expand Down Expand Up @@ -97,6 +104,20 @@
"stackTrace": "Rastro de pila",
"timestamp": "Marca de tiempo",
"path": "Ruta",
"method": "Método"
"method": "Método",
"refresh": "Actualizar",
"filterBySource": "Filtrar por origen",
"allSources": "Todos los orígenes",
"markResolved": "Marcar como resuelto",
"copyDetails": "Copiar detalles del error",
"noErrors": "No se detectaron errores",
"systemHealthy": "El sistema está en buen estado",
"showStackTrace": "Mostrar traza de pila"
},
"footer": {
"label": "Pie de página",
"copyright": "© {year} {name}. Código abierto con licencia MIT.",
"documentation": "Documentación",
"api": "API"
}
}
}
29 changes: 25 additions & 4 deletions ui/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@
"success": "Succès",
"live": "En direct",
"offline": "Hors ligne",
"admin": "Admin"
"admin": "Admin",
"viewAll": "Tout afficher",
"language": "Langue",
"openNavigation": "Ouvrir la navigation",
"mainNavigation": "Navigation principale",
"skipToContent": "Aller au contenu principal",
"switchToDark": "Passer au thème sombre",
"switchToLight": "Passer au thème clair"
},
"dashboard": {
"welcome": "Bienvenue sur WebEncode",
"welcome": "Bienvenue sur <span>WebEncode</span>",
"activeJobs": "Tâches actives",
"workersOnline": "Travailleurs en ligne",
"completedJobs": "Tâches terminées",
Expand Down Expand Up @@ -97,6 +104,20 @@
"stackTrace": "Trace de la pile",
"timestamp": "Horodatage",
"path": "Chemin",
"method": "Méthode"
"method": "Méthode",
"refresh": "Actualiser",
"filterBySource": "Filtrer par source",
"allSources": "Toutes les sources",
"markResolved": "Marquer comme résolu",
"copyDetails": "Copier les détails de l'erreur",
"noErrors": "Aucune erreur détectée",
"systemHealthy": "Le système est sain",
"showStackTrace": "Afficher la trace d'appels"
},
"footer": {
"label": "Pied de page",
"copyright": "© {year} {name}. Open source sous licence MIT.",
"documentation": "Documentation",
"api": "API"
}
}
}
29 changes: 25 additions & 4 deletions ui/messages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@
"success": "成功",
"live": "ライブ",
"offline": "オフライン",
"admin": "管理者"
"admin": "管理者",
"viewAll": "すべて表示",
"language": "言語",
"openNavigation": "ナビゲーションを開く",
"mainNavigation": "メインナビゲーション",
"skipToContent": "メインコンテンツへスキップ",
"switchToDark": "ダークテーマに切り替え",
"switchToLight": "ライトテーマに切り替え"
},
"dashboard": {
"welcome": "WebEncodeへようこそ",
"welcome": "<span>WebEncode</span>へようこそ",
"activeJobs": "アクティブなジョブ",
"workersOnline": "オンラインのワーカー",
"completedJobs": "完了したジョブ",
Expand Down Expand Up @@ -97,6 +104,20 @@
"stackTrace": "スタックトレース",
"timestamp": "タイムスタンプ",
"path": "パス",
"method": "メソッド"
"method": "メソッド",
"refresh": "更新",
"filterBySource": "ソースで絞り込む",
"allSources": "すべてのソース",
"markResolved": "解決済みにする",
"copyDetails": "エラーの詳細をコピー",
"noErrors": "エラーは検出されていません",
"systemHealthy": "システムは正常です",
"showStackTrace": "スタックトレースを表示"
},
"footer": {
"label": "フッター",
"copyright": "© {year} {name}. MIT ライセンスのオープンソース。",
"documentation": "ドキュメント",
"api": "API"
}
}
}
Loading
Loading