diff --git a/.cspell.json b/.cspell.json new file mode 100644 index 00000000..e0f49a79 --- /dev/null +++ b/.cspell.json @@ -0,0 +1,32 @@ +{ + "version": "0.2", + "language": "en", + "dictionaries": ["custom-dictionary"], + "dictionaryDefinitions": [ + { + "name": "custom-dictionary", + "path": "./spelling.txt", + "addWords": true + } + ], + "ignorePaths": [ + "node_modules/**", + "packages/**", + "docs/api/**", + ".git/**", + "*.lock", + "yarn.lock", + "package-lock.json" + ], + "ignoreRegExpList": ["JSXComment", "/^\\s*```[\\s\\S]*?^\\s*```/gm"], + + "patterns": [ + { + "name": "JSXComment", + "pattern": "\\{/\\*[\\s\\S]*?\\*/\\}" + } + ], + "enableFiletypes": ["mdx"], + "allowCompoundWords": true, + "ignoreWords": [] +} diff --git a/.github/workflows/static_check.yml b/.github/workflows/static_check.yml index 6ff2b398..7367cdc3 100644 --- a/.github/workflows/static_check.yml +++ b/.github/workflows/static_check.yml @@ -22,7 +22,7 @@ jobs: - name: Install node dependencies run: yarn --immutable - name: Spellcheck - run: yarn spellcheck:report + run: yarn spellcheck - name: Check formatting run: yarn format:check - name: Check types diff --git a/docs/api/_category_.json b/docs/api/_category_.json index 458afb85..24fd9392 100644 --- a/docs/api/_category_.json +++ b/docs/api/_category_.json @@ -1,9 +1,10 @@ { "label": "API", - "position": 10, + "position": 6, "link": { "type": "generated-index", - "description": "API documentation for Web and Mobile SDKs." + "description": "API documentation for Client and Server SDKs.", + "slug": "/api" }, "customProps": { "id": "generated-api" diff --git a/docs/explanation/_category_.json b/docs/explanation/_category_.json new file mode 100644 index 00000000..d34d9b78 --- /dev/null +++ b/docs/explanation/_category_.json @@ -0,0 +1,11 @@ +{ + "label": "Explanation", + "position": 4, + "link": { + "type": "generated-index", + "title": "Explanation", + "description": "Big-picture explanations of higher-level Fishjam concepts. Most useful for building understanding of a particular topic.", + "slug": "/explanation" + }, + "collapsible": false +} diff --git a/docs/explanation/architecture.mdx b/docs/explanation/architecture.mdx new file mode 100644 index 00000000..c48bf75c --- /dev/null +++ b/docs/explanation/architecture.mdx @@ -0,0 +1,91 @@ +--- +type: explanation +sidebar_position: 2 +--- + +# Fishjam Architecture + +_Understanding how Fishjam works under the hood_ + +This document explains the technical architecture of Fishjam and how data flows through the system. + +## High-level Architecture + +Streaming with Fishjam is simple: you create a room, add peers to it, and start streaming. Below is a high-level overview of how Fishjam works. + +![Fishjam Data Flow](@site/static/img/architecture.svg) + +## Components Overview + +### 1. Your Backend Server + +Your application's backend server is responsible for: + +- Authenticating users +- Creating rooms using Fishjam Server SDKs +- Generating peer tokens for clients +- Managing room lifecycle and permissions + +### 2. Fishjam Media Server + +The Fishjam Media Server is the core infrastructure component that: + +- Routes audio and video streams between participants +- Handles WebRTC negotiations and connections +- Manages different room types (conference, audio-only, livestream) +- Processes and transcodes media when needed +- Enforces security policies and token validation + +### 3. Client Applications + +Client applications (React Native, React) use Fishjam Client SDKs to: + +- Connect to rooms using peer tokens +- Send and receive audio/video streams +- Handle device management (cameras, microphones) +- Manage connection state and reconnections + +## Data Flow + +### 1. Room Creation Flow + +```mermaid +sequenceDiagram + participant FM as Fishjam Media Server + participant BE as Your Backend + participant Client as Client App + + Client->>BE: Request to join room + BE->>FM: Create room (Server SDK) + FM->>BE: Return room ID + BE->>FM: Create peer (Server SDK) + FM->>BE: Return peer token + BE->>Client: Send peer token + Fishjam URL +``` + +### 2. Media Streaming Flow + +```mermaid +sequenceDiagram + participant C1 as Client 1 + participant FM as Fishjam Media Server + participant C2 as Client 2 + + C1->>FM: Connect with peer token + C2->>FM: Connect with peer token + C1->>FM: Send video/audio stream + FM->>C2: Route stream to other peers + C2->>FM: Send video/audio stream + FM->>C1: Route stream to other peers +``` + +## Next Steps + +To understand different room types in detail, see [Room Types Explained](/explanation/room-types). + +To learn about security and token management, see [Security & Token Model](/explanation/security-tokens). + +Ready to implement? Start with our tutorials: + +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) diff --git a/docs/glossary.md b/docs/explanation/glossary.md similarity index 94% rename from docs/glossary.md rename to docs/explanation/glossary.md index d4dc4ea8..63a67ffd 100644 --- a/docs/glossary.md +++ b/docs/explanation/glossary.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +type: reference --- # Glossary @@ -32,4 +32,4 @@ The URL to your Fishjam instance. It is used by your backend server to add peers ### Room Manager -Our test app is available **only** in the Sandbox environment. It allows you to test Fishjam without needing to add room creation functionality to your backend. You can find more details [here](/room-manager). +Our test app is available **only** in the Sandbox environment. It allows you to test Fishjam without needing to add room creation functionality to your backend. You can find more details [here](/how-to/features/room-manager-testing). diff --git a/docs/explanation/room-manager-concept.mdx b/docs/explanation/room-manager-concept.mdx new file mode 100644 index 00000000..a80735f7 --- /dev/null +++ b/docs/explanation/room-manager-concept.mdx @@ -0,0 +1,87 @@ +--- +type: explanation +sidebar_position: 1 +--- + +# What is Room Manager? + +_Understanding what Room Manager is and why it exists_ + +Room Manager is a development tool that simplifies getting started with Fishjam by providing a simple backend for testing, eliminating the need to build your own server initially. + +## What can Room Manager do? + +Room Manager is an HTTP server that comes with Fishjam's Sandbox environment. +It provides basic room creation and peer management functionality without requiring you to set up your own backend infrastructure. + +### Key Characteristics + +- **Batteries-included**: No extra setup required to start using room manager. +- **Development-focused**: Designed for initial development and testing +- **No authentication**: Simplified access for quick prototyping +- **Sandbox-only**: Only available in the Sandbox environment + +## The Problem Room Manager Solves + +When starting with videoconferencing or livestreaming development, you typically need: + +1. A **Backend server** to create rooms +2. An **Authentication system** to manage users +3. **Token management** for secure peer access +4. **API endpoints** for your frontend to call + +This creates a problem: to test your frontend, you need a backend, but during prototyping you want to focus on frontend development first. +Room Manager mitigates this issue and allows you to start frontend development ASAP. + +## Relationship to Server SDKs + +Room Manager is essentially a simplified application built using the Fishjam Server SDKs: + +```typescript +import { + FishjamClient, + RoomConfigRoomTypeEnum, +} from "@fishjam-cloud/js-server-sdk"; +import express from "express"; +const fishjamUrl = ""; +const managementToken = ""; +const app = express(); + +// ---cut--- +// What Room Manager does internally (simplified) +const fishjamClient = new FishjamClient({ fishjamUrl, managementToken }); + +app.get( + "/room-manager", + async (req: express.Request, res: express.Response) => { + const { roomName, peerName, roomType } = req.query; + + // Create or get room + const room = await fishjamClient.createRoom({ + roomType: roomType as RoomConfigRoomTypeEnum, + }); + + // Create or get peer + const { peer, peerToken } = await fishjamClient.createPeer(room.id); + + res.json({ peerToken, url: fishjamUrl }); + }, +); +``` + +This shows you exactly what your production backend needs to do, just with proper authentication and error handling. + +## See also + +To understand how to use Room Manager for development: + +- [How to use Room Manager for testing](/how-to/features/room-manager-testing) + +To learn about building your own backend: + +- [Backend Quick Start Tutorial](/tutorials/backend-quick-start) +- [How to set up your server](/how-to/backend/server-setup) + +To understand the security model: + +- [Security & Token Model](/explanation/security-tokens) diff --git a/docs/explanation/room-types.mdx b/docs/explanation/room-types.mdx new file mode 100644 index 00000000..ac55eb39 --- /dev/null +++ b/docs/explanation/room-types.mdx @@ -0,0 +1,130 @@ +--- +type: explanation +sidebar_position: 3 +--- + +# Room Types Explained + +_Understanding different types of rooms and when to use them_ + +Fishjam provides three distinct room types, each optimized for different use cases and scenarios. +Understanding these room types helps you choose the right approach for your application. + +## Conference Rooms (Default) + +### What are Conference Rooms? + +Conference rooms are the default room type designed for multi-participant video conferencing scenarios. They support all Fishjam features and provide the most flexibility. + +### Key Characteristics + +- **Multi-participant**: Support for many participants simultaneously +- **Bidirectional media**: All participants can send and receive video/audio +- **Multiple sources**: Participants can share their camera, screen, microphone and more all at once +- **Flexible track management**: Participants can add/remove tracks dynamically + +### Best Use Cases + +- **Video conferencing applications** +- **Interactive webinars** with participant engagement + +### Cost Considerations + +Conference rooms are priced based on total connection time of all peers. + +## Audio-only Rooms + +### What are Audio-only Rooms? + +Audio-only rooms are optimized specifically for voice communication, removing video capabilities to improve performance and reduce costs. + +### Key Characteristics + +- **Voice-only communication**: No video tracks allowed +- **Cheap pricing**: Audio only rooms cost much less than other room types +- **Optimized network usage**: Works well in degraded network conditions + +### Best Use Cases + +- **Audio chat applications** +- **Podcast recording** with multiple participants +- **Large-scale audio events** (town halls, announcements) + +### Cost Benefits + +Audio-only rooms come at a **75% discount** compared to conference rooms: + +- 2 peers for 30 minutes = 60 minutes total time in conference room +- Same scenario in audio-only room = 15 minutes equivalent cost + +### Video Behavior in Audio-only Rooms + +If you attempt to add video to an audio-only room: + +- Video tracks are ignored (not transmitted) +- SDKs log warnings to help with debugging +- Only audio from screen sharing is transmitted +- No errors thrown, graceful degradation + +## Livestream Rooms + +### What are Livestream Rooms? + +Livestream rooms are designed for one-to-many livestreaming scenarios where a single streamer streams to multiple viewers. + +### Key Characteristics + +- **One sender**: Only one streamer can send media +- **Many receivers**: Unlimited viewers can watch +- **Optimized for scale**: Efficient distribution architecture + +### Livestreaming Limitations + +- **Single video track**: Only one video stream allowed +- **Single audio track**: Only one audio stream allowed +- **Additional tracks ignored**: Extra tracks are not forwarded to viewers + +### Viewer Experience + +- **Configurable access**: Livestreams can either be public, where anyone with the stream's ID can join, or private, where every viewer needs a token +- **Standard compatibility**: Any [WHEP](https://blog.swmansion.com/building-interactive-streaming-apps-webrtc-whip-whep-explained-d38f4825ec90)-compatible player works + +### Best Use Cases + +- **Live events** +- **Streaming platforms** and content distribution +- **Corporate livestreams** and announcements +- **Sports and entertainment** streaming + +### Cost Benefits + +Livestream rooms are **20% cheaper** than conference rooms for equivalent usage. + +## Choosing the Right Room Type + +### Decision Matrix + +| Use Case | Room Type | Why | +| ---------------------- | ---------- | ------------------------------------------- | +| Classic video meetings | Conference | Multiple video sources | +| Voice-only meetings | Audio-only | Cheapest and most performant option | +| Live Podcasts | Audio-only | Cheapest and most performant option | +| Sport streaming | Livestream | Highly scalable and cheaper than conference | +| Interactive workshop | Conference | Multiple video sources | + +## Next Steps + +To understand how to implement each room type: + +- [How to create audio-only calls](/how-to/features/audio-only-calls) +- [How to implement livestreaming](/how-to/features/livestreaming) + +To learn about the underlying architecture: + +- [Fishjam Architecture](/explanation/architecture) +- [Security & Token Model](/explanation/security-tokens) + +Ready to start building? Check our tutorials: + +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) diff --git a/docs/explanation/security-tokens.mdx b/docs/explanation/security-tokens.mdx new file mode 100644 index 00000000..f9565020 --- /dev/null +++ b/docs/explanation/security-tokens.mdx @@ -0,0 +1,122 @@ +--- +type: explanation +sidebar_position: 4 +--- + +# Security & Token Model + +_Understanding Fishjam's security architecture and token system_ + +Fishjam uses a token-based security model to ensure secure access control while keeping the developer experience simple. + +## Security Architecture Overview + +Fishjam's security is built on a **two-tier token system**: + +1. **Management Tokens**: For backend-to-Fishjam server communication +2. **Peer Tokens**: For client-to-Fishjam server communication + +This separation ensures that sensitive operations remain on your backend while allowing clients secure, limited access to media streaming. + +## Management Tokens + +### Purpose + +Management tokens provide your backend server with administrative access to Fishjam resources. They allow creating, managing, and deleting rooms and peers. + +### Characteristics + +- **Long-lived**: Management tokens remain valid until manually regenerated +- **High privilege**: Management tokens allow performing administrative operations and should only be used in backend applications. +- **Backend-only**: Management tokens should never be sent to client applications. +- **Environment-specific**: There are different tokens for sandbox and production. + +### What Management Tokens Can Do + +Management tokens give permission to: + +- Create and manage rooms and peers +- Setup [webhooks](/how-to/backend/server-setup#webhooks) +- Set [immutable peer metadata](/how-to/backend/server-setup#metadata) + +## Peer Tokens + +### Purpose + +Peer tokens provide client applications with limited, time-bound access to join a specific room as a specific peer. + +### Characteristics + +- **Short-lived**: Peer tokens expire 24h after creation. +- **Scope-limited**: Peer tokens give access to one specific room as one specific peer only. +- **Client-safe**: Peer tokens are safe to send to frontend applications. + +### What Peer Tokens Can Do + +Peer tokens give permission to: + +- Connect to the specific room they were issued for +- Participate in room activities (audio/video/screen sharing) +- Access peer metadata and room state + +### What Peer Tokens Cannot Do + +- Create or delete rooms +- Access multiple rooms +- Add or remove peers + +### Generation Process + +```typescript +import { FishjamClient, RoomId } from "@fishjam-cloud/js-server-sdk"; +import express from "express"; +const res = {} as any; +const fishjamUrl = ""; +const managementToken = ""; +const roomId = "" as unknown as RoomId; +const fishjamClient = new FishjamClient({ fishjamUrl, managementToken }); + +// ---cut--- +// Backend generates peer token (using management token) +const { peer, peerToken } = await fishjamClient.createPeer(roomId, { + metadata: { name: "John Doe", userId: "user-123" }, +}); + +// Backend sends peer token to client +res.json({ + peerToken, // Client uses this to connect + fishjamUrl, // Fishjam server URL + roomId, // Room information +}); +``` + +### Client Usage + +```typescript +import { useConnection } from "@fishjam-cloud/react-client"; +const joinRoom = {} as any; +const fishjamUrl = ""; +const peerToken = ""; + +// ---cut--- +// Client uses peer token to connect (safe to use in frontend) +await joinRoom({ + url: fishjamUrl, + peerToken: peerToken, // This is safe in client code +}); +``` + +## Next Steps + +To implement secure authentication: + +- [Backend Quick Start Tutorial](/tutorials/backend-quick-start) +- [How to set up your server](/how-to/backend/server-setup) + +To understand the broader architecture: + +- [Fishjam Architecture](/explanation/architecture) + +To learn about Room Manager's security limitations: + +- [Room Manager Concept](/explanation/room-manager-concept) diff --git a/docs/explanation/what-is-fishjam.mdx b/docs/explanation/what-is-fishjam.mdx new file mode 100644 index 00000000..09c842cc --- /dev/null +++ b/docs/explanation/what-is-fishjam.mdx @@ -0,0 +1,67 @@ +--- +type: explanation +sidebar_position: 0 +--- + +# What is Fishjam? + +_Understanding the role and purpose of Fishjam_ + +Fishjam is a multimedia streaming toolkit that allows you to build real-time video and audio streaming applications. +It uses [WebRTC](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API) under the hood to ensure sub-second (in most cases **less than 300ms**) latency. +We provide the infrastructure, media server, and client SDKs so you can focus on building your apps. + +**No WebRTC knowledge is required!** + +## The Problem Fishjam Solves + +Building real-time video and audio applications is complex. Developers typically need to: + +- Set up and manage WebRTC infrastructure +- Handle complex peer-to-peer networking +- Manage media servers and scaling +- Deal with different devices and codec compatibility +- Implement secure token-based authentication + +Fishjam abstracts away this complexity, providing a simple API and managed infrastructure. + +## What Fishjam Provides + +Fishjam consists of several components that work together to provide a seamless multimedia streaming experience: + +| Component | Description | +| --------------------- | ------------------------------------------------------------------------------------------------------- | +| Developer panel | The place to access your credentials and manage your Fishjam usage. | +| Fishjam Media Servers | Media servers route your multimedia traffic. We host and manage them for you. | +| Fishjam Client SDKs | Toolkit used for multimedia integration on endpoint devices. | +| Fishjam Server SDKs | Toolkit for integrating your backend with Fishjam. We currently support Python and NodeJS. | +| Room Manager | Simple backend for creating test rooms. You can test Fishjam without having to set up your own backend. | + +## Use Cases + +Fishjam is ideal for: + +### Video Conferencing + +Build videoconferencing applications with multiple participants in rooms, screen sharing, and audio/video. + +### Livestreaming + +Stream live content from one streamer to many viewers with low latency. +Perfect for live events or streaming platforms. + +### Audio-only Applications + +Create voice-only experiences like audio conferencing, podcasts, or voice chat applications. + +## Next Steps + +To understand how Fishjam works technically, see [Fishjam Architecture](/explanation/architecture). + +To learn about the different types of rooms available, see [Room Types Explained](/explanation/room-types). + +Ready to start building? Check out our tutorials: + +- [React Native Quick Start](/tutorials/react-native-quick-start) +- [React Quick Start](/tutorials/react-quick-start) +- [Backend Quick Start](/tutorials/backend-quick-start) diff --git a/docs/how-to/_category_.json b/docs/how-to/_category_.json new file mode 100644 index 00000000..a932906d --- /dev/null +++ b/docs/how-to/_category_.json @@ -0,0 +1,11 @@ +{ + "label": "How-to Guides", + "position": 3, + "link": { + "type": "generated-index", + "title": "How-to Guides", + "description": "Practical step-by-step guides to help you achieve a specific goal. Most useful when you're trying to get something done.", + "slug": "/how-to" + }, + "collapsible": false +} diff --git a/docs/_common/metadata/header.mdx b/docs/how-to/_common/metadata/header.mdx similarity index 76% rename from docs/_common/metadata/header.mdx rename to docs/how-to/_common/metadata/header.mdx index 7f38d1de..1e5298ec 100644 --- a/docs/_common/metadata/header.mdx +++ b/docs/how-to/_common/metadata/header.mdx @@ -4,7 +4,7 @@ However, it can be also used to send the peer's camera type, application informa :::info -You can also set metadata on [the server side, when adding user to the room](/production/server#metadata). This metadata is persistent throughout its lifetime and is useful for attaching information that +You can also set metadata on [the server side, when adding user to the room](/how-to/backend/server-setup#metadata). This metadata is persistent throughout its lifetime and is useful for attaching information that can't be overwritten by the peer, like information about real user names or basic permission info. ::: diff --git a/docs/_common/metadata/joining_room.mdx b/docs/how-to/_common/metadata/joining_room.mdx similarity index 100% rename from docs/_common/metadata/joining_room.mdx rename to docs/how-to/_common/metadata/joining_room.mdx diff --git a/docs/_common/metadata/reading.mdx b/docs/how-to/_common/metadata/reading.mdx similarity index 83% rename from docs/_common/metadata/reading.mdx rename to docs/how-to/_common/metadata/reading.mdx index fc1eb216..5894a3e2 100644 --- a/docs/_common/metadata/reading.mdx +++ b/docs/how-to/_common/metadata/reading.mdx @@ -4,6 +4,6 @@ Peer metadata is available as the `metadata` property for each peer. Therefore, the metadata associated with them. Note that the `metadata.peer` property contains only the metadata set by the client SDK (as in the examples examples above). The metadata set on the server side is available as `metadata.server`. -Learn more about server metadata [here](/production/server#metadata). +Learn more about server metadata [here](/how-to/backend/server-setup#metadata). {props.children} diff --git a/docs/how-to/_common/metadata/updating.mdx b/docs/how-to/_common/metadata/updating.mdx new file mode 100644 index 00000000..97bd1a1b --- /dev/null +++ b/docs/how-to/_common/metadata/updating.mdx @@ -0,0 +1,5 @@ +## Updating metadata during connection + +Once you've joined the room, you can update your peer metadata with the `updatePeerMetadata` method of the `useUpdatePeerMetadata` hook: + +{props.children} diff --git a/docs/how-to/backend/_category_.json b/docs/how-to/backend/_category_.json new file mode 100644 index 00000000..2d5af2e1 --- /dev/null +++ b/docs/how-to/backend/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Backend", + "position": 4 +} diff --git a/docs/production/examples/fastapi.mdx b/docs/how-to/backend/fastapi-example.mdx similarity index 92% rename from docs/production/examples/fastapi.mdx rename to docs/how-to/backend/fastapi-example.mdx index c4560a46..1596f1f7 100644 --- a/docs/production/examples/fastapi.mdx +++ b/docs/how-to/backend/fastapi-example.mdx @@ -6,7 +6,7 @@ title: FastAPI # FastAPI example The example assumes you've already installed [**our SDK**](https://github.com/fishjam-cloud/python-server-sdk) and you're ready to go. -If you wish to see more general info, visit [**Set up your server**](/production/server) article. +If you wish to see more general info, visit [**Set up your server**](/how-to/backend/server-setup) article. ## Minimal setup @@ -75,7 +75,7 @@ It doesn't interact with the FastAPI library per se, just start the event loop a ```python import asyncio -from jellyfish import FishjamNotifier +from fishjam import FishjamNotifier notifier = FishjamNotifier(server_address=fishjam_url, server_api_token=management_token) @@ -83,15 +83,15 @@ notifier = FishjamNotifier(server_address=fishjam_url, server_api_token=manageme def handle_notification(notification): match notification: case ServerMessagePeerAdded(): - print(f"Peer added: {fishjam_message.peer_id}") + print(f"Peer added: {notification.peer_id}") case _: ... async def run_notifier(): - notifier_task = asyncio.create_task(fishjam_notifier.connect()) + notifier_task = asyncio.create_task(notifier.connect()) # Wait for the notifier to be ready to receive messages - await fishjam_notifier.wait_ready() + await notifier.wait_ready() await notifier_task diff --git a/docs/production/examples/fastify.mdx b/docs/how-to/backend/fastify-example.mdx similarity index 99% rename from docs/production/examples/fastify.mdx rename to docs/how-to/backend/fastify-example.mdx index 7f4d9604..20b636c5 100644 --- a/docs/production/examples/fastify.mdx +++ b/docs/how-to/backend/fastify-example.mdx @@ -9,7 +9,7 @@ import TabItem from "@theme/TabItem"; # Fastify example The example assumes you've already installed [**our SDK**](https://www.npmjs.com/package/@fishjam-cloud/js-server-sdk) and you're ready to go. -If you wish to see more general info, visit [**set up your server**](/production/server) article. +If you wish to see more general info, visit [**set up your server**](/how-to/backend/server-setup) article. ## Load environment variables to Fastify @@ -233,8 +233,8 @@ const fishjamNotifierPlugin = fastifyPlugin((fastify) => { () => fastify.log.error("Failed to connect Fishjam notifier"), ); }); -// ---cut--- +// ---cut--- await fastify.register(fishjamPlugin); await fastify.register(fishjamNotifierPlugin); ``` diff --git a/docs/how-to/backend/production-deployment.mdx b/docs/how-to/backend/production-deployment.mdx new file mode 100644 index 00000000..120ac740 --- /dev/null +++ b/docs/how-to/backend/production-deployment.mdx @@ -0,0 +1,298 @@ +--- +type: how-to +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# How to Deploy Fishjam to Production + +**How-to Guide** - _Deploy your Fishjam backend safely to production_ + +This guide covers the essential steps to move from development (using Room Manager) to a production-ready Fishjam backend deployment. + +## Prerequisites + +- Working Fishjam backend (see [Backend Quick Start](/tutorials/backend-quick-start)) +- Production Fishjam environment (not Sandbox) +- Domain and SSL certificates for your backend +- Production database and infrastructure + +## Step 1: Set up production Fishjam environment + +### Get production credentials + +1. Log in to [Fishjam Dashboard](https://fishjam.io/app) +2. Create or select your **Production** environment (not Sandbox) +3. Copy your production **Fishjam URL** and **Management Token** +4. Note: These are different from your sandbox credentials + +### Environment variables setup + +Create production environment variables: + +```bash +# Production Fishjam credentials +FISHJAM_URL="your-production-fishjam-url" +FISHJAM_MANAGEMENT_TOKEN="your-production-management-token" + +# Your application settings +NODE_ENV="production" +PORT="3000" +DATABASE_URL="your-production-database-url" + +# Security settings +JWT_SECRET="your-secure-jwt-secret" +CORS_ORIGIN="https://yourdomain.com" +``` + +## Step 2: Implement proper authentication + +### Replace Room Manager calls + +Remove any Room Manager dependencies from your client code: + +```typescript +// @noErrors: 2451 +import express from "express"; +const authenticateUser = {} as any; +const app = express(); + +const ROOM_MANAGER_ID = ""; +const userToken = ""; +const roomName = ""; + +// ---cut--- +// ❌ Remove: Room Manager calls +const response = await fetch( + `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager?...`, +); + +// ✅ Replace with: Your authenticated API +const response = await fetch("/api/join-room", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${userToken}`, + }, + body: JSON.stringify({ roomName }), +}); +``` + +### Implement user authentication + +```typescript +// @noErrors: 2339 +const jwt = {} as any; +import { FishjamClient, Room } from "@fishjam-cloud/js-server-sdk"; +import express from "express"; + +const app = express(); +const getUserById = async (userId: string) => ({ + id: userId, + name: "User", + avatar: "", + role: "user", +}); +const getOrCreateRoom = async (roomName: string) => + ({ id: "room-id" }) as unknown as Room; +const canUserJoinRoom = (user: any, room: any) => true; +process.env.FISHJAM_URL = ""; +process.env.FISHJAM_MANAGEMENT_TOKEN = ""; +process.env.JWT_SECRET = ""; + +// ---cut--- +const fishjamClient = new FishjamClient({ + fishjamUrl: process.env.FISHJAM_URL!, + managementToken: process.env.FISHJAM_MANAGEMENT_TOKEN!, +}); + +// Authentication middleware +const authenticateUser = async ( + req: express.Request, + res: express.Response, + next: express.NextFunction, +) => { + try { + const token = req.headers.authorization?.replace("Bearer ", ""); + if (!token) { + return res.status(401).json({ error: "Authentication required" }); + } + + const decoded = jwt.verify(token, process.env.JWT_SECRET); + req.user = await getUserById(decoded.userId); + next(); + } catch (error) { + res.status(401).json({ error: "Invalid token" }); + } +}; + +// Protected endpoint for joining rooms +app.post("/api/join-room", authenticateUser, async (req, res) => { + try { + const { roomName } = req.body; + const user = req.user; + + // Create or get room + const room = await getOrCreateRoom(roomName); + + // Verify user has permission to join this room + if (!canUserJoinRoom(user, room)) { + return res.status(403).json({ error: "Access denied" }); + } + + // Create peer with user metadata + const { peer, peerToken } = await fishjamClient.createPeer(room.id, { + metadata: { + userId: user.id, + name: user.name, + avatar: user.avatar, + role: user.role, + }, + }); + + res.json({ + peerToken, + fishjamUrl: process.env.FISHJAM_URL, + }); + } catch (error) { + console.error("Join room error:", error); + res.status(500).json({ error: "Failed to join room" }); + } +}); +``` + +## (Optional) Step 3: Handle webhooks and events + +You may wish to receive events from Fishjam regarding created rooms and peers. +All you need for this is a single api endpoint: + +### Webhook endpoint + +```typescript +import express from "express"; +const crypto = {} as any; +const app = express(); + +const handlePeerConnected = {} as any; +const handlePeerDisconnected = {} as any; +const handleRoomEmpty = {} as any; + +// ---cut--- +// Webhook signature verification +const verifyWebhookSignature = ( + req: express.Request, + res: express.Response, + next: express.NextFunction, +) => { + const signature = req.headers["x-fishjam-signature"]; + const payload = JSON.stringify(req.body); + + const expectedSignature = crypto + .createHmac("sha256", process.env.WEBHOOK_SECRET) + .update(payload, "utf8") + .digest("hex"); + + if (signature !== expectedSignature) { + return res.status(401).json({ error: "Invalid signature" }); + } + + next(); +}; + +// Webhook handler +app.post( + "/api/webhooks/fishjam", + express.raw({ type: "application/json" }), + verifyWebhookSignature, + (req: express.Request, res: express.Response) => { + const event = req.body; + + switch (event.type) { + case "peer_connected": + handlePeerConnected(event.data); + break; + case "peer_disconnected": + handlePeerDisconnected(event.data); + break; + case "room_empty": + handleRoomEmpty(event.data); + break; + default: + console.log("Unhandled event type:", event.type); + } + + res.status(200).json({ received: true }); + }, +); +``` + +### Enabling webhooks + +Now, with your endpoint setup, all you need to do is supply your webhook endpoint to Fishjam when creating a room: + +```typescript +import { FishjamClient } from "@fishjam-cloud/js-server-sdk"; +const fishjamClient = {} as any; + +// ---cut--- +const createRoomWithWebhooks = async ( + roomName: string, + roomType = "conference", +) => { + const room = await fishjamClient.createRoom({ + roomType, + webhookUrl: `${process.env.BASE_URL}/api/webhooks/fishjam`, + }); + + return room; +}; +``` + +## Common production issues + +### Issue: Token expiration handling + +Peer tokens expire 24h after creation. +We encourage keeping room and peer lifetimes as short as possible +(typically a single room corresponds to a single video call or stream). +However, if you wish to reuse a single peer over multiple days, you can make use of token refreshing: + + + + + ```ts + import { FishjamClient, RoomId, PeerId } from "@fishjam-cloud/js-server-sdk"; + const fishjamClient = new FishjamClient({ + fishjamUrl: "", + managementToken: "", + }); + const roomId = "" as RoomId; + const peerId = "" as PeerId; + + // ---cut--- + const newToken = fishjamClient.refreshPeerToken(roomId, peerId); + ``` + + + + + + ```python + new_token = fishjam_client.refresh_peer_token(room_id, peer_id) + ``` + + + + +## See also + +For scaling considerations: + +- [Understanding Fishjam Architecture](/explanation/architecture) +- [Security best practices](/explanation/security-tokens) + +For specific backend frameworks: + +- [FastAPI example](/how-to/backend/fastapi-example) +- [Fastify example](/how-to/backend/fastify-example) diff --git a/docs/production/server.mdx b/docs/how-to/backend/server-setup.mdx similarity index 95% rename from docs/production/server.mdx rename to docs/how-to/backend/server-setup.mdx index 5c3f89f9..552e7ea9 100644 --- a/docs/production/server.mdx +++ b/docs/how-to/backend/server-setup.mdx @@ -58,8 +58,8 @@ They are required to proceed. Now, we are ready to dive into the code. ```ts process.env.FISHJAM_URL = "https://fishjam.io"; process.env.FISHJAM_MANAGEMENT_TOKEN = "bbb"; - // ---cut--- + // ---cut--- import { FishjamClient } from '@fishjam-cloud/js-server-sdk'; const fishjamUrl = process.env.FISHJAM_URL; @@ -155,7 +155,7 @@ At any time you can terminate user's access by deleting the peer. ```python peer, token = fishjam_client.create_peer(room_id) - fishjam_url.delete_peer(room_id, peer.id) + fishjam_client.delete_peer(room_id, peer.id) ``` @@ -164,8 +164,8 @@ At any time you can terminate user's access by deleting the peer. #### Metadata -When creating a peer, you can also assign metadata to that peer, which can be read later on with the [mobile SDK](/react-native/metadata) -or [web SDK](/react/metadata). This metadata can be only set when creating the peer and can't be updated later. +When creating a peer, you can also assign metadata to that peer, which can be read later with the [mobile SDK](/how-to/react-native/metadata-and-broadcasting) +or [web SDK](/how-to/react/metadata). This metadata can be only set when creating the peer and can't be updated later. @@ -179,7 +179,7 @@ or [web SDK](/react/metadata). This metadata can be only set when creating the p const created_room = await fishjamClient.createRoom(); // ---cut--- const { peer, peerToken } = await fishjamClient.createPeer(created_room.id, { - metadata: { realName: 'Keanu Reeves' }, + metadata: { realName: 'Tom Reeves' }, }); ``` @@ -189,7 +189,7 @@ or [web SDK](/react/metadata). This metadata can be only set when creating the p ```py options = PeerOptions( - metadata={"realName": "Keanu Reeves"}, + metadata={"realName": "Tom Reeves"}, ) peer, token = self.fishjam_client.create_peer(room_id, options=options) ``` diff --git a/docs/how-to/features/_category_.json b/docs/how-to/features/_category_.json new file mode 100644 index 00000000..4aaeb074 --- /dev/null +++ b/docs/how-to/features/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Features", + "position": 3 +} diff --git a/docs/audio-calls.mdx b/docs/how-to/features/audio-only-calls.mdx similarity index 62% rename from docs/audio-calls.mdx rename to docs/how-to/features/audio-only-calls.mdx index eb03f1c0..8491cd2e 100644 --- a/docs/audio-calls.mdx +++ b/docs/how-to/features/audio-only-calls.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +type: how-to --- import Tabs from "@theme/Tabs"; @@ -7,21 +7,22 @@ import TabItem from "@theme/TabItem"; # Audio-only Calls +**How-to Guide** - _Set up voice-only communication with cost savings_ + In many use cases, you only need real-time audio, without any video streaming. If your use case falls into this category, then you can benefit greatly from using `audio_only` rooms in Fishjam. - - - - - - - - +## Why Should I Care? + +Audio-only rooms are heavily discounted compared to normal rooms. +As described in more detail on the [pricing page](https://fishjam.io/#pricing), Fishjam rooms are priced based on the total connection time of peers in them. +Audio-only rooms come at a 75% discount. +For example, if you have a normal room with 2 peers connected for 30 minutes, then the total cost of the room will be equal to the cost of 60 minutes. +If the same room were audio-only, then the final cost of the room will only be equal to 15 minutes. ## How Do I Use It? -Using this feature is as easy as setting the `roomType` field to `audio_only` when creating a room using our [Server SDKs](/production/server) +Using this feature is as easy as setting the `roomType` field to `audio_only` when creating a room using our [Server SDKs](/how-to/backend/server-setup) @@ -48,7 +49,7 @@ Using this feature is as easy as setting the `roomType` field to `audio_only` wh -Now, you can connect peers normally to the room as described in our [React Native](/react-native/connecting) and [React](/react/connecting) docs. +Now, you can connect peers normally to the room as described in our [React Native](/how-to/react-native/connecting) and [React](/how-to/react/connecting) docs. :::info The React Native and React SDKs will log a warning in the console if any attempt to add video to an audio-only room is made. diff --git a/docs/livestreaming.mdx b/docs/how-to/features/livestreaming.mdx similarity index 80% rename from docs/livestreaming.mdx rename to docs/how-to/features/livestreaming.mdx index 080ed62f..00080d04 100644 --- a/docs/livestreaming.mdx +++ b/docs/how-to/features/livestreaming.mdx @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +type: how-to --- import Tabs from "@theme/Tabs"; @@ -13,7 +13,7 @@ If your case involves streaming live audio and/or video from one source to many ### Streamer -First, you need to create a room with the livestream type using our [Server SDKs](/production/server). If you are using our sandbox, the [Room Manager](/room-manager) also allows you to create such a room. As the streaming is one-to-many, you can have only one streaming participant in that room. +First, you need to create a room with the livestream type using our [Server SDKs](/how-to/backend/server-setup). If you are using our sandbox, the [Room Manager](/how-to/features/room-manager-testing) also allows you to create such a room. As the streaming is one-to-many, you can have only one streaming participant in that room. #### Using Room Manager @@ -54,7 +54,7 @@ https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager?roomName=foo&p -Now, you can connect to the room and start streaming as described in our [React Native](/react-native/connecting) and [React](/react/connecting) docs. +Now, you can connect to the room and start streaming as described in our [React Native](/how-to/react-native/connecting) and [React](/how-to/react/connecting) docs. :::note Livestreaming scenario allows only one video and one audio track to be sent at a time. @@ -63,7 +63,7 @@ Livestreaming scenario allows only one video and one audio track to be sent at a ### Viewers -To view the streamed content, you need to obtain a viewer token that can be generated using [Server SDKs](/production/server). If you are using our sandbox, the [Room Manager](/room-manager) also allows you to create such a token. +To view the streamed content, you need to obtain a viewer token that can be generated using [Server SDKs](/how-to/backend/server-setup). If you are using our sandbox, the [Room Manager](/how-to/features/room-manager-testing) also allows you to create such a token. #### Using Room Manager @@ -99,7 +99,7 @@ https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager//li -Now you can connect the viewer to the livestream as described in our React Native and [React](/react/livestreaming) docs. +Now you can connect the viewer to the livestream as described in our React Native and [React](/how-to/react/livestreaming) docs. :::info Viewers connect using [WHEP](https://blog.swmansion.com/building-interactive-streaming-apps-webrtc-whip-whep-explained-d38f4825ec90) standard, allowing the use of any player that supports the WHEP standard. diff --git a/docs/how-to/features/room-manager-testing.mdx b/docs/how-to/features/room-manager-testing.mdx new file mode 100644 index 00000000..3cb3cad3 --- /dev/null +++ b/docs/how-to/features/room-manager-testing.mdx @@ -0,0 +1,292 @@ +--- +type: how-to +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Testing with Room Manager + +**How-to Guide** - _Use Room Manager to test your Fishjam integration quickly without a backend_ + +Room Manager is a development tool that lets you create rooms and peers for testing without setting up your own backend server. This guide shows you how to use it effectively. + +## Prerequisites + +- Access to [Fishjam Dashboard](https://fishjam.io/app) +- A Sandbox environment set up + +## Step 1: Get your Room Manager URL + +1. Log in to [Fishjam Dashboard](https://fishjam.io/app) +2. Navigate to your [Sandbox App](https://fishjam.io/app/sandbox) +3. Copy your **Room Manager URL** - it will look like: + ``` + https://fishjam.io/api/v1/connect/YOUR_APP_UUID/room-manager + ``` + +:::note +`YOUR_APP_UUID` is your unique sandbox identifier. Anyone who knows this ID can join your rooms, so keep it secure during development. +::: + +## Step 2: Create a room and get peer tokens + +### Using HTTP GET requests + +The Room Manager API uses simple GET requests. Add query parameters to create rooms and peers: + +``` +https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=foo&peerName=bar&roomType=conference +``` + +### Required parameters: + +- `roomName` - Name of the room to create/join +- `peerName` - Name for the peer joining the room + +### Optional parameters: + +- `roomType` - Type of room to create (defaults to `conference`) + +### Room types available: + +- `conference` - For video/audio conferencing (default) +- `audio-only` - For audio-only conferencing +- `livestream` - For one-to-many video/audio streaming + +## Step 3: Handle the response + +The Room Manager returns a JSON response with connection details: + +```json +{ + "peerToken": "", + "url": "wss://fishjam.io/api/v1/connect/${YOUR_APP_UUID}", + "room": { + "id": "", + "name": "foo" + }, + "peer": { + "id": "", + "name": "bar" + } +} +``` + +## Step 4: Use the tokens in your client app + +Below are examples on how to use the tokens from room manager in your frontend applications: + + + + + ```tsx + import React, { useEffect, useState } from "react"; + import { Text } from "react-native"; + import { FishjamRoom } from "@fishjam-cloud/react-native-client"; + + const roomName = "testRoom"; + const peerName = `user_${Date.now()}`; + const YOUR_APP_UUID = "your-app-uuid-here"; + + // ---cut--- + export default function TestScreen() { + const [roomData, setRoomData] = useState<{ + url: string; + peerToken: string; + } | null>(null); + + useEffect(() => { + const fetchRoomData = async () => { + try { + const response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=${roomName}&peerName=${peerName}&roomType=conference`, + ); + const data = await response.json(); + setRoomData(data); + } catch (error) { + console.error("Failed to create room:", error); + } + }; + + fetchRoomData(); + }, []); + + if (!roomData) { + return Creating room...; + } + + return ( + + ); + } + ``` + + + + + + ```tsx + import React, { useState, useEffect } from "react"; + import { FishjamProvider, useConnection } from "@fishjam-cloud/react-client"; + + const YOUR_APP_UUID = "your-app-uuid-here"; + + // ---cut--- + function VideoCallComponent() { + const { joinRoom } = useConnection(); + const [isConnected, setIsConnected] = useState(false); + + const handleJoinRoom = async () => { + const roomName = "testRoom"; + const peerName = `user_${Date.now()}`; + + try { + const response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=${roomName}&peerName=${peerName}`, + ); + const { url, peerToken } = await response.json(); + + await joinRoom({ url, peerToken }); + setIsConnected(true); + } catch (error) { + console.error("Failed to join room:", error); + } + }; + + return ( +
+ {!isConnected && } + {isConnected &&

Connected to room!

} +
+ ); + } + + export default function App() { + return ( + + + + ); + } + ``` + +
+
+ +## Step 5: Test different room types + +### Testing audio-only rooms: + +``` +const audioOnlyUrl = `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=audioTest&peerName=user1&roomType=audio-only`; +``` + +### Testing livestream rooms: + +``` +// For the streamer +const streamerUrl = `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=liveStream&peerName=streamer&roomType=livestream`; + +// For viewers, you need a viewer token (different endpoint) +const viewerTokenUrl = `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager/liveStream/livestream-viewer-token`; +``` + +## Step 6: Handle multiple peers + +To test with multiple participants, create multiple peer tokens with different peer names: + +``` +// First peer +const peer1Response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=multiTest&peerName=alice`, +); + +// Second peer +const peer2Response = await fetch( + `https://fishjam.io/api/v1/connect/${YOUR_APP_UUID}/room-manager?roomName=multiTest&peerName=bob`, +); +``` + +Both peers will join the same room (`multiTest`) and can communicate with each other. + +## Common testing patterns + +### Pattern 1: Random room names for isolation + +```typescript +const roomName = `test_${Math.random().toString(36).substring(7)}`; +const peerName = `user_${Date.now()}`; +``` + +### Pattern 2: Consistent naming for repeated tests + +```typescript +// @noErrors: 2451 +const roomName = "development-room"; +const peerName = `developer_1`; +``` + +### Pattern 3: Feature-specific room names + +```typescript +// @noErrors: 2451 +const roomName = `screenshare-test-${Date.now()}`; +const roomName = `audio-only-test`; +const roomName = `livestream-demo`; +``` + +## Troubleshooting + +### Issue: Room not found errors + +**Problem**: Rooms might not persist between requests. + +**Solution**: Always create rooms fresh for each test session. + +### Issue: Connection failures + +**Problem**: Invalid app UUID or network issues. + +**Solution**: + +1. Verify your app UUID in the Fishjam Dashboard +2. Check network connectivity +3. Ensure you're using the sandbox environment + +## Security reminder + +:::danger +**Room Manager is not safe for production!** + +- No authentication required +- Anyone with your app UUID can join rooms +- Identical room/peer names get the same tokens +- No rate limiting or abuse protection + +Only use Room Manager for development and testing. +::: + +## Resetting your app + +If you need to reset your Room Manager: + +1. Go to [Fishjam Dashboard](https://fishjam.io/app/sandbox) +2. Click **Settings** +3. Click **Reset App** +4. Get your new app UUID + +This will invalidate all existing tokens (including the management token!) and give you a fresh sandbox environment. + +## Next steps + +Once you've tested your integration with Room Manager: + +- [Set up your own backend](/tutorials/backend-quick-start) +- [Learn more about Room Manager](/explanation/room-manager-concept) +- [Understand security implications](/explanation/security-tokens) + +For production deployment: + +- [How to set up a production server](/how-to/backend/server-setup) +- [How to implement proper authentication](/explanation/security-tokens) diff --git a/docs/how-to/react-native/_category_.json b/docs/how-to/react-native/_category_.json new file mode 100644 index 00000000..1fd79841 --- /dev/null +++ b/docs/how-to/react-native/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "React Native", + "position": 1 +} diff --git a/docs/react-native/_components/configure-permissions.mdx b/docs/how-to/react-native/_components/configure-permissions.mdx similarity index 100% rename from docs/react-native/_components/configure-permissions.mdx rename to docs/how-to/react-native/_components/configure-permissions.mdx diff --git a/docs/react-native/_components/install-package.mdx b/docs/how-to/react-native/_components/install-package.mdx similarity index 87% rename from docs/react-native/_components/install-package.mdx rename to docs/how-to/react-native/_components/install-package.mdx index deb3b083..356da871 100644 --- a/docs/react-native/_components/install-package.mdx +++ b/docs/how-to/react-native/_components/install-package.mdx @@ -14,7 +14,7 @@ npm install @fishjam-cloud/react-native-client ### Install Expo dependencies -Follow instructions form official [Expo documentation](https://docs.expo.dev/bare/installing-expo-modules/). +Follow instructions from official [Expo documentation](https://docs.expo.dev/bare/installing-expo-modules/). ### Install Fishjam diff --git a/docs/react-native/assets/ios-new-folder.png b/docs/how-to/react-native/assets/ios-new-folder.png similarity index 100% rename from docs/react-native/assets/ios-new-folder.png rename to docs/how-to/react-native/assets/ios-new-folder.png diff --git a/docs/react-native/assets/ios-new-group.png b/docs/how-to/react-native/assets/ios-new-group.png similarity index 100% rename from docs/react-native/assets/ios-new-group.png rename to docs/how-to/react-native/assets/ios-new-group.png diff --git a/docs/react-native/assets/ios-new-target.png b/docs/how-to/react-native/assets/ios-new-target.png similarity index 100% rename from docs/react-native/assets/ios-new-target.png rename to docs/how-to/react-native/assets/ios-new-target.png diff --git a/docs/react-native/background.mdx b/docs/how-to/react-native/background-streaming.mdx similarity index 100% rename from docs/react-native/background.mdx rename to docs/how-to/react-native/background-streaming.mdx diff --git a/docs/react-native/connecting.mdx b/docs/how-to/react-native/connecting.mdx similarity index 92% rename from docs/react-native/connecting.mdx rename to docs/how-to/react-native/connecting.mdx index 626b0515..17f1b63c 100644 --- a/docs/react-native/connecting.mdx +++ b/docs/how-to/react-native/connecting.mdx @@ -19,7 +19,7 @@ your Room). Once you get your account on [Fishjam](https://fishjam.io), you will have access to the Sandbox App. This app comes -with a pre-configured test service called [Room Manager](/room-manager). This is basically a service that will create a Room, add your app as +with a pre-configured test service called [Room Manager](/how-to/features/room-manager-testing). This is basically a service that will create a Room, add your app as the Room's Peer, and return the token required to use that Room. To use that, simply call `fetch`: @@ -40,7 +40,7 @@ const { fishjamUrl, peerToken } = await response.json(); For the production app, you need to implement your own backend service that will provide the user with a **Peer Token**. To do that, -follow our [server setup instructions](/production/server). +follow our [server setup instructions](/how-to/backend/server-setup). diff --git a/docs/how-to/react-native/custom-video-sources/_category_.json b/docs/how-to/react-native/custom-video-sources/_category_.json new file mode 100644 index 00000000..c7673c88 --- /dev/null +++ b/docs/how-to/react-native/custom-video-sources/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Custom Video Sources", + "position": 9 +} diff --git a/docs/react-native/custom-video-sources/index.mdx b/docs/how-to/react-native/custom-video-sources/index.mdx similarity index 53% rename from docs/react-native/custom-video-sources/index.mdx rename to docs/how-to/react-native/custom-video-sources/index.mdx index 409d3085..767771b2 100644 --- a/docs/react-native/custom-video-sources/index.mdx +++ b/docs/how-to/react-native/custom-video-sources/index.mdx @@ -10,5 +10,5 @@ This section contains guides for implementing custom video sources in the Fishja ## Available Guides -- [Custom Source](/react-native/custom-video-sources/overview) - Learn how to create a basic custom video source -- [Vision Camera](/react-native/custom-video-sources/vision-camera) - Learn how to implement Vision Camera as a custom video source +- [Custom Source](/how-to/react-native/custom-video-sources/overview) - Learn how to create a basic custom video source +- [Vision Camera](/how-to/react-native/custom-video-sources/vision-camera) - Learn how to implement Vision Camera as a custom video source diff --git a/docs/react-native/custom-video-sources/overview.mdx b/docs/how-to/react-native/custom-video-sources/overview.mdx similarity index 99% rename from docs/react-native/custom-video-sources/overview.mdx rename to docs/how-to/react-native/custom-video-sources/overview.mdx index df1cf3ef..45e0858e 100644 --- a/docs/react-native/custom-video-sources/overview.mdx +++ b/docs/how-to/react-native/custom-video-sources/overview.mdx @@ -23,11 +23,9 @@ Check out our [**working example**](https://github.com/fishjam-cloud/mobile-clie To create a custom video source, follow these steps: 1. **Implement the CustomSource Interface**: - - On iOS and Android, implement the `CustomSource` interface. This interface provides metadata for the video track and a delegate/consumer to send frames. 1. **Extract and Send Frames**: - - Extract frames from your video source. - Pass these frames to the delegate/consumer (`CMSampleBuffer` on iOS and `ImageProxy` on Android). diff --git a/docs/react-native/custom-video-sources/vision-camera.mdx b/docs/how-to/react-native/custom-video-sources/vision-camera.mdx similarity index 99% rename from docs/react-native/custom-video-sources/vision-camera.mdx rename to docs/how-to/react-native/custom-video-sources/vision-camera.mdx index 9eb78c8d..6ebed8e0 100644 --- a/docs/react-native/custom-video-sources/vision-camera.mdx +++ b/docs/how-to/react-native/custom-video-sources/vision-camera.mdx @@ -23,12 +23,10 @@ Check out our [**complete example implementation**](https://github.com/fishjam-c There are two main components to implement: 1. **Create a Frame Processor Plugin**: - - This plugin extracts frames from Vision Camera and passes them to the Fishjam SDK. - For more details on frame processor plugins, check out the Vision Camera documentation [here](https://react-native-vision-camera.com/docs/guides/frame-processors-plugins-overview). 2. **Create a CustomSource**: - - This component sends the camera frames to Fishjam. - Check out the [CustomSource overview](./overview.mdx) to learn more about this concept. @@ -37,7 +35,6 @@ There are two main components to implement: The `FrameProcessorPlugin` and `CustomSource` work together to process and transmit video frames from the Vision Camera to the Fishjam SDK. Here's a clearer breakdown of their roles: 1. **FrameProcessorPlugin**: - - Extracts frames from the Vision Camera. - Processes each frame and prepares it for transmission. - Passes the processed frames to the `CustomSource`. @@ -106,7 +103,6 @@ public class WebrtcFrameProcessorPlugin: FrameProcessorPlugin { ``` 3. Register the FrameProcessorPlugin with Vision Camera: - - Follow the [official documentation on registering plugins](https://react-native-vision-camera.com/docs/guides/frame-processors-plugins-ios). 4. Register the CustomSource with Fishjam SDK to create a new track: @@ -166,7 +162,6 @@ class WebrtcFrameProcessorPlugin(proxy: VisionCameraProxy, options: Map +Welcome to the Fishjam documentation! + +Learn how to create live video and audio streaming applications with Fishjam, the all-in-one multimedia streaming toolkit. +To get started, we recommend you check out one of the two guides below: + +

