Skip to content

Repository files navigation

PolyDub: Real-Time Multilingual Video Dubbing

Speak any language. Be heard in any language. Live.

Next.jsReactTypeScriptDeepgramLingo.dev

PolyDub is a browser-based multilingual dubbing platform for live broadcasts, video rooms, and uploaded media. It captures speech, transcribes it with Deepgram, translates it, generates dubbed speech, and plays it back to listeners in their selected language.

Features

ModeRouteWhat it does
Live Broadcast/broadcast, /broadcast/[id]/[lang]One host speaks while listeners receive translated transcripts and dubbed audio.
Multilingual Rooms/rooms, /room/[roomId]Multiple participants speak in their own language and hear others in their selected language.
VOD Dubbing/vodUpload media and generate dubbed audio, SRT subtitles, and a muxed MP4.

Highlights:

  • Low-latency browser dubbing target for live speech.
  • Native Aura-2 voice options for English, Spanish, French, German, Italian, Japanese, and Dutch.
  • Per-listener TTS queues so generated room audio does not interleave across speakers.
  • English + 11 translated UI locales compiled at build time with Lingo.dev.
  • VOD pipeline for prerecorded transcription, translation, TTS audio, SRT generation, and FFmpeg muxing.

Screenshots

Landing Page

Landing Page

Broadcast Mode

Broadcast Mode

Multilingual Room

Room Mode

VOD Dubbing Studio

VOD Studio

How It Works

See ARCHITECTURE.md for sequence diagrams, WebSocket role routing, and pipeline details.

Mic PCM -> WebSocket
-> Deepgram Nova-2 STT
-> Google Translate gtx adapter
-> Deepgram Aura-2 TTS
-> WebSocket -> Browser AudioContext -> Speaker

PolyDub runs as two cooperating processes:

Next.js app (:3000)
- /broadcast
- /broadcast/[id]/[lang]
- /rooms
- /room/[roomId]
- /vod
- /api/dub
- /api/mux
- /api/tts-preview
WebSocket server (:8080)
- broadcast hosts and listeners
- room audio and video sockets
- Deepgram streaming STT
- translation cache and in-flight deduplication
- Deepgram streaming TTS

Supported Languages

Live/VOD source language options: English, Spanish, French, German, Italian, Dutch, Japanese, Portuguese, Hindi, Arabic, Korean, Turkish, Vietnamese, Ukrainian, and Polish.

Aura-2 target voices exposed in the UI:

LanguageVoices
EnglishThalia, Andromeda, Apollo, Arcas
SpanishCeleste, Estrella, Nestor, Sirio
FrenchAgathe, Hector
GermanViktoria, Elara, Julius, Fabian
ItalianLivia, Melia, Dionisio, Elio
JapaneseIzanami, Uzume, Ama, Ebisu, Fujin
DutchRhea, Beatrix, Sander, Lars

Tech Stack

  • App: Next.js 16, React 19, TypeScript
  • UI: Tailwind CSS v4, shadcn-style UI primitives, Radix UI, Phosphor Icons
  • Realtime: Node.js, ws, browser Web Audio APIs
  • STT: Deepgram Nova-2 streaming and prerecorded transcription
  • Translation: Google Translate unofficial gtx endpoint with LRU cache and in-flight deduplication
  • TTS: Deepgram Aura-2
  • VOD muxing: System ffmpeg binary invoked by /api/mux
  • UI i18n: Lingo.dev compiler
  • Testing: TestSprite-generated backend and frontend tests

Prerequisites

  • Node.js 18 or newer
  • pnpm
  • A Deepgram API key for STT and TTS
  • A Lingo.dev API key for UI translation compilation
  • FFmpeg installed and available as ffmpeg on PATH for production VOD muxing

Getting Started

git clone https://github.com/crypticsaiyan/polydub.git
cd polydub
pnpm install
cp .env.example .env

Edit .env:

DEEPGRAM_API_KEY=your_deepgram_api_key_hereLINGO_API_KEY=your_lingo_api_key_hereLINGO_BUILD_MODE=translatePORT=8080WEBSOCKET_PORT=8080NEXT_PUBLIC_WS_URL=ws://localhost:8080

Start both processes in separate terminals:

pnpm dev
pnpm run server

Open http://localhost:3000.

Scripts

