Skip to content

Commit 9786ca4

Browse files
committed
Fix compose
1 parent d2250be commit 9786ca4

File tree

10 files changed

+97
-2
lines changed

10 files changed

+97
-2
lines changed

conference-to-stream/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.env

conference-to-stream/README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Conference to Stream
2+
3+
A demo showcasing Fishjam's track forwarding capability combined with [Foundry](https://compositor.live) (Smelter) for real-time video composition. Participants join a video conference, their tracks are automatically forwarded to Foundry, composed into a single stream using a Tiles layout, and made available as a WHEP stream that can be previewed alongside the conference.
4+
5+
## How It Works
6+
7+
1. The backend creates a Foundry composition and a Fishjam conference room with track forwarding enabled.
8+
2. When a participant joins and publishes their camera/microphone, Fishjam forwards the tracks to Foundry.
9+
3. The backend listens for `TrackForwarding` notifications via WebSocket and updates the Foundry composition layout (Tiles grid + audio mix).
10+
4. The frontend displays the conference (via Fishjam React SDK) side-by-side with a live WHEP preview of the composed stream.
11+
12+
## Running Locally
13+
14+
Before running, copy `.env.example` to `.env` and set the following values:
15+
16+
```bash
17+
FISHJAM_ID=...
18+
FISHJAM_MANAGEMENT_TOKEN=...
19+
VITE_FISHJAM_ID=...
20+
```
21+
22+
You can get `FISHJAM_ID` and `FISHJAM_MANAGEMENT_TOKEN` for free by logging in at <https://fishjam.io/app>. `VITE_FISHJAM_ID` should be set to the same value as `FISHJAM_ID`.
23+
24+
### Docker Compose (Recommended)
25+
26+
The easiest way to run the app is with [Docker Compose](https://docs.docker.com/compose/install/).
27+
28+
```bash
29+
docker compose --env-file .env up --build
30+
```
31+
32+
The web UI will be available at <http://localhost:5173> and the backend at <http://localhost:8080>.
33+
34+
### Running Manually
35+
36+
#### Requirements
37+
- [Go](https://go.dev/dl/) `>= 1.23`
38+
- [Node.js](https://nodejs.org/en/download) `>= 20`
39+
40+
#### Backend
41+
42+
```bash
43+
cd backend
44+
go run main.go
45+
```
46+
47+
The server starts on <http://localhost:8080> by default.
48+
49+
#### Frontend
50+
51+
```bash
52+
cd web
53+
npm install
54+
npm run dev
55+
```
56+
57+
Open the UI at <http://localhost:5173>.
58+
59+
## Repo Structure
60+
61+
- `backend/` — Go server that orchestrates Fishjam rooms and Foundry compositions.
62+
- `fishjam/` — REST client for rooms, peers, and track forwarding + WebSocket notification listener (protobuf).
63+
- `foundry/` — HTTP client for Foundry composition API (create, start, register/update output).
64+
- `handler/` — HTTP handlers and in-memory room state management.
65+
- `proto/` — Generated protobuf Go code for Fishjam server notifications.
66+
- `web/` — React + Vite frontend.
67+
- `components/JoinForm.tsx` — Room name and user name form.
68+
- `components/Conference.tsx` — Peer grid with camera/mic controls + WHEP preview sidebar.
69+
- `components/WhepPlayer.tsx` — WHEP stream player using WebRTC.
70+
- `whep.ts` — WHEP client (SDP negotiation over HTTP).
71+
72+
### Tech Stack
73+
74+
- [Fishjam](https://fishjam.io) for real-time videoconferencing and track forwarding.
75+
- [Foundry / Smelter](https://compositor.live) for real-time video composition.
76+
- Go backend with direct HTTP/WebSocket calls (no SDK).
77+
- React + Vite frontend with `@fishjam-cloud/react-client`.
78+
- Tailwind CSS for styling.

conference-to-stream/backend/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.23-alpine AS builder
1+
FROM golang:1.26-alpine AS builder
22
WORKDIR /app
33
COPY go.mod go.sum ./
44
RUN go mod download

conference-to-stream/backend/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ require (
77
github.com/rs/cors v1.11.1
88
google.golang.org/protobuf v1.36.11
99
)
10+
11+
require github.com/joho/godotenv v1.5.1 // indirect

conference-to-stream/backend/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
22
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
33
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
44
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
5+
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
6+
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
57
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
68
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
79
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=

conference-to-stream/backend/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ import (
99
"conference-to-stream/foundry"
1010
"conference-to-stream/handler"
1111

12+
"github.com/joho/godotenv"
1213
"github.com/rs/cors"
1314
)
1415

1516
func main() {
17+
// Load .env from parent directory (conference-to-stream/.env) when running locally
18+
_ = godotenv.Load("../.env")
19+
1620
fishjamID := os.Getenv("FISHJAM_ID")
1721
if fishjamID == "" {
1822
log.Fatal("FISHJAM_ID is required")

conference-to-stream/docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ services:
1313
web:
1414
build:
1515
context: ./web
16+
args:
17+
VITE_FISHJAM_ID: ${VITE_FISHJAM_ID}
18+
VITE_BACKEND_URL: ${VITE_BACKEND_URL:-http://localhost:8080}
1619
ports:
1720
- "5173:80"
1821
depends_on:

conference-to-stream/web/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ WORKDIR /app
33
COPY package.json ./
44
RUN npm install
55
COPY . .
6+
ARG VITE_FISHJAM_ID
7+
ARG VITE_BACKEND_URL=http://localhost:8080
8+
ENV VITE_FISHJAM_ID=$VITE_FISHJAM_ID
9+
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
610
RUN npm run build
711

812
FROM nginx:alpine

conference-to-stream/web/src/components/JoinForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function JoinForm({ onJoined }: Props) {
1515
const [loading, setLoading] = useState(false);
1616

1717
useEffect(() => {
18-
// initializeDevices({ enableVideo: true, enableAudio: true });
18+
initializeDevices({ enableVideo: true, enableAudio: true });
1919
}, [initializeDevices]);
2020

2121
async function handleSubmit(e: React.FormEvent) {

conference-to-stream/web/vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ import { defineConfig } from "vite";
44

55
export default defineConfig({
66
plugins: [react(), tailwindcss()],
7+
envDir: "..",
78
});

0 commit comments

Comments
 (0)