diff --git a/docs/explanation/moq-streaming.mdx b/docs/explanation/moq-with-fishjam.mdx similarity index 87% rename from docs/explanation/moq-streaming.mdx rename to docs/explanation/moq-with-fishjam.mdx index 18133b80..5a279ea7 100644 --- a/docs/explanation/moq-streaming.mdx +++ b/docs/explanation/moq-with-fishjam.mdx @@ -1,14 +1,20 @@ --- type: explanation -sidebar_position: 6 -title: Media over QUIC (MoQ) +sidebar_position: 9 +title: Media over QUIC in Fishjam description: Understand how Media over QUIC (MoQ) works in Fishjam — the relay model, publish/subscribe architecture, paths, and token-based access control. --- -# MoQ Streaming with Fishjam +# Media over QUIC in Fishjam _How Media over QUIC (MoQ) works in Fishjam_ +:::warning[MoQ is a standalone feature] +MoQ runs as a **separate delivery path** in Fishjam — it handles publishing and subscribing to a live broadcast over the MoQ relay, and the rest of Fishjam's feature set does not apply to a MoQ stream. In particular, a MoQ broadcast is not part of a WebRTC [room](./rooms), so you cannot use features like [Agents](../tutorials/agents), [data channels](./data-channels), and others that are part of the Fishjam WebRTC ecosystem. + +What MoQ supports is covered end to end in the [MoQ tutorials](../tutorials/moq/web-publishing). +::: + ## What is MoQ? [Media over QUIC (MoQ)](https://datatracker.ietf.org/wg/moq/about/) is a new internet standard for live media delivery, designed from the ground up for **scalable, low-latency streaming to large audiences**. @@ -129,11 +135,11 @@ The SDK's `createMoqToken` method accepts either a `publishPath` or a `subscribe Your backend then delivers each token to the appropriate client (publisher or viewer), which uses it to connect to the relay. -See the [MoQ Streaming tutorial](../tutorials/moq) for working code examples of both approaches. +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. ## See also -- [MoQ Streaming tutorial](../tutorials/moq) — step-by-step guide to publishing and subscribing +- [Web Publishing](../tutorials/moq/web-publishing) / [Web Subscribing](../tutorials/moq/web-subscribing) — step-by-step guides to publishing and subscribing - [What is the Sandbox API?](./sandbox-api-concept) — when and why to use the Sandbox API - [Security & Token Model](./security-tokens) — broader overview of Fishjam's token system - [Livestreams](./livestreams) — WebRTC-based livestreaming with WHIP/WHEP diff --git a/docs/tutorials/moq/_category_.json b/docs/tutorials/moq/_category_.json new file mode 100644 index 00000000..87f92e9c --- /dev/null +++ b/docs/tutorials/moq/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Media over QUIC (MoQ)", + "position": 5, + "collapsed": false, + "link": { + "type": "doc", + "id": "tutorials/moq/index" + } +} diff --git a/docs/tutorials/moq/index.mdx b/docs/tutorials/moq/index.mdx new file mode 100644 index 00000000..2308eb6a --- /dev/null +++ b/docs/tutorials/moq/index.mdx @@ -0,0 +1,17 @@ +--- +type: tutorial +title: Media over QUIC (MoQ) +description: Step-by-step guides for publishing and subscribing to live broadcasts over Media over QUIC (MoQ) with Fishjam, on both web and React Native. +--- + +import DocCardList from "@theme/DocCardList"; + +# Media over QUIC (MoQ) + +Step-by-step guides for publishing and subscribing to live broadcasts over [Media over QUIC (MoQ)](https://datatracker.ietf.org/wg/moq/about/) with Fishjam. For the big-picture overview of how MoQ fits into Fishjam, see [Media over QUIC in Fishjam](../../explanation/moq-with-fishjam.mdx). + +:::warning[MoQ is a standalone feature] +MoQ runs as a **separate delivery path** in Fishjam — it handles publishing and subscribing to a live broadcast over the MoQ relay, and the rest of Fishjam's feature set does not apply to a MoQ stream. In particular, a MoQ broadcast is not part of a WebRTC [room](../../explanation/rooms.mdx), so you cannot use features like [Agents](../agents.mdx), [data channels](../../explanation/data-channels.mdx), and others that are part of the Fishjam WebRTC ecosystem. +::: + + diff --git a/docs/tutorials/moq/react-native-publishing.mdx b/docs/tutorials/moq/react-native-publishing.mdx new file mode 100644 index 00000000..2c00b181 --- /dev/null +++ b/docs/tutorials/moq/react-native-publishing.mdx @@ -0,0 +1,230 @@ +--- +type: tutorial +sidebar_position: 3 +title: React Native Publishing +description: Publish a live video and audio broadcast over Media over QUIC (MoQ) from a React Native mobile app with Fishjam, from sandbox prototyping to production. +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# React Native Publishing + +This tutorial explains how to **publish** a live stream from a **React Native mobile app** using [Media over QUIC (MoQ)](https://datatracker.ietf.org/wg/moq/about/) with Fishjam. To watch a stream instead, see [React Native Subscribing](./react-native-subscribing). + +It uses [`react-native-moq`](https://github.com/software-mansion-labs/react-native-moq) — React Native bindings for MoQKit, with a small, reactive hooks-based API. For the web equivalent, see [Web Publishing](./web-publishing). + +:::info +If you're new to MoQ, then we recommend getting familiar with the [MoQ with Fishjam](../../explanation/moq-with-fishjam) explanation. +::: + +## Requirements + +`react-native-moq` targets the React Native **New Architecture** (Fabric / TurboModules): + +- iOS 16+ +- Android API 30+ + +## Installation + +```bash npm2yarn +npm install react-native-moq +``` + +Then install the iOS pods: + +```sh +cd ios && pod install +``` + +Publishing captures the camera and microphone, so the host app is responsible for runtime permissions: request `CAMERA` / `RECORD_AUDIO` on Android, and add `NSCameraUsageDescription` / `NSMicrophoneUsageDescription` to `Info.plist` on iOS. The library does not request these for you. + +:::tip +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 React Native app published with `react-native-moq` can be watched in the browser with [`@moq/watch`](./web-subscribing#connecting-and-subscribing), and vice versa. +::: + +## Quickstart with the Sandbox API + +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 + +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). +::: + + + + + The `useSandbox` hook from `@fishjam-cloud/react-native-client` wraps the Sandbox API request for you: + + ```tsx + // @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({ + sandboxApiUrl: SANDBOX_API_URL, + }); + + // Request a publisher token scoped to the publisher path + const publishToken = await getSandboxMoqPublisherToken(PUBLISHER_PATH); + ``` + + + + + + If you don't want to pull in the whole client library just for the `useSandbox` hook, you can call the Sandbox API directly with `fetch`: + + ```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(); + ``` + + + + +### Connecting and publishing + +`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: + +```tsx +// @noErrors +import { useEffect } from "react"; +import { Button, PermissionsAndroid, Platform } from "react-native"; +import { + PublisherView, + useCamera, + useMicrophone, + usePublisher, + 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}`; + +function PublishScreen() { + // Open the MoQ session against the Fishjam relay + const session = useSession(relayUrl, (s) => s.connect()); + const camera = useCamera({ position: "front" }); + const microphone = useMicrophone(); + const publisher = usePublisher(session); + + // Request camera + mic permissions on Android (iOS handles it automatically when Info.plist is configured) + useEffect(() => { + if (Platform.OS === "android") { + PermissionsAndroid.requestMultiple([ + PermissionsAndroid.PERMISSIONS.CAMERA, + PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, + ]); + } + }, []); + + const isPublishing = publisher.state === "publishing"; + + return ( + <> + +