CommandDescription
pnpm devStart the Next.js dev server on http://localhost:3000.
pnpm run serverStart the TypeScript WebSocket server on port 8080.
pnpm buildBuild the Next.js app and run Lingo compilation.
pnpm startStart the built Next.js app.
pnpm server:buildCompile the WebSocket server TypeScript to dist-server/.
pnpm server:startStart the compiled WebSocket server from dist-server/index.js.
pnpm lintRun ESLint.

Environment Variables

VariableUsed byRequiredDescription
DEEPGRAM_API_KEYNext.js API routes, WebSocket serverYesDeepgram STT and TTS API key.
LINGO_API_KEYNext.js build, /api/dub guardYes for full build/VOD flowMapped to LINGODOTDEV_API_KEY in next.config.mjs for Lingo.dev compilation.
LINGO_BUILD_MODENext.js buildNoOptional Lingo compiler mode. Defaults to translate.
PORTWebSocket serverNoPrimary WebSocket server port. Defaults to 8080.
WEBSOCKET_PORTWebSocket serverNoFallback port when PORT is not set.
NEXT_PUBLIC_WS_URLBrowser clientYesPublic WebSocket URL, for example ws://localhost:8080 or wss://your-ws-domain.com.

API Reference

POST /api/dub

Accepts multipart form data and returns generated subtitles plus base64 audio.

FieldRequiredDescription
fileYesUploaded audio/video file.
targetLanguage or target_languageYesTarget language code for dubbing.
sourceLanguage or source_languageNoSource language code. Defaults to auto.
voiceId or voice_idNoDeepgram Aura-2 voice ID override.

Response:

{
"srt": "1\n00:00:00,000 --> 00:00:01,500\n...",
"mp3": "base64-encoded-audio"
}

POST /api/mux

Accepts multipart form data and returns a video/mp4 response.

FieldRequiredDescription
video or original_videoYesOriginal video file.
audio or dubbed_audioYesDubbed audio file.

POST /api/tts-preview

Returns preview audio for a short text/voice sample used by the voice selector UI.

Project Structure

app/
broadcast/ Live broadcast host page
broadcast/[id]/[lang]/ Live broadcast listener page
room/[roomId]/ Multilingual room page
rooms/ Room lobby
vod/ VOD dubbing studio
api/dub/ STT -> translate -> TTS -> SRT/audio
api/mux/ FFmpeg audio/video muxing
api/tts-preview/ Voice preview endpoint
components/polydub/ Core product UI components
components/room/ Room video components
components/ui/ Shared UI primitives
hooks/ WebSocket and responsive UI hooks
lib/srt.ts SRT subtitle generation
server/ WebSocket server and Deepgram/translation wrappers
testsprite_tests/ Generated TestSprite tests and reports

Testing

Tests are generated and executed using TestSprite MCP.

Initial Round: Issues Found

TestSprite surfaced two concrete bugs on the first run:

  1. TC003 (POST /api/dub third-party failure): The error handler was returning a plain text string on API failures instead of a JSON response. This caused clients to receive an unparseable body on 500 errors.
  2. TC009 (malformed room ID): The frontend form was submitting malformed room IDs to the server without client-side validation. The server rejected them but no user-visible error was shown.

Both were fixed before Round 2.

Final Rounds: All Tests Passing

TestSprite MCP dashboard showing PolyDub run history, progressing from 0/5 to 5/5 Pass across multiple runs

Backend API Tests (5/5 Passing)

TestWhat it checks
TC001POST /api/dub returns JSON with non-empty srt and valid base64 mp3.
TC002POST /api/dub missing params returns 400 with Missing parameters.
TC003POST /api/dub third-party failure returns 500 with an error body.
TC004POST /api/mux valid video + audio produces a video/mp4 stream.
TC005POST /api/mux missing inputs returns 400 with Missing video or audio file.

Frontend / E2E Tests (12 Cases Passing)

TestWhat it checks
TC001Start live broadcast after selecting source and target languages.
TC002Create a new room and reach the in-room view.
TC003Join an existing room by ID.
TC004Leave and rejoin a room with the same ID.
TC005Prevent broadcast start when no target languages are selected.
TC006Change language and voice selection in an active room.
TC007VOD studio opens in upload-ready state.
TC008Navigate from landing page to broadcast setup.
TC009Show validation when joining with a malformed room ID.
TC010Navigate from landing page to rooms lobby.
TC011Reject unsupported VOD file type on upload.
TC012Navigate from landing page to VOD studio.

Test files are in testsprite_tests/.

License

MIT

About

Real-time multilingual video dubbing and communication platform powered by AI.

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages