diff --git a/docs/explanation/moq-with-fishjam.mdx b/docs/explanation/moq-with-fishjam.mdx index 5a279ea7..41b6c3a5 100644 --- a/docs/explanation/moq-with-fishjam.mdx +++ b/docs/explanation/moq-with-fishjam.mdx @@ -98,42 +98,51 @@ Access to the relay is controlled by **MoQ tokens** — short-lived JWTs that ar | Publisher token | Write access to a specific path | Streamer | | Subscriber token | Read access to a path or namespace | Viewer | -A token is attached to the relay URL as a query parameter (`?jwt=`). The relay validates the token and enforces its scope before allowing any media to flow. +A token is attached to the relay URL as a query parameter (`?jwt=`). The relay validates the token and enforces its scope before allowing any media to flow. Both the Sandbox API and the Server SDK hand you the authenticated **connection URL** (the relay URL with the token already embedded), so the client can just take it as is and connect. Keeping publisher and subscriber tokens separate ensures that a viewer can never accidentally publish to the stream, and a publisher cannot subscribe to paths it does not own. -## Getting Tokens +## Where to get the Connection URL from? -There are two ways to obtain MoQ tokens, depending on where you are in the development lifecycle. +There are two ways to obtain a MoQ connection URL, depending on where you are in the development lifecycle. ### Sandbox API (prototyping) -The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues tokens without requiring you to build your own server, so you can start streaming immediately. +The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues connection URLs without requiring you to build your own server, so you can start streaming immediately. -To get a publisher token, call: +To get a publisher connection URL, call: ``` GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PUBLISHER-PATH}/publisher ``` -To get a subscriber token, call: +To get a subscriber connection URL, call: ``` GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{SUBSCRIBER-PATH}/subscriber ``` +To get a full-access connection URL — one that can both publish to and subscribe on the path — call: + +``` +GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PATH}/full-access +``` + +Each returns a JSON object with a `connection_url` field — the relay URL with the JWT embedded as `?jwt=` — alongside the raw `token`. + The Sandbox API is **not intended for production** — it has no authentication and is only available in the Sandbox environment. See [What is the Sandbox API?](./sandbox-api-concept) for more context. ### Fishjam Server SDK (production) -In production, your backend generates tokens using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe. +In production, your backend generates connection URLs using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe. -The SDK's `createMoqToken` method accepts either a `publishPath` or a `subscribePath`: +The SDK's `createMoqAccess` method accepts a `publishPath`, a `subscribePath`, or both, and returns the MoQ access details — a `connection_url` (the relay URL with the JWT embedded) alongside the raw `token`: -- `publishPath` — issues a publisher token scoped to that path. -- `subscribePath` — issues a subscriber token scoped to that path or namespace prefix. +- `publishPath` — returns a publisher connection URL scoped to that path. +- `subscribePath` — returns a subscriber connection URL scoped to that path or namespace prefix. +- both `publishPath` and `subscribePath` — returns a full-access connection URL that can publish and subscribe on those paths. -Your backend then delivers each token to the appropriate client (publisher or viewer), which uses it to connect to the relay. +Your backend then delivers each connection URL to the appropriate client (publisher or viewer), which uses it to connect to the relay. See the [Web Publishing](../tutorials/moq/web-publishing) and [Web Subscribing](../tutorials/moq/web-subscribing) tutorials (or their [React Native](../tutorials/moq/react-native-publishing) [counterparts](../tutorials/moq/react-native-subscribing)) for working code examples. diff --git a/docs/tutorials/moq/react-native-publishing.mdx b/docs/tutorials/moq/react-native-publishing.mdx index 2c00b181..a1616fc5 100644 --- a/docs/tutorials/moq/react-native-publishing.mdx +++ b/docs/tutorials/moq/react-native-publishing.mdx @@ -47,12 +47,12 @@ MoQ is a protocol with a well-defined negotiation, so a publisher and a subscrib If you don't have a backend server set up, you can prototype publishing using the [Sandbox API](../../explanation/sandbox-api-concept). -### Obtaining a publisher token +### Obtaining a publisher connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -64,17 +64,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-native-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqPublisherToken } = useSandbox({ + const { getSandboxMoqPublisherAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a publisher token scoped to the publisher path - const publishToken = await getSandboxMoqPublisherToken(PUBLISHER_PATH); + // Request a publisher connection URL scoped to the publisher path + const { connection_url: publishUrl } = await getSandboxMoqPublisherAccess(PUBLISHER_PATH); ``` @@ -85,14 +84,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${PUBLISHER_PATH}/publisher`, ); - const { token: publishToken } = await response.json(); + const { connection_url: publishUrl } = await response.json(); ``` @@ -102,7 +100,7 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do `react-native-moq` is hooks-based. You open a session against the relay, capture the camera and microphone, and hand them to a publisher. -Build the relay URL using the publisher token, open the session, and publish the camera + microphone tracks: +Open the session with the publisher connection URL, capture the camera and microphone, and publish the tracks: ```tsx // @noErrors @@ -116,16 +114,12 @@ import { useSession, } from "react-native-moq"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; -const publishToken = ""; // from the step above - -// Build the relay URL using the publisher token -const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${publishToken}`; +const publishUrl = ""; // from the step above function PublishScreen() { - // Open the MoQ session against the Fishjam relay - const session = useSession(relayUrl, (s) => s.connect()); + // Open the MoQ session against the Fishjam relay using the publisher connection URL + const session = useSession(publishUrl, (s) => s.connect()); const camera = useCamera({ position: "front" }); const microphone = useMicrophone(); const publisher = usePublisher(session); @@ -174,7 +168,7 @@ The session owns the connection to the relay; the publisher reuses it. Because p The [Quickstart](#quickstart-with-the-sandbox-api) gets you publishing quickly. In production, your backend generates tokens with proper authorization, so you control who can publish. -A **publisher token** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: +A **publisher connection URL** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: @@ -193,8 +187,8 @@ A **publisher token** grants write access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows publishing to 'stream-alice' - const { token: publishToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows publishing to 'stream-alice' + const { connection_url: publishUrl } = await fishjamClient.createMoqAccess({ publishPath: streamPath, }); ``` @@ -213,14 +207,14 @@ A **publisher token** grants write access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows publishing to 'stream-alice' - publish_token = fishjam_client.create_moq_token(publish_path=stream_path) + # Generate a connection URL that allows publishing to 'stream-alice' + publish_url = fishjam_client.create_moq_access(publish_path=stream_path).connection_url ``` -Deliver this token to the mobile client, then use it to build the relay URL and connect as described in [Connecting and publishing](#connecting-and-publishing). +Deliver this connection URL to the mobile client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing). ## See also diff --git a/docs/tutorials/moq/react-native-subscribing.mdx b/docs/tutorials/moq/react-native-subscribing.mdx index ee62f1e1..1ff9680e 100644 --- a/docs/tutorials/moq/react-native-subscribing.mdx +++ b/docs/tutorials/moq/react-native-subscribing.mdx @@ -55,12 +55,12 @@ If you don't have a backend server set up, you can prototype subscribing using t MoQ is a protocol with a well-defined negotiation, so a publisher and a subscriber don't need to use the same client library. A stream published from the browser with [`@moq/publish`](./web-publishing) can be watched with `react-native-moq`, and vice versa. ::: -### Obtaining a subscriber token +### Obtaining a subscriber connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -72,17 +72,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-native-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqSubscriberToken } = useSandbox({ + const { getSandboxMoqSubscriberAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a subscriber token scoped to the subscriber path - const subscribeToken = await getSandboxMoqSubscriberToken(SUBSCRIBER_PATH); + // Request a subscriber connection URL scoped to the subscriber path + const { connection_url: subscribeUrl } = await getSandboxMoqSubscriberAccess(SUBSCRIBER_PATH); ``` @@ -93,14 +92,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${SUBSCRIBER_PATH}/subscriber`, ); - const { token: subscribeToken } = await response.json(); + const { connection_url: subscribeUrl } = await response.json(); ``` @@ -121,16 +119,12 @@ import { } from "react-native-moq"; import type { BroadcastInfo } from "react-native-moq"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; -const subscribeToken = ""; // from the step above - -// Build the relay URL using the subscriber token -const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${subscribeToken}`; +const subscribeUrl = ""; // from the step above function WatchScreen() { - // Connect to the Fishjam MoQ relay on mount - const session = useSession(relayUrl, (s) => s.connect()); + // Connect to the Fishjam MoQ relay on mount using the subscriber connection URL + const session = useSession(subscribeUrl, (s) => s.connect()); // Discover broadcasts under the subscriber path const broadcasts = useBroadcasts(session, SUBSCRIBER_PATH); @@ -198,7 +192,7 @@ It exposes imperative `enterFullscreen()` / `exitFullscreen()` methods on its re The [Quickstart](#quickstart-with-the-sandbox-api) gets you watching quickly. In production, your backend generates tokens with proper authorization, so you control who can subscribe. -A **subscriber token** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: +A **subscriber connection URL** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: @@ -217,8 +211,8 @@ A **subscriber token** grants read access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows subscribing to 'stream-alice' - const { token: subscribeToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows subscribing to 'stream-alice' + const { connection_url: subscribeUrl } = await fishjamClient.createMoqAccess({ subscribePath: streamPath, }); ``` @@ -237,21 +231,21 @@ A **subscriber token** grants read access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows subscribing to 'stream-alice' - subscribe_token = fishjam_client.create_moq_token(subscribe_path=stream_path) + # Generate a connection URL that allows subscribing to 'stream-alice' + subscribe_url = fishjam_client.create_moq_access(subscribe_path=stream_path).connection_url ``` -Deliver this token to the mobile client, then use it to build the relay URL and connect as described in [Connecting and subscribing](#connecting-and-subscribing). +Deliver this connection URL to the mobile client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing). ### Subscribe to a namespace When multiple publishers join a room, you won't know their exact paths in advance. Instead of consuming a single path, you can **discover** all broadcasts published under a namespace prefix and subscribe to each one as they appear. -To do this, generate a subscriber token scoped to the room namespace instead of a single stream path. +To do this, generate a subscriber connection URL scoped to the room namespace instead of a single stream path. @@ -267,16 +261,16 @@ To do this, generate a subscriber token scoped to the room namespace instead of const roomName = 'my-room'; - const { token: alicePublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: alicePublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/alice", }); - const { token: bobPublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: bobPublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/bob", }); - const { token: namespaceToken } = await fishjamClient.createMoqToken({ + const { connection_url: namespaceUrl } = await fishjamClient.createMoqAccess({ subscribePath: roomName, }); ``` @@ -295,21 +289,21 @@ To do this, generate a subscriber token scoped to the room namespace instead of room_name = 'my-room' - alice_publisher_token = fishjam_client.create_moq_token( + alice_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/alice", - ) + ).connection_url - bob_publisher_token = fishjam_client.create_moq_token( + bob_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/bob", - ) + ).connection_url - namespace_token = fishjam_client.create_moq_token(subscribe_path=room_name) + namespace_url = fishjam_client.create_moq_access(subscribe_path=room_name).connection_url ``` -On the client, pass the namespace token's relay URL to `useSession`, then call `useBroadcasts(session, roomName)` with the room prefix. It returns a reactive `BroadcastInfo[]` that re-renders every time a publisher joins or leaves — no manual diffing of an announce set. Map over it to mount a player per broadcast: +On the client, pass the namespace connection URL to `useSession`, then call `useBroadcasts(session, roomName)` with the room prefix. It returns a reactive `BroadcastInfo[]` that re-renders every time a publisher joins or leaves — no manual diffing of an announce set. Map over it to mount a player per broadcast: ```tsx // @noErrors @@ -321,14 +315,11 @@ import { } from "react-native-moq"; import type { BroadcastInfo } from "react-native-moq"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const ROOM_NAME = "my-room"; -const namespaceToken = "token"; - -const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${namespaceToken}`; +const namespaceUrl = ""; function RoomGrid() { - const session = useSession(relayUrl, (s) => s.connect()); + const session = useSession(namespaceUrl, (s) => s.connect()); // Every broadcast published under the 'my-room' prefix, kept live const broadcasts = useBroadcasts(session, ROOM_NAME); diff --git a/docs/tutorials/moq/web-publishing.mdx b/docs/tutorials/moq/web-publishing.mdx index f55c0d3a..fba64604 100644 --- a/docs/tutorials/moq/web-publishing.mdx +++ b/docs/tutorials/moq/web-publishing.mdx @@ -16,7 +16,7 @@ This tutorial explains how to **publish** a live stream from the browser using [ If you're new to MoQ, then we recommend getting familiar with the [MoQ with Fishjam](../../explanation/moq-with-fishjam) explanation. ::: -To start publishing a MoQ stream, you need two things: a _publisher token_ and the relay URL. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). +To start publishing a MoQ stream, you need a _publisher connection URL_ — the relay URL with a publisher token embedded as a `?jwt=` query parameter. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). :::tip MoQ is a protocol with a well-defined negotiation, so in theory any compliant MoQ client should work. That said, we recommend using the `@moq` client libraries — the reference TypeScript implementation maintained alongside the protocol. For more details, see the [documentation](https://doc.moq.dev/lib/js/). @@ -26,12 +26,12 @@ MoQ is a protocol with a well-defined negotiation, so in theory any compliant Mo If you don't have a backend server set up, you can prototype publishing using the [Sandbox API](../../explanation/sandbox-api-concept). -### Obtaining a publisher token +### Obtaining a publisher connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -43,17 +43,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqPublisherToken } = useSandbox({ + const { getSandboxMoqPublisherAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a publisher token scoped to the publisher path - const publishToken = await getSandboxMoqPublisherToken(PUBLISHER_PATH); + // Request a publisher connection URL scoped to the publisher path + const { connection_url: publishUrl } = await getSandboxMoqPublisherAccess(PUBLISHER_PATH); ``` @@ -64,14 +63,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${PUBLISHER_PATH}/publisher`, ); - const { token: publishToken } = await response.json(); + const { connection_url: publishUrl } = await response.json(); ``` @@ -85,25 +83,19 @@ Install the MoQ packages: npm install @moq/lite @moq/publish ``` -Use the token to connect to the Fishjam MoQ relay and start broadcasting: +Use the connection URL to connect to the Fishjam MoQ relay and start broadcasting: ```ts // @noErrors import * as Moq from "@moq/lite"; import * as Publish from "@moq/publish"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; -const publishToken = ""; +const publishUrl = ""; // ---cut--- -// Build the relay URL using the publisher token -const relayUrl = new URL( - `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${publishToken}`, -); - -// Connect to the Fishjam MoQ relay -const connection = await Moq.Connection.connect(relayUrl); +// Connect to the Fishjam MoQ relay using the publisher connection URL +const connection = await Moq.Connection.connect(new URL(publishUrl)); const camera = new Publish.Source.Camera({ enabled: true }); const microphone = new Publish.Source.Microphone({ enabled: true }); @@ -130,7 +122,7 @@ The stream is now live on the MoQ relay! Viewers can now start watching it — f The [Quickstart](#quickstart-with-the-sandbox-api) gets you publishing quickly. In production, your backend generates tokens with proper authorization, so you control who can publish. -A **publisher token** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: +A **publisher connection URL** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: @@ -149,8 +141,8 @@ A **publisher token** grants write access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows publishing to 'stream-alice' - const { token: publishToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows publishing to 'stream-alice' + const { connection_url: publishUrl } = await fishjamClient.createMoqAccess({ publishPath: streamPath, }); ``` @@ -169,14 +161,14 @@ A **publisher token** grants write access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows publishing to 'stream-alice' - publish_token = fishjam_client.create_moq_token(publish_path=stream_path) + # Generate a connection URL that allows publishing to 'stream-alice' + publish_url = fishjam_client.create_moq_access(publish_path=stream_path).connection_url ``` -Deliver this token to the broadcasting client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing). +Deliver this connection URL to the broadcasting client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing). ## See also diff --git a/docs/tutorials/moq/web-subscribing.mdx b/docs/tutorials/moq/web-subscribing.mdx index 4e69cf83..d23620e2 100644 --- a/docs/tutorials/moq/web-subscribing.mdx +++ b/docs/tutorials/moq/web-subscribing.mdx @@ -16,7 +16,7 @@ This tutorial explains how to **subscribe** to a live stream and render it in th If you're new to MoQ, then we recommend getting familiar with the [MoQ with Fishjam](../../explanation/moq-with-fishjam) explanation. ::: -To receive a MoQ stream you need one thing: a _subscriber token_. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). +To receive a MoQ stream you need one thing: a _subscriber connection URL_ — the relay URL with a subscriber token embedded as a `?jwt=` query parameter. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). :::tip MoQ is a protocol with a well-defined negotiation, so in theory any compliant MoQ client should work. That said, we recommend using the [`@moq`](https://github.com/moq-dev/moq) client libraries — the reference TypeScript implementation maintained alongside the protocol. For more details, see the [documentation](https://doc.moq.dev/lib/js/). @@ -26,12 +26,12 @@ MoQ is a protocol with a well-defined negotiation, so in theory any compliant Mo If you don't have a backend server set up, you can prototype subscribing using the [Sandbox API](../../explanation/sandbox-api-concept). -### Obtaining a subscriber token +### Obtaining a subscriber connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -43,17 +43,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqSubscriberToken } = useSandbox({ + const { getSandboxMoqSubscriberAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a subscriber token scoped to the subscriber path - const subscribeToken = await getSandboxMoqSubscriberToken(SUBSCRIBER_PATH); + // Request a subscriber connection URL scoped to the subscriber path + const { connection_url: subscribeUrl } = await getSandboxMoqSubscriberAccess(SUBSCRIBER_PATH); ``` @@ -64,14 +63,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${SUBSCRIBER_PATH}/subscriber`, ); - const { token: subscribeToken } = await response.json(); + const { connection_url: subscribeUrl } = await response.json(); ``` @@ -91,25 +89,19 @@ Add a `` element to your page — `MultiBackend` will paint decoded fram ``` -Then use the token to connect and render the stream onto that canvas: +Then use the connection URL to connect and render the stream onto that canvas: ```ts // @noErrors import * as Moq from "@moq/lite"; import * as Watch from "@moq/watch"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; -const subscribeToken = ""; +const subscribeUrl = ""; // ---cut--- -// Build the relay URL using the subscriber token -const relayUrl = new URL( - `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${subscribeToken}`, -); - -// Connect to the Fishjam MoQ relay -const connection = await Moq.Connection.connect(relayUrl); +// Connect to the Fishjam MoQ relay using the subscriber connection URL +const connection = await Moq.Connection.connect(new URL(subscribeUrl)); // Subscribe to the broadcast const broadcast = new Watch.Broadcast({ @@ -146,7 +138,7 @@ import "@moq/watch/element"; import "@moq/watch/ui"; ``` -Then drop `` wrapping `` into your HTML — pass the relay URL (with the JWT token in the query string) and the broadcast path: +Then drop `` wrapping `` into your HTML — pass the connection URL (returned by the SDK or Sandbox API, with the JWT already in the query string) and the broadcast path: ```html @@ -167,7 +159,7 @@ The element observes attributes like `url`, `name`, `paused`, `muted`, `volume`, The [Quickstart](#quickstart-with-the-sandbox-api) gets you watching quickly. In production, your backend generates tokens with proper authorization, so you control who can subscribe. -A **subscriber token** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: +A **subscriber connection URL** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: @@ -186,8 +178,8 @@ A **subscriber token** grants read access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows subscribing to 'stream-alice' - const { token: subscribeToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows subscribing to 'stream-alice' + const { connection_url: subscribeUrl } = await fishjamClient.createMoqAccess({ subscribePath: streamPath, }); ``` @@ -206,21 +198,21 @@ A **subscriber token** grants read access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows subscribing to 'stream-alice' - subscribe_token = fishjam_client.create_moq_token(subscribe_path=stream_path) + # Generate a connection URL that allows subscribing to 'stream-alice' + subscribe_url = fishjam_client.create_moq_access(subscribe_path=stream_path).connection_url ``` -Deliver this token to the viewing client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing). +Deliver this connection URL to the viewing client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing). ### Subscribe to a namespace When multiple publishers join a room, you won't know their exact paths in advance. Instead of consuming a single path, you can **discover** all broadcasts published under a namespace prefix and subscribe to each one as they appear. -To do this, generate a subscriber token scoped to the room namespace instead of a single stream path. +To do this, generate a subscriber connection URL scoped to the room namespace instead of a single stream path. @@ -236,16 +228,16 @@ To do this, generate a subscriber token scoped to the room namespace instead of const roomName = 'my-room'; - const { token: alicePublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: alicePublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/alice", }); - const { token: bobPublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: bobPublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/bob", }); - const { token: namespaceToken } = await fishjamClient.createMoqToken({ + const { connection_url: namespaceUrl } = await fishjamClient.createMoqAccess({ subscribePath: roomName, }); ``` @@ -264,15 +256,15 @@ To do this, generate a subscriber token scoped to the room namespace instead of room_name = 'my-room' - alice_publisher_token = fishjam_client.create_moq_token( + alice_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/alice", - ) + ).connection_url - bob_publisher_token = fishjam_client.create_moq_token( + bob_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/bob", - ) + ).connection_url - namespace_token = fishjam_client.create_moq_token(subscribe_path=room_name) + namespace_url = fishjam_client.create_moq_access(subscribe_path=room_name).connection_url ``` @@ -286,16 +278,13 @@ import * as Moq from "@moq/lite"; import { Effect, Signal } from "@moq/signals"; import * as Watch from "@moq/watch"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; -const namespaceToken = "token"; +const namespaceUrl = ""; // ---cut--- // Reload manages the WebTransport session: it connects, auto-reconnects on drop, // and exposes `announced` as a reactive Set of publishers currently online. const connection = new Moq.Connection.Reload({ - url: new Signal( - new URL(`https://moq.fishjam.work/${FISHJAM_ID}?jwt=${namespaceToken}`), - ), + url: new Signal(new URL(namespaceUrl)), enabled: new Signal(true), }); diff --git a/packages/js-server-sdk b/packages/js-server-sdk index d70af8c6..0e8fe3e0 160000 --- a/packages/js-server-sdk +++ b/packages/js-server-sdk @@ -1 +1 @@ -Subproject commit d70af8c6517be3f35a70de3a0c4ad33de743db55 +Subproject commit 0e8fe3e0eb13127bade0b761ca254aed03cb2c46 diff --git a/packages/python-server-sdk b/packages/python-server-sdk index ef11da89..fdd55700 160000 --- a/packages/python-server-sdk +++ b/packages/python-server-sdk @@ -1 +1 @@ -Subproject commit ef11da8909a9c33d0156ffb0532f5827a5e23a96 +Subproject commit fdd5570033f84a4e8f49bf2ac7fedc019b5b99df diff --git a/packages/web-client-sdk b/packages/web-client-sdk index 29d7e58d..ceda88fa 160000 --- a/packages/web-client-sdk +++ b/packages/web-client-sdk @@ -1 +1 @@ -Subproject commit 29d7e58d0e8147d691a9a39b74b9b4529ab32c98 +Subproject commit ceda88fac251ac2189bd63cb47161985f1801e67 diff --git a/versioned_docs/version-0.28.0/explanation/moq-with-fishjam.mdx b/versioned_docs/version-0.28.0/explanation/moq-with-fishjam.mdx index 5a279ea7..41b6c3a5 100644 --- a/versioned_docs/version-0.28.0/explanation/moq-with-fishjam.mdx +++ b/versioned_docs/version-0.28.0/explanation/moq-with-fishjam.mdx @@ -98,42 +98,51 @@ Access to the relay is controlled by **MoQ tokens** — short-lived JWTs that ar | Publisher token | Write access to a specific path | Streamer | | Subscriber token | Read access to a path or namespace | Viewer | -A token is attached to the relay URL as a query parameter (`?jwt=`). The relay validates the token and enforces its scope before allowing any media to flow. +A token is attached to the relay URL as a query parameter (`?jwt=`). The relay validates the token and enforces its scope before allowing any media to flow. Both the Sandbox API and the Server SDK hand you the authenticated **connection URL** (the relay URL with the token already embedded), so the client can just take it as is and connect. Keeping publisher and subscriber tokens separate ensures that a viewer can never accidentally publish to the stream, and a publisher cannot subscribe to paths it does not own. -## Getting Tokens +## Where to get the Connection URL from? -There are two ways to obtain MoQ tokens, depending on where you are in the development lifecycle. +There are two ways to obtain a MoQ connection URL, depending on where you are in the development lifecycle. ### Sandbox API (prototyping) -The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues tokens without requiring you to build your own server, so you can start streaming immediately. +The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues connection URLs without requiring you to build your own server, so you can start streaming immediately. -To get a publisher token, call: +To get a publisher connection URL, call: ``` GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PUBLISHER-PATH}/publisher ``` -To get a subscriber token, call: +To get a subscriber connection URL, call: ``` GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{SUBSCRIBER-PATH}/subscriber ``` +To get a full-access connection URL — one that can both publish to and subscribe on the path — call: + +``` +GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PATH}/full-access +``` + +Each returns a JSON object with a `connection_url` field — the relay URL with the JWT embedded as `?jwt=` — alongside the raw `token`. + The Sandbox API is **not intended for production** — it has no authentication and is only available in the Sandbox environment. See [What is the Sandbox API?](./sandbox-api-concept) for more context. ### Fishjam Server SDK (production) -In production, your backend generates tokens using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe. +In production, your backend generates connection URLs using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe. -The SDK's `createMoqToken` method accepts either a `publishPath` or a `subscribePath`: +The SDK's `createMoqAccess` method accepts a `publishPath`, a `subscribePath`, or both, and returns the MoQ access details — a `connection_url` (the relay URL with the JWT embedded) alongside the raw `token`: -- `publishPath` — issues a publisher token scoped to that path. -- `subscribePath` — issues a subscriber token scoped to that path or namespace prefix. +- `publishPath` — returns a publisher connection URL scoped to that path. +- `subscribePath` — returns a subscriber connection URL scoped to that path or namespace prefix. +- both `publishPath` and `subscribePath` — returns a full-access connection URL that can publish and subscribe on those paths. -Your backend then delivers each token to the appropriate client (publisher or viewer), which uses it to connect to the relay. +Your backend then delivers each connection URL to the appropriate client (publisher or viewer), which uses it to connect to the relay. See the [Web Publishing](../tutorials/moq/web-publishing) and [Web Subscribing](../tutorials/moq/web-subscribing) tutorials (or their [React Native](../tutorials/moq/react-native-publishing) [counterparts](../tutorials/moq/react-native-subscribing)) for working code examples. diff --git a/versioned_docs/version-0.28.0/tutorials/moq/react-native-publishing.mdx b/versioned_docs/version-0.28.0/tutorials/moq/react-native-publishing.mdx index 2c00b181..a1616fc5 100644 --- a/versioned_docs/version-0.28.0/tutorials/moq/react-native-publishing.mdx +++ b/versioned_docs/version-0.28.0/tutorials/moq/react-native-publishing.mdx @@ -47,12 +47,12 @@ MoQ is a protocol with a well-defined negotiation, so a publisher and a subscrib If you don't have a backend server set up, you can prototype publishing using the [Sandbox API](../../explanation/sandbox-api-concept). -### Obtaining a publisher token +### Obtaining a publisher connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -64,17 +64,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-native-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqPublisherToken } = useSandbox({ + const { getSandboxMoqPublisherAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a publisher token scoped to the publisher path - const publishToken = await getSandboxMoqPublisherToken(PUBLISHER_PATH); + // Request a publisher connection URL scoped to the publisher path + const { connection_url: publishUrl } = await getSandboxMoqPublisherAccess(PUBLISHER_PATH); ``` @@ -85,14 +84,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${PUBLISHER_PATH}/publisher`, ); - const { token: publishToken } = await response.json(); + const { connection_url: publishUrl } = await response.json(); ``` @@ -102,7 +100,7 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do `react-native-moq` is hooks-based. You open a session against the relay, capture the camera and microphone, and hand them to a publisher. -Build the relay URL using the publisher token, open the session, and publish the camera + microphone tracks: +Open the session with the publisher connection URL, capture the camera and microphone, and publish the tracks: ```tsx // @noErrors @@ -116,16 +114,12 @@ import { useSession, } from "react-native-moq"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; -const publishToken = ""; // from the step above - -// Build the relay URL using the publisher token -const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${publishToken}`; +const publishUrl = ""; // from the step above function PublishScreen() { - // Open the MoQ session against the Fishjam relay - const session = useSession(relayUrl, (s) => s.connect()); + // Open the MoQ session against the Fishjam relay using the publisher connection URL + const session = useSession(publishUrl, (s) => s.connect()); const camera = useCamera({ position: "front" }); const microphone = useMicrophone(); const publisher = usePublisher(session); @@ -174,7 +168,7 @@ The session owns the connection to the relay; the publisher reuses it. Because p The [Quickstart](#quickstart-with-the-sandbox-api) gets you publishing quickly. In production, your backend generates tokens with proper authorization, so you control who can publish. -A **publisher token** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: +A **publisher connection URL** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: @@ -193,8 +187,8 @@ A **publisher token** grants write access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows publishing to 'stream-alice' - const { token: publishToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows publishing to 'stream-alice' + const { connection_url: publishUrl } = await fishjamClient.createMoqAccess({ publishPath: streamPath, }); ``` @@ -213,14 +207,14 @@ A **publisher token** grants write access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows publishing to 'stream-alice' - publish_token = fishjam_client.create_moq_token(publish_path=stream_path) + # Generate a connection URL that allows publishing to 'stream-alice' + publish_url = fishjam_client.create_moq_access(publish_path=stream_path).connection_url ``` -Deliver this token to the mobile client, then use it to build the relay URL and connect as described in [Connecting and publishing](#connecting-and-publishing). +Deliver this connection URL to the mobile client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing). ## See also diff --git a/versioned_docs/version-0.28.0/tutorials/moq/react-native-subscribing.mdx b/versioned_docs/version-0.28.0/tutorials/moq/react-native-subscribing.mdx index ee62f1e1..1ff9680e 100644 --- a/versioned_docs/version-0.28.0/tutorials/moq/react-native-subscribing.mdx +++ b/versioned_docs/version-0.28.0/tutorials/moq/react-native-subscribing.mdx @@ -55,12 +55,12 @@ If you don't have a backend server set up, you can prototype subscribing using t MoQ is a protocol with a well-defined negotiation, so a publisher and a subscriber don't need to use the same client library. A stream published from the browser with [`@moq/publish`](./web-publishing) can be watched with `react-native-moq`, and vice versa. ::: -### Obtaining a subscriber token +### Obtaining a subscriber connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -72,17 +72,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-native-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqSubscriberToken } = useSandbox({ + const { getSandboxMoqSubscriberAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a subscriber token scoped to the subscriber path - const subscribeToken = await getSandboxMoqSubscriberToken(SUBSCRIBER_PATH); + // Request a subscriber connection URL scoped to the subscriber path + const { connection_url: subscribeUrl } = await getSandboxMoqSubscriberAccess(SUBSCRIBER_PATH); ``` @@ -93,14 +92,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${SUBSCRIBER_PATH}/subscriber`, ); - const { token: subscribeToken } = await response.json(); + const { connection_url: subscribeUrl } = await response.json(); ``` @@ -121,16 +119,12 @@ import { } from "react-native-moq"; import type { BroadcastInfo } from "react-native-moq"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; -const subscribeToken = ""; // from the step above - -// Build the relay URL using the subscriber token -const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${subscribeToken}`; +const subscribeUrl = ""; // from the step above function WatchScreen() { - // Connect to the Fishjam MoQ relay on mount - const session = useSession(relayUrl, (s) => s.connect()); + // Connect to the Fishjam MoQ relay on mount using the subscriber connection URL + const session = useSession(subscribeUrl, (s) => s.connect()); // Discover broadcasts under the subscriber path const broadcasts = useBroadcasts(session, SUBSCRIBER_PATH); @@ -198,7 +192,7 @@ It exposes imperative `enterFullscreen()` / `exitFullscreen()` methods on its re The [Quickstart](#quickstart-with-the-sandbox-api) gets you watching quickly. In production, your backend generates tokens with proper authorization, so you control who can subscribe. -A **subscriber token** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: +A **subscriber connection URL** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: @@ -217,8 +211,8 @@ A **subscriber token** grants read access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows subscribing to 'stream-alice' - const { token: subscribeToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows subscribing to 'stream-alice' + const { connection_url: subscribeUrl } = await fishjamClient.createMoqAccess({ subscribePath: streamPath, }); ``` @@ -237,21 +231,21 @@ A **subscriber token** grants read access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows subscribing to 'stream-alice' - subscribe_token = fishjam_client.create_moq_token(subscribe_path=stream_path) + # Generate a connection URL that allows subscribing to 'stream-alice' + subscribe_url = fishjam_client.create_moq_access(subscribe_path=stream_path).connection_url ``` -Deliver this token to the mobile client, then use it to build the relay URL and connect as described in [Connecting and subscribing](#connecting-and-subscribing). +Deliver this connection URL to the mobile client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing). ### Subscribe to a namespace When multiple publishers join a room, you won't know their exact paths in advance. Instead of consuming a single path, you can **discover** all broadcasts published under a namespace prefix and subscribe to each one as they appear. -To do this, generate a subscriber token scoped to the room namespace instead of a single stream path. +To do this, generate a subscriber connection URL scoped to the room namespace instead of a single stream path. @@ -267,16 +261,16 @@ To do this, generate a subscriber token scoped to the room namespace instead of const roomName = 'my-room'; - const { token: alicePublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: alicePublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/alice", }); - const { token: bobPublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: bobPublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/bob", }); - const { token: namespaceToken } = await fishjamClient.createMoqToken({ + const { connection_url: namespaceUrl } = await fishjamClient.createMoqAccess({ subscribePath: roomName, }); ``` @@ -295,21 +289,21 @@ To do this, generate a subscriber token scoped to the room namespace instead of room_name = 'my-room' - alice_publisher_token = fishjam_client.create_moq_token( + alice_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/alice", - ) + ).connection_url - bob_publisher_token = fishjam_client.create_moq_token( + bob_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/bob", - ) + ).connection_url - namespace_token = fishjam_client.create_moq_token(subscribe_path=room_name) + namespace_url = fishjam_client.create_moq_access(subscribe_path=room_name).connection_url ``` -On the client, pass the namespace token's relay URL to `useSession`, then call `useBroadcasts(session, roomName)` with the room prefix. It returns a reactive `BroadcastInfo[]` that re-renders every time a publisher joins or leaves — no manual diffing of an announce set. Map over it to mount a player per broadcast: +On the client, pass the namespace connection URL to `useSession`, then call `useBroadcasts(session, roomName)` with the room prefix. It returns a reactive `BroadcastInfo[]` that re-renders every time a publisher joins or leaves — no manual diffing of an announce set. Map over it to mount a player per broadcast: ```tsx // @noErrors @@ -321,14 +315,11 @@ import { } from "react-native-moq"; import type { BroadcastInfo } from "react-native-moq"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const ROOM_NAME = "my-room"; -const namespaceToken = "token"; - -const relayUrl = `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${namespaceToken}`; +const namespaceUrl = ""; function RoomGrid() { - const session = useSession(relayUrl, (s) => s.connect()); + const session = useSession(namespaceUrl, (s) => s.connect()); // Every broadcast published under the 'my-room' prefix, kept live const broadcasts = useBroadcasts(session, ROOM_NAME); diff --git a/versioned_docs/version-0.28.0/tutorials/moq/web-publishing.mdx b/versioned_docs/version-0.28.0/tutorials/moq/web-publishing.mdx index f55c0d3a..fba64604 100644 --- a/versioned_docs/version-0.28.0/tutorials/moq/web-publishing.mdx +++ b/versioned_docs/version-0.28.0/tutorials/moq/web-publishing.mdx @@ -16,7 +16,7 @@ This tutorial explains how to **publish** a live stream from the browser using [ If you're new to MoQ, then we recommend getting familiar with the [MoQ with Fishjam](../../explanation/moq-with-fishjam) explanation. ::: -To start publishing a MoQ stream, you need two things: a _publisher token_ and the relay URL. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). +To start publishing a MoQ stream, you need a _publisher connection URL_ — the relay URL with a publisher token embedded as a `?jwt=` query parameter. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). :::tip MoQ is a protocol with a well-defined negotiation, so in theory any compliant MoQ client should work. That said, we recommend using the `@moq` client libraries — the reference TypeScript implementation maintained alongside the protocol. For more details, see the [documentation](https://doc.moq.dev/lib/js/). @@ -26,12 +26,12 @@ MoQ is a protocol with a well-defined negotiation, so in theory any compliant Mo If you don't have a backend server set up, you can prototype publishing using the [Sandbox API](../../explanation/sandbox-api-concept). -### Obtaining a publisher token +### Obtaining a publisher connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -43,17 +43,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqPublisherToken } = useSandbox({ + const { getSandboxMoqPublisherAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a publisher token scoped to the publisher path - const publishToken = await getSandboxMoqPublisherToken(PUBLISHER_PATH); + // Request a publisher connection URL scoped to the publisher path + const { connection_url: publishUrl } = await getSandboxMoqPublisherAccess(PUBLISHER_PATH); ``` @@ -64,14 +63,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${PUBLISHER_PATH}/publisher`, ); - const { token: publishToken } = await response.json(); + const { connection_url: publishUrl } = await response.json(); ``` @@ -85,25 +83,19 @@ Install the MoQ packages: npm install @moq/lite @moq/publish ``` -Use the token to connect to the Fishjam MoQ relay and start broadcasting: +Use the connection URL to connect to the Fishjam MoQ relay and start broadcasting: ```ts // @noErrors import * as Moq from "@moq/lite"; import * as Publish from "@moq/publish"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const PUBLISHER_PATH = "stream-alice"; -const publishToken = ""; +const publishUrl = ""; // ---cut--- -// Build the relay URL using the publisher token -const relayUrl = new URL( - `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${publishToken}`, -); - -// Connect to the Fishjam MoQ relay -const connection = await Moq.Connection.connect(relayUrl); +// Connect to the Fishjam MoQ relay using the publisher connection URL +const connection = await Moq.Connection.connect(new URL(publishUrl)); const camera = new Publish.Source.Camera({ enabled: true }); const microphone = new Publish.Source.Microphone({ enabled: true }); @@ -130,7 +122,7 @@ The stream is now live on the MoQ relay! Viewers can now start watching it — f The [Quickstart](#quickstart-with-the-sandbox-api) gets you publishing quickly. In production, your backend generates tokens with proper authorization, so you control who can publish. -A **publisher token** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: +A **publisher connection URL** grants write access to a specific path. Generate one on your backend and deliver it to the broadcasting client: @@ -149,8 +141,8 @@ A **publisher token** grants write access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows publishing to 'stream-alice' - const { token: publishToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows publishing to 'stream-alice' + const { connection_url: publishUrl } = await fishjamClient.createMoqAccess({ publishPath: streamPath, }); ``` @@ -169,14 +161,14 @@ A **publisher token** grants write access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows publishing to 'stream-alice' - publish_token = fishjam_client.create_moq_token(publish_path=stream_path) + # Generate a connection URL that allows publishing to 'stream-alice' + publish_url = fishjam_client.create_moq_access(publish_path=stream_path).connection_url ``` -Deliver this token to the broadcasting client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing). +Deliver this connection URL to the broadcasting client, then use it to connect as described in [Connecting and publishing](#connecting-and-publishing). ## See also diff --git a/versioned_docs/version-0.28.0/tutorials/moq/web-subscribing.mdx b/versioned_docs/version-0.28.0/tutorials/moq/web-subscribing.mdx index 4e69cf83..d23620e2 100644 --- a/versioned_docs/version-0.28.0/tutorials/moq/web-subscribing.mdx +++ b/versioned_docs/version-0.28.0/tutorials/moq/web-subscribing.mdx @@ -16,7 +16,7 @@ This tutorial explains how to **subscribe** to a live stream and render it in th If you're new to MoQ, then we recommend getting familiar with the [MoQ with Fishjam](../../explanation/moq-with-fishjam) explanation. ::: -To receive a MoQ stream you need one thing: a _subscriber token_. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). +To receive a MoQ stream you need one thing: a _subscriber connection URL_ — the relay URL with a subscriber token embedded as a `?jwt=` query parameter. We show how to quickly prototype with the [Sandbox API](#quickstart-with-the-sandbox-api) and how to get ready for [production](#production-with-server-sdks). :::tip MoQ is a protocol with a well-defined negotiation, so in theory any compliant MoQ client should work. That said, we recommend using the [`@moq`](https://github.com/moq-dev/moq) client libraries — the reference TypeScript implementation maintained alongside the protocol. For more details, see the [documentation](https://doc.moq.dev/lib/js/). @@ -26,12 +26,12 @@ MoQ is a protocol with a well-defined negotiation, so in theory any compliant Mo If you don't have a backend server set up, you can prototype subscribing using the [Sandbox API](../../explanation/sandbox-api-concept). -### Obtaining a subscriber token +### Obtaining a subscriber connection URL For more on what the Sandbox API is and its limitations, see [What is the Sandbox API?](../../explanation/sandbox-api-concept). :::info -To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you don't have them already, see [Sandbox API URL and Fishjam ID](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). +To obtain a MoQ connection URL you'll need your Sandbox API URL. If you don't have it already, see [Sandbox API URL](../../explanation/sandbox-api-concept#sandbox-api-url-and-fishjam-id). ::: @@ -43,17 +43,16 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do // @noErrors import { useSandbox } from "@fishjam-cloud/react-client"; - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; // Inside a React component: - const { getSandboxMoqSubscriberToken } = useSandbox({ + const { getSandboxMoqSubscriberAccess } = useSandbox({ sandboxApiUrl: SANDBOX_API_URL, }); - // Request a subscriber token scoped to the subscriber path - const subscribeToken = await getSandboxMoqSubscriberToken(SUBSCRIBER_PATH); + // Request a subscriber connection URL scoped to the subscriber path + const { connection_url: subscribeUrl } = await getSandboxMoqSubscriberAccess(SUBSCRIBER_PATH); ``` @@ -64,14 +63,13 @@ To obtain a MoQ token you'll need your Fishjam ID and Sandbox API URL. If you do ```ts // @noErrors - const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; const SANDBOX_API_URL = "YOUR_SANDBOX_API_URL"; const response = await fetch( `${SANDBOX_API_URL}/moq/${SUBSCRIBER_PATH}/subscriber`, ); - const { token: subscribeToken } = await response.json(); + const { connection_url: subscribeUrl } = await response.json(); ``` @@ -91,25 +89,19 @@ Add a `` element to your page — `MultiBackend` will paint decoded fram ``` -Then use the token to connect and render the stream onto that canvas: +Then use the connection URL to connect and render the stream onto that canvas: ```ts // @noErrors import * as Moq from "@moq/lite"; import * as Watch from "@moq/watch"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; const SUBSCRIBER_PATH = "stream-alice"; -const subscribeToken = ""; +const subscribeUrl = ""; // ---cut--- -// Build the relay URL using the subscriber token -const relayUrl = new URL( - `https://relay.fishjam.io/${FISHJAM_ID}?jwt=${subscribeToken}`, -); - -// Connect to the Fishjam MoQ relay -const connection = await Moq.Connection.connect(relayUrl); +// Connect to the Fishjam MoQ relay using the subscriber connection URL +const connection = await Moq.Connection.connect(new URL(subscribeUrl)); // Subscribe to the broadcast const broadcast = new Watch.Broadcast({ @@ -146,7 +138,7 @@ import "@moq/watch/element"; import "@moq/watch/ui"; ``` -Then drop `` wrapping `` into your HTML — pass the relay URL (with the JWT token in the query string) and the broadcast path: +Then drop `` wrapping `` into your HTML — pass the connection URL (returned by the SDK or Sandbox API, with the JWT already in the query string) and the broadcast path: ```html @@ -167,7 +159,7 @@ The element observes attributes like `url`, `name`, `paused`, `muted`, `volume`, The [Quickstart](#quickstart-with-the-sandbox-api) gets you watching quickly. In production, your backend generates tokens with proper authorization, so you control who can subscribe. -A **subscriber token** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: +A **subscriber connection URL** grants read access to a specific path. Generate one on your backend and deliver it to the viewing client: @@ -186,8 +178,8 @@ A **subscriber token** grants read access to a specific path. Generate one on yo const streamPath = 'stream-alice'; - // Generate a token that allows subscribing to 'stream-alice' - const { token: subscribeToken } = await fishjamClient.createMoqToken({ + // Generate a connection URL that allows subscribing to 'stream-alice' + const { connection_url: subscribeUrl } = await fishjamClient.createMoqAccess({ subscribePath: streamPath, }); ``` @@ -206,21 +198,21 @@ A **subscriber token** grants read access to a specific path. Generate one on yo stream_path = 'stream-alice' - # Generate a token that allows subscribing to 'stream-alice' - subscribe_token = fishjam_client.create_moq_token(subscribe_path=stream_path) + # Generate a connection URL that allows subscribing to 'stream-alice' + subscribe_url = fishjam_client.create_moq_access(subscribe_path=stream_path).connection_url ``` -Deliver this token to the viewing client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing). +Deliver this connection URL to the viewing client, then use it to connect as described in [Connecting and subscribing](#connecting-and-subscribing). ### Subscribe to a namespace When multiple publishers join a room, you won't know their exact paths in advance. Instead of consuming a single path, you can **discover** all broadcasts published under a namespace prefix and subscribe to each one as they appear. -To do this, generate a subscriber token scoped to the room namespace instead of a single stream path. +To do this, generate a subscriber connection URL scoped to the room namespace instead of a single stream path. @@ -236,16 +228,16 @@ To do this, generate a subscriber token scoped to the room namespace instead of const roomName = 'my-room'; - const { token: alicePublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: alicePublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/alice", }); - const { token: bobPublisherToken } = await fishjamClient.createMoqToken({ + const { connection_url: bobPublisherUrl } = await fishjamClient.createMoqAccess({ publishPath: roomName + "/bob", }); - const { token: namespaceToken } = await fishjamClient.createMoqToken({ + const { connection_url: namespaceUrl } = await fishjamClient.createMoqAccess({ subscribePath: roomName, }); ``` @@ -264,15 +256,15 @@ To do this, generate a subscriber token scoped to the room namespace instead of room_name = 'my-room' - alice_publisher_token = fishjam_client.create_moq_token( + alice_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/alice", - ) + ).connection_url - bob_publisher_token = fishjam_client.create_moq_token( + bob_publisher_url = fishjam_client.create_moq_access( publish_path=room_name + "/bob", - ) + ).connection_url - namespace_token = fishjam_client.create_moq_token(subscribe_path=room_name) + namespace_url = fishjam_client.create_moq_access(subscribe_path=room_name).connection_url ``` @@ -286,16 +278,13 @@ import * as Moq from "@moq/lite"; import { Effect, Signal } from "@moq/signals"; import * as Watch from "@moq/watch"; -const FISHJAM_ID = "YOUR_FISHJAM_ID"; -const namespaceToken = "token"; +const namespaceUrl = ""; // ---cut--- // Reload manages the WebTransport session: it connects, auto-reconnects on drop, // and exposes `announced` as a reactive Set of publishers currently online. const connection = new Moq.Connection.Reload({ - url: new Signal( - new URL(`https://moq.fishjam.work/${FISHJAM_ID}?jwt=${namespaceToken}`), - ), + url: new Signal(new URL(namespaceUrl)), enabled: new Signal(true), });