+ +## Tutorials + +
+
+

+ Learning-oriented lessons that take you through a series of steps to + complete a project. Most useful when you want to get started with Fishjam. +

+ +
+ +
+ +## How-to Guides + +
+
+

+ Practical step-by-step guides to help you achieve a specific goal. Most + useful when you're trying to get something done. +

+ +
+ +
+ +## Explanation + +
+
+

+ Big-picture explanations of higher-level Fishjam concepts. Most useful for + building understanding of a particular topic. +

+ +
+ +
+ +## API Reference + +
+
+

+ Nitty-gritty technical descriptions of how Fishjam works. Most useful when + you need detailed information about Fishjam's APIs. +

+ +
+ +
+ +--- + +**Looking for live examples?** Check out our [Fishjam Chat demo](https://room.fishjam.io/) → diff --git a/docs/introduction.mdx b/docs/introduction.mdx deleted file mode 100644 index 1a4c131e..00000000 --- a/docs/introduction.mdx +++ /dev/null @@ -1,63 +0,0 @@ ---- -sidebar_position: 0 ---- - -import QuickNavigation from "@site/src/components/QuickNavigation"; -import { items } from "@site/src/content/cardItems"; - -# Introduction - -Welcome to the Fishjam documentation! -Here you will find everything you need to start building your multimedia streaming applications using Fishjam. - -## What is Fishjam? - -Fishjam is a multimedia streaming toolkit that allows you to build real-time video and audio streaming applications using [WebRTC](https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API). -We provide the infrastructure, media server, and client SDKs so you can focus on building your apps. - -**No WebRTC knowledge is required!** - -## How can I try it out? - -1. To get started with Fishjam, you need to create an account on our [developer panel](https://fishjam.io/app). -2. Once you have an account, Fishjam will assign you a Sandbox instance automatically. Sandbox instances come with [**Room Manager**](/room-manager.md) - a simple backend for creating test rooms. Copy the Room Manager URL from the developer panel. -3. Pick a client SDK that you want to use and follow the Quick Start guide. We provide SDKs for [React Native](/react-native/quick-setup.mdx) and [React](/react/installation.mdx). - - item.title.toLowerCase().includes("setup"))} -/> - -## Do you have any running examples? - -We are maintaining a simple video conferencing app called [Videoroom](https://room.fishjam.io/). -It is a publicly accessible app where you can see Fishjam in action. - -You can access it at [room.fishjam.io](https://room.fishjam.io/) - just pick a room name and peer name, and you can start a video call between any two devices. - -## Are there any examples I can run locally? - -Absolutely! You'll find ready-to-run examples in our GitHub repositories, typically located in the `examples` directory of each project. - -For both web and mobile, the easiest way to get started is with our minimal examples, simple applications that demonstrate video and audio streaming with Fishjam. Check out the code here: - -- [Minimal React Native](https://github.com/fishjam-cloud/mobile-client-sdk/tree/main/examples/minimal-react-native) -- [Minimal React](https://github.com/fishjam-cloud/web-client-sdk/tree/main/examples/react-client/minimal-react) - -## What does Fishjam consist of? - -Fishjam consists of several components that work together to provide a seamless multimedia streaming experience. -Below is a list of components that you will need to get started: - -| Component | Description | Link | -| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -| Developer panel | Developer panel for setting up your own Fishjam Media Server. | [fishjam.io/app](https://fishjam.io/app) | -| Fishjam Media Server | A media server that will route your multimedia traffic. We host and manage it for you. You can control it via the developer panel. | — | -| Fishjam Client SDKs | Toolkit used for multimedia integration on endpoint devices. | [React Native](/react-native/quick-setup.mdx), [React](/react/installation.mdx) | -| Fishjam Server SDKs | Toolkit for integrating your backend with Fishjam. We support Python and NodeJS as well as REST API. | [Python, NodeJS, and REST](/production/server.mdx) | -| Room Manager | Simple backend for creating test rooms. You no longer need to bring your own backend to develop frontend apps. | [Repository](https://github.com/fishjam-cloud/js-server-sdk/tree/main/examples/room-manager) | - -## How does it work? - -Streaming with Fishjam is simple. You create a room, add peers to it, and start streaming. Below is a high-level overview of how Fishjam works. - -![Fishjam Data Flow](@site/static/img/architecture.svg) diff --git a/docs/production/_category_.json b/docs/production/_category_.json deleted file mode 100644 index aae1c275..00000000 --- a/docs/production/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Going to production", - "position": 7, - "link": { - "type": "generated-index" - } -} diff --git a/docs/production/examples/_category_.json b/docs/production/examples/_category_.json deleted file mode 100644 index 37ad9f38..00000000 --- a/docs/production/examples/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Examples", - "position": 2, - "link": { - "type": "generated-index" - } -} diff --git a/docs/react-native/_category_.json b/docs/react-native/_category_.json deleted file mode 100644 index a33ed1fd..00000000 --- a/docs/react-native/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "React Native Integration", - "position": 3, - "link": { - "type": "generated-index", - "description": "How to integrate Fishjam into your React Native mobile app." - } -} diff --git a/docs/react-native/quick-setup.mdx b/docs/react-native/quick-setup.mdx deleted file mode 100644 index 7bdf9050..00000000 --- a/docs/react-native/quick-setup.mdx +++ /dev/null @@ -1,200 +0,0 @@ ---- -sidebar_position: 0 ---- - -import InstallPackage from "./_components/install-package.mdx"; -import ConfigurePermissions from "./_components/configure-permissions.mdx"; - -# Quick Setup - -This article is a fast track to integrate Fishjam into your React Native application. -It contains all the required steps to start streaming video with Fishjam. -You can also [see a minimal example](#minimal-example) at the end of the article. - -## Prerequisites - -In this part, let's focus on everything you need to prepare to use Fishjam in your project. - -### 1. Install the package - - - -### 2. Build native dependencies - -```bash -npx expo prebuild -``` - -### 3. Configure required app permissions - - - -### 4. Get Room Manager URL - -Log in to [Fishjam Dashboard](https://fishjam.io/app) and get your [Room Manager](/room-manager) URL. - -## Step-by-step instructions - -Now you are good to jump right into your IDE and integrate Fishjam into your app. -In a few simple steps, you will be able to implement a simple video call functionality. - -### 1. Fetch peer token - -Use your Room Manager URL to fetch a peer token to get a new room: - -```ts -const ROOM_MANAGER_ID = "..."; -const roomName = "room"; -const peerName = "user"; -// ---cut--- -const response = await fetch( - `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager/?roomName=${roomName}&peerName=${peerName}`, -); - -const { url, peerToken } = await response.json(); -``` - -### 2. Join Room and start streaming - -:::danger - -If you want to use the camera, you must first request permission. Check -[permission guide](/react-native/installation#step-2-configure-app-permissions) for more information. - -::: - -:::important - -Keep in mind that this won't work on the iOS Simulator, as the Simulator can't access the camera. - -::: - -To start streaming, you have to prepare your camera and join the room: - -```tsx -const ROOM_MANAGER_ID = "..."; -// ---cut--- -import React, { useCallback } from "react"; -import { Button } from "react-native"; -import { useCamera, useConnection } from "@fishjam-cloud/react-native-client"; - -export function StartStreamingButton({ - roomName, - peerName, -}: { - roomName: string; - peerName: string; -}) { - const { prepareCamera } = useCamera(); // [!code highlight] - const { joinRoom } = useConnection(); // [!code highlight] - - const startStreaming = useCallback(async () => { - const response = await fetch( - `https://fishjam.io/api/v1/connect/${ROOM_MANAGER_ID}/room-manager/?roomName=${roomName}&peerName=${peerName}`, - ); - const { url, peerToken } = await response.json(); - - await prepareCamera({ cameraEnabled: true }); // [!code highlight] - - await joinRoom({ url, peerToken }); // [!code highlight] - }, [joinRoom, prepareCamera, roomName, peerName]); - - return ; +} +``` + +## Step 3: Display other participants + +Show video from other peers: + +```tsx +import React from "react"; +import { useEffect, useRef } from "react"; +import { usePeers } from "@fishjam-cloud/react-client"; + +function VideoPlayer({ stream }: { stream: MediaStream | null | undefined }) { + const videoRef = useRef(null); + + useEffect(() => { + if (!videoRef.current) return; + videoRef.current.srcObject = stream ?? null; + }, [stream]); + + return