The Problem

Users need real‑time speech translation on desktop or in‑browser without juggling separate capture, AI, and UI components. Existing tools are either closed‑source, platform‑restricted, or require manual wiring of audio pipelines and API keys.

What This Does

sokuji ships six self‑contained projects that together deliver live translation via OpenAI, Google Gemini, Palabra.ai, and Kizuna AI.

  • The Electron app (electron/main.js) boots a Chromium window that loads src/index.html, which mounts the React tree under src/components/MainPanel/MainPanel.tsx.
  • The browser extension lives in extension/, built with Webpack (extension/webpack.config.js) and packaged for Chrome/Edge.
  • Eval scripts (evals/runner/cli.ts, evals/runner/index.ts) provide a CLI harness for automated testing of audio‑service integrations.
  • Shared utilities (src/lib/analytics.ts, src/utils/environment.ts) and type definitions (src/types/Provider.ts) are reused across all projects.

How It Is Wired

Execution starts in electron/main.js (or docs/index.html for the web demo). The main process creates a BrowserWindow, then the renderer loads src/index.html, which runs the bundled React entry (src/main.tsx). React renders MainPanel – the UI hub that orchestrates audio capture, AI client selection, and result display.

  • Audio flow – src/lib/modern-audio/ModernBrowserAudioService is instantiated by src/services/ServiceFactory.ts (via createAudioService). The service emits raw PCM to the selected AI client (src/services/clients/*Client.ts).
  • AI clients implement src/services/interfaces/IClient. The concrete classes (GeminiClient, OpenAIClient, etc.) are selected based on src/types/Provider.ts and user settings stored in src/stores/settingsStore.ts.
  • Analytics – src/lib/analytics.ts subscribes to events from settingsStore, audioStore, and UI components, sending data to PostHog. This module is a hub (22 inbound imports) and participates in a circular import with audioStore and ServiceFactory.
  • State management – Redux‑style stores (src/stores/*Store.ts) expose observable state; MainPanel reads settingsStore and audioStore to drive UI updates.
  • Extension – extension/background.ts mirrors the same service factory logic but runs in a service worker, communicating with content scripts via Chrome messaging.

Circular dependencies (35 edges) involve analytics.ts, audioStore.ts, and ServiceFactory.ts; they increase change‑impact risk because a modification can trigger recompilation of multiple bundles. The most fan‑in module (src/types/Provider.ts) is a stability anchor – keep its API minimal.

How To Use It

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

# Install all npm workspaces
npm ci

# Copy example env and fill in your API keys
cp .env.example .env
# edit .env → set OPENAI_API_KEY, GEMINI_API_KEY, etc.

# Run the desktop app (development mode)
npm run dev   # defined in package.json, invokes electron/main.js via vite

# Build the browser extension
npm run build:extension   # uses extension/webpack.config.js, outputs to dist/

The Electron app reads .env at startup; the extension expects the same variables injected at build time (see docs/README.md for details). No additional database or server is required.

Real‑World Use

A remote‑learning platform can embed the extension in its web UI. When a teacher speaks, ModernBrowserAudioService captures the microphone stream, forwards it to OpenAIClient via the Realtime API, and the translated subtitles are injected into the video element by the content script (extension/contentScript.ts). The same flow works in the desktop app for standalone meetings.

Code Health & Issues

  • High – Pin third‑party GitHub Actions to commit SHAs (.github/workflows/*).
  • Medium – Add Dependabot (.github/dependabot.yml).
  • Medium – Gate PRs with a dependency‑vulnerability scan (dependency-review-action or osv-scanner).
  • Medium – Move large binary screenshots/demo.mp4 (5.8 MiB) to Git LFS.
  • Medium – Set persist-credentials: false on checkout steps (.github/workflows/build.yml).
  • Medium – Expand test coverage; only 1 test file covers 131 source files (ratio 0.008).
  • Low – Define timeout-minutes on CI jobs.
  • Low – Add convention files (.editorconfig, .gitattributes, formatter config).

Static analysis also flagged 40 import‑cycle members, six oversized files (e.g., src/components/MainPanel/MainPanel.tsx at 740 lines), and deep nesting (max depth 8) in UI components. These patterns inflate cognitive load and increase the blast radius of changes.

The Bottom Line

sokuji provides a functional, cross‑platform live translation stack with clear entry points and reusable service factories, but the codebase suffers from import cycles, large monolithic modules, and modest test coverage. It is suitable for teams that need a quick prototype or are willing to invest in refactoring the identified hotspots.