Skip to content
Merged
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
7 changes: 7 additions & 0 deletions translation-demo/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Required: your Fishjam ID — the relay's root namespace and the connection path segment.
# MoQ tokens are scoped to paths under it (a stream `<name>` token authorizes `<fishjam-id>/<name>`).
VITE_FISHJAM_ID=ea94930e3ffd47c490f5144c43d57340

# Required: Fishjam sandbox API base URL. The app fetches a MoQ JWT from the sandbox and
# appends it to the relay connection URL as `?jwt=`. Get it at https://fishjam.io/app/sandbox.
VITE_SANDBOX_API_URL=https://fishjam.io/api/v1/connect/ea94930e3ffd47c490f5144c43d57340/room-manager
27 changes: 27 additions & 0 deletions translation-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Dependencies
node_modules

# Build output
dist
dist-ssr
*.local

# Env
.env

# Yarn (Berry)
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Logs
*.log

# Editor / OS
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
15 changes: 15 additions & 0 deletions translation-demo/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
nodeLinker: node-modules

packageExtensions:
"@moq/hang@0.2.10":
dependencies:
"@svta/cml-utils": "1.5.0"
"@moq/loc@0.1.1":
dependencies:
zod: "^4.4.3"
"@moq/publish@0.2.15":
dependencies:
zod: "^4.4.3"
"@moq/watch@0.2.17":
dependencies:
zod: "^4.4.3"
28 changes: 28 additions & 0 deletions translation-demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Translation Demo

An example React app that streams over the MoQ protocol with Fishjam, with live audio translation and captions for the viewer.

## Getting Started

Install dependencies:

```bash
yarn
```

Configure the MoQ relay (required):

```bash
cp .env.example .env
# then set VITE_MOQ_URL and VITE_MOQ_FISHJAM_ID in .env to your MoQ relay URL
```

Start the development server:

```bash
yarn dev
```

## Environment Variables

- `VITE_MOQ_URL` (required) — URL of the MoQ relay to connect to. The app has no built-in default and will not connect until this is set.
18 changes: 18 additions & 0 deletions translation-demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Translation Demo</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap"
rel="stylesheet" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
48 changes: 48 additions & 0 deletions translation-demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@moq/translation-demo",
"private": true,
"version": "0.1.0",
"description": "MoQ streaming demo with live audio translation and captions",
"license": "(MIT OR Apache-2.0)",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@fishjam-cloud/react-client": "0.28.1",
"@moq/publish": "0.2.15",
"@moq/signals": "0.1.9",
"@moq/watch": "0.2.17",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.17",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-slot": "^1.1.1",
"@svta/cml-utils": "1.5.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"lucide-react": "^0.476.0",
"qrcode.react": "^4.2.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router": "^7.1.5",
"sonner": "^2.0.3",
"tailwind-merge": "^3.0.2",
"tailwindcss-animate": "^1.0.7",
"unique-names-generator": "^4.7.1"
},
"devDependencies": {
"@types/node": "^22.12.0",
"@types/react": "19.2.17",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react-swc": "^3.7.2",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3",
"vite": "^6.0.11"
},
"packageManager": "yarn@4.6.0"
}
6 changes: 6 additions & 0 deletions translation-demo/postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
10 changes: 10 additions & 0 deletions translation-demo/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions translation-demo/public/fishjam-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions translation-demo/public/gemini-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions translation-demo/src/components/BrandHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { cn } from "@/utils/cn";

type Props = {
className?: string;
};

// The Gemini wordmark sits a touch low in its viewBox, so a small upward nudge
// (-translate-y-2) keeps it baseline-aligned with the Fishjam mark.
export const BrandHeader = ({ className }: Props) => (
<div
className={cn("flex flex-col items-center justify-center gap-2", className)}
>
<div className="flex items-center justify-center gap-4">
<a
href="https://fishjam.swmansion.com"
target="_blank"
rel="noopener noreferrer"
>
<img src="/fishjam-logo.svg" alt="Fishjam" className="h-12 w-auto" />
</a>
<span className="text-3xl font-light text-stone-600 select-none">×</span>
<img
src="/gemini-logo.svg"
alt="Gemini"
className="h-12 w-auto -translate-y-2"
/>
</div>
<p className="max-w-md text-center text-sm text-stone-600">
Live streaming with real-time AI translation — powered by Fishjam, Gemini,
and Media over QUIC.
</p>
</div>
);
Loading