diff --git a/0.2.1.html b/0.2.1.html index 590b8ec4..d338ecf1 100644 --- a/0.2.1.html +++ b/0.2.1.html @@ -4,8 +4,8 @@ What is Jellyfish? | Jellyfish - - + +
Skip to main content
Version: 0.2.1

What is Jellyfish?

diff --git a/0.2.1/cluster.html b/0.2.1/cluster.html index 189ff86e..f785dc44 100644 --- a/0.2.1/cluster.html +++ b/0.2.1/cluster.html @@ -4,8 +4,8 @@ Cluster | Jellyfish - - + +
Version: 0.2.1

Cluster

diff --git a/0.2.1/deploying/fly_io.html b/0.2.1/deploying/fly_io.html index ba728751..092d2704 100644 --- a/0.2.1/deploying/fly_io.html +++ b/0.2.1/deploying/fly_io.html @@ -4,8 +4,8 @@ Fly.io (experimental) | Jellyfish - - + +
Version: 0.2.1

Fly.io (experimental)

diff --git a/0.2.1/deploying/vps.html b/0.2.1/deploying/vps.html index 5b5971d3..961f2ee3 100644 --- a/0.2.1/deploying/vps.html +++ b/0.2.1/deploying/vps.html @@ -4,8 +4,8 @@ Cloud VPS with cloud-init | Jellyfish - - + +
Version: 0.2.1

Cloud VPS with cloud-init

diff --git a/0.2.1/examples.html b/0.2.1/examples.html index ded971d1..8aaf415a 100644 --- a/0.2.1/examples.html +++ b/0.2.1/examples.html @@ -4,8 +4,8 @@ Examples | Jellyfish - - + +
Version: 0.2.1

Examples

diff --git a/0.2.1/for_developers/api_reference.html b/0.2.1/for_developers/api_reference.html index f4f32d36..c44c2366 100644 --- a/0.2.1/for_developers/api_reference.html +++ b/0.2.1/for_developers/api_reference.html @@ -4,8 +4,8 @@ API Reference | Jellyfish - - + +
Version: 0.2.1

API Reference

diff --git a/0.2.1/for_developers/api_reference/rest_api.html b/0.2.1/for_developers/api_reference/rest_api.html index 2f4605fd..b3ec2bfa 100644 --- a/0.2.1/for_developers/api_reference/rest_api.html +++ b/0.2.1/for_developers/api_reference/rest_api.html @@ -4,11 +4,11 @@ Rest API | Jellyfish - - + + -
Version: 0.2.1

Rest API

Version: 0.2.1

Rest API

Healthy

Response samples

Content type
application/json
{
  • "data": {
    }
}

hls

Subscribe the HLS component to the tracks of peers or components

Authorizations:
authorization
path Parameters
room_id
required
string

Response samples

Content type
application/json
{
  • "data": {
    }
}

hls

Subscribe the HLS component to the tracks of peers or components

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

Request Body schema: application/json
optional

Subscribe configuration

@@ -44,7 +44,7 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Unauthorized

Request samples

Content type
application/json
{
  • "origins": [
    ]
}

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Retrieve HLS Content

Authorizations:
authorization
path Parameters
room_id
required
string

Request samples

Content type
application/json
{
  • "origins": [
    ]
}

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Retrieve HLS Content

Authorizations:
authorization
path Parameters
room_id
required
string

Room id

filename
required
string

Name of the file

@@ -62,13 +62,13 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Invalid filename

Response samples

Content type
application/json
"string"

recording

Lists all available recordings

Authorizations:
authorization

Responses

Response samples

Content type
application/json
"string"

recording

Lists all available recordings

Authorizations:
authorization

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Deletes the recording

Authorizations:
authorization
path Parameters
recording_id
required
string

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Deletes the recording

Authorizations:
authorization
path Parameters
recording_id
required
string

Recording id

Responses

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Retrieve Recording (HLS) Content

Authorizations:
authorization
path Parameters
recording_id
required
string

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Retrieve Recording (HLS) Content

Authorizations:
authorization
path Parameters
recording_id
required
string

Recording id

filename
required
string

Name of the file

@@ -88,14 +88,16 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Invalid request

Response samples

Content type
application/json
"string"

room

Show information about all rooms

Authorizations:
authorization

Responses

Response samples

Content type
application/json
"string"

room

Show information about all rooms

Authorizations:
authorization

Responses

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Creates a room

Authorizations:
authorization
Request Body schema: application/json
optional

Response samples

Content type
application/json
{
  • "data": [
    ]
}

Creates a room

Authorizations:
authorization
Request Body schema: application/json
optional

Room configuration

maxPeers
integer or null >= 1

Maximum amount of peers allowed into the room

+
peerlessPurgeTimeout
integer or null >= 1

Duration (in seconds) after which the room will be removed if no peers are connected. If not provided, this feature is disabled.

roomId
string or null

Custom id used for identifying room within Jellyfish. Must be unique across all rooms. If not provided, random UUID is generated.

videoCodec
string or null
Enum: "h264" "vp8"

Invalid request structure

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete the room

Authorizations:
authorization
path Parameters
room_id
required
string

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete the room

Authorizations:
authorization
path Parameters
room_id
required
string

Room id

Responses

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Shows information about the room

Authorizations:
authorization
path Parameters
room_id
required
string

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Shows information about the room

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

Responses

Response samples

Content type
application/json
{
  • "data": {
    }
}

Creates the component and adds it to the room

Authorizations:
authorization
path Parameters
room_id
required
string

Response samples

Content type
application/json
{
  • "data": {
    }
}

Creates the component and adds it to the room

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

Request Body schema: application/json
optional

Component config

-
ComponentOptionsHLS (object) or ComponentOptionsRTSP (object) or ComponentOptionsFile (object) (ComponentOptions)
ComponentOptionsHLS (object) or ComponentOptionsRTSP (object) or ComponentOptionsFile (object) or ComponentOptionsSIP (object) (ComponentOptions)

Component-specific options

type
required
string (ComponentType)

Component type

@@ -140,7 +142,7 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Unauthorized

Request samples

Content type
application/json
{
  • "options": {
    },
  • "type": "hls"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete the component from the room

Authorizations:
authorization
path Parameters
room_id
required
string

Request samples

Content type
application/json
{
  • "options": {
    },
  • "type": "hls"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete the component from the room

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

id
required
string

Component ID

@@ -150,7 +152,7 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Unauthorized

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Create peer

Authorizations:
authorization
path Parameters
room_id
required
string

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Create peer

Authorizations:
authorization
path Parameters
room_id
required
string

Room id

Request Body schema: application/json
optional

Peer specification

@@ -168,7 +170,7 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Room doesn't exist

Request samples

Content type
application/json
{
  • "options": {
    },
  • "type": "webrtc"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete peer

Authorizations:
authorization
path Parameters
room_id
required
string

Request samples

Content type
application/json
{
  • "options": {
    },
  • "type": "webrtc"
}

Response samples

Content type
application/json
{
  • "data": {
    }
}

Delete peer

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

id
required
string

Peer id

@@ -178,6 +180,34 @@ " class="sc-iKOmoZ sc-cCzLxZ cpUhEB gLSMbL sc-ckdEwu LxEPk">

Unauthorized

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}
+

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

sip

Finish call made by SIP component

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

+
component_id
required
string

SIP Component ID

+

Responses

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}

Make a call from the SIP component to the provided phone number

Authorizations:
authorization
path Parameters
room_id
required
string

Room ID

+
component_id
required
string

SIP Component ID

+
Request Body schema: application/json
optional

Phone Number configuration

+
phoneNumber
string

Phone number on which SIP Component will call

+

Responses

Request samples

Content type
application/json
{
  • "phoneNumber": "string"
}

Response samples

Content type
application/json
{
  • "errors": "Token has expired"
}
\ No newline at end of file diff --git a/0.2.1/for_developers/design_docs.html b/0.2.1/for_developers/design_docs.html index 0b270393..62bb4a62 100644 --- a/0.2.1/for_developers/design_docs.html +++ b/0.2.1/for_developers/design_docs.html @@ -4,8 +4,8 @@ Design Docs | Jellyfish - - + +
Version: 0.2.1

Design Docs

diff --git a/0.2.1/getting_started/architecture.html b/0.2.1/getting_started/architecture.html index ce96a1e6..ada97bc7 100644 --- a/0.2.1/getting_started/architecture.html +++ b/0.2.1/getting_started/architecture.html @@ -4,8 +4,8 @@ Architecture | Jellyfish - - + +
Version: 0.2.1

Architecture

diff --git a/0.2.1/getting_started/authentication.html b/0.2.1/getting_started/authentication.html index f9241216..3d5c5aec 100644 --- a/0.2.1/getting_started/authentication.html +++ b/0.2.1/getting_started/authentication.html @@ -4,8 +4,8 @@ Authentication | Jellyfish - - + +
Version: 0.2.1

Authentication

diff --git a/0.2.1/getting_started/components/hls.html b/0.2.1/getting_started/components/hls.html index 3c8b9f6c..36ed94b6 100644 --- a/0.2.1/getting_started/components/hls.html +++ b/0.2.1/getting_started/components/hls.html @@ -4,8 +4,8 @@ HLS | Jellyfish - - + +
Version: 0.2.1

HLS

diff --git a/0.2.1/getting_started/components/rtsp.html b/0.2.1/getting_started/components/rtsp.html index 8a8dfa74..1c61e272 100644 --- a/0.2.1/getting_started/components/rtsp.html +++ b/0.2.1/getting_started/components/rtsp.html @@ -4,8 +4,8 @@ RTSP | Jellyfish - - + +
Version: 0.2.1

RTSP

diff --git a/0.2.1/getting_started/installation.html b/0.2.1/getting_started/installation.html index f234f499..b035b752 100644 --- a/0.2.1/getting_started/installation.html +++ b/0.2.1/getting_started/installation.html @@ -4,8 +4,8 @@ Installation | Jellyfish - - + +
Version: 0.2.1

Installation

diff --git a/0.2.1/getting_started/metrics.html b/0.2.1/getting_started/metrics.html index ec757dfa..4f7f7b60 100644 --- a/0.2.1/getting_started/metrics.html +++ b/0.2.1/getting_started/metrics.html @@ -4,8 +4,8 @@ Metrics | Jellyfish - - + +
Version: 0.2.1

Metrics

diff --git a/0.2.1/getting_started/notifications.html b/0.2.1/getting_started/notifications.html index eaf473ca..bf14ebc2 100644 --- a/0.2.1/getting_started/notifications.html +++ b/0.2.1/getting_started/notifications.html @@ -4,8 +4,8 @@ Notifications | Jellyfish - - + +
Version: 0.2.1

Notifications

diff --git a/0.2.1/getting_started/peers/webrtc.html b/0.2.1/getting_started/peers/webrtc.html index e1303f2c..9a1b8c38 100644 --- a/0.2.1/getting_started/peers/webrtc.html +++ b/0.2.1/getting_started/peers/webrtc.html @@ -4,8 +4,8 @@ WebRTC | Jellyfish - - + +
Version: 0.2.1

WebRTC

diff --git a/0.2.1/getting_started/sdks.html b/0.2.1/getting_started/sdks.html index 98972725..a84b6b8d 100644 --- a/0.2.1/getting_started/sdks.html +++ b/0.2.1/getting_started/sdks.html @@ -4,8 +4,8 @@ SDKs | Jellyfish - - + +
Version: 0.2.1

SDKs

diff --git a/0.2.1/introduction/basic_concepts.html b/0.2.1/introduction/basic_concepts.html index 9070d520..de19cf31 100644 --- a/0.2.1/introduction/basic_concepts.html +++ b/0.2.1/introduction/basic_concepts.html @@ -4,8 +4,8 @@ Basic Concepts | Jellyfish - - + +
Version: 0.2.1

Basic Concepts

diff --git a/0.2.1/introduction/example_scenarios.html b/0.2.1/introduction/example_scenarios.html index 262d6999..6c38628d 100644 --- a/0.2.1/introduction/example_scenarios.html +++ b/0.2.1/introduction/example_scenarios.html @@ -4,8 +4,8 @@ Example Scenarios | Jellyfish - - + +
Version: 0.2.1

Example Scenarios

diff --git a/0.2.1/tutorials/dashboard.html b/0.2.1/tutorials/dashboard.html index d647c1d1..e1963732 100644 --- a/0.2.1/tutorials/dashboard.html +++ b/0.2.1/tutorials/dashboard.html @@ -4,8 +4,8 @@ Jellyfish Dashboard | Jellyfish - - + +
Version: 0.2.1

The Whats and Hows of Jellyfish Dashboard

diff --git a/0.2.1/tutorials/react-native.html b/0.2.1/tutorials/react-native.html index a6537619..535a177a 100644 --- a/0.2.1/tutorials/react-native.html +++ b/0.2.1/tutorials/react-native.html @@ -4,8 +4,8 @@ React Native | Jellyfish - - + +
Version: 0.2.1

React Native Minimal Working Example

diff --git a/0.2.1/tutorials/simple-react-app.html b/0.2.1/tutorials/simple-react-app.html index b6726d4a..1618a7a6 100644 --- a/0.2.1/tutorials/simple-react-app.html +++ b/0.2.1/tutorials/simple-react-app.html @@ -4,8 +4,8 @@ Simple React App | Jellyfish - - + +
Version: 0.2.1

Simple React App

diff --git a/404.html b/404.html index 5d70253f..bf27594a 100644 --- a/404.html +++ b/404.html @@ -4,8 +4,8 @@ Jellyfish - - + +

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

diff --git a/assets/js/06d81fef.af98c25c.js b/assets/js/06d81fef.af98c25c.js deleted file mode 100644 index e9c9a64e..00000000 --- a/assets/js/06d81fef.af98c25c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[6921],{5956:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>d,frontMatter:()=>o,metadata:()=>r,toc:()=>a});var i=s(7624),n=s(2172);const o={id:"what_is_jellyfish",slug:"/"},l="What is Jellyfish?",r={id:"introduction/what_is_jellyfish",title:"What is Jellyfish?",description:"Jellyfish is an open-source, general-purpose media server that ships with support for multiple media protocols.",source:"@site/docs/introduction/what_is_jellyfish.md",sourceDirName:"introduction",slug:"/",permalink:"/jellyfish-docs/next/",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/introduction/what_is_jellyfish.md",tags:[],version:"current",frontMatter:{id:"what_is_jellyfish",slug:"/"},sidebar:"mainSidebar",next:{title:"Basic Concepts",permalink:"/jellyfish-docs/next/introduction/basic_concepts"}},c={},a=[{value:"Supported protocols",id:"supported-protocols",level:2}];function h(e){const t={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,n.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"what-is-jellyfish",children:"What is Jellyfish?"}),"\n",(0,i.jsxs)(t.p,{children:["Jellyfish is an open-source, general-purpose media server that ships with support for multiple media protocols.\nIt can be thought of as a multimedia bridge meant for creating different types of multimedia systems.\nWith Jellyfish you can easily create a real-time video conferencing system, a broadcasting solution or both at the same time.\nThe unique feature of our media server is the ability to combine different multimedia protocols.\nFor example, one can stream video from its CCTV camera via RTSP to the server, convert it to WebRTC and send it to some web application.\nIn general, there are no limitations.\nSee ",(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/introduction/example_scenarios",children:"Example Scenarios"})," for more information."]}),"\n",(0,i.jsx)(t.p,{children:"Jellyfish comes with:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/authentication",children:"built-in authentication"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/sdks",children:"client and server SDKs"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/notifications",children:"server-side notifications"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"#supported-protocols",children:"support for multiple media protocols"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/cluster",children:"built-in clustering"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/tutorials/dashboard",children:"tutorials"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/jellyfish-dev/jellyfish/pkgs/container/jellyfish",children:"Docker images for multiple architectures"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/deploying/vps",children:"deployment instructions"})}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"supported-protocols",children:"Supported protocols"}),"\n",(0,i.jsx)(t.p,{children:"Jellyfish supports following protocols:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})," - used for creating real-time video conferencing systems"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})," - allows for implementing broadcasting solutions"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})," - very often used for consuming streams from IP cameras"]}),"\n"]})]})}function d(e={}){const{wrapper:t}={...(0,n.M)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},2172:(e,t,s)=>{s.d(t,{I:()=>r,M:()=>l});var i=s(1504);const n={},o=i.createContext(n);function l(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:l(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/06d81fef.e39d0055.js b/assets/js/06d81fef.e39d0055.js new file mode 100644 index 00000000..1899075c --- /dev/null +++ b/assets/js/06d81fef.e39d0055.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[6921],{5956:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>l,metadata:()=>r,toc:()=>a});var i=t(7624),n=t(2172);const l={id:"what_is_jellyfish",slug:"/"},o="What is Jellyfish?",r={id:"introduction/what_is_jellyfish",title:"What is Jellyfish?",description:"Jellyfish is an open-source, general-purpose media server that ships with support for multiple media protocols.",source:"@site/docs/introduction/what_is_jellyfish.md",sourceDirName:"introduction",slug:"/",permalink:"/jellyfish-docs/next/",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/introduction/what_is_jellyfish.md",tags:[],version:"current",frontMatter:{id:"what_is_jellyfish",slug:"/"},sidebar:"mainSidebar",next:{title:"Basic Concepts",permalink:"/jellyfish-docs/next/introduction/basic_concepts"}},c={},a=[{value:"Supported protocols",id:"supported-protocols",level:2}];function h(e){const s={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,n.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(s.h1,{id:"what-is-jellyfish",children:"What is Jellyfish?"}),"\n",(0,i.jsxs)(s.p,{children:["Jellyfish is an open-source, general-purpose media server that ships with support for multiple media protocols.\nIt can be thought of as a multimedia bridge meant for creating different types of multimedia systems.\nWith Jellyfish you can easily create a real-time video conferencing system, a broadcasting solution or both at the same time.\nThe unique feature of our media server is the ability to combine different multimedia protocols.\nFor example, one can stream video from its CCTV camera via RTSP to the server, convert it to WebRTC and send it to some web application.\nIn general, there are no limitations.\nSee ",(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/introduction/example_scenarios",children:"Example Scenarios"})," for more information."]}),"\n",(0,i.jsx)(s.p,{children:"Jellyfish comes with:"}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/authentication",children:"built-in authentication"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/sdks",children:"client and server SDKs"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/notifications",children:"server-side notifications"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"#supported-protocols",children:"support for multiple media protocols"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/cluster",children:"built-in clustering"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/tutorials/dashboard",children:"tutorials"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"https://github.com/jellyfish-dev/jellyfish/pkgs/container/jellyfish",children:"Docker images for multiple architectures"})}),"\n",(0,i.jsx)(s.li,{children:(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/deploying/vps",children:"deployment instructions"})}),"\n"]}),"\n",(0,i.jsx)(s.h2,{id:"supported-protocols",children:"Supported protocols"}),"\n",(0,i.jsx)(s.p,{children:"Jellyfish supports following protocols:"}),"\n",(0,i.jsxs)(s.ul,{children:["\n",(0,i.jsxs)(s.li,{children:[(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})," - used for creating real-time video conferencing systems"]}),"\n",(0,i.jsxs)(s.li,{children:[(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})," - allows for implementing broadcasting solutions"]}),"\n",(0,i.jsxs)(s.li,{children:[(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})," - very often used for consuming streams from IP cameras"]}),"\n",(0,i.jsxs)(s.li,{children:[(0,i.jsx)(s.a,{href:"/jellyfish-docs/next/getting_started/components/sip",children:"SIP"})," - used for making VoIP calls"]}),"\n"]})]})}function d(e={}){const{wrapper:s}={...(0,n.M)(),...e.components};return s?(0,i.jsx)(s,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},2172:(e,s,t)=>{t.d(s,{I:()=>r,M:()=>o});var i=t(1504);const n={},l=i.createContext(n);function o(e){const s=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:o(e.components),i.createElement(l.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/33da16d7.e2a03e50.js b/assets/js/33da16d7.e2a03e50.js new file mode 100644 index 00000000..f9580ec8 --- /dev/null +++ b/assets/js/33da16d7.e2a03e50.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[4972],{7640:e=>{e.exports=JSON.parse('{"url":"https://raw.githubusercontent.com/jellyfish-dev/jellyfish/main/openapi.yaml","themeId":"theme-redoc","isSpecFile":false,"spec":{"components":{"responses":{},"schemas":{"PeerStatus":{"description":"Informs about the peer status","enum":["connected","disconnected"],"example":"disconnected","title":"PeerStatus","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Status"},"HealthReportStatus":{"description":"Informs about the status of Jellyfish or a specific service","enum":["UP","DOWN"],"example":"UP","title":"HealthReportStatus","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport.Status"},"RoomDetailsResponse":{"description":"Response containing room details","properties":{"data":{"$ref":"#/components/schemas/Room"}},"required":["data"],"title":"RoomDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomDetailsResponse"},"ComponentOptionsRTSP":{"description":"Options specific to the RTSP component","properties":{"keepAliveInterval":{"default":15000,"description":"Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source","minimum":0,"type":"integer"},"pierceNat":{"default":true,"description":"Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup","type":"boolean"},"reconnectDelay":{"default":15000,"description":"Delay (in ms) between successive reconnect attempts","minimum":0,"type":"integer"},"rtpPort":{"default":20000,"description":"Local port RTP stream will be received at","maximum":65535,"minimum":1,"type":"integer"},"sourceUri":{"description":"URI of RTSP source stream","example":"rtsp://localhost:554/stream","type":"string"}},"required":["sourceUri"],"title":"ComponentOptionsRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP.Options"},"ComponentOptionsSIP":{"description":"Options specific to the SIP component","properties":{"registrarCredentials":{"description":"Credentials used to authorize in SIP Provider service","properties":{"address":{"description":"SIP provider address. Can be in the form of FQDN (my-sip-registrar.net) or IPv4 (1.2.3.4). Port can be specified e.g: 5.6.7.8:9999. If not given, the default SIP port `5060` will be assumed","example":"example.org","type":"string"},"password":{"description":"Password in SIP service provider","type":"string"},"username":{"description":"Username in SIP service provider","type":"string"}},"required":["address","username","password"],"title":"SIPCredentials","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.SIP.SIPCredentials"}},"required":["registrarCredentials"],"title":"ComponentOptionsSIP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.SIP.Options"},"ComponentPropertiesHLS":{"description":"Properties specific to the HLS component","properties":{"lowLatency":{"description":"Whether the component uses LL-HLS","type":"boolean"},"persistent":{"description":"Whether the video is stored after end of stream","type":"boolean"},"playable":{"description":"Whether the generated HLS playlist is playable","type":"boolean"},"subscribeMode":{"description":"Whether the HLS component should subscribe to tracks automatically or manually","enum":["auto","manual"],"type":"string"},"targetWindowDuration":{"description":"Duration of stream available for viewer","nullable":true,"type":"integer"}},"required":["playable","lowLatency","persistent","targetWindowDuration","subscribeMode"],"title":"ComponentPropertiesHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.Properties"},"Room":{"description":"Description of the room state","properties":{"components":{"description":"List of all components","items":{"$ref":"#/components/schemas/Component"},"type":"array"},"config":{"$ref":"#/components/schemas/RoomConfig"},"id":{"description":"Room ID","example":"room-1","type":"string"},"peers":{"description":"List of all peers","items":{"$ref":"#/components/schemas/Peer"},"type":"array"}},"required":["id","config","components","peers"],"title":"Room","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Room"},"Component":{"description":"Describes component","discriminator":{"mapping":{"file":"#/components/schemas/ComponentFile","hls":"#/components/schemas/ComponentHLS","rtsp":"#/components/schemas/ComponentRTSP","sip":"#/components/schemas/ComponentSIP"},"propertyName":"type"},"oneOf":[{"$ref":"#/components/schemas/ComponentHLS"},{"$ref":"#/components/schemas/ComponentRTSP"},{"$ref":"#/components/schemas/ComponentFile"},{"$ref":"#/components/schemas/ComponentSIP"}],"title":"Component","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component"},"PeerOptionsWebRTC":{"description":"Options specific to the WebRTC peer","properties":{"enableSimulcast":{"default":true,"description":"Enables the peer to use simulcast","type":"boolean"}},"title":"PeerOptionsWebRTC","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.WebRTC"},"HealthcheckResponse":{"description":"Response containing health report of Jellyfish","properties":{"data":{"$ref":"#/components/schemas/HealthReport"}},"required":["data"],"title":"HealthcheckResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthcheckResponse"},"ComponentSIP":{"description":"Describes the SIP component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesSIP"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"sip","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentSIP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.SIP"},"ComponentHLS":{"description":"Describes the HLS component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesHLS"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"hls","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS"},"HlsSkip":{"description":"Set to \\"YES\\" if delta manifest should be requested","example":"YES","nullable":true,"title":"HlsSkip","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsSkip"},"PeerMetadata":{"description":"Custom metadata set by the peer","example":{"name":"JellyfishUser"},"nullable":true,"title":"PeerMetadata","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.PeerMetadata"},"ComponentPropertiesFile":{"description":"Properties specific to the File component","properties":{"filePath":{"description":"Relative path to track file. Must be either OPUS encapsulated in Ogg or raw h264","type":"string"},"framerate":{"description":"Framerate of video in a file. It is only valid for video track","example":30,"nullable":true,"type":"integer"}},"required":["filePath","framerate"],"title":"ComponentPropertiesFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File.Properties"},"ComponentFile":{"description":"Describes the File component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesFile"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"file","type":"string"}},"required":["id","type","tracks"],"title":"ComponentFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File"},"SubscriptionConfig":{"description":"Subscription config","properties":{"origins":{"description":"List of peers and components ids whose tracks the HLS endpoint will subscribe to","items":{"type":"string"},"type":"array"}},"title":"SubscriptionConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Subscription.Origins"},"HlsMsn":{"description":"Segment sequence number","example":10,"minimum":0,"nullable":true,"title":"HlsMsn","type":"integer","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsMsn"},"DialConfig":{"description":"Dial config","properties":{"phoneNumber":{"description":"Phone number on which SIP Component will call","type":"string"}},"title":"DialConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Dial.PhoneNumber"},"ComponentRTSP":{"description":"Describes the RTSP component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesRTSP"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"hls","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP"},"HlsPart":{"description":"Partial segment sequence number","example":10,"minimum":0,"nullable":true,"title":"HlsPart","type":"integer","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsPart"},"ComponentDetailsResponse":{"description":"Response containing component details","properties":{"data":{"$ref":"#/components/schemas/Component"}},"required":["data"],"title":"ComponentDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.ComponentDetailsResponse"},"ComponentOptionsHLS":{"description":"Options specific to the HLS component","properties":{"lowLatency":{"default":false,"description":"Whether the component should use LL-HLS","type":"boolean"},"persistent":{"default":false,"description":"Whether the video is stored after end of stream","type":"boolean"},"s3":{"description":"Credentials to AWS S3 bucket.","nullable":true,"oneOf":[{"$ref":"#/components/schemas/S3Credentials"}],"type":"object"},"subscribeMode":{"default":"auto","description":"Whether the HLS component should subscribe to tracks automatically or manually.","enum":["auto","manual"],"type":"string"},"targetWindowDuration":{"description":"Duration of stream available for viewer","nullable":true,"type":"integer"}},"title":"ComponentOptionsHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.Options"},"SIPCredentials":{"description":"Credentials used to authorize in SIP Provider service","properties":{"address":{"description":"SIP provider address. Can be in the form of FQDN (my-sip-registrar.net) or IPv4 (1.2.3.4). Port can be specified e.g: 5.6.7.8:9999. If not given, the default SIP port `5060` will be assumed","example":"example.org","type":"string"},"password":{"description":"Password in SIP service provider","type":"string"},"username":{"description":"Username in SIP service provider","type":"string"}},"required":["address","username","password"],"title":"SIPCredentials","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.SIP.SIPCredentials"},"S3Credentials":{"description":"An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided","properties":{"accessKeyId":{"description":"An AWS access key identifier, linked to your AWS account.","type":"string"},"bucket":{"description":"The name of the S3 bucket where your data will be stored.","type":"string"},"region":{"description":"The AWS region where your bucket is located.","type":"string"},"secretAccessKey":{"description":"The secret key that is linked to the Access Key ID.","type":"string"}},"required":["accessKeyId","secretAccessKey","region","bucket"],"title":"S3Credentials","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.S3"},"RecordingListResponse":{"description":"Response containing list of all recording","properties":{"data":{"items":{"type":"string"},"type":"array"}},"required":["data"],"title":"RecordingListResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RecordingListResponse"},"ComponentOptions":{"description":"Component-specific options","oneOf":[{"$ref":"#/components/schemas/ComponentOptionsHLS"},{"$ref":"#/components/schemas/ComponentOptionsRTSP"},{"$ref":"#/components/schemas/ComponentOptionsFile"},{"$ref":"#/components/schemas/ComponentOptionsSIP"}],"title":"ComponentOptions","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.Options"},"Track":{"description":"Describes media track of a Peer or Component","properties":{"id":{"type":"string"},"metadata":{"nullable":true},"type":{"enum":["audio","video"],"type":"string"}},"title":"Track","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Track"},"HealthReportDistribution":{"description":"Informs about the status of Jellyfish distribution","properties":{"enabled":{"description":"Whether distribution is enabled on this Jellyfish","type":"boolean"},"nodeStatus":{"$ref":"#/components/schemas/HealthReportStatus"},"nodesInCluster":{"description":"Amount of nodes (including this Jellyfish\'s node) in the distribution cluster","type":"integer"}},"required":["nodeStatus","nodesInCluster"],"title":"HealthReportDistribution","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport.Distribution"},"ComponentPropertiesRTSP":{"description":"Properties specific to the RTSP component","properties":{"keepAliveInterval":{"description":"Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source","type":"integer"},"pierceNat":{"description":"Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup","type":"boolean"},"reconnectDelay":{"description":"Delay (in ms) between successive reconnect attempts","type":"integer"},"rtpPort":{"description":"Local port RTP stream will be received at","type":"integer"},"sourceUri":{"description":"URI of RTSP source stream","type":"string"}},"required":["sourceUri","rtpPort","reconnectDelay","keepAliveInterval","pierceNat"],"title":"ComponentPropertiesRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP.Properties"},"PeerOptions":{"description":"Peer-specific options","oneOf":[{"$ref":"#/components/schemas/PeerOptionsWebRTC"}],"title":"PeerOptions","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Options"},"HealthReport":{"description":"Describes overall Jellyfish health","properties":{"distribution":{"$ref":"#/components/schemas/HealthReportDistribution"},"status":{"$ref":"#/components/schemas/HealthReportStatus"},"uptime":{"description":"Uptime of Jellyfish (in seconds)","type":"integer"}},"required":["status","uptime","distribution"],"title":"HealthReport","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport"},"Peer":{"description":"Describes peer status","properties":{"id":{"description":"Assigned peer id","example":"peer-1","type":"string"},"metadata":{"$ref":"#/components/schemas/PeerMetadata"},"status":{"$ref":"#/components/schemas/PeerStatus"},"tracks":{"description":"List of all peer\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"$ref":"#/components/schemas/PeerType"}},"required":["id","type","status","tracks","metadata"],"title":"Peer","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer"},"ComponentType":{"description":"Component type","example":"hls","title":"ComponentType","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.Type"},"AuthToken":{"description":"Token for authorizing websocket connection","example":"5cdac726-57a3-4ecb-b1d5-72a3d62ec242","title":"AuthToken","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Token"},"RoomsListingResponse":{"description":"Response containing list of all rooms","properties":{"data":{"items":{"$ref":"#/components/schemas/Room"},"type":"array"}},"required":["data"],"title":"RoomsListingResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomsListingResponse"},"ComponentPropertiesSIP":{"description":"Properties specific to the SIP component","properties":{"registrarCredentials":{"description":"Credentials used to authorize in SIP Provider service","properties":{"address":{"description":"SIP provider address. Can be in the form of FQDN (my-sip-registrar.net) or IPv4 (1.2.3.4). Port can be specified e.g: 5.6.7.8:9999. If not given, the default SIP port `5060` will be assumed","example":"example.org","type":"string"},"password":{"description":"Password in SIP service provider","type":"string"},"username":{"description":"Username in SIP service provider","type":"string"}},"required":["address","username","password"],"title":"SIPCredentials","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.SIP.SIPCredentials"}},"required":["registrarCredentials"],"title":"ComponentPropertiesSIP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.SIP.Properties"},"PeerDetailsResponse":{"description":"Response containing peer details and their token","properties":{"data":{"properties":{"peer":{"$ref":"#/components/schemas/Peer"},"token":{"$ref":"#/components/schemas/AuthToken"}},"required":["peer","token"],"type":"object"}},"required":["data"],"title":"PeerDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.PeerDetailsResponse"},"HlsResponse":{"description":"Requested file","title":"HlsResponse","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Response"},"PeerType":{"description":"Peer type","example":"webrtc","title":"PeerType","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Type"},"RoomCreateDetailsResponse":{"description":"Response containing room details","properties":{"data":{"properties":{"jellyfish_address":{"description":"Jellyfish instance address where the room was created. This might be different than the address of Jellyfish where the request was sent only when running a cluster of Jellyfishes.","example":"jellyfish1:5003","type":"string"},"room":{"$ref":"#/components/schemas/Room"}},"required":["room","jellyfish_address"],"type":"object"}},"required":["data"],"title":"RoomCreateDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomCreateDetailsResponse"},"ComponentOptionsFile":{"description":"Options specific to the File component","properties":{"filePath":{"description":"Path to track file. Must be either OPUS encapsulated in Ogg or raw h264","example":"/root/video.h264","type":"string"},"framerate":{"description":"Framerate of video in a file. It is only valid for video track","example":30,"nullable":true,"type":"integer"}},"required":["filePath"],"title":"ComponentOptionsFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File.Options"},"Error":{"description":"Error message","properties":{"errors":{"description":"Error details","example":"Token has expired","type":"string"}},"required":["errors"],"title":"Error","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Error"},"RoomConfig":{"description":"Room configuration","properties":{"maxPeers":{"description":"Maximum amount of peers allowed into the room","example":10,"minimum":1,"nullable":true,"type":"integer"},"peerlessPurgeTimeout":{"description":"Duration (in seconds) after which the room will be removed if no peers are connected. If not provided, this feature is disabled.","example":60,"minimum":1,"nullable":true,"type":"integer"},"roomId":{"description":"Custom id used for identifying room within Jellyfish. Must be unique across all rooms. If not provided, random UUID is generated.","nullable":true,"type":"string"},"videoCodec":{"description":"Enforces video codec for each peer in the room","enum":["h264","vp8"],"nullable":true,"type":"string"},"webhookUrl":{"description":"URL where Jellyfish notifications will be sent","example":"https://backend.address.com/jellyfish-notifications-endpoint","nullable":true,"type":"string"}},"title":"RoomConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Room.Config"}},"securitySchemes":{"authorization":{"scheme":"bearer","type":"http"}}},"info":{"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0"},"title":"Jellyfish Media Server","version":"0.2.0"},"openapi":"3.0.0","paths":{"/health":{"get":{"callbacks":{},"operationId":"healthcheck","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthcheckResponse"}}},"description":"Healthy"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Describes the health of Jellyfish","tags":["health"]}},"/hls/{room_id}/subscribe":{"post":{"callbacks":{},"operationId":"subscribe_hls_to","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionConfig"}}},"description":"Subscribe configuration","required":false},"responses":{"201":{"description":"Tracks succesfully added."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Subscribe the HLS component to the tracks of peers or components","tags":["hls"]}},"/hls/{room_id}/{filename}":{"get":{"callbacks":{},"operationId":"getHlsContent","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Name of the file","in":"path","name":"filename","required":true,"schema":{"type":"string"}},{"description":"Byte range of partial segment","in":"header","name":"range","required":false,"schema":{"type":"string"}},{"description":"Segment sequence number","in":"query","name":"_HLS_msn","required":false,"schema":{"$ref":"#/components/schemas/HlsMsn"}},{"description":"Partial segment sequence number","in":"query","name":"_HLS_part","required":false,"schema":{"$ref":"#/components/schemas/HlsPart"}},{"description":"Is delta manifest requested","in":"query","name":"_HLS_skip","required":false,"schema":{"$ref":"#/components/schemas/HlsSkip"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HlsResponse"}}},"description":"File was found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid filename"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"File not found"}},"summary":"Retrieve HLS Content","tags":["hls"]}},"/recording":{"get":{"callbacks":{},"operationId":"get_recordings","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordingListResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unable to obtain recordings"}},"summary":"Lists all available recordings","tags":["recording"]}},"/recording/{recording_id}":{"delete":{"callbacks":{},"operationId":"delete_recording","parameters":[{"description":"Recording id","in":"path","name":"recording_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted recording"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid recording"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Recording doesn\'t exist"}},"summary":"Deletes the recording","tags":["recording"]}},"/recording/{recording_id}/{filename}":{"get":{"callbacks":{},"operationId":"getRecordingContent","parameters":[{"description":"Recording id","in":"path","name":"recording_id","required":true,"schema":{"type":"string"}},{"description":"Name of the file","in":"path","name":"filename","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HlsResponse"}}},"description":"File was found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"File not found"}},"summary":"Retrieve Recording (HLS) Content","tags":["recording"]}},"/room":{"get":{"callbacks":{},"operationId":"get_all_rooms","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomsListingResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Show information about all rooms","tags":["room"]},"post":{"callbacks":{},"operationId":"create_room","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomConfig"}}},"description":"Room configuration","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomCreateDetailsResponse"}}},"description":"Room successfully created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Creates a room","tags":["room"]}},"/room/{room_id}":{"delete":{"callbacks":{},"operationId":"delete_room","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted room"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Delete the room","tags":["room"]},"get":{"callbacks":{},"operationId":"get_room","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomDetailsResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Shows information about the room","tags":["room"]}},"/room/{room_id}/component":{"post":{"callbacks":{},"operationId":"add_component","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"options":{"$ref":"#/components/schemas/ComponentOptions"},"type":{"$ref":"#/components/schemas/ComponentType"}},"required":["type"],"type":"object"}}},"description":"Component config","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComponentDetailsResponse"}}},"description":"Successfully added component"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Creates the component and adds it to the room","tags":["room"]}},"/room/{room_id}/component/{id}":{"delete":{"callbacks":{},"operationId":"delete_component","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Component ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Either component or the room doesn\'t exist"}},"summary":"Delete the component from the room","tags":["room"]}},"/room/{room_id}/peer":{"post":{"callbacks":{},"operationId":"add_peer","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"options":{"$ref":"#/components/schemas/PeerOptions"},"type":{"$ref":"#/components/schemas/PeerType"}},"required":["type","options"],"type":"object"}}},"description":"Peer specification","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeerDetailsResponse"}}},"description":"Peer successfully created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request body structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Peer limit has been reached"}},"summary":"Create peer","tags":["room"]}},"/room/{room_id}/peer/{id}":{"delete":{"callbacks":{},"operationId":"delete_peer","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Peer id","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Peer successfully deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room ID or Peer ID references a resource that doesn\'t exist"}},"summary":"Delete peer","tags":["room"]}},"/sip/{room_id}/{component_id}/call":{"delete":{"callbacks":{},"operationId":"end_call","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"SIP Component ID","in":"path","name":"component_id","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Call ended"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Finish call made by SIP component","tags":["sip"]},"post":{"callbacks":{},"operationId":"dial","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"SIP Component ID","in":"path","name":"component_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialConfig"}}},"description":"Phone Number configuration","required":false},"responses":{"201":{"description":"Call started"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Make a call from the SIP component to the provided phone number","tags":["sip"]}}},"security":[{"authorization":[]}],"servers":[],"tags":[]}}')}}]); \ No newline at end of file diff --git a/assets/js/33da16d7.f71b86b0.js b/assets/js/33da16d7.f71b86b0.js deleted file mode 100644 index 8ba34895..00000000 --- a/assets/js/33da16d7.f71b86b0.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[4972],{7640:e=>{e.exports=JSON.parse('{"url":"https://raw.githubusercontent.com/jellyfish-dev/jellyfish/main/openapi.yaml","themeId":"theme-redoc","isSpecFile":false,"spec":{"components":{"responses":{},"schemas":{"PeerStatus":{"description":"Informs about the peer status","enum":["connected","disconnected"],"example":"disconnected","title":"PeerStatus","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Status"},"HealthReportStatus":{"description":"Informs about the status of Jellyfish or a specific service","enum":["UP","DOWN"],"example":"UP","title":"HealthReportStatus","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport.Status"},"RoomDetailsResponse":{"description":"Response containing room details","properties":{"data":{"$ref":"#/components/schemas/Room"}},"required":["data"],"title":"RoomDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomDetailsResponse"},"ComponentOptionsRTSP":{"description":"Options specific to the RTSP component","properties":{"keepAliveInterval":{"default":15000,"description":"Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source","minimum":0,"type":"integer"},"pierceNat":{"default":true,"description":"Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup","type":"boolean"},"reconnectDelay":{"default":15000,"description":"Delay (in ms) between successive reconnect attempts","minimum":0,"type":"integer"},"rtpPort":{"default":20000,"description":"Local port RTP stream will be received at","maximum":65535,"minimum":1,"type":"integer"},"sourceUri":{"description":"URI of RTSP source stream","example":"rtsp://localhost:554/stream","type":"string"}},"required":["sourceUri"],"title":"ComponentOptionsRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP.Options"},"ComponentPropertiesHLS":{"description":"Properties specific to the HLS component","properties":{"lowLatency":{"description":"Whether the component uses LL-HLS","type":"boolean"},"persistent":{"description":"Whether the video is stored after end of stream","type":"boolean"},"playable":{"description":"Whether the generated HLS playlist is playable","type":"boolean"},"subscribeMode":{"description":"Whether the HLS component should subscribe to tracks automatically or manually","enum":["auto","manual"],"type":"string"},"targetWindowDuration":{"description":"Duration of stream available for viewer","nullable":true,"type":"integer"}},"required":["playable","lowLatency","persistent","targetWindowDuration","subscribeMode"],"title":"ComponentPropertiesHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.Properties"},"Room":{"description":"Description of the room state","properties":{"components":{"description":"List of all components","items":{"$ref":"#/components/schemas/Component"},"type":"array"},"config":{"$ref":"#/components/schemas/RoomConfig"},"id":{"description":"Room ID","example":"room-1","type":"string"},"peers":{"description":"List of all peers","items":{"$ref":"#/components/schemas/Peer"},"type":"array"}},"required":["id","config","components","peers"],"title":"Room","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Room"},"Component":{"description":"Describes component","discriminator":{"mapping":{"file":"#/components/schemas/ComponentFile","hls":"#/components/schemas/ComponentHLS","rtsp":"#/components/schemas/ComponentRTSP"},"propertyName":"type"},"oneOf":[{"$ref":"#/components/schemas/ComponentHLS"},{"$ref":"#/components/schemas/ComponentRTSP"},{"$ref":"#/components/schemas/ComponentFile"}],"title":"Component","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component"},"PeerOptionsWebRTC":{"description":"Options specific to the WebRTC peer","properties":{"enableSimulcast":{"default":true,"description":"Enables the peer to use simulcast","type":"boolean"}},"title":"PeerOptionsWebRTC","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.WebRTC"},"HealthcheckResponse":{"description":"Response containing health report of Jellyfish","properties":{"data":{"$ref":"#/components/schemas/HealthReport"}},"required":["data"],"title":"HealthcheckResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthcheckResponse"},"ComponentHLS":{"description":"Describes the HLS component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesHLS"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"hls","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS"},"HlsSkip":{"description":"Set to \\"YES\\" if delta manifest should be requested","example":"YES","nullable":true,"title":"HlsSkip","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsSkip"},"PeerMetadata":{"description":"Custom metadata set by the peer","example":{"name":"JellyfishUser"},"nullable":true,"title":"PeerMetadata","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.PeerMetadata"},"ComponentPropertiesFile":{"description":"Properties specific to the File component","properties":{"filePath":{"description":"Relative path to track file. Must be either OPUS encapsulated in Ogg or raw h264","type":"string"},"framerate":{"description":"Framerate of video in a file. It is only valid for video track","example":30,"nullable":true,"type":"integer"}},"required":["filePath","framerate"],"title":"ComponentPropertiesFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File.Properties"},"ComponentFile":{"description":"Describes the File component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesFile"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"file","type":"string"}},"required":["id","type","tracks"],"title":"ComponentFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File"},"SubscriptionConfig":{"description":"Subscription config","properties":{"origins":{"description":"List of peers and components ids whose tracks the HLS endpoint will subscribe to","items":{"type":"string"},"type":"array"}},"title":"SubscriptionConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Subscription.Origins"},"HlsMsn":{"description":"Segment sequence number","example":10,"minimum":0,"nullable":true,"title":"HlsMsn","type":"integer","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsMsn"},"ComponentRTSP":{"description":"Describes the RTSP component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesRTSP"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"hls","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP"},"HlsPart":{"description":"Partial segment sequence number","example":10,"minimum":0,"nullable":true,"title":"HlsPart","type":"integer","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsPart"},"ComponentDetailsResponse":{"description":"Response containing component details","properties":{"data":{"$ref":"#/components/schemas/Component"}},"required":["data"],"title":"ComponentDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.ComponentDetailsResponse"},"ComponentOptionsHLS":{"description":"Options specific to the HLS component","properties":{"lowLatency":{"default":false,"description":"Whether the component should use LL-HLS","type":"boolean"},"persistent":{"default":false,"description":"Whether the video is stored after end of stream","type":"boolean"},"s3":{"description":"Credentials to AWS S3 bucket.","nullable":true,"oneOf":[{"$ref":"#/components/schemas/S3Credentials"}],"type":"object"},"subscribeMode":{"default":"auto","description":"Whether the HLS component should subscribe to tracks automatically or manually.","enum":["auto","manual"],"type":"string"},"targetWindowDuration":{"description":"Duration of stream available for viewer","nullable":true,"type":"integer"}},"title":"ComponentOptionsHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.Options"},"S3Credentials":{"description":"An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided","properties":{"accessKeyId":{"description":"An AWS access key identifier, linked to your AWS account.","type":"string"},"bucket":{"description":"The name of the S3 bucket where your data will be stored.","type":"string"},"region":{"description":"The AWS region where your bucket is located.","type":"string"},"secretAccessKey":{"description":"The secret key that is linked to the Access Key ID.","type":"string"}},"required":["accessKeyId","secretAccessKey","region","bucket"],"title":"S3Credentials","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.S3"},"RecordingListResponse":{"description":"Response containing list of all recording","properties":{"data":{"items":{"type":"string"},"type":"array"}},"required":["data"],"title":"RecordingListResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RecordingListResponse"},"ComponentOptions":{"description":"Component-specific options","oneOf":[{"$ref":"#/components/schemas/ComponentOptionsHLS"},{"$ref":"#/components/schemas/ComponentOptionsRTSP"},{"$ref":"#/components/schemas/ComponentOptionsFile"}],"title":"ComponentOptions","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.Options"},"Track":{"description":"Describes media track of a Peer or Component","properties":{"id":{"type":"string"},"metadata":{"nullable":true},"type":{"enum":["audio","video"],"type":"string"}},"title":"Track","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Track"},"HealthReportDistribution":{"description":"Informs about the status of Jellyfish distribution","properties":{"enabled":{"description":"Whether distribution is enabled on this Jellyfish","type":"boolean"},"nodeStatus":{"$ref":"#/components/schemas/HealthReportStatus"},"nodesInCluster":{"description":"Amount of nodes (including this Jellyfish\'s node) in the distribution cluster","type":"integer"}},"required":["nodeStatus","nodesInCluster"],"title":"HealthReportDistribution","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport.Distribution"},"ComponentPropertiesRTSP":{"description":"Properties specific to the RTSP component","properties":{"keepAliveInterval":{"description":"Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source","type":"integer"},"pierceNat":{"description":"Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup","type":"boolean"},"reconnectDelay":{"description":"Delay (in ms) between successive reconnect attempts","type":"integer"},"rtpPort":{"description":"Local port RTP stream will be received at","type":"integer"},"sourceUri":{"description":"URI of RTSP source stream","type":"string"}},"required":["sourceUri","rtpPort","reconnectDelay","keepAliveInterval","pierceNat"],"title":"ComponentPropertiesRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP.Properties"},"PeerOptions":{"description":"Peer-specific options","oneOf":[{"$ref":"#/components/schemas/PeerOptionsWebRTC"}],"title":"PeerOptions","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Options"},"HealthReport":{"description":"Describes overall Jellyfish health","properties":{"distribution":{"$ref":"#/components/schemas/HealthReportDistribution"},"status":{"$ref":"#/components/schemas/HealthReportStatus"},"uptime":{"description":"Uptime of Jellyfish (in seconds)","type":"integer"}},"required":["status","uptime","distribution"],"title":"HealthReport","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport"},"Peer":{"description":"Describes peer status","properties":{"id":{"description":"Assigned peer id","example":"peer-1","type":"string"},"metadata":{"$ref":"#/components/schemas/PeerMetadata"},"status":{"$ref":"#/components/schemas/PeerStatus"},"tracks":{"description":"List of all peer\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"$ref":"#/components/schemas/PeerType"}},"required":["id","type","status","tracks","metadata"],"title":"Peer","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer"},"ComponentType":{"description":"Component type","example":"hls","title":"ComponentType","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.Type"},"AuthToken":{"description":"Token for authorizing websocket connection","example":"5cdac726-57a3-4ecb-b1d5-72a3d62ec242","title":"AuthToken","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Token"},"RoomsListingResponse":{"description":"Response containing list of all rooms","properties":{"data":{"items":{"$ref":"#/components/schemas/Room"},"type":"array"}},"required":["data"],"title":"RoomsListingResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomsListingResponse"},"PeerDetailsResponse":{"description":"Response containing peer details and their token","properties":{"data":{"properties":{"peer":{"$ref":"#/components/schemas/Peer"},"token":{"$ref":"#/components/schemas/AuthToken"}},"required":["peer","token"],"type":"object"}},"required":["data"],"title":"PeerDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.PeerDetailsResponse"},"HlsResponse":{"description":"Requested file","title":"HlsResponse","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Response"},"PeerType":{"description":"Peer type","example":"webrtc","title":"PeerType","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Type"},"RoomCreateDetailsResponse":{"description":"Response containing room details","properties":{"data":{"properties":{"jellyfish_address":{"description":"Jellyfish instance address where the room was created. This might be different than the address of Jellyfish where the request was sent only when running a cluster of Jellyfishes.","example":"jellyfish1:5003","type":"string"},"room":{"$ref":"#/components/schemas/Room"}},"required":["room","jellyfish_address"],"type":"object"}},"required":["data"],"title":"RoomCreateDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomCreateDetailsResponse"},"ComponentOptionsFile":{"description":"Options specific to the File component","properties":{"filePath":{"description":"Path to track file. Must be either OPUS encapsulated in Ogg or raw h264","example":"/root/video.h264","type":"string"},"framerate":{"description":"Framerate of video in a file. It is only valid for video track","example":30,"nullable":true,"type":"integer"}},"required":["filePath"],"title":"ComponentOptionsFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File.Options"},"Error":{"description":"Error message","properties":{"errors":{"description":"Error details","example":"Token has expired","type":"string"}},"required":["errors"],"title":"Error","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Error"},"RoomConfig":{"description":"Room configuration","properties":{"maxPeers":{"description":"Maximum amount of peers allowed into the room","example":10,"minimum":1,"nullable":true,"type":"integer"},"roomId":{"description":"Custom id used for identifying room within Jellyfish. Must be unique across all rooms. If not provided, random UUID is generated.","nullable":true,"type":"string"},"videoCodec":{"description":"Enforces video codec for each peer in the room","enum":["h264","vp8"],"nullable":true,"type":"string"},"webhookUrl":{"description":"URL where Jellyfish notifications will be sent","example":"https://backend.address.com/jellyfish-notifications-endpoint","nullable":true,"type":"string"}},"title":"RoomConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Room.Config"}},"securitySchemes":{"authorization":{"scheme":"bearer","type":"http"}}},"info":{"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0"},"title":"Jellyfish Media Server","version":"0.2.0"},"openapi":"3.0.0","paths":{"/health":{"get":{"callbacks":{},"operationId":"healthcheck","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthcheckResponse"}}},"description":"Healthy"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Describes the health of Jellyfish","tags":["health"]}},"/hls/{room_id}/subscribe":{"post":{"callbacks":{},"operationId":"subscribe_hls_to","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionConfig"}}},"description":"Subscribe configuration","required":false},"responses":{"201":{"description":"Tracks succesfully added."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Subscribe the HLS component to the tracks of peers or components","tags":["hls"]}},"/hls/{room_id}/{filename}":{"get":{"callbacks":{},"operationId":"getHlsContent","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Name of the file","in":"path","name":"filename","required":true,"schema":{"type":"string"}},{"description":"Byte range of partial segment","in":"header","name":"range","required":false,"schema":{"type":"string"}},{"description":"Segment sequence number","in":"query","name":"_HLS_msn","required":false,"schema":{"$ref":"#/components/schemas/HlsMsn"}},{"description":"Partial segment sequence number","in":"query","name":"_HLS_part","required":false,"schema":{"$ref":"#/components/schemas/HlsPart"}},{"description":"Is delta manifest requested","in":"query","name":"_HLS_skip","required":false,"schema":{"$ref":"#/components/schemas/HlsSkip"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HlsResponse"}}},"description":"File was found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid filename"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"File not found"}},"summary":"Retrieve HLS Content","tags":["hls"]}},"/recording":{"get":{"callbacks":{},"operationId":"get_recordings","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordingListResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unable to obtain recordings"}},"summary":"Lists all available recordings","tags":["recording"]}},"/recording/{recording_id}":{"delete":{"callbacks":{},"operationId":"delete_recording","parameters":[{"description":"Recording id","in":"path","name":"recording_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted recording"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid recording"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Recording doesn\'t exist"}},"summary":"Deletes the recording","tags":["recording"]}},"/recording/{recording_id}/{filename}":{"get":{"callbacks":{},"operationId":"getRecordingContent","parameters":[{"description":"Recording id","in":"path","name":"recording_id","required":true,"schema":{"type":"string"}},{"description":"Name of the file","in":"path","name":"filename","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HlsResponse"}}},"description":"File was found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"File not found"}},"summary":"Retrieve Recording (HLS) Content","tags":["recording"]}},"/room":{"get":{"callbacks":{},"operationId":"get_all_rooms","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomsListingResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Show information about all rooms","tags":["room"]},"post":{"callbacks":{},"operationId":"create_room","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomConfig"}}},"description":"Room configuration","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomCreateDetailsResponse"}}},"description":"Room successfully created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Creates a room","tags":["room"]}},"/room/{room_id}":{"delete":{"callbacks":{},"operationId":"delete_room","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted room"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Delete the room","tags":["room"]},"get":{"callbacks":{},"operationId":"get_room","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomDetailsResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Shows information about the room","tags":["room"]}},"/room/{room_id}/component":{"post":{"callbacks":{},"operationId":"add_component","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"options":{"$ref":"#/components/schemas/ComponentOptions"},"type":{"$ref":"#/components/schemas/ComponentType"}},"required":["type"],"type":"object"}}},"description":"Component config","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComponentDetailsResponse"}}},"description":"Successfully added component"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Creates the component and adds it to the room","tags":["room"]}},"/room/{room_id}/component/{id}":{"delete":{"callbacks":{},"operationId":"delete_component","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Component ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Either component or the room doesn\'t exist"}},"summary":"Delete the component from the room","tags":["room"]}},"/room/{room_id}/peer":{"post":{"callbacks":{},"operationId":"add_peer","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"options":{"$ref":"#/components/schemas/PeerOptions"},"type":{"$ref":"#/components/schemas/PeerType"}},"required":["type","options"],"type":"object"}}},"description":"Peer specification","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeerDetailsResponse"}}},"description":"Peer successfully created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request body structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Peer limit has been reached"}},"summary":"Create peer","tags":["room"]}},"/room/{room_id}/peer/{id}":{"delete":{"callbacks":{},"operationId":"delete_peer","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Peer id","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Peer successfully deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room ID or Peer ID references a resource that doesn\'t exist"}},"summary":"Delete peer","tags":["room"]}}},"security":[{"authorization":[]}],"servers":[],"tags":[]}}')}}]); \ No newline at end of file diff --git a/assets/js/4cf40d90.b1a9d32a.js b/assets/js/4cf40d90.b1a9d32a.js new file mode 100644 index 00000000..69c83118 --- /dev/null +++ b/assets/js/4cf40d90.b1a9d32a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[8e3],{8196:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=i(7624),o=i(2172);const s={},r="File",l={id:"getting_started/components/file",title:"File",description:"Publishes media stream from a local file.",source:"@site/docs/getting_started/components/file.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/file",permalink:"/jellyfish-docs/next/getting_started/components/file",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/file.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"RTSP",permalink:"/jellyfish-docs/next/getting_started/components/rtsp"},next:{title:"SIP",permalink:"/jellyfish-docs/next/getting_started/components/sip"}},c={},d=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"file",children:"File"}),"\n",(0,t.jsx)(n.p,{children:"Publishes media stream from a local file."}),"\n",(0,t.jsx)(n.p,{children:"Supports H264 for video and OPUS for audio files."}),"\n",(0,t.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/sip",children:"SIP"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["If the File component publishes a video, it does so in the H264 standard.\nIf File component publishes video and the ",(0,t.jsx)(n.a,{href:"../../introduction/basic_concepts#room",children:"Room"}),"\nin which the File component is created enforces a video codec,\nit must be set to H264.\nSee ",(0,t.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/create_room",children:"API"}),"\nfor more information."]}),"\n",(0,t.jsx)(n.li,{children:"The input file can be either audio or video"}),"\n",(0,t.jsxs)(n.li,{children:["The video must be encoded in raw H264. The framerate can be specified through ",(0,t.jsx)(n.code,{children:"framerate"})," option.\nIf not specified 30 is set as a default.\nYou can convert the video using the following ffmpeg command:\n",(0,t.jsx)(n.code,{children:"ffmpeg -i input_video -filter:v fps=30 -vcodec libx264 output.h264"})]}),"\n",(0,t.jsxs)(n.li,{children:["The audio must be monophonic, encoded in OPUS and encapsulated in Ogg container.\nYou can convert the audio using the following ffmpeg command:\n",(0,t.jsx)(n.code,{children:"ffmpeg -i input_audio -ac 1 -acodec libopus output.ogg"})]}),"\n",(0,t.jsxs)(n.li,{children:["The input files must be located inside ",(0,t.jsx)(n.code,{children:"$JF_RESOURCES_BASE_PATH/file_component_sources"})," path.\nTake a look at ",(0,t.jsx)(n.code,{children:"JF_RESOURCES_BASE_PATH"})," environment variable in the\n",(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/installation#environment-variables",children:"installation guide"})," for more info"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Required"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"filePath"})," (string) - path for media file, relative to the ",(0,t.jsx)(n.code,{children:"$JF_RESOURCES_BASE_PATH/file_component_sources"})," directory, with either ",(0,t.jsx)(n.code,{children:".ogg"})," or ",(0,t.jsx)(n.code,{children:".h264"})," extension"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,t.jsx)(n.p,{children:"Currently, there are no environment variables related to this component."})]})}function h(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},2172:(e,n,i)=>{i.d(n,{I:()=>l,M:()=>r});var t=i(1504);const o={},s=t.createContext(o);function r(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4cf40d90.f2f06a3b.js b/assets/js/4cf40d90.f2f06a3b.js deleted file mode 100644 index aa1c710f..00000000 --- a/assets/js/4cf40d90.f2f06a3b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[8e3],{8196:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var t=i(7624),o=i(2172);const s={},r="File",l={id:"getting_started/components/file",title:"File",description:"Publishes media stream from a local file.",source:"@site/docs/getting_started/components/file.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/file",permalink:"/jellyfish-docs/next/getting_started/components/file",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/file.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"RTSP",permalink:"/jellyfish-docs/next/getting_started/components/rtsp"},next:{title:"WebRTC",permalink:"/jellyfish-docs/next/getting_started/peers/webrtc"}},c={},d=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"file",children:"File"}),"\n",(0,t.jsx)(n.p,{children:"Publishes media stream from a local file."}),"\n",(0,t.jsx)(n.p,{children:"Supports H264 for video and OPUS for audio files."}),"\n",(0,t.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["If the File component publishes a video, it does so in the H264 standard.\nIf File component publishes video and the ",(0,t.jsx)(n.a,{href:"../../introduction/basic_concepts#room",children:"Room"}),"\nin which the File component is created enforces a video codec,\nit must be set to H264.\nSee ",(0,t.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/create_room",children:"API"}),"\nfor more information."]}),"\n",(0,t.jsx)(n.li,{children:"The input file can be either audio or video"}),"\n",(0,t.jsxs)(n.li,{children:["The video must be encoded in raw H264. The framerate can be specified through ",(0,t.jsx)(n.code,{children:"framerate"})," option.\nIf not specified 30 is set as a default.\nYou can convert the video using the following ffmpeg command:\n",(0,t.jsx)(n.code,{children:"ffmpeg -i input_video -filter:v fps=30 -vcodec libx264 output.h264"})]}),"\n",(0,t.jsxs)(n.li,{children:["The audio must be monophonic, encoded in OPUS and encapsulated in Ogg container.\nYou can convert the audio using the following ffmpeg command:\n",(0,t.jsx)(n.code,{children:"ffmpeg -i input_audio -ac 1 -acodec libopus output.ogg"})]}),"\n",(0,t.jsxs)(n.li,{children:["The input files must be located inside ",(0,t.jsx)(n.code,{children:"$JF_RESOURCES_BASE_PATH/file_component_sources"})," path.\nTake a look at ",(0,t.jsx)(n.code,{children:"JF_RESOURCES_BASE_PATH"})," environment variable in the\n",(0,t.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/installation#environment-variables",children:"installation guide"})," for more info"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Required"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"filePath"})," (string) - path for media file, relative to the ",(0,t.jsx)(n.code,{children:"$JF_RESOURCES_BASE_PATH/file_component_sources"})," directory, with either ",(0,t.jsx)(n.code,{children:".ogg"})," or ",(0,t.jsx)(n.code,{children:".h264"})," extension"]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,t.jsx)(n.p,{children:"Currently, there are no environment variables related to this component."})]})}function h(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},2172:(e,n,i)=>{i.d(n,{I:()=>l,M:()=>r});var t=i(1504);const o={},s=t.createContext(o);function r(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/533aebff.d63a7460.js b/assets/js/533aebff.d63a7460.js new file mode 100644 index 00000000..73c8d3f2 --- /dev/null +++ b/assets/js/533aebff.d63a7460.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[9328],{4980:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>p,frontMatter:()=>l,metadata:()=>c,toc:()=>u});var r=t(7624),o=t(2172),s=t(1268),i=t(5388);const l={},a="HLS",c={id:"getting_started/components/hls",title:"HLS",description:"Creates HLS playlist that is ready to be broadcasted via CDN.",source:"@site/docs/getting_started/components/hls.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/hls",permalink:"/jellyfish-docs/next/getting_started/components/hls",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/hls.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"Room",permalink:"/jellyfish-docs/next/getting_started/room"},next:{title:"RTSP",permalink:"/jellyfish-docs/next/getting_started/components/rtsp"}},d={},u=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2},{value:"Output",id:"output",level:2},{value:"Example Docker commands",id:"example-docker-commands",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"hls",children:"HLS"}),"\n",(0,r.jsxs)(n.p,{children:["Creates HLS playlist that is ready to be broadcasted via CDN.\nRead more about HLS ",(0,r.jsx)(n.a,{href:"https://developer.apple.com/streaming/",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/sip",children:"SIP"})}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The ",(0,r.jsx)(n.a,{href:"../../introduction/basic_concepts#room",children:"Room"})," in which the HLS component is created must have the video codec set to H264.\nSee ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/create_room",children:"API"})," for more information."]}),"\n",(0,r.jsx)(n.li,{children:"Max 1 HLS component allowed per room."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Optional"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"lowLatency"})," (boolean, default: false) - whether the component should use LL-HLS"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"persistent"})," (boolean, default: false) - whether the stream should be saved or not.\nAfter a meeting that integrates an HLS component (with the persistent option set to true) ends, the meeting is preserved as a recording.\nTo manage this recording, use the ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/recording",children:"Recording API"}),".\nThe recording is also available as ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/recording/operation/getRecordingContent",children:"HLS Video On Demand (VOD) API"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"targetWindowDuration"})," (positive integer, default: null) - represents the duration, in seconds, of the live streaming content to be\nmaintained in a rolling window. If set to null (default), the entire stream will be available."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"s3"})," (object, default: null) - AWS S3 credentials. If credentials are set, the stream will be saved to the specified bucket.\nThis solution will automatically send your streams to an AWS bucket right after the end of your meeting.\nThe uploaded stream will be accessible in the ",(0,r.jsx)(n.code,{children:"/"})," folder within the S3 bucket.\nFor the exact credential structure see ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/add_component",children:"Configuration API"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"subscribeMode"}),' (string "manual" or "auto", default: "auto") - whether HLS component should automatically start consuming available tracks.\nWhen set to ',(0,r.jsx)(n.code,{children:"manual"}),", HLS component has to be explicitly told to subscribe to a specific peer/component tracks using\nthe ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/hls/operation/subscribe_hls_to",children:"Subscription API"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.c,{children:[(0,r.jsx)(i.c,{value:"elixir",label:"Elixir",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-elixir",children:'server_address = "localhost:5002"\nserver_api_token = "development"\n\nclient = Jellyfish.Client.new(server_address: server_address, server_api_token: server_api_token)\n\n{:ok, room, _jellyfish_address} = Jellyfish.Room.create(client, video_codec: :h264)\n{:ok, peer, _peer_token} = Jellyfish.Room.add_peer(client, room.id, Jellyfish.Peer.WebRTC)\n\nhls_options = %Jellyfish.Component.HLS{subscribe_mode: :manual}\n{:ok, _component} = Jellyfish.Room.add_component(client, room.id, hls_options)\n\n:ok = Jellyfish.Room.hls_subscribe(client, room.id, [peer.id])\n'})})}),(0,r.jsx)(i.c,{value:"python",label:"Python",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"from jellyfish import RoomApi, ComponentOptionsHLS, PeerOptionsWebRTC\n\nserver_address = \"localhost:5002\"\nserver_api_token = \"development\"\n\nroom_api = RoomApi(server_address='localhost:5002', server_api_token='development')\n\njellyfish_address, room = room_api.create_room(video_codec='h264')\npeer_token, peer = room_api.add_peer(room.id, options=PeerOptionsWebRTC())\n\nhls_options = ComponentOptionsHLS(subscribe_mode=\"manual\")\ncomponent_hls = room_api.add_component(room.id, options=hls_options)\n\nroom_api.hls_subscribe(room.id, [peer.id])\n"})})})]}),"\n",(0,r.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,r.jsx)(n.p,{children:"Currently, there are no environment variables related to this component."}),"\n",(0,r.jsx)(n.h2,{id:"output",children:"Output"}),"\n",(0,r.jsxs)(n.p,{children:["After adding a WebRTC peer (and at least one track) or an RTSP component, the HLS stream will be available\nunder ",(0,r.jsx)(n.code,{children:"http:///hls//index.m3u8"})," (or ",(0,r.jsx)(n.code,{children:"https://"}),", if using TLS)."]}),"\n",(0,r.jsx)(n.h2,{id:"example-docker-commands",children:"Example Docker commands"}),"\n",(0,r.jsxs)(n.p,{children:["The HLS playlist will be created inside the Docker container. To access it from the host,\nyou need to create a volume, e.g. by adding the option ",(0,r.jsx)(n.code,{children:"-v $(pwd)/jellyfish_resources:/app/jellyfish_resources"}),"\nto your Docker command."]}),"\n",(0,r.jsx)(n.p,{children:"Other than that, your Docker commands shouldn't be affected by adding this component."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"docker run -p 8080:8080/tcp \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n -v $(pwd)/jellyfish_resources:/app/jellyfish_resources \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})})]})}function p(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},5388:(e,n,t)=>{t.d(n,{c:()=>i});t(1504);var r=t(4064);const o={tabItem:"tabItem_Ymn6"};var s=t(7624);function i(e){let{children:n,hidden:t,className:i}=e;return(0,s.jsx)("div",{role:"tabpanel",className:(0,r.c)(o.tabItem,i),hidden:t,children:n})}},1268:(e,n,t)=>{t.d(n,{c:()=>y});var r=t(1504),o=t(4064),s=t(3943),i=t(5592),l=t(5288),a=t(632),c=t(7128),d=t(1148);function u(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function h(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,c.w)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function p(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,i.Uz)(),s=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,a._M)(s),(0,r.useCallback)((e=>{if(!s)return;const n=new URLSearchParams(o.location.search);n.set(s,e),o.replace({...o.location,search:n.toString()})}),[s,o])]}function f(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,s=h(e),[i,a]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:s}))),[c,u]=m({queryString:t,groupId:o}),[f,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,s]=(0,d.IN)(t);return[o,(0,r.useCallback)((e=>{t&&s.set(e)}),[t,s])]}({groupId:o}),v=(()=>{const e=c??f;return p({value:e,tabValues:s})?e:null})();(0,l.c)((()=>{v&&a(v)}),[v]);return{selectedValue:i,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:s}))throw new Error(`Can't select invalid tab value=${e}`);a(e),u(e),b(e)}),[u,b,s]),tabValues:s}}var b=t(3664);const v={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var g=t(7624);function x(e){let{className:n,block:t,selectedValue:r,selectValue:i,tabValues:l}=e;const a=[],{blockElementScrollPositionUntilNextRender:c}=(0,s.MV)(),d=e=>{const n=e.currentTarget,t=a.indexOf(n),o=l[t].value;o!==r&&(c(n),i(o))},u=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=a.indexOf(e.currentTarget)+1;n=a[t]??a[0];break}case"ArrowLeft":{const t=a.indexOf(e.currentTarget)-1;n=a[t]??a[a.length-1];break}}n?.focus()};return(0,g.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.c)("tabs",{"tabs--block":t},n),children:l.map((e=>{let{value:n,label:t,attributes:s}=e;return(0,g.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>a.push(e),onKeyDown:u,onClick:d,...s,className:(0,o.c)("tabs__item",v.tabItem,s?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function j(e){let{lazy:n,children:t,selectedValue:o}=e;const s=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=s.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,g.jsx)("div",{className:"margin-top--md",children:s.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function _(e){const n=f(e);return(0,g.jsxs)("div",{className:(0,o.c)("tabs-container",v.tabList),children:[(0,g.jsx)(x,{...e,...n}),(0,g.jsx)(j,{...e,...n})]})}function y(e){const n=(0,b.c)();return(0,g.jsx)(_,{...e,children:u(e.children)},String(n))}},2172:(e,n,t)=>{t.d(n,{I:()=>l,M:()=>i});var r=t(1504);const o={},s=r.createContext(o);function i(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/533aebff.e5bba2f6.js b/assets/js/533aebff.e5bba2f6.js deleted file mode 100644 index ee5b7aa4..00000000 --- a/assets/js/533aebff.e5bba2f6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[9328],{4980:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>u});var r=t(7624),o=t(2172),s=t(1268),a=t(5388);const i={},l="HLS",c={id:"getting_started/components/hls",title:"HLS",description:"Creates HLS playlist that is ready to be broadcasted via CDN.",source:"@site/docs/getting_started/components/hls.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/hls",permalink:"/jellyfish-docs/next/getting_started/components/hls",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/hls.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"Room",permalink:"/jellyfish-docs/next/getting_started/room"},next:{title:"RTSP",permalink:"/jellyfish-docs/next/getting_started/components/rtsp"}},d={},u=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2},{value:"Output",id:"output",level:2},{value:"Example Docker commands",id:"example-docker-commands",level:2}];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"hls",children:"HLS"}),"\n",(0,r.jsxs)(n.p,{children:["Creates HLS playlist that is ready to be broadcasted via CDN.\nRead more about HLS ",(0,r.jsx)(n.a,{href:"https://developer.apple.com/streaming/",children:"here"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["The ",(0,r.jsx)(n.a,{href:"../../introduction/basic_concepts#room",children:"Room"})," in which the HLS component is created must have the video codec set to H264.\nSee ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/create_room",children:"API"})," for more information."]}),"\n",(0,r.jsx)(n.li,{children:"Max 1 HLS component allowed per room."}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Optional"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"lowLatency"})," (boolean, default: false) - whether the component should use LL-HLS"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"persistent"})," (boolean, default: false) - whether the stream should be saved or not.\nAfter a meeting that integrates an HLS component (with the persistent option set to true) ends, the meeting is preserved as a recording.\nTo manage this recording, use the ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/recording",children:"Recording API"}),".\nThe recording is also available as ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/recording/operation/getRecordingContent",children:"HLS Video On Demand (VOD) API"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"targetWindowDuration"})," (positive integer, default: null) - represents the duration, in seconds, of the live streaming content to be\nmaintained in a rolling window. If set to null (default), the entire stream will be available."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"s3"})," (object, default: null) - AWS S3 credentials. If credentials are set, the stream will be saved to the specified bucket.\nThis solution will automatically send your streams to an AWS bucket right after the end of your meeting.\nThe uploaded stream will be accessible in the ",(0,r.jsx)(n.code,{children:"/"})," folder within the S3 bucket.\nFor the exact credential structure see ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/add_component",children:"Configuration API"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"subscribeMode"}),' (string "manual" or "auto", default: "auto") - whether HLS component should automatically start consuming available tracks.\nWhen set to ',(0,r.jsx)(n.code,{children:"manual"}),", HLS component has to be explicitly told to subscribe to a specific peer/component tracks using\nthe ",(0,r.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/hls/operation/subscribe_hls_to",children:"Subscription API"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(s.c,{children:[(0,r.jsx)(a.c,{value:"elixir",label:"Elixir",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-elixir",children:'server_address = "localhost:5002"\nserver_api_token = "development"\n\nclient = Jellyfish.Client.new(server_address: server_address, server_api_token: server_api_token)\n\n{:ok, room, _jellyfish_address} = Jellyfish.Room.create(client, video_codec: :h264)\n{:ok, peer, _peer_token} = Jellyfish.Room.add_peer(client, room.id, Jellyfish.Peer.WebRTC)\n\nhls_options = %Jellyfish.Component.HLS{subscribe_mode: :manual}\n{:ok, _component} = Jellyfish.Room.add_component(client, room.id, hls_options)\n\n:ok = Jellyfish.Room.hls_subscribe(client, room.id, [peer.id])\n'})})}),(0,r.jsx)(a.c,{value:"python",label:"Python",children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"from jellyfish import RoomApi, ComponentOptionsHLS, PeerOptionsWebRTC\n\nserver_address = \"localhost:5002\"\nserver_api_token = \"development\"\n\nroom_api = RoomApi(server_address='localhost:5002', server_api_token='development')\n\njellyfish_address, room = room_api.create_room(video_codec='h264')\npeer_token, peer = room_api.add_peer(room.id, options=PeerOptionsWebRTC())\n\nhls_options = ComponentOptionsHLS(subscribe_mode=\"manual\")\ncomponent_hls = room_api.add_component(room.id, options=hls_options)\n\nroom_api.hls_subscribe(room.id, [peer.id])\n"})})})]}),"\n",(0,r.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,r.jsx)(n.p,{children:"Currently, there are no environment variables related to this component."}),"\n",(0,r.jsx)(n.h2,{id:"output",children:"Output"}),"\n",(0,r.jsxs)(n.p,{children:["After adding a WebRTC peer (and at least one track) or an RTSP component, the HLS stream will be available\nunder ",(0,r.jsx)(n.code,{children:"http:///hls//index.m3u8"})," (or ",(0,r.jsx)(n.code,{children:"https://"}),", if using TLS)."]}),"\n",(0,r.jsx)(n.h2,{id:"example-docker-commands",children:"Example Docker commands"}),"\n",(0,r.jsxs)(n.p,{children:["The HLS playlist will be created inside the Docker container. To access it from the host,\nyou need to create a volume, e.g. by adding the option ",(0,r.jsx)(n.code,{children:"-v $(pwd)/jellyfish_resources:/app/jellyfish_resources"}),"\nto your Docker command."]}),"\n",(0,r.jsx)(n.p,{children:"Other than that, your Docker commands shouldn't be affected by adding this component."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"docker run -p 8080:8080/tcp \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n -v $(pwd)/jellyfish_resources:/app/jellyfish_resources \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})})]})}function p(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},5388:(e,n,t)=>{t.d(n,{c:()=>a});t(1504);var r=t(4064);const o={tabItem:"tabItem_Ymn6"};var s=t(7624);function a(e){let{children:n,hidden:t,className:a}=e;return(0,s.jsx)("div",{role:"tabpanel",className:(0,r.c)(o.tabItem,a),hidden:t,children:n})}},1268:(e,n,t)=>{t.d(n,{c:()=>y});var r=t(1504),o=t(4064),s=t(3943),a=t(5592),i=t(5288),l=t(632),c=t(7128),d=t(1148);function u(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function h(e){const{values:n,children:t}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return u(e).map((e=>{let{props:{value:n,label:t,attributes:r,default:o}}=e;return{value:n,label:t,attributes:r,default:o}}))}(t);return function(e){const n=(0,c.w)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,t])}function p(e){let{value:n,tabValues:t}=e;return t.some((e=>e.value===n))}function m(e){let{queryString:n=!1,groupId:t}=e;const o=(0,a.Uz)(),s=function(e){let{queryString:n=!1,groupId:t}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!t)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return t??null}({queryString:n,groupId:t});return[(0,l._M)(s),(0,r.useCallback)((e=>{if(!s)return;const n=new URLSearchParams(o.location.search);n.set(s,e),o.replace({...o.location,search:n.toString()})}),[s,o])]}function f(e){const{defaultValue:n,queryString:t=!1,groupId:o}=e,s=h(e),[a,l]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:t}=e;if(0===t.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!p({value:n,tabValues:t}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${t.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=t.find((e=>e.default))??t[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:s}))),[c,u]=m({queryString:t,groupId:o}),[f,b]=function(e){let{groupId:n}=e;const t=function(e){return e?`docusaurus.tab.${e}`:null}(n),[o,s]=(0,d.IN)(t);return[o,(0,r.useCallback)((e=>{t&&s.set(e)}),[t,s])]}({groupId:o}),v=(()=>{const e=c??f;return p({value:e,tabValues:s})?e:null})();(0,i.c)((()=>{v&&l(v)}),[v]);return{selectedValue:a,selectValue:(0,r.useCallback)((e=>{if(!p({value:e,tabValues:s}))throw new Error(`Can't select invalid tab value=${e}`);l(e),u(e),b(e)}),[u,b,s]),tabValues:s}}var b=t(3664);const v={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var g=t(7624);function x(e){let{className:n,block:t,selectedValue:r,selectValue:a,tabValues:i}=e;const l=[],{blockElementScrollPositionUntilNextRender:c}=(0,s.MV)(),d=e=>{const n=e.currentTarget,t=l.indexOf(n),o=i[t].value;o!==r&&(c(n),a(o))},u=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const t=l.indexOf(e.currentTarget)+1;n=l[t]??l[0];break}case"ArrowLeft":{const t=l.indexOf(e.currentTarget)-1;n=l[t]??l[l.length-1];break}}n?.focus()};return(0,g.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,o.c)("tabs",{"tabs--block":t},n),children:i.map((e=>{let{value:n,label:t,attributes:s}=e;return(0,g.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>l.push(e),onKeyDown:u,onClick:d,...s,className:(0,o.c)("tabs__item",v.tabItem,s?.className,{"tabs__item--active":r===n}),children:t??n},n)}))})}function j(e){let{lazy:n,children:t,selectedValue:o}=e;const s=(Array.isArray(t)?t:[t]).filter(Boolean);if(n){const e=s.find((e=>e.props.value===o));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,g.jsx)("div",{className:"margin-top--md",children:s.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==o})))})}function _(e){const n=f(e);return(0,g.jsxs)("div",{className:(0,o.c)("tabs-container",v.tabList),children:[(0,g.jsx)(x,{...e,...n}),(0,g.jsx)(j,{...e,...n})]})}function y(e){const n=(0,b.c)();return(0,g.jsx)(_,{...e,children:u(e.children)},String(n))}},2172:(e,n,t)=>{t.d(n,{I:()=>i,M:()=>a});var r=t(1504);const o={},s=r.createContext(o);function a(e){const n=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6915c912.6ce1f9d0.js b/assets/js/6915c912.6ce1f9d0.js new file mode 100644 index 00000000..2fe32a73 --- /dev/null +++ b/assets/js/6915c912.6ce1f9d0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[674],{1300:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var i=n(7624),s=n(2172);const r={},o="SIP",l={id:"getting_started/components/sip",title:"SIP",description:"Makes a SIP connection with the specified provider.",source:"@site/docs/getting_started/components/sip.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/sip",permalink:"/jellyfish-docs/next/getting_started/components/sip",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/sip.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"File",permalink:"/jellyfish-docs/next/getting_started/components/file"},next:{title:"WebRTC",permalink:"/jellyfish-docs/next/getting_started/peers/webrtc"}},c={},d=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2}];function a(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"sip",children:"SIP"}),"\n",(0,i.jsxs)(t.p,{children:["Makes a SIP connection with the specified provider.\nFrom this connection it consumes a remote RTP stream with G711 A-law audio\nand publishes through this connection all audio tracks from the ",(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/room",children:"Room"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Read more about SIP ",(0,i.jsx)(t.a,{href:"https://www.rfc-editor.org/rfc/rfc3261.html",children:"here"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"requirements",children:"Requirements"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"The specified SIP provider needs to support G711 A-law as it will be a format in which audio from\nSIP Endpoint will be published."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Required"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"registrarCredentials"})," (object) - registrar credentials which allows to make a connection with a SIP provider.\nFor the exact credential structure see ",(0,i.jsx)(t.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/add_component",children:"Configuration API"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"JF_SIP_USED"})," - has to be ",(0,i.jsx)(t.code,{children:"true"})," if SIP component will be used"]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.code,{children:"JF_SIP_IP"})," - the IP address on which SIP server will listen. It must be a public IP and reachable from the outside network."]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,s.M)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},2172:(e,t,n)=>{n.d(t,{I:()=>l,M:()=>o});var i=n(1504);const s={},r=i.createContext(s);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/78c80559.167e7769.js b/assets/js/78c80559.167e7769.js deleted file mode 100644 index aa89840c..00000000 --- a/assets/js/78c80559.167e7769.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[9048],{4048:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>c,toc:()=>a});var s=t(7624),i=t(2172);const r={},o="RTSP",c={id:"getting_started/components/rtsp",title:"RTSP",description:"Consumes a remote RTSP stream (e.g. from an IP camera).",source:"@site/docs/getting_started/components/rtsp.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/rtsp",permalink:"/jellyfish-docs/next/getting_started/components/rtsp",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/rtsp.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"HLS",permalink:"/jellyfish-docs/next/getting_started/components/hls"},next:{title:"File",permalink:"/jellyfish-docs/next/getting_started/components/file"}},l={},a=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2},{value:"Example Docker commands",id:"example-docker-commands",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"rtsp",children:"RTSP"}),"\n",(0,s.jsx)(n.p,{children:"Consumes a remote RTSP stream (e.g. from an IP camera).\nThe RTSP component initializes communication by connecting to\na remote source and requesting its stream."}),"\n",(0,s.jsx)(n.p,{children:"Supports H264 streams only."}),"\n",(0,s.jsxs)(n.p,{children:["Read more about RTSP ",(0,s.jsx)(n.a,{href:"https://www.rfc-editor.org/rfc/rfc2326.html",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["RTSP component always outputs H264 stream so if the ",(0,s.jsx)(n.a,{href:"../../introduction/basic_concepts#room",children:"Room"})," in which the RTSP component is created enforces a video codec,\nit must be set to H264.\nSee ",(0,s.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/create_room",children:"API"})," for more information."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Required"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"sourceUri"})," (string) - URI of RTSP source stream, e.g. ",(0,s.jsx)(n.code,{children:'"rtsp://mysite.net:554/stream"'})]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Optional"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"rtpPort"})," (integer 1..65535, default: 20000) - Local port RTP stream will be received at"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"reconnectDelay"})," (integer 0.., default: 15000) - Delay (in ms) between successive reconnect attempts"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"keepAliveInterval"})," (integer 0.., default: 15000) - Interval (in ms) in which keep-alive\nRTSP messages will be sent to the remote stream source"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"pierceNat"})," (boolean, default: true) - Whether to attempt to create client-side NAT binding\nby sending an empty datagram from client to source, after the completion of RTSP setup"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,s.jsx)(n.p,{children:"Currently, there are no environment variables related to this component."}),"\n",(0,s.jsx)(n.h2,{id:"example-docker-commands",children:"Example Docker commands"}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["If the client is behind NAT, the option ",(0,s.jsx)(n.code,{children:"--network=host"})," is necessary\nsince Docker can change the source port of UDP packets for routing reasons,\nwhich breaks the ",(0,s.jsx)(n.code,{children:"pierceNat"})," functionality."]}),(0,s.jsx)(n.p,{children:"This means that users on macOS will most likely be unable to access any\nRTSP stream source outside of their network when running Jellyfish using Docker."}),(0,s.jsxs)(n.p,{children:["If you're on macOS and want to receive RTSP streams from behind NAT,\nright now the only way is to ",(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/installation#building-from-source",children:"build Jellyfish natively from source"}),"."]})]}),"\n",(0,s.jsx)(n.p,{children:"Explicit port exposure (macOS compatible)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -p 20000:20000/udp \\\n -p 8080:8080/tcp \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["Make sure that the exposed UDP port matches the one used by the RTSP component\n(option ",(0,s.jsx)(n.code,{children:"rtpPort"}),", default: 20000)."]}),(0,s.jsx)(n.p,{children:"If using multiple RTSP components, more ports will need to be exposed."})]}),"\n",(0,s.jsx)(n.p,{children:"Using host network (Linux only)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run --network=host \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>c,M:()=>o});var s=t(1504);const i={},r=s.createContext(i);function o(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/78c80559.afbde9c6.js b/assets/js/78c80559.afbde9c6.js new file mode 100644 index 00000000..f54ac6d4 --- /dev/null +++ b/assets/js/78c80559.afbde9c6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[9048],{4048:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>a});var s=t(7624),i=t(2172);const r={},o="RTSP",l={id:"getting_started/components/rtsp",title:"RTSP",description:"Consumes a remote RTSP stream (e.g. from an IP camera).",source:"@site/docs/getting_started/components/rtsp.md",sourceDirName:"getting_started/components",slug:"/getting_started/components/rtsp",permalink:"/jellyfish-docs/next/getting_started/components/rtsp",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/components/rtsp.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"HLS",permalink:"/jellyfish-docs/next/getting_started/components/hls"},next:{title:"File",permalink:"/jellyfish-docs/next/getting_started/components/file"}},c={},a=[{value:"Compatibility",id:"compatibility",level:2},{value:"Requirements",id:"requirements",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2},{value:"Example Docker commands",id:"example-docker-commands",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"rtsp",children:"RTSP"}),"\n",(0,s.jsx)(n.p,{children:"Consumes a remote RTSP stream (e.g. from an IP camera).\nThe RTSP component initializes communication by connecting to\na remote source and requesting its stream."}),"\n",(0,s.jsx)(n.p,{children:"Supports H264 streams only."}),"\n",(0,s.jsxs)(n.p,{children:["Read more about RTSP ",(0,s.jsx)(n.a,{href:"https://www.rfc-editor.org/rfc/rfc2326.html",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"WebRTC"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/sip",children:"SIP"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"requirements",children:"Requirements"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["RTSP component always outputs H264 stream so if the ",(0,s.jsx)(n.a,{href:"../../introduction/basic_concepts#room",children:"Room"})," in which the RTSP component is created enforces a video codec,\nit must be set to H264.\nSee ",(0,s.jsx)(n.a,{href:"../../for_developers/api_reference/rest_api#tag/room/operation/create_room",children:"API"})," for more information."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Required"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"sourceUri"})," (string) - URI of RTSP source stream, e.g. ",(0,s.jsx)(n.code,{children:'"rtsp://mysite.net:554/stream"'})]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Optional"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"rtpPort"})," (integer 1..65535, default: 20000) - Local port RTP stream will be received at"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"reconnectDelay"})," (integer 0.., default: 15000) - Delay (in ms) between successive reconnect attempts"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"keepAliveInterval"})," (integer 0.., default: 15000) - Interval (in ms) in which keep-alive\nRTSP messages will be sent to the remote stream source"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"pierceNat"})," (boolean, default: true) - Whether to attempt to create client-side NAT binding\nby sending an empty datagram from client to source, after the completion of RTSP setup"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,s.jsx)(n.p,{children:"Currently, there are no environment variables related to this component."}),"\n",(0,s.jsx)(n.h2,{id:"example-docker-commands",children:"Example Docker commands"}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["If the client is behind NAT, the option ",(0,s.jsx)(n.code,{children:"--network=host"})," is necessary\nsince Docker can change the source port of UDP packets for routing reasons,\nwhich breaks the ",(0,s.jsx)(n.code,{children:"pierceNat"})," functionality."]}),(0,s.jsx)(n.p,{children:"This means that users on macOS will most likely be unable to access any\nRTSP stream source outside of their network when running Jellyfish using Docker."}),(0,s.jsxs)(n.p,{children:["If you're on macOS and want to receive RTSP streams from behind NAT,\nright now the only way is to ",(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/installation#building-from-source",children:"build Jellyfish natively from source"}),"."]})]}),"\n",(0,s.jsx)(n.p,{children:"Explicit port exposure (macOS compatible)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -p 20000:20000/udp \\\n -p 8080:8080/tcp \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})}),"\n",(0,s.jsxs)(n.admonition,{type:"caution",children:[(0,s.jsxs)(n.p,{children:["Make sure that the exposed UDP port matches the one used by the RTSP component\n(option ",(0,s.jsx)(n.code,{children:"rtpPort"}),", default: 20000)."]}),(0,s.jsx)(n.p,{children:"If using multiple RTSP components, more ports will need to be exposed."})]}),"\n",(0,s.jsx)(n.p,{children:"Using host network (Linux only)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run --network=host \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>l,M:()=>o});var s=t(1504);const i={},r=s.createContext(i);function o(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.44c32120.js b/assets/js/935f2afb.44c32120.js deleted file mode 100644 index da672d3a..00000000 --- a/assets/js/935f2afb.44c32120.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[5696],{5988:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"mainSidebar":[{"type":"category","label":"Introduction","collapsed":false,"items":[{"type":"link","label":"What is Jellyfish?","href":"/jellyfish-docs/next/","docId":"introduction/what_is_jellyfish","unlisted":false},{"type":"link","label":"Basic Concepts","href":"/jellyfish-docs/next/introduction/basic_concepts","docId":"introduction/basic_concepts","unlisted":false},{"type":"link","label":"Example Scenarios","href":"/jellyfish-docs/next/introduction/example_scenarios","docId":"introduction/example_scenarios","unlisted":false}],"collapsible":true},{"type":"category","label":"Getting Started","collapsed":true,"items":[{"type":"link","label":"Installation","href":"/jellyfish-docs/next/getting_started/installation","docId":"getting_started/installation","unlisted":false},{"type":"link","label":"Architecture","href":"/jellyfish-docs/next/getting_started/architecture","docId":"getting_started/architecture","unlisted":false},{"type":"link","label":"Authentication","href":"/jellyfish-docs/next/getting_started/authentication","docId":"getting_started/authentication","unlisted":false},{"type":"link","label":"Notifications","href":"/jellyfish-docs/next/getting_started/notifications","docId":"getting_started/notifications","unlisted":false},{"type":"link","label":"Metrics","href":"/jellyfish-docs/next/getting_started/metrics","docId":"getting_started/metrics","unlisted":false},{"type":"link","label":"SDKs","href":"/jellyfish-docs/next/getting_started/sdks","docId":"getting_started/sdks","unlisted":false},{"type":"link","label":"Room","href":"/jellyfish-docs/next/getting_started/room","docId":"getting_started/room","unlisted":false},{"type":"category","label":"Components","collapsed":true,"items":[{"type":"link","label":"HLS","href":"/jellyfish-docs/next/getting_started/components/hls","docId":"getting_started/components/hls","unlisted":false},{"type":"link","label":"RTSP","href":"/jellyfish-docs/next/getting_started/components/rtsp","docId":"getting_started/components/rtsp","unlisted":false},{"type":"link","label":"File","href":"/jellyfish-docs/next/getting_started/components/file","docId":"getting_started/components/file","unlisted":false}],"collapsible":true},{"type":"category","label":"Peers","collapsed":true,"items":[{"type":"link","label":"WebRTC","href":"/jellyfish-docs/next/getting_started/peers/webrtc","docId":"getting_started/peers/webrtc","unlisted":false}],"collapsible":true}],"collapsible":true},{"type":"category","label":"Tutorials","collapsed":true,"items":[{"type":"category","label":"Minimal Working Examples","collapsible":false,"collapsed":false,"items":[{"type":"link","label":"Jellyfish Dashboard","href":"/jellyfish-docs/next/tutorials/dashboard","docId":"tutorials/dashboard","unlisted":false},{"type":"link","label":"Simple React App","href":"/jellyfish-docs/next/tutorials/simple-react-app","docId":"tutorials/simple-react-app","unlisted":false},{"type":"link","label":"React Native","href":"/jellyfish-docs/next/tutorials/react-native","docId":"tutorials/react-native","unlisted":false}]}],"collapsible":true},{"type":"link","label":"Cluster","href":"/jellyfish-docs/next/cluster","docId":"cluster","unlisted":false},{"type":"category","label":"Deploying","collapsed":true,"items":[{"type":"link","label":"Cloud VPS with cloud-init","href":"/jellyfish-docs/next/deploying/vps","docId":"deploying/vps","unlisted":false},{"type":"link","label":"Fly.io (experimental)","href":"/jellyfish-docs/next/deploying/fly_io","docId":"deploying/fly_io","unlisted":false}],"collapsible":true},{"type":"category","label":"Benchmarks","collapsed":true,"items":[{"type":"link","label":"HLS","href":"/jellyfish-docs/next/benchmarks/hls","docId":"benchmarks/hls","unlisted":false},{"type":"link","label":"WebRTC","href":"/jellyfish-docs/next/benchmarks/webrtc","docId":"benchmarks/webrtc","unlisted":false}],"collapsible":true,"href":"/jellyfish-docs/next/benchmarks"},{"type":"category","label":"For Developers","items":[{"type":"link","label":"Design Docs","href":"/jellyfish-docs/next/for_developers/design_docs","docId":"for_developers/design_docs","unlisted":false},{"type":"link","label":"Metrics Design","href":"/jellyfish-docs/next/for_developers/metrics_design","docId":"for_developers/metrics_design","unlisted":false},{"type":"category","label":"API Reference","collapsed":true,"items":[{"type":"link","label":"Rest API","href":"/jellyfish-docs/next/for_developers/api_reference/rest_api","docId":"for_developers/api_reference/rest_api","unlisted":false}],"collapsible":true,"href":"/jellyfish-docs/next/for_developers/api_reference"}],"collapsed":true,"collapsible":true},{"type":"link","label":"Release Notes","href":"/jellyfish-docs/next/release_notes","docId":"release_notes","unlisted":false}]},"docs":{"benchmarks":{"id":"benchmarks","title":"Benchmarks","description":"Performance tests for our Jellyfish media server were carried out with particular emphasis","sidebar":"mainSidebar"},"benchmarks/hls":{"id":"benchmarks/hls","title":"HLS","description":"The conducted stress tests were geared towards assessing performance of both regular HLS","sidebar":"mainSidebar"},"benchmarks/webrtc":{"id":"benchmarks/webrtc","title":"WebRTC","description":"The WebRTC tests conducted for the Jellyfish media server aimed to assess its performance and reliability in handling real-time communication scenarios, replicating real-life online meetings.","sidebar":"mainSidebar"},"cluster":{"id":"cluster","title":"Cluster","description":"Jellyfish comes with a built-in clustering mechanism.","sidebar":"mainSidebar"},"deploying/fly_io":{"id":"deploying/fly_io","title":"Fly.io (experimental)","description":"This deployment guide is experimental and may not reliably work each time or for every user.","sidebar":"mainSidebar"},"deploying/vps":{"id":"deploying/vps","title":"Cloud VPS with cloud-init","description":"We\'re encouraging you to use VPS as the most customizable option.","sidebar":"mainSidebar"},"examples":{"id":"examples","title":"Examples","description":"Jellyfish usage examples utilising server SDKs can be found in the following locations:"},"for_developers/api_reference":{"id":"for_developers/api_reference","title":"API Reference","description":"Jellyfish API is composed of three layers","sidebar":"mainSidebar"},"for_developers/api_reference/rest_api":{"id":"for_developers/api_reference/rest_api","title":"Rest API","description":"","sidebar":"mainSidebar"},"for_developers/design_docs":{"id":"for_developers/design_docs","title":"Design Docs","description":"Crucial parts of Jellyfish architecture are always discussed and written down in the form","sidebar":"mainSidebar"},"for_developers/metrics_design":{"id":"for_developers/metrics_design","title":"Metrics Design","description":"Currently, jellyfish exposed a few metrics, which included a label room_id.","sidebar":"mainSidebar"},"getting_started/architecture":{"id":"getting_started/architecture","title":"Architecture","description":"Jellyfish ships with a couple of SDKs that make it easier to manage its state, as well as","sidebar":"mainSidebar"},"getting_started/authentication":{"id":"getting_started/authentication","title":"Authentication","description":"The Authentication mechanism is based on a bearer token.","sidebar":"mainSidebar"},"getting_started/components/file":{"id":"getting_started/components/file","title":"File","description":"Publishes media stream from a local file.","sidebar":"mainSidebar"},"getting_started/components/hls":{"id":"getting_started/components/hls","title":"HLS","description":"Creates HLS playlist that is ready to be broadcasted via CDN.","sidebar":"mainSidebar"},"getting_started/components/rtsp":{"id":"getting_started/components/rtsp","title":"RTSP","description":"Consumes a remote RTSP stream (e.g. from an IP camera).","sidebar":"mainSidebar"},"getting_started/installation":{"id":"getting_started/installation","title":"Installation","description":"There are two ways of running Jellyfish:","sidebar":"mainSidebar"},"getting_started/metrics":{"id":"getting_started/metrics","title":"Metrics","description":"Jellyfish exports several metrics in the Prometheus format.","sidebar":"mainSidebar"},"getting_started/notifications":{"id":"getting_started/notifications","title":"Notifications","description":"Jellyfish sends server side notifications whenever some important event occurs, e.g.:","sidebar":"mainSidebar"},"getting_started/peers/webrtc":{"id":"getting_started/peers/webrtc","title":"WebRTC","description":"WebRTC peer allows you to connect to Jellyfish via WebRTC standard.","sidebar":"mainSidebar"},"getting_started/room":{"id":"getting_started/room","title":"Room","description":"The holder for peers and components.","sidebar":"mainSidebar"},"getting_started/sdks":{"id":"getting_started/sdks","title":"SDKs","description":"See here for more information about client and server SDKs.","sidebar":"mainSidebar"},"introduction/basic_concepts":{"id":"introduction/basic_concepts","title":"Basic Concepts","description":"This section outlines Jellyfish building blocks. We suggest reading this before","sidebar":"mainSidebar"},"introduction/example_scenarios":{"id":"introduction/example_scenarios","title":"Example Scenarios","description":"Below, we present example scenarios that can be achieved with Jellyfish.","sidebar":"mainSidebar"},"introduction/what_is_jellyfish":{"id":"introduction/what_is_jellyfish","title":"What is Jellyfish?","description":"Jellyfish is an open-source, general-purpose media server that ships with support for multiple media protocols.","sidebar":"mainSidebar"},"release_notes":{"id":"release_notes","title":"Release Notes","description":"0.3.0 - 09.01.2024","sidebar":"mainSidebar"},"tutorials/dashboard":{"id":"tutorials/dashboard","title":"Jellyfish Dashboard","description":"What is Jellyfish Dashboard?","sidebar":"mainSidebar"},"tutorials/react-native":{"id":"tutorials/react-native","title":"React Native","description":"This guide expects that you have read Basic Concepts and Example Scenarios","sidebar":"mainSidebar"},"tutorials/simple-react-app":{"id":"tutorials/simple-react-app","title":"Simple React App","description":"What you\'ll learn","sidebar":"mainSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/935f2afb.743732c8.js b/assets/js/935f2afb.743732c8.js new file mode 100644 index 00000000..5202f90c --- /dev/null +++ b/assets/js/935f2afb.743732c8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[5696],{5988:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"mainSidebar":[{"type":"category","label":"Introduction","collapsed":false,"items":[{"type":"link","label":"What is Jellyfish?","href":"/jellyfish-docs/next/","docId":"introduction/what_is_jellyfish","unlisted":false},{"type":"link","label":"Basic Concepts","href":"/jellyfish-docs/next/introduction/basic_concepts","docId":"introduction/basic_concepts","unlisted":false},{"type":"link","label":"Example Scenarios","href":"/jellyfish-docs/next/introduction/example_scenarios","docId":"introduction/example_scenarios","unlisted":false}],"collapsible":true},{"type":"category","label":"Getting Started","collapsed":true,"items":[{"type":"link","label":"Installation","href":"/jellyfish-docs/next/getting_started/installation","docId":"getting_started/installation","unlisted":false},{"type":"link","label":"Architecture","href":"/jellyfish-docs/next/getting_started/architecture","docId":"getting_started/architecture","unlisted":false},{"type":"link","label":"Authentication","href":"/jellyfish-docs/next/getting_started/authentication","docId":"getting_started/authentication","unlisted":false},{"type":"link","label":"Notifications","href":"/jellyfish-docs/next/getting_started/notifications","docId":"getting_started/notifications","unlisted":false},{"type":"link","label":"Metrics","href":"/jellyfish-docs/next/getting_started/metrics","docId":"getting_started/metrics","unlisted":false},{"type":"link","label":"SDKs","href":"/jellyfish-docs/next/getting_started/sdks","docId":"getting_started/sdks","unlisted":false},{"type":"link","label":"Room","href":"/jellyfish-docs/next/getting_started/room","docId":"getting_started/room","unlisted":false},{"type":"category","label":"Components","collapsed":true,"items":[{"type":"link","label":"HLS","href":"/jellyfish-docs/next/getting_started/components/hls","docId":"getting_started/components/hls","unlisted":false},{"type":"link","label":"RTSP","href":"/jellyfish-docs/next/getting_started/components/rtsp","docId":"getting_started/components/rtsp","unlisted":false},{"type":"link","label":"File","href":"/jellyfish-docs/next/getting_started/components/file","docId":"getting_started/components/file","unlisted":false},{"type":"link","label":"SIP","href":"/jellyfish-docs/next/getting_started/components/sip","docId":"getting_started/components/sip","unlisted":false}],"collapsible":true},{"type":"category","label":"Peers","collapsed":true,"items":[{"type":"link","label":"WebRTC","href":"/jellyfish-docs/next/getting_started/peers/webrtc","docId":"getting_started/peers/webrtc","unlisted":false}],"collapsible":true}],"collapsible":true},{"type":"category","label":"Tutorials","collapsed":true,"items":[{"type":"category","label":"Minimal Working Examples","collapsible":false,"collapsed":false,"items":[{"type":"link","label":"Jellyfish Dashboard","href":"/jellyfish-docs/next/tutorials/dashboard","docId":"tutorials/dashboard","unlisted":false},{"type":"link","label":"Simple React App","href":"/jellyfish-docs/next/tutorials/simple-react-app","docId":"tutorials/simple-react-app","unlisted":false},{"type":"link","label":"React Native","href":"/jellyfish-docs/next/tutorials/react-native","docId":"tutorials/react-native","unlisted":false}]}],"collapsible":true},{"type":"link","label":"Cluster","href":"/jellyfish-docs/next/cluster","docId":"cluster","unlisted":false},{"type":"category","label":"Deploying","collapsed":true,"items":[{"type":"link","label":"Cloud VPS with cloud-init","href":"/jellyfish-docs/next/deploying/vps","docId":"deploying/vps","unlisted":false},{"type":"link","label":"Fly.io (experimental)","href":"/jellyfish-docs/next/deploying/fly_io","docId":"deploying/fly_io","unlisted":false}],"collapsible":true},{"type":"category","label":"Benchmarks","collapsed":true,"items":[{"type":"link","label":"HLS","href":"/jellyfish-docs/next/benchmarks/hls","docId":"benchmarks/hls","unlisted":false},{"type":"link","label":"WebRTC","href":"/jellyfish-docs/next/benchmarks/webrtc","docId":"benchmarks/webrtc","unlisted":false}],"collapsible":true,"href":"/jellyfish-docs/next/benchmarks"},{"type":"category","label":"For Developers","items":[{"type":"link","label":"Design Docs","href":"/jellyfish-docs/next/for_developers/design_docs","docId":"for_developers/design_docs","unlisted":false},{"type":"link","label":"Metrics Design","href":"/jellyfish-docs/next/for_developers/metrics_design","docId":"for_developers/metrics_design","unlisted":false},{"type":"category","label":"API Reference","collapsed":true,"items":[{"type":"link","label":"Rest API","href":"/jellyfish-docs/next/for_developers/api_reference/rest_api","docId":"for_developers/api_reference/rest_api","unlisted":false}],"collapsible":true,"href":"/jellyfish-docs/next/for_developers/api_reference"}],"collapsed":true,"collapsible":true},{"type":"link","label":"Release Notes","href":"/jellyfish-docs/next/release_notes","docId":"release_notes","unlisted":false}]},"docs":{"benchmarks":{"id":"benchmarks","title":"Benchmarks","description":"Performance tests for our Jellyfish media server were carried out with particular emphasis","sidebar":"mainSidebar"},"benchmarks/hls":{"id":"benchmarks/hls","title":"HLS","description":"The conducted stress tests were geared towards assessing performance of both regular HLS","sidebar":"mainSidebar"},"benchmarks/webrtc":{"id":"benchmarks/webrtc","title":"WebRTC","description":"The WebRTC tests conducted for the Jellyfish media server aimed to assess its performance and reliability in handling real-time communication scenarios, replicating real-life online meetings.","sidebar":"mainSidebar"},"cluster":{"id":"cluster","title":"Cluster","description":"Jellyfish comes with a built-in clustering mechanism.","sidebar":"mainSidebar"},"deploying/fly_io":{"id":"deploying/fly_io","title":"Fly.io (experimental)","description":"This deployment guide is experimental and may not reliably work each time or for every user.","sidebar":"mainSidebar"},"deploying/vps":{"id":"deploying/vps","title":"Cloud VPS with cloud-init","description":"We\'re encouraging you to use VPS as the most customizable option.","sidebar":"mainSidebar"},"examples":{"id":"examples","title":"Examples","description":"Jellyfish usage examples utilising server SDKs can be found in the following locations:"},"for_developers/api_reference":{"id":"for_developers/api_reference","title":"API Reference","description":"Jellyfish API is composed of three layers","sidebar":"mainSidebar"},"for_developers/api_reference/rest_api":{"id":"for_developers/api_reference/rest_api","title":"Rest API","description":"","sidebar":"mainSidebar"},"for_developers/design_docs":{"id":"for_developers/design_docs","title":"Design Docs","description":"Crucial parts of Jellyfish architecture are always discussed and written down in the form","sidebar":"mainSidebar"},"for_developers/metrics_design":{"id":"for_developers/metrics_design","title":"Metrics Design","description":"Currently, jellyfish exposed a few metrics, which included a label room_id.","sidebar":"mainSidebar"},"getting_started/architecture":{"id":"getting_started/architecture","title":"Architecture","description":"Jellyfish ships with a couple of SDKs that make it easier to manage its state, as well as","sidebar":"mainSidebar"},"getting_started/authentication":{"id":"getting_started/authentication","title":"Authentication","description":"The Authentication mechanism is based on a bearer token.","sidebar":"mainSidebar"},"getting_started/components/file":{"id":"getting_started/components/file","title":"File","description":"Publishes media stream from a local file.","sidebar":"mainSidebar"},"getting_started/components/hls":{"id":"getting_started/components/hls","title":"HLS","description":"Creates HLS playlist that is ready to be broadcasted via CDN.","sidebar":"mainSidebar"},"getting_started/components/rtsp":{"id":"getting_started/components/rtsp","title":"RTSP","description":"Consumes a remote RTSP stream (e.g. from an IP camera).","sidebar":"mainSidebar"},"getting_started/components/sip":{"id":"getting_started/components/sip","title":"SIP","description":"Makes a SIP connection with the specified provider.","sidebar":"mainSidebar"},"getting_started/installation":{"id":"getting_started/installation","title":"Installation","description":"There are two ways of running Jellyfish:","sidebar":"mainSidebar"},"getting_started/metrics":{"id":"getting_started/metrics","title":"Metrics","description":"Jellyfish exports several metrics in the Prometheus format.","sidebar":"mainSidebar"},"getting_started/notifications":{"id":"getting_started/notifications","title":"Notifications","description":"Jellyfish sends server side notifications whenever some important event occurs, e.g.:","sidebar":"mainSidebar"},"getting_started/peers/webrtc":{"id":"getting_started/peers/webrtc","title":"WebRTC","description":"WebRTC peer allows you to connect to Jellyfish via WebRTC standard.","sidebar":"mainSidebar"},"getting_started/room":{"id":"getting_started/room","title":"Room","description":"The holder for peers and components.","sidebar":"mainSidebar"},"getting_started/sdks":{"id":"getting_started/sdks","title":"SDKs","description":"See here for more information about client and server SDKs.","sidebar":"mainSidebar"},"introduction/basic_concepts":{"id":"introduction/basic_concepts","title":"Basic Concepts","description":"This section outlines Jellyfish building blocks. We suggest reading this before","sidebar":"mainSidebar"},"introduction/example_scenarios":{"id":"introduction/example_scenarios","title":"Example Scenarios","description":"Below, we present example scenarios that can be achieved with Jellyfish.","sidebar":"mainSidebar"},"introduction/what_is_jellyfish":{"id":"introduction/what_is_jellyfish","title":"What is Jellyfish?","description":"Jellyfish is an open-source, general-purpose media server that ships with support for multiple media protocols.","sidebar":"mainSidebar"},"release_notes":{"id":"release_notes","title":"Release Notes","description":"0.3.0 - 09.01.2024","sidebar":"mainSidebar"},"tutorials/dashboard":{"id":"tutorials/dashboard","title":"Jellyfish Dashboard","description":"What is Jellyfish Dashboard?","sidebar":"mainSidebar"},"tutorials/react-native":{"id":"tutorials/react-native","title":"React Native","description":"This guide expects that you have read Basic Concepts and Example Scenarios","sidebar":"mainSidebar"},"tutorials/simple-react-app":{"id":"tutorials/simple-react-app","title":"Simple React App","description":"What you\'ll learn","sidebar":"mainSidebar"}}}')}}]); \ No newline at end of file diff --git a/assets/js/a1054fe7.0c340423.js b/assets/js/a1054fe7.0c340423.js new file mode 100644 index 00000000..95b76636 --- /dev/null +++ b/assets/js/a1054fe7.0c340423.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[940],{4224:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=t(7624),i=t(2172);const r={},l="WebRTC",o={id:"getting_started/peers/webrtc",title:"WebRTC",description:"WebRTC peer allows you to connect to Jellyfish via WebRTC standard.",source:"@site/docs/getting_started/peers/webrtc.md",sourceDirName:"getting_started/peers",slug:"/getting_started/peers/webrtc",permalink:"/jellyfish-docs/next/getting_started/peers/webrtc",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/peers/webrtc.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"SIP",permalink:"/jellyfish-docs/next/getting_started/components/sip"},next:{title:"Jellyfish Dashboard",permalink:"/jellyfish-docs/next/tutorials/dashboard"}},c={},d=[{value:"Compatibility",id:"compatibility",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2},{value:"Example Docker commands",id:"example-docker-commands",level:2}];function a(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"webrtc",children:"WebRTC"}),"\n",(0,s.jsx)(n.p,{children:"WebRTC peer allows you to connect to Jellyfish via WebRTC standard."}),"\n",(0,s.jsxs)(n.p,{children:["Read more about WebRTC ",(0,s.jsx)(n.a,{href:"https://webrtc.org/",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/sip",children:"SIP"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Optional"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"enableSimulcast"})," (boolean, default: true) - Enables the peer to use simulcast"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_USED"})," - has to be ",(0,s.jsx)(n.code,{children:"true"})," if WebRTC peers will be used"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_LISTEN_IP"})," - the IP address on which TURN servers will listen.\nBy default set to ",(0,s.jsx)(n.code,{children:"127.0.0.1"}),".\nWhen running Jellyfish via Docker, this MUST be set to ",(0,s.jsx)(n.code,{children:"0.0.0.0"}),", even for local tests."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_IP"})," - the IP address, under which TURN will present itself to the clients. By default set to ",(0,s.jsx)(n.code,{children:"127.0.0.1"}),".\nWhen running Jellyfish via Docker, this MUST be set to real (non-loopback) address, even for local tests."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_PORT_RANGE"})," - port range, where UDP TURN will try to open ports. By default set to ",(0,s.jsx)(n.code,{children:"50000-59999"}),".\nThe bigger the range is, the more users server will be able to handle.\nUseful when not using the ",(0,s.jsx)(n.code,{children:"--network=host"})," option to limit the UDP ports\nused only to ones published from a Docker container."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_TCP_PORT"})," - port number of TCP TURN"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"example-docker-commands",children:"Example Docker commands"}),"\n",(0,s.jsx)(n.p,{children:"Explicit port exposure (macOS compatible)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -p 50000-50050:50000-50050/udp \\\n -p 8080:8080/tcp \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n -e JF_WEBRTC_USED=true \\\n -e JF_WEBRTC_TURN_PORT_RANGE=50000-50050 \\\n -e JF_WEBRTC_TURN_IP=192.168.0.1 \\\n -e JF_WEBRTC_TURN_LISTEN_IP=0.0.0.0 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["Make sure that the exposed UDP ports match ",(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_PORT_RANGE"}),".\nThe range of the ports shouldn't be too wide as it might cause problems with container startup."]})}),"\n",(0,s.jsx)(n.p,{children:"Using host network (Linux only)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run --network=host \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n -e JF_WEBRTC_USED=true \\\n -e JF_WEBRTC_TURN_IP=192.168.0.1 \\\n -e JF_WEBRTC_TURN_LISTEN_IP=0.0.0.0 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>o,M:()=>l});var s=t(1504);const i={},r=s.createContext(i);function l(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a1054fe7.bff2c844.js b/assets/js/a1054fe7.bff2c844.js deleted file mode 100644 index 5954633f..00000000 --- a/assets/js/a1054fe7.bff2c844.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[940],{4224:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>d});var s=t(7624),i=t(2172);const l={},r="WebRTC",o={id:"getting_started/peers/webrtc",title:"WebRTC",description:"WebRTC peer allows you to connect to Jellyfish via WebRTC standard.",source:"@site/docs/getting_started/peers/webrtc.md",sourceDirName:"getting_started/peers",slug:"/getting_started/peers/webrtc",permalink:"/jellyfish-docs/next/getting_started/peers/webrtc",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/peers/webrtc.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"File",permalink:"/jellyfish-docs/next/getting_started/components/file"},next:{title:"Jellyfish Dashboard",permalink:"/jellyfish-docs/next/tutorials/dashboard"}},c={},d=[{value:"Compatibility",id:"compatibility",level:2},{value:"Configuration options",id:"configuration-options",level:2},{value:"Env variables",id:"env-variables",level:2},{value:"Example Docker commands",id:"example-docker-commands",level:2}];function a(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"webrtc",children:"WebRTC"}),"\n",(0,s.jsx)(n.p,{children:"WebRTC peer allows you to connect to Jellyfish via WebRTC standard."}),"\n",(0,s.jsxs)(n.p,{children:["Read more about WebRTC ",(0,s.jsx)(n.a,{href:"https://webrtc.org/",children:"here"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"compatibility",children:"Compatibility"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"HLS"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/rtsp",children:"RTSP"})}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/file",children:"File"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"configuration-options",children:"Configuration options"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Optional"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"enableSimulcast"})," (boolean, default: true) - Enables the peer to use simulcast"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"env-variables",children:"Env variables"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_USED"})," - has to be ",(0,s.jsx)(n.code,{children:"true"})," if WebRTC peers will be used"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_LISTEN_IP"})," - the IP address on which TURN servers will listen.\nBy default set to ",(0,s.jsx)(n.code,{children:"127.0.0.1"}),".\nWhen running Jellyfish via Docker, this MUST be set to ",(0,s.jsx)(n.code,{children:"0.0.0.0"}),", even for local tests."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_IP"})," - the IP address, under which TURN will present itself to the clients. By default set to ",(0,s.jsx)(n.code,{children:"127.0.0.1"}),".\nWhen running Jellyfish via Docker, this MUST be set to real (non-loopback) address, even for local tests."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_PORT_RANGE"})," - port range, where UDP TURN will try to open ports. By default set to ",(0,s.jsx)(n.code,{children:"50000-59999"}),".\nThe bigger the range is, the more users server will be able to handle.\nUseful when not using the ",(0,s.jsx)(n.code,{children:"--network=host"})," option to limit the UDP ports\nused only to ones published from a Docker container."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_TCP_PORT"})," - port number of TCP TURN"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"example-docker-commands",children:"Example Docker commands"}),"\n",(0,s.jsx)(n.p,{children:"Explicit port exposure (macOS compatible)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run -p 50000-50050:50000-50050/udp \\\n -p 8080:8080/tcp \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n -e JF_WEBRTC_USED=true \\\n -e JF_WEBRTC_TURN_PORT_RANGE=50000-50050 \\\n -e JF_WEBRTC_TURN_IP=192.168.0.1 \\\n -e JF_WEBRTC_TURN_LISTEN_IP=0.0.0.0 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"caution",children:(0,s.jsxs)(n.p,{children:["Make sure that the exposed UDP ports match ",(0,s.jsx)(n.code,{children:"JF_WEBRTC_TURN_PORT_RANGE"}),".\nThe range of the ports shouldn't be too wide as it might cause problems with container startup."]})}),"\n",(0,s.jsx)(n.p,{children:"Using host network (Linux only)"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"docker run --network=host \\\n -e JF_SERVER_API_TOKEN=token \\\n -e JF_HOST=localhost:8080 \\\n -e JF_WEBRTC_USED=true \\\n -e JF_WEBRTC_TURN_IP=192.168.0.1 \\\n -e JF_WEBRTC_TURN_LISTEN_IP=0.0.0.0 \\\n ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>o,M:()=>r});var s=t(1504);const i={},l=s.createContext(i);function r(e){const n=s.useContext(l);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f2711dff.c7482545.js b/assets/js/f2711dff.c7482545.js deleted file mode 100644 index 532a8569..00000000 --- a/assets/js/f2711dff.c7482545.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[6784],{7520:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>x,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var r=s(7624),i=s(2172),l=s(1268),t=s(5388);const o={},c="Installation",a={id:"getting_started/installation",title:"Installation",description:"There are two ways of running Jellyfish:",source:"@site/docs/getting_started/installation.md",sourceDirName:"getting_started",slug:"/getting_started/installation",permalink:"/jellyfish-docs/next/getting_started/installation",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/installation.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"Example Scenarios",permalink:"/jellyfish-docs/next/introduction/example_scenarios"},next:{title:"Architecture",permalink:"/jellyfish-docs/next/getting_started/architecture"}},d={},h=[{value:"Building from source",id:"building-from-source",level:2},{value:"Running with Docker",id:"running-with-docker",level:2},{value:"Environment variables",id:"environment-variables",level:2},{value:"Required in production:",id:"required-in-production",level:4},{value:"Optional:",id:"optional",level:4},{value:"Distribution:",id:"distribution",level:4},{value:"Distribution NODES_LIST specific:",id:"distribution-nodes_list-specific",level:6},{value:"Distribution DNS specific:",id:"distribution-dns-specific",level:6}];function u(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h4:"h4",h6:"h6",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"installation",children:"Installation"}),"\n",(0,r.jsx)(n.p,{children:"There are two ways of running Jellyfish:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"building from source (requires Elixir and native dependencies)"}),"\n",(0,r.jsx)(n.li,{children:"using Jellyfish Docker images"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"At the moment, Jellyfish doesn't provide pre-built binaries."}),"\n",(0,r.jsx)(n.h2,{id:"building-from-source",children:"Building from source"}),"\n",(0,r.jsx)(n.p,{children:"Make sure to have both Elixir and Rust installed. Check the links below for instructions:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://elixir-lang.org/install.html",children:"Elixir"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://rustup.rs",children:"Rust"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Clone the Jellyfish repo"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"git clone https://github.com/jellyfish-dev/jellyfish.git\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Install native dependencies"})}),"\n",(0,r.jsxs)(l.c,{children:[(0,r.jsxs)(t.c,{value:"mac-intel",label:"macOS Intel",default:!0,children:[(0,r.jsxs)(n.p,{children:["These instructions assume you have Homebrew installed. You can get it ",(0,r.jsx)("a",{href:"https://brew.sh",children:"here"}),"."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'brew install srtp libnice clang-format ffmpeg opus pkg-config\nexport LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"\nexport CFLAGS="-I/usr/local/opt/openssl@1.1/include/"\nexport CPPFLAGS="-I/usr/local/opt/openssl@1.1/include/"\nexport PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"\n'})})]}),(0,r.jsxs)(t.c,{value:"mac-m1",label:"macOS Apple Silicon",default:!0,children:[(0,r.jsxs)(n.p,{children:["These instructions assume you have Homebrew installed. You can get it ",(0,r.jsx)("a",{href:"https://brew.sh",children:"here"}),"."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"brew install srtp libnice clang-format ffmpeg opus\nexport C_INCLUDE_PATH=/opt/homebrew/Cellar/libnice/0.1.18/include:/opt/homebrew/Cellar/opus/1.3.1/include:/opt/homebrew/Cellar/openssl@1.1/1.1.1l_1/include\nexport LIBRARY_PATH=/opt/homebrew/Cellar/opus/1.3.1/lib\nexport PKG_CONFIG_PATH=/opt/homebrew/Cellar/openssl@1.1/1.1.1l_1/lib/pkgconfig/\n"})})]}),(0,r.jsx)(t.c,{value:"ubuntu",label:"Ubuntu",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"sudo apt install pkg-config libsrtp2-dev libnice-dev libavcodec-dev libavformat-dev libavutil-dev libopus-dev libfdk-aac-dev\n"})})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Install elixir dependencies"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"mix deps.get\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Run the server in development"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"mix phx.server\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Create a binary"})}),"\n",(0,r.jsx)(n.p,{children:"You can also create Jellyfish binary with:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"MIX_ENV=prod mix release\n"})}),"\n",(0,r.jsx)(n.p,{children:"Then follow instructions printed in your terminal."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["The difference between running with ",(0,r.jsx)(n.code,{children:"mix phx.server"})," and generating target\nbinary is that the latter is prepared for running in production so e.g.\nit includes some Erlang Virtual Machine tweaks.\nJellyfish Dockerfile always uses ",(0,r.jsx)(n.code,{children:"mix release"})," under the hood."]})}),"\n",(0,r.jsx)(n.h2,{id:"running-with-docker",children:"Running with Docker"}),"\n",(0,r.jsxs)(n.p,{children:["Docker images are built for production which means that you always\nneed to set a couple of ",(0,r.jsx)(n.a,{href:"#environment-variables",children:"environment variables"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"An example docker command running bare Jellyfish HTTP service locally:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"docker run -p 8080:8080/tcp -e JF_HOST=localhost:8080 -e JF_SERVER_API_TOKEN=token ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that in real case scenarios, docker commands depend on peers/components you are going to use.\nTherefore, we don't present them here but rather in each peer/component's documentation.\nAs an example see ",(0,r.jsx)(n.a,{href:"./peers/webrtc#example-docker-commands",children:"WebRTC Peer"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["For the full list of Jellyfish Docker images, ",(0,r.jsx)(n.a,{href:"https://github.com/jellyfish-dev/jellyfish/pkgs/container/jellyfish",children:"see this page"}),"."]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["Instead of passing environmental variables manually, you can use the ",(0,r.jsx)(n.code,{children:"--env-file ./env-file"})," flag,\nwhere the ",(0,r.jsx)(n.code,{children:"env-file"})," is a file containing the variables that the image expects,\nsee example file ",(0,r.jsx)(n.code,{children:".env.sample"})," in the Jellyfish repository."]})}),"\n",(0,r.jsx)(n.h2,{id:"environment-variables",children:"Environment variables"}),"\n",(0,r.jsx)(n.p,{children:"Environment variables are split into two groups:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"general ones - presented below"}),"\n",(0,r.jsxs)(n.li,{children:["peer/component-specific - each Peer and Component can expose its own environment variables.\nThey are always listed in a Peer/Component description.\nSee the list of ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"Peers"})," and ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/hls",children:"Components"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Below there are general, Jellyfish environment variables.\nIf you are running Jellyfish in development, you don't need to\nset any of them."}),"\n",(0,r.jsx)(n.h4,{id:"required-in-production",children:"Required in production:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SERVER_API_TOKEN"})," - token for authorizing HTTP requests.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"development"})," for development builds."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_HOST"})," - defines how Jellyfish should be seen from the outside.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"JF_IP:JF_PORT"}),".",(0,r.jsx)("br",{}),"\nIt can be in the form of ",(0,r.jsx)(n.code,{children:"ip:port"}),", ",(0,r.jsx)(n.code,{children:"domain:port"})," or simply ",(0,r.jsx)(n.code,{children:"domain"}),".\nAdditionally, you can specify a path (e.g. ",(0,r.jsx)(n.code,{children:"ip:port/path"}),", ",(0,r.jsx)(n.code,{children:"domain:port/path"}),", ",(0,r.jsx)(n.code,{children:"domain/path"}),").\nUseful when hosting Jellyfish behind proxy.\nIt is returned e.g. when creating a new room.\nWhen running with Docker, ",(0,r.jsx)(n.code,{children:"JF_IP"})," is set to ",(0,r.jsx)(n.code,{children:"0.0.0.0"}),"\nmaking the default value of ",(0,r.jsx)(n.code,{children:"JF_HOST"})," incorrect.\nTherefore, for Docker, you have to set ",(0,r.jsx)(n.code,{children:"JF_HOST"})," manually.\nFor running Docker locally, it can simply be ",(0,r.jsx)(n.code,{children:"localhost:8080"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"optional",children:"Optional:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_IP"})," - an ip address to run the HTTP server on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"127.0.0.1"})," when running from source or using ",(0,r.jsx)(n.code,{children:"mix release"}),", or ",(0,r.jsx)(n.code,{children:"0.0.0.0"})," for Docker."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_PORT"})," - port to run the HTTP server on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"5002"})," for development builds and ",(0,r.jsx)(n.code,{children:"8080"})," for production builds (",(0,r.jsx)(n.code,{children:"mix release"})," or Docker)."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SSL_KEY_PATH"})," - an absolute path to the SSL key.\nWhen both ",(0,r.jsx)(n.code,{children:"JF_SSL_KEY_PATH"})," and ",(0,r.jsx)(n.code,{children:"JF_SSL_CERT_PATH"})," are set, Jellyfish will\nrun HTTPS server instead of HTTP one.\nAn address where this server listens to is still configured via ",(0,r.jsx)(n.code,{children:"JF_IP"})," and ",(0,r.jsx)(n.code,{children:"JF_PORT"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SSL_CERT_PATH"})," - an absolute path the the SSL certificate.\nWhen both ",(0,r.jsx)(n.code,{children:"JF_SSL_KEY_PATH"})," and ",(0,r.jsx)(n.code,{children:"JF_SSL_CERT_PATH"})," are set, Jellyfish will\nrun HTTPS server instead of HTTP one.\nAn address where this server listens to is still configured via ",(0,r.jsx)(n.code,{children:"JF_IP"})," and ",(0,r.jsx)(n.code,{children:"JF_PORT"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SECRET_KEY_BASE"})," - used to sign/encrypt tokens generated for Peers.\nGenerated if not provided."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_CHECK_ORIGIN"})," - defines if Jellyfish will check the origin of incoming requests and socket connection. ",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"true"}),".",(0,r.jsx)("br",{}),"\nPossible values are ",(0,r.jsx)(n.code,{children:"true"}),", ",(0,r.jsx)(n.code,{children:"false"})," or a space-separated list of allowed origins (wildcards are allowed). ",(0,r.jsx)("br",{}),"\nExample: ",(0,r.jsx)(n.code,{children:'JF_CHECK_ORIGIN="https://example.com //another.com:888 //*.other.com"'})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_RESOURCES_BASE_PATH"})," - a base path where Jellyfish multimedia files are stored",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"./jellyfish_resources/"}),".",(0,r.jsx)("br",{}),"\nWhen running via docker, the directory can be mounted as ",(0,r.jsx)(n.code,{children:"-v $(pwd)/host_directory:/app/jellyfish_resources"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_METRICS_IP"})," - an IP address to run metrics endpoint on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"127.0.0.1"})," when running from source or using ",(0,r.jsx)(n.code,{children:"mix release"}),", or ",(0,r.jsx)(n.code,{children:"0.0.0.0"})," for Docker."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_METRICS_PORT"})," - a port to run metrics endpoint on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"9568"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"MIX_ENV"})," - defines compilation environment.\nThis variable takes effect only when running from the source.\nDocker images are always built with ",(0,r.jsx)(n.code,{children:"MIX_ENV=prod"}),".\nPossible values are:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"dev"})," - uses default values for environment variables\n(default option when running with ",(0,r.jsx)(n.code,{children:"mix phx.server"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"prod"})," - requires that you provide values for environment variables"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"test"})," - used in tests"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"distribution",children:"Distribution:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_ENABLED"})," - whether to run Jellyfish in a cluster.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"false"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_STRATEGY_NAME"})," - specify which clustering strategy to use.",(0,r.jsx)("br",{}),"\nPossible values are ",(0,r.jsx)(n.code,{children:"DNS"})," or ",(0,r.jsx)(n.code,{children:"NODES_LIST"}),".\nDefaults to ",(0,r.jsx)(n.code,{children:"NODES_LIST"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_NODE_NAME"})," - Node name used in a cluster.\nDefaults to ",(0,r.jsx)(n.code,{children:"jellyfish@(hostname)"}),". ",(0,r.jsx)("br",{}),"\nIt consists of two parts - nodename@hostname.\nThe first part identifies a node on a single machine and can\nbe any string.\nThe second part identifies the host machine jellyfish runs on and has to be resolvable.\nIts format depends on ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"}),".\nIf ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," is set to ",(0,r.jsx)(n.code,{children:"name"}),", the ",(0,r.jsx)(n.code,{children:"hostname"})," has to be an IP address or FQDN.\nIf ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," is set to ",(0,r.jsx)(n.code,{children:"sname"}),", the ",(0,r.jsx)(n.code,{children:"hostname"})," can be any string.\nIf you run a cluster using ",(0,r.jsx)(n.code,{children:"DNS"})," strategy, every Jellyfish instance must have ",(0,r.jsx)(n.code,{children:"nodename"})," set to the same value.\nIf ",(0,r.jsx)(n.code,{children:"hostname"})," is not an IP address, it will be automatically resolved as DNS strategy requires\nnode names to use IP addresses.\nThis also means that ",(0,r.jsx)(n.code,{children:"DNS"})," strategy has to be run with ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," set to ",(0,r.jsx)(n.code,{children:"name"}),".\nSee our ",(0,r.jsx)(n.a,{href:"https://github.com/jellyfish-dev/jellyfish/blob/main/docker-compose-epmd.yaml",children:"docker-compose-epmd.yaml"})," or ",(0,r.jsx)(n.a,{href:"https://github.com/jellyfish-dev/jellyfish/blob/main/docker-compose-dns.yaml",children:"docker-compose-dns.yaml"}),", which we use in our integration tests or refer to ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/cluster",children:"Cluster"})," section for examples."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," - distribution mode - can be ",(0,r.jsx)(n.code,{children:"name"})," or ",(0,r.jsx)(n.code,{children:"sname"}),".",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"sname"}),".",(0,r.jsx)("br",{}),"\nWhen using ",(0,r.jsx)(n.code,{children:"name"}),", your hostname has to be an IP address or FQDN of a machine Jellyfish runs on.\nWhen using ",(0,r.jsx)(n.code,{children:"sname"}),", your hostname can be any string.\nSee ",(0,r.jsx)(n.code,{children:"JF_DIST_NODE_NAME"})," for more information."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_COOKIE"})," - used to group Jellyfishes in a cluster.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"jellyfish_cookie"}),".",(0,r.jsx)("br",{}),"\nUse different cookies to create multiple clusters on the same machine.",(0,r.jsx)("br",{}),"\n",(0,r.jsx)(n.strong,{children:"Important"}),": cookie does not provide any cryptographic security.\nIts only purpose is to prevent a node from connecting to a cluster with which\nit is not intended to communicate."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_MIN_PORT"}),"- minimal port used by Jellyfish when forming a cluster\n(connecting to other Jellyfishes).",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"9000"})," when running with Docker.",(0,r.jsx)("br",{}),"\nOnly available when running with Docker or ",(0,r.jsx)(n.code,{children:"mix release"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_MAX_PORT"}),"- maximal port used by Jellyfish when forming a cluster\n(connecting to other Jellyfishes).",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"9000"})," when running with Docker.",(0,r.jsx)("br",{}),"\nOnly available when running with Docker or ",(0,r.jsx)(n.code,{children:"mix release"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h6,{id:"distribution-nodes_list-specific",children:"Distribution NODES_LIST specific:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_NODES"})," - space-separated list of other Jellyfishes to connect to.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:'""'}),".",(0,r.jsx)("br",{}),"\nExample: ",(0,r.jsx)(n.code,{children:'JF_DIST_NODES="jellyfish1@127.0.0.1 jellyfish2@127.0.0.1"'}),".",(0,r.jsx)("br",{}),"\nThis list can also include ourselves so that you can pass the same value\nto every Jellyfish.\nNote: Jellyfish connection to other Jellyfish is transitive meaning that\nwhen you connect to one Jellyfish you also connect to all other Jellyfishes\nthis one was connected to."]}),"\n"]}),"\n",(0,r.jsx)(n.h6,{id:"distribution-dns-specific",children:"Distribution DNS specific:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_QUERY"})," - query sent to DNS to discover other Jellyfishes. ",(0,r.jsx)("br",{}),"\nReturned list of IPs from DNS is used for creating distribution node name in the format ",(0,r.jsx)(n.code,{children:"@"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_POLLING_INTERVAL"})," - DNS polling interval in ms. ",(0,r.jsx)("br",{}),"\nDefault value is 5000."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsx)(n.p,{children:"You can use a single port to form a cluster, even if a cluster consists of\nmore than two Jellyfishes."})}),"\n",(0,r.jsx)(n.admonition,{type:"caution",children:(0,r.jsxs)(n.p,{children:["Besides ports specified using ",(0,r.jsx)(n.code,{children:"JF_DIST_MIN_PORT"})," and ",(0,r.jsx)(n.code,{children:"JF_DIST_MAX_PORT"}),", Jellyfish\nalso uses one more service called EPMD that runs on port 4369.\nThis port has to be explicitly exported when running with Docker.\nRead more in the ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/cluster",children:"Cluster"})," section."]})})]})}function x(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},5388:(e,n,s)=>{s.d(n,{c:()=>t});s(1504);var r=s(4064);const i={tabItem:"tabItem_Ymn6"};var l=s(7624);function t(e){let{children:n,hidden:s,className:t}=e;return(0,l.jsx)("div",{role:"tabpanel",className:(0,r.c)(i.tabItem,t),hidden:s,children:n})}},1268:(e,n,s)=>{s.d(n,{c:()=>_});var r=s(1504),i=s(4064),l=s(3943),t=s(5592),o=s(5288),c=s(632),a=s(7128),d=s(1148);function h(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function u(e){const{values:n,children:s}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:s,attributes:r,default:i}}=e;return{value:n,label:s,attributes:r,default:i}}))}(s);return function(e){const n=(0,a.w)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,s])}function x(e){let{value:n,tabValues:s}=e;return s.some((e=>e.value===n))}function p(e){let{queryString:n=!1,groupId:s}=e;const i=(0,t.Uz)(),l=function(e){let{queryString:n=!1,groupId:s}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!s)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return s??null}({queryString:n,groupId:s});return[(0,c._M)(l),(0,r.useCallback)((e=>{if(!l)return;const n=new URLSearchParams(i.location.search);n.set(l,e),i.replace({...i.location,search:n.toString()})}),[l,i])]}function j(e){const{defaultValue:n,queryString:s=!1,groupId:i}=e,l=u(e),[t,c]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:s}=e;if(0===s.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!x({value:n,tabValues:s}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${s.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=s.find((e=>e.default))??s[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:l}))),[a,h]=p({queryString:s,groupId:i}),[j,f]=function(e){let{groupId:n}=e;const s=function(e){return e?`docusaurus.tab.${e}`:null}(n),[i,l]=(0,d.IN)(s);return[i,(0,r.useCallback)((e=>{s&&l.set(e)}),[s,l])]}({groupId:i}),m=(()=>{const e=a??j;return x({value:e,tabValues:l})?e:null})();(0,o.c)((()=>{m&&c(m)}),[m]);return{selectedValue:t,selectValue:(0,r.useCallback)((e=>{if(!x({value:e,tabValues:l}))throw new Error(`Can't select invalid tab value=${e}`);c(e),h(e),f(e)}),[h,f,l]),tabValues:l}}var f=s(3664);const m={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var b=s(7624);function g(e){let{className:n,block:s,selectedValue:r,selectValue:t,tabValues:o}=e;const c=[],{blockElementScrollPositionUntilNextRender:a}=(0,l.MV)(),d=e=>{const n=e.currentTarget,s=c.indexOf(n),i=o[s].value;i!==r&&(a(n),t(i))},h=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const s=c.indexOf(e.currentTarget)+1;n=c[s]??c[0];break}case"ArrowLeft":{const s=c.indexOf(e.currentTarget)-1;n=c[s]??c[c.length-1];break}}n?.focus()};return(0,b.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.c)("tabs",{"tabs--block":s},n),children:o.map((e=>{let{value:n,label:s,attributes:l}=e;return(0,b.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:h,onClick:d,...l,className:(0,i.c)("tabs__item",m.tabItem,l?.className,{"tabs__item--active":r===n}),children:s??n},n)}))})}function v(e){let{lazy:n,children:s,selectedValue:i}=e;const l=(Array.isArray(s)?s:[s]).filter(Boolean);if(n){const e=l.find((e=>e.props.value===i));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,b.jsx)("div",{className:"margin-top--md",children:l.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==i})))})}function y(e){const n=j(e);return(0,b.jsxs)("div",{className:(0,i.c)("tabs-container",m.tabList),children:[(0,b.jsx)(g,{...e,...n}),(0,b.jsx)(v,{...e,...n})]})}function _(e){const n=(0,f.c)();return(0,b.jsx)(y,{...e,children:h(e.children)},String(n))}},2172:(e,n,s)=>{s.d(n,{I:()=>o,M:()=>t});var r=s(1504);const i={},l=r.createContext(i);function t(e){const n=r.useContext(l);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f2711dff.df6d9b08.js b/assets/js/f2711dff.df6d9b08.js new file mode 100644 index 00000000..de1ad333 --- /dev/null +++ b/assets/js/f2711dff.df6d9b08.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[6784],{7520:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>x,frontMatter:()=>o,metadata:()=>a,toc:()=>h});var r=s(7624),i=s(2172),l=s(1268),t=s(5388);const o={},c="Installation",a={id:"getting_started/installation",title:"Installation",description:"There are two ways of running Jellyfish:",source:"@site/docs/getting_started/installation.md",sourceDirName:"getting_started",slug:"/getting_started/installation",permalink:"/jellyfish-docs/next/getting_started/installation",draft:!1,unlisted:!1,editUrl:"https://github.com/jellyfish-dev/jellyfish-docs/docs/getting_started/installation.md",tags:[],version:"current",frontMatter:{},sidebar:"mainSidebar",previous:{title:"Example Scenarios",permalink:"/jellyfish-docs/next/introduction/example_scenarios"},next:{title:"Architecture",permalink:"/jellyfish-docs/next/getting_started/architecture"}},d={},h=[{value:"Building from source",id:"building-from-source",level:2},{value:"Running with Docker",id:"running-with-docker",level:2},{value:"Environment variables",id:"environment-variables",level:2},{value:"Required in production:",id:"required-in-production",level:4},{value:"Optional:",id:"optional",level:4},{value:"Distribution:",id:"distribution",level:4},{value:"Distribution NODES_LIST specific:",id:"distribution-nodes_list-specific",level:6},{value:"Distribution DNS specific:",id:"distribution-dns-specific",level:6}];function u(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h4:"h4",h6:"h6",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"installation",children:"Installation"}),"\n",(0,r.jsx)(n.p,{children:"There are two ways of running Jellyfish:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"building from source (requires Elixir and native dependencies)"}),"\n",(0,r.jsx)(n.li,{children:"using Jellyfish Docker images"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"At the moment, Jellyfish doesn't provide pre-built binaries."}),"\n",(0,r.jsx)(n.h2,{id:"building-from-source",children:"Building from source"}),"\n",(0,r.jsx)(n.p,{children:"Make sure to have both Elixir and Rust installed. Check the links below for instructions:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://elixir-lang.org/install.html",children:"Elixir"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"https://rustup.rs",children:"Rust"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Clone the Jellyfish repo"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"git clone https://github.com/jellyfish-dev/jellyfish.git\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Install native dependencies"})}),"\n",(0,r.jsxs)(l.c,{children:[(0,r.jsxs)(t.c,{value:"mac-intel",label:"macOS Intel",default:!0,children:[(0,r.jsxs)(n.p,{children:["These instructions assume you have Homebrew installed. You can get it ",(0,r.jsx)("a",{href:"https://brew.sh",children:"here"}),"."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:'brew install srtp libnice clang-format ffmpeg opus pkg-config\nexport LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"\nexport CFLAGS="-I/usr/local/opt/openssl@1.1/include/"\nexport CPPFLAGS="-I/usr/local/opt/openssl@1.1/include/"\nexport PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"\n'})})]}),(0,r.jsxs)(t.c,{value:"mac-m1",label:"macOS Apple Silicon",default:!0,children:[(0,r.jsxs)(n.p,{children:["These instructions assume you have Homebrew installed. You can get it ",(0,r.jsx)("a",{href:"https://brew.sh",children:"here"}),"."]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"brew install srtp libnice clang-format ffmpeg opus\nexport C_INCLUDE_PATH=/opt/homebrew/Cellar/libnice/0.1.18/include:/opt/homebrew/Cellar/opus/1.3.1/include:/opt/homebrew/Cellar/openssl@1.1/1.1.1l_1/include\nexport LIBRARY_PATH=/opt/homebrew/Cellar/opus/1.3.1/lib\nexport PKG_CONFIG_PATH=/opt/homebrew/Cellar/openssl@1.1/1.1.1l_1/lib/pkgconfig/\n"})})]}),(0,r.jsx)(t.c,{value:"ubuntu",label:"Ubuntu",default:!0,children:(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"sudo apt install pkg-config libsrtp2-dev libnice-dev libavcodec-dev libavformat-dev libavutil-dev libopus-dev libfdk-aac-dev\n"})})})]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Install elixir dependencies"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"mix deps.get\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Run the server in development"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"mix phx.server\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Create a binary"})}),"\n",(0,r.jsx)(n.p,{children:"You can also create Jellyfish binary with:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"MIX_ENV=prod mix release\n"})}),"\n",(0,r.jsx)(n.p,{children:"Then follow instructions printed in your terminal."}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["The difference between running with ",(0,r.jsx)(n.code,{children:"mix phx.server"})," and generating target\nbinary is that the latter is prepared for running in production so e.g.\nit includes some Erlang Virtual Machine tweaks.\nJellyfish Dockerfile always uses ",(0,r.jsx)(n.code,{children:"mix release"})," under the hood."]})}),"\n",(0,r.jsx)(n.h2,{id:"running-with-docker",children:"Running with Docker"}),"\n",(0,r.jsxs)(n.p,{children:["Docker images are built for production which means that you always\nneed to set a couple of ",(0,r.jsx)(n.a,{href:"#environment-variables",children:"environment variables"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"An example docker command running bare Jellyfish HTTP service locally:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"docker run -p 8080:8080/tcp -e JF_HOST=localhost:8080 -e JF_SERVER_API_TOKEN=token ghcr.io/jellyfish-dev/jellyfish:0.3.0\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Note that in real case scenarios, docker commands depend on peers/components you are going to use.\nTherefore, we don't present them here but rather in each peer/component's documentation.\nAs an example see ",(0,r.jsx)(n.a,{href:"./peers/webrtc#example-docker-commands",children:"WebRTC Peer"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["For the full list of Jellyfish Docker images, ",(0,r.jsx)(n.a,{href:"https://github.com/jellyfish-dev/jellyfish/pkgs/container/jellyfish",children:"see this page"}),"."]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsxs)(n.p,{children:["Instead of passing environmental variables manually, you can use the ",(0,r.jsx)(n.code,{children:"--env-file ./env-file"})," flag,\nwhere the ",(0,r.jsx)(n.code,{children:"env-file"})," is a file containing the variables that the image expects,\nsee example file ",(0,r.jsx)(n.code,{children:".env.sample"})," in the Jellyfish repository."]})}),"\n",(0,r.jsx)(n.h2,{id:"environment-variables",children:"Environment variables"}),"\n",(0,r.jsx)(n.p,{children:"Environment variables are split into two groups:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"general ones - presented below"}),"\n",(0,r.jsxs)(n.li,{children:["peer/component-specific - each Peer and Component can expose its own environment variables.\nThey are always listed in a Peer/Component description.\nSee for example the list of ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/peers/webrtc",children:"Peers"})," and ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/getting_started/components/sip",children:"SIP Component"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Below there are general, Jellyfish environment variables.\nIf you are running Jellyfish in development, you don't need to\nset any of them."}),"\n",(0,r.jsx)(n.h4,{id:"required-in-production",children:"Required in production:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SERVER_API_TOKEN"})," - token for authorizing HTTP requests.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"development"})," for development builds."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_HOST"})," - defines how Jellyfish should be seen from the outside.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"JF_IP:JF_PORT"}),".",(0,r.jsx)("br",{}),"\nIt can be in the form of ",(0,r.jsx)(n.code,{children:"ip:port"}),", ",(0,r.jsx)(n.code,{children:"domain:port"})," or simply ",(0,r.jsx)(n.code,{children:"domain"}),".\nAdditionally, you can specify a path (e.g. ",(0,r.jsx)(n.code,{children:"ip:port/path"}),", ",(0,r.jsx)(n.code,{children:"domain:port/path"}),", ",(0,r.jsx)(n.code,{children:"domain/path"}),").\nUseful when hosting Jellyfish behind proxy.\nIt is returned e.g. when creating a new room.\nWhen running with Docker, ",(0,r.jsx)(n.code,{children:"JF_IP"})," is set to ",(0,r.jsx)(n.code,{children:"0.0.0.0"}),"\nmaking the default value of ",(0,r.jsx)(n.code,{children:"JF_HOST"})," incorrect.\nTherefore, for Docker, you have to set ",(0,r.jsx)(n.code,{children:"JF_HOST"})," manually.\nFor running Docker locally, it can simply be ",(0,r.jsx)(n.code,{children:"localhost:8080"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"optional",children:"Optional:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_IP"})," - an ip address to run the HTTP server on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"127.0.0.1"})," when running from source or using ",(0,r.jsx)(n.code,{children:"mix release"}),", or ",(0,r.jsx)(n.code,{children:"0.0.0.0"})," for Docker."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_PORT"})," - port to run the HTTP server on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"5002"})," for development builds and ",(0,r.jsx)(n.code,{children:"8080"})," for production builds (",(0,r.jsx)(n.code,{children:"mix release"})," or Docker)."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SSL_KEY_PATH"})," - an absolute path to the SSL key.\nWhen both ",(0,r.jsx)(n.code,{children:"JF_SSL_KEY_PATH"})," and ",(0,r.jsx)(n.code,{children:"JF_SSL_CERT_PATH"})," are set, Jellyfish will\nrun HTTPS server instead of HTTP one.\nAn address where this server listens to is still configured via ",(0,r.jsx)(n.code,{children:"JF_IP"})," and ",(0,r.jsx)(n.code,{children:"JF_PORT"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SSL_CERT_PATH"})," - an absolute path the the SSL certificate.\nWhen both ",(0,r.jsx)(n.code,{children:"JF_SSL_KEY_PATH"})," and ",(0,r.jsx)(n.code,{children:"JF_SSL_CERT_PATH"})," are set, Jellyfish will\nrun HTTPS server instead of HTTP one.\nAn address where this server listens to is still configured via ",(0,r.jsx)(n.code,{children:"JF_IP"})," and ",(0,r.jsx)(n.code,{children:"JF_PORT"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_SECRET_KEY_BASE"})," - used to sign/encrypt tokens generated for Peers.\nGenerated if not provided."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_CHECK_ORIGIN"})," - defines if Jellyfish will check the origin of incoming requests and socket connection. ",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"true"}),".",(0,r.jsx)("br",{}),"\nPossible values are ",(0,r.jsx)(n.code,{children:"true"}),", ",(0,r.jsx)(n.code,{children:"false"})," or a space-separated list of allowed origins (wildcards are allowed). ",(0,r.jsx)("br",{}),"\nExample: ",(0,r.jsx)(n.code,{children:'JF_CHECK_ORIGIN="https://example.com //another.com:888 //*.other.com"'})]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_RESOURCES_BASE_PATH"})," - a base path where Jellyfish multimedia files are stored",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"./jellyfish_resources/"}),".",(0,r.jsx)("br",{}),"\nWhen running via docker, the directory can be mounted as ",(0,r.jsx)(n.code,{children:"-v $(pwd)/host_directory:/app/jellyfish_resources"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_METRICS_IP"})," - an IP address to run metrics endpoint on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"127.0.0.1"})," when running from source or using ",(0,r.jsx)(n.code,{children:"mix release"}),", or ",(0,r.jsx)(n.code,{children:"0.0.0.0"})," for Docker."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_METRICS_PORT"})," - a port to run metrics endpoint on.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"9568"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"MIX_ENV"})," - defines compilation environment.\nThis variable takes effect only when running from the source.\nDocker images are always built with ",(0,r.jsx)(n.code,{children:"MIX_ENV=prod"}),".\nPossible values are:"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"dev"})," - uses default values for environment variables\n(default option when running with ",(0,r.jsx)(n.code,{children:"mix phx.server"}),")"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"prod"})," - requires that you provide values for environment variables"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"test"})," - used in tests"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"distribution",children:"Distribution:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_ENABLED"})," - whether to run Jellyfish in a cluster.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"false"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_STRATEGY_NAME"})," - specify which clustering strategy to use.",(0,r.jsx)("br",{}),"\nPossible values are ",(0,r.jsx)(n.code,{children:"DNS"})," or ",(0,r.jsx)(n.code,{children:"NODES_LIST"}),".\nDefaults to ",(0,r.jsx)(n.code,{children:"NODES_LIST"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_NODE_NAME"})," - Node name used in a cluster.\nDefaults to ",(0,r.jsx)(n.code,{children:"jellyfish@(hostname)"}),". ",(0,r.jsx)("br",{}),"\nIt consists of two parts - nodename@hostname.\nThe first part identifies a node on a single machine and can\nbe any string.\nThe second part identifies the host machine jellyfish runs on and has to be resolvable.\nIts format depends on ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"}),".\nIf ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," is set to ",(0,r.jsx)(n.code,{children:"name"}),", the ",(0,r.jsx)(n.code,{children:"hostname"})," has to be an IP address or FQDN.\nIf ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," is set to ",(0,r.jsx)(n.code,{children:"sname"}),", the ",(0,r.jsx)(n.code,{children:"hostname"})," can be any string.\nIf you run a cluster using ",(0,r.jsx)(n.code,{children:"DNS"})," strategy, every Jellyfish instance must have ",(0,r.jsx)(n.code,{children:"nodename"})," set to the same value.\nIf ",(0,r.jsx)(n.code,{children:"hostname"})," is not an IP address, it will be automatically resolved as DNS strategy requires\nnode names to use IP addresses.\nThis also means that ",(0,r.jsx)(n.code,{children:"DNS"})," strategy has to be run with ",(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," set to ",(0,r.jsx)(n.code,{children:"name"}),".\nSee our ",(0,r.jsx)(n.a,{href:"https://github.com/jellyfish-dev/jellyfish/blob/main/docker-compose-epmd.yaml",children:"docker-compose-epmd.yaml"})," or ",(0,r.jsx)(n.a,{href:"https://github.com/jellyfish-dev/jellyfish/blob/main/docker-compose-dns.yaml",children:"docker-compose-dns.yaml"}),", which we use in our integration tests or refer to ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/cluster",children:"Cluster"})," section for examples."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_MODE"})," - distribution mode - can be ",(0,r.jsx)(n.code,{children:"name"})," or ",(0,r.jsx)(n.code,{children:"sname"}),".",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"sname"}),".",(0,r.jsx)("br",{}),"\nWhen using ",(0,r.jsx)(n.code,{children:"name"}),", your hostname has to be an IP address or FQDN of a machine Jellyfish runs on.\nWhen using ",(0,r.jsx)(n.code,{children:"sname"}),", your hostname can be any string.\nSee ",(0,r.jsx)(n.code,{children:"JF_DIST_NODE_NAME"})," for more information."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_COOKIE"})," - used to group Jellyfishes in a cluster.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"jellyfish_cookie"}),".",(0,r.jsx)("br",{}),"\nUse different cookies to create multiple clusters on the same machine.",(0,r.jsx)("br",{}),"\n",(0,r.jsx)(n.strong,{children:"Important"}),": cookie does not provide any cryptographic security.\nIts only purpose is to prevent a node from connecting to a cluster with which\nit is not intended to communicate."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_MIN_PORT"}),"- minimal port used by Jellyfish when forming a cluster\n(connecting to other Jellyfishes).",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"9000"})," when running with Docker.",(0,r.jsx)("br",{}),"\nOnly available when running with Docker or ",(0,r.jsx)(n.code,{children:"mix release"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_MAX_PORT"}),"- maximal port used by Jellyfish when forming a cluster\n(connecting to other Jellyfishes).",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:"9000"})," when running with Docker.",(0,r.jsx)("br",{}),"\nOnly available when running with Docker or ",(0,r.jsx)(n.code,{children:"mix release"}),"."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h6,{id:"distribution-nodes_list-specific",children:"Distribution NODES_LIST specific:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_NODES"})," - space-separated list of other Jellyfishes to connect to.",(0,r.jsx)("br",{}),"\nDefaults to ",(0,r.jsx)(n.code,{children:'""'}),".",(0,r.jsx)("br",{}),"\nExample: ",(0,r.jsx)(n.code,{children:'JF_DIST_NODES="jellyfish1@127.0.0.1 jellyfish2@127.0.0.1"'}),".",(0,r.jsx)("br",{}),"\nThis list can also include ourselves so that you can pass the same value\nto every Jellyfish.\nNote: Jellyfish connection to other Jellyfish is transitive meaning that\nwhen you connect to one Jellyfish you also connect to all other Jellyfishes\nthis one was connected to."]}),"\n"]}),"\n",(0,r.jsx)(n.h6,{id:"distribution-dns-specific",children:"Distribution DNS specific:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_QUERY"})," - query sent to DNS to discover other Jellyfishes. ",(0,r.jsx)("br",{}),"\nReturned list of IPs from DNS is used for creating distribution node name in the format ",(0,r.jsx)(n.code,{children:"@"}),"."]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"JF_DIST_POLLING_INTERVAL"})," - DNS polling interval in ms. ",(0,r.jsx)("br",{}),"\nDefault value is 5000."]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.admonition,{type:"tip",children:(0,r.jsx)(n.p,{children:"You can use a single port to form a cluster, even if a cluster consists of\nmore than two Jellyfishes."})}),"\n",(0,r.jsx)(n.admonition,{type:"caution",children:(0,r.jsxs)(n.p,{children:["Besides ports specified using ",(0,r.jsx)(n.code,{children:"JF_DIST_MIN_PORT"})," and ",(0,r.jsx)(n.code,{children:"JF_DIST_MAX_PORT"}),", Jellyfish\nalso uses one more service called EPMD that runs on port 4369.\nThis port has to be explicitly exported when running with Docker.\nRead more in the ",(0,r.jsx)(n.a,{href:"/jellyfish-docs/next/cluster",children:"Cluster"})," section."]})})]})}function x(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},5388:(e,n,s)=>{s.d(n,{c:()=>t});s(1504);var r=s(4064);const i={tabItem:"tabItem_Ymn6"};var l=s(7624);function t(e){let{children:n,hidden:s,className:t}=e;return(0,l.jsx)("div",{role:"tabpanel",className:(0,r.c)(i.tabItem,t),hidden:s,children:n})}},1268:(e,n,s)=>{s.d(n,{c:()=>_});var r=s(1504),i=s(4064),l=s(3943),t=s(5592),o=s(5288),c=s(632),a=s(7128),d=s(1148);function h(e){return r.Children.toArray(e).filter((e=>"\n"!==e)).map((e=>{if(!e||(0,r.isValidElement)(e)&&function(e){const{props:n}=e;return!!n&&"object"==typeof n&&"value"in n}(e))return e;throw new Error(`Docusaurus error: Bad child <${"string"==typeof e.type?e.type:e.type.name}>: all children of the component should be , and every should have a unique "value" prop.`)}))?.filter(Boolean)??[]}function u(e){const{values:n,children:s}=e;return(0,r.useMemo)((()=>{const e=n??function(e){return h(e).map((e=>{let{props:{value:n,label:s,attributes:r,default:i}}=e;return{value:n,label:s,attributes:r,default:i}}))}(s);return function(e){const n=(0,a.w)(e,((e,n)=>e.value===n.value));if(n.length>0)throw new Error(`Docusaurus error: Duplicate values "${n.map((e=>e.value)).join(", ")}" found in . Every value needs to be unique.`)}(e),e}),[n,s])}function x(e){let{value:n,tabValues:s}=e;return s.some((e=>e.value===n))}function p(e){let{queryString:n=!1,groupId:s}=e;const i=(0,t.Uz)(),l=function(e){let{queryString:n=!1,groupId:s}=e;if("string"==typeof n)return n;if(!1===n)return null;if(!0===n&&!s)throw new Error('Docusaurus error: The component groupId prop is required if queryString=true, because this value is used as the search param name. You can also provide an explicit value such as queryString="my-search-param".');return s??null}({queryString:n,groupId:s});return[(0,c._M)(l),(0,r.useCallback)((e=>{if(!l)return;const n=new URLSearchParams(i.location.search);n.set(l,e),i.replace({...i.location,search:n.toString()})}),[l,i])]}function j(e){const{defaultValue:n,queryString:s=!1,groupId:i}=e,l=u(e),[t,c]=(0,r.useState)((()=>function(e){let{defaultValue:n,tabValues:s}=e;if(0===s.length)throw new Error("Docusaurus error: the component requires at least one children component");if(n){if(!x({value:n,tabValues:s}))throw new Error(`Docusaurus error: The has a defaultValue "${n}" but none of its children has the corresponding value. Available values are: ${s.map((e=>e.value)).join(", ")}. If you intend to show no default tab, use defaultValue={null} instead.`);return n}const r=s.find((e=>e.default))??s[0];if(!r)throw new Error("Unexpected error: 0 tabValues");return r.value}({defaultValue:n,tabValues:l}))),[a,h]=p({queryString:s,groupId:i}),[j,f]=function(e){let{groupId:n}=e;const s=function(e){return e?`docusaurus.tab.${e}`:null}(n),[i,l]=(0,d.IN)(s);return[i,(0,r.useCallback)((e=>{s&&l.set(e)}),[s,l])]}({groupId:i}),m=(()=>{const e=a??j;return x({value:e,tabValues:l})?e:null})();(0,o.c)((()=>{m&&c(m)}),[m]);return{selectedValue:t,selectValue:(0,r.useCallback)((e=>{if(!x({value:e,tabValues:l}))throw new Error(`Can't select invalid tab value=${e}`);c(e),h(e),f(e)}),[h,f,l]),tabValues:l}}var f=s(3664);const m={tabList:"tabList__CuJ",tabItem:"tabItem_LNqP"};var b=s(7624);function g(e){let{className:n,block:s,selectedValue:r,selectValue:t,tabValues:o}=e;const c=[],{blockElementScrollPositionUntilNextRender:a}=(0,l.MV)(),d=e=>{const n=e.currentTarget,s=c.indexOf(n),i=o[s].value;i!==r&&(a(n),t(i))},h=e=>{let n=null;switch(e.key){case"Enter":d(e);break;case"ArrowRight":{const s=c.indexOf(e.currentTarget)+1;n=c[s]??c[0];break}case"ArrowLeft":{const s=c.indexOf(e.currentTarget)-1;n=c[s]??c[c.length-1];break}}n?.focus()};return(0,b.jsx)("ul",{role:"tablist","aria-orientation":"horizontal",className:(0,i.c)("tabs",{"tabs--block":s},n),children:o.map((e=>{let{value:n,label:s,attributes:l}=e;return(0,b.jsx)("li",{role:"tab",tabIndex:r===n?0:-1,"aria-selected":r===n,ref:e=>c.push(e),onKeyDown:h,onClick:d,...l,className:(0,i.c)("tabs__item",m.tabItem,l?.className,{"tabs__item--active":r===n}),children:s??n},n)}))})}function v(e){let{lazy:n,children:s,selectedValue:i}=e;const l=(Array.isArray(s)?s:[s]).filter(Boolean);if(n){const e=l.find((e=>e.props.value===i));return e?(0,r.cloneElement)(e,{className:"margin-top--md"}):null}return(0,b.jsx)("div",{className:"margin-top--md",children:l.map(((e,n)=>(0,r.cloneElement)(e,{key:n,hidden:e.props.value!==i})))})}function y(e){const n=j(e);return(0,b.jsxs)("div",{className:(0,i.c)("tabs-container",m.tabList),children:[(0,b.jsx)(g,{...e,...n}),(0,b.jsx)(v,{...e,...n})]})}function _(e){const n=(0,f.c)();return(0,b.jsx)(y,{...e,children:h(e.children)},String(n))}},2172:(e,n,s)=>{s.d(n,{I:()=>o,M:()=>t});var r=s(1504);const i={},l=r.createContext(i);function t(e){const n=r.useContext(l);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/main.7cb46f10.js b/assets/js/main.7cb46f10.js deleted file mode 100644 index 8d1fb354..00000000 --- a/assets/js/main.7cb46f10.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.7cb46f10.js.LICENSE.txt */ -(self.webpackChunkjellyfish_docs=self.webpackChunkjellyfish_docs||[]).push([[1590],{5052:(e,t,n)=>{"use strict";n.d(t,{I:()=>o});var r=n(1504);function o(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},628:(e,t,n)=>{"use strict";n.d(t,{c:()=>p});n(1504);var r=n(8852),o=n.n(r),a=n(4504);const i={"00efe26d":[()=>n.e(3856).then(n.bind(n,5404)),"@site/versioned_docs/version-0.3.0/getting_started/peers/webrtc.md",5404],"06d81fef":[()=>n.e(6921).then(n.bind(n,5956)),"@site/docs/introduction/what_is_jellyfish.md",5956],"07e658c8":[()=>n.e(1252).then(n.bind(n,3732)),"@site/docs/benchmarks/webrtc.md",3732],"09d5ad39":[()=>n.e(596).then(n.bind(n,7356)),"@site/docs/examples.md",7356],"0bb15743":[()=>n.e(2404).then(n.bind(n,9379)),"@site/versioned_docs/version-0.3.0/getting_started/components/rtsp.md",9379],"0ca6cd30":[()=>Promise.all([n.e(2176),n.e(8244)]).then(n.bind(n,3972)),"@site/docs/tutorials/dashboard.mdx",3972],"10febcc7":[()=>n.e(5900).then(n.bind(n,4228)),"@site/versioned_docs/version-0.2.1/introduction/example_scenarios.md",4228],17896441:[()=>Promise.all([n.e(2176),n.e(6752)]).then(n.bind(n,4760)),"@theme/DocItem",4760],"1a4e3797":[()=>Promise.all([n.e(2176),n.e(9648)]).then(n.bind(n,752)),"@theme/SearchPage",752],"1ae5f91e":[()=>n.e(128).then(n.bind(n,1036)),"@site/versioned_docs/version-0.3.0/benchmarks/webrtc.md",1036],"1d74c428":[()=>n.e(7762).then(n.bind(n,7888)),"@site/versioned_docs/version-0.3.0/benchmarks/hls.md",7888],"1f702618":[()=>n.e(8384).then(n.bind(n,2236)),"@site/docs/getting_started/metrics.md",2236],"2112e5bd":[()=>n.e(436).then(n.t.bind(n,1858,19)),"~docs/default/version-0-2-1-metadata-prop-000.json",1858],"21ed7c22":[()=>n.e(4024).then(n.bind(n,8300)),"@site/versioned_docs/version-0.2.1/for_developers/design_docs.md",8300],"27ccd4a7":[()=>n.e(8555).then(n.bind(n,8780)),"@site/versioned_docs/version-0.3.0/getting_started/metrics.md",8780],"27edd659":[()=>Promise.all([n.e(2176),n.e(100)]).then(n.bind(n,6116)),"@site/versioned_docs/version-0.2.1/getting_started/authentication.md",6116],"31ce0643":[()=>n.e(2995).then(n.bind(n,5508)),"@site/docs/getting_started/sdks.md",5508],"33da16d7":[()=>n.e(4972).then(n.t.bind(n,7640,19)),"/home/runner/work/jellyfish-docs/jellyfish-docs/.docusaurus/docusaurus-plugin-redoc/jellyfish-rest-api/redocApiSpecV1.2-jellyfish-rest-api.json",7640],"35845c3a":[()=>Promise.all([n.e(2176),n.e(1012)]).then(n.bind(n,9868)),"@site/versioned_docs/version-0.3.0/tutorials/react-native.mdx",9868],"36708fee":[()=>Promise.all([n.e(2176),n.e(4066)]).then(n.bind(n,932)),"@site/versioned_docs/version-0.2.1/getting_started/installation.md",932],"39530b49":[()=>n.e(1552).then(n.bind(n,6548)),"@site/versioned_docs/version-0.3.0/for_developers/design_docs.md",6548],"3a057c9d":[()=>n.e(4704).then(n.bind(n,3840)),"@site/versioned_docs/version-0.2.1/deploying/vps.md",3840],"3b1f92db":[()=>n.e(8192).then(n.bind(n,5992)),"@site/docs/benchmarks/hls.md",5992],"3d2de946":[()=>n.e(5424).then(n.bind(n,4256)),"@site/docs/for_developers/metrics_design.md",4256],40149981:[()=>n.e(5216).then(n.bind(n,772)),"@site/docs/getting_started/room.md",772],"4093c5c2":[()=>n.e(2328).then(n.bind(n,5772)),"@site/docs/for_developers/design_docs.md",5772],"43c242c4":[()=>n.e(2252).then(n.bind(n,7300)),"@site/versioned_docs/version-0.2.1/getting_started/sdks.md",7300],"46afa356":[()=>n.e(208).then(n.bind(n,1336)),"@site/versioned_docs/version-0.3.0/release_notes.md",1336],"4a332b92":[()=>n.e(6348).then(n.bind(n,6836)),"@site/docs/getting_started/architecture.md",6836],"4c8c074b":[()=>Promise.all([n.e(2176),n.e(3336)]).then(n.bind(n,2692)),"@site/versioned_docs/version-0.2.1/tutorials/react-native.mdx",2692],"4cf40d90":[()=>n.e(8e3).then(n.bind(n,8196)),"@site/docs/getting_started/components/file.md",8196],"533aebff":[()=>Promise.all([n.e(2176),n.e(9328)]).then(n.bind(n,4980)),"@site/docs/getting_started/components/hls.md",4980],"55d4ba5e":[()=>Promise.all([n.e(2176),n.e(9908)]).then(n.bind(n,3584)),"@site/versioned_docs/version-0.3.0/getting_started/authentication.md",3584],"5a21b1fb":[()=>n.e(632).then(n.bind(n,8552)),"@site/versioned_docs/version-0.2.1/getting_started/notifications.md",8552],"5ac0f6fc":[()=>n.e(1084).then(n.bind(n,524)),"@site/versioned_docs/version-0.3.0/getting_started/components/file.md",524],"5d43be05":[()=>n.e(872).then(n.bind(n,1816)),"@site/docs/introduction/basic_concepts.md",1816],"5d85105e":[()=>Promise.all([n.e(2176),n.e(4856),n.e(7388)]).then(n.bind(n,9972)),"@site/docs/for_developers/api_reference/rest_api.md",9972],"5daaa58f":[()=>n.e(5712).then(n.bind(n,7620)),"@site/versioned_docs/version-0.2.1/getting_started/architecture.md",7620],"5e95c892":[()=>n.e(4304).then(n.bind(n,3564)),"@theme/DocsRoot",3564],"5f012ce0":[()=>n.e(1444).then(n.t.bind(n,8736,19)),"~docs/default/version-0-3-0-metadata-prop-150.json",8736],"600cd2d3":[()=>n.e(9404).then(n.t.bind(n,9699,19)),"/home/runner/work/jellyfish-docs/jellyfish-docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",9699],"60a6062a":[()=>n.e(8056).then(n.bind(n,312)),"@site/versioned_docs/version-0.3.0/deploying/fly_io.md",312],"62feff6b":[()=>n.e(5032).then(n.bind(n,3008)),"@site/versioned_docs/version-0.3.0/getting_started/sdks.md",3008],"63002c07":[()=>n.e(8876).then(n.bind(n,3684)),"@site/versioned_docs/version-0.3.0/getting_started/architecture.md",3684],"69ed952a":[()=>Promise.all([n.e(2176),n.e(1412)]).then(n.bind(n,3540)),"@site/docs/tutorials/react-native.mdx",3540],"73522d53":[()=>n.e(4336).then(n.bind(n,9420)),"@site/versioned_docs/version-0.2.1/introduction/what_is_jellyfish.md",9420],"7355fc42":[()=>n.e(848).then(n.bind(n,2588)),"@site/versioned_docs/version-0.3.0/benchmarks.md",2588],"73d55eec":[()=>n.e(7316).then(n.bind(n,7716)),"@site/versioned_docs/version-0.2.1/getting_started/peers/webrtc.md",7716],"74b3eea0":[()=>Promise.all([n.e(2176),n.e(8436)]).then(n.bind(n,6596)),"@site/versioned_docs/version-0.3.0/tutorials/dashboard.mdx",6596],"75da9f0f":[()=>n.e(232).then(n.bind(n,6308)),"@site/versioned_docs/version-0.2.1/getting_started/metrics.md",6308],"768642a8":[()=>n.e(1792).then(n.bind(n,400)),"@site/versioned_docs/version-0.3.0/for_developers/metrics_design.md",400],"78c80559":[()=>n.e(9048).then(n.bind(n,4048)),"@site/docs/getting_started/components/rtsp.md",4048],"794d58d2":[()=>n.e(9370).then(n.bind(n,2668)),"@site/versioned_docs/version-0.3.0/for_developers/api_reference.md",2668],"7989af0e":[()=>Promise.all([n.e(2176),n.e(4664)]).then(n.bind(n,572)),"@site/versioned_docs/version-0.3.0/getting_started/installation.md",572],"79a00ea7":[()=>n.e(7448).then(n.bind(n,3492)),"@site/versioned_docs/version-0.3.0/examples.md",3492],"7dab705f":[()=>Promise.all([n.e(2176),n.e(9112)]).then(n.bind(n,1623)),"@site/docs/getting_started/authentication.md",1623],"861638b8":[()=>n.e(9280).then(n.bind(n,1984)),"@site/versioned_docs/version-0.2.1/deploying/fly_io.md",1984],"887a5d8d":[()=>n.e(8040).then(n.bind(n,512)),"@site/versioned_docs/version-0.3.0/introduction/basic_concepts.md",512],"88f389e2":[()=>Promise.all([n.e(2176),n.e(5706)]).then(n.bind(n,1772)),"@site/versioned_docs/version-0.3.0/getting_started/notifications.md",1772],"935f2afb":[()=>n.e(5696).then(n.t.bind(n,5988,19)),"~docs/default/version-current-metadata-prop-751.json",5988],"94d315a1":[()=>n.e(1365).then(n.bind(n,6559)),"@site/versioned_docs/version-0.2.1/getting_started/components/hls.md",6559],"95d85754":[()=>n.e(5316).then(n.bind(n,7700)),"@site/versioned_docs/version-0.2.1/getting_started/components/rtsp.md",7700],"9a2cec18":[()=>n.e(820).then(n.bind(n,468)),"@site/docs/release_notes.md",468],"9bbc544f":[()=>n.e(4198).then(n.bind(n,2784)),"@site/versioned_docs/version-0.3.0/cluster.md",2784],"9cdf073a":[()=>n.e(3304).then(n.bind(n,6728)),"@site/versioned_docs/version-0.3.0/introduction/example_scenarios.md",6728],"9d08b8f2":[()=>n.e(8720).then(n.bind(n,7140)),"@site/versioned_docs/version-0.3.0/introduction/what_is_jellyfish.md",7140],a1054fe7:[()=>n.e(940).then(n.bind(n,4224)),"@site/docs/getting_started/peers/webrtc.md",4224],a2748788:[()=>Promise.all([n.e(2176),n.e(4856),n.e(7128)]).then(n.bind(n,8308)),"@site/versioned_docs/version-0.2.1/for_developers/api_reference/rest_api.md",8308],a7bd4aaa:[()=>n.e(6500).then(n.bind(n,2e3)),"@theme/DocVersionRoot",2e3],a94703ab:[()=>Promise.all([n.e(2176),n.e(4666)]).then(n.bind(n,996)),"@theme/DocRoot",996],ae302c60:[()=>n.e(9928).then(n.bind(n,2076)),"@site/docs/for_developers/api_reference.md",2076],b3305401:[()=>n.e(3696).then(n.bind(n,6284)),"@site/versioned_docs/version-0.2.1/introduction/basic_concepts.md",6284],b50b123e:[()=>Promise.all([n.e(2176),n.e(9844)]).then(n.bind(n,9636)),"@site/docs/tutorials/simple-react-app.mdx",9636],b5d665f7:[()=>n.e(3052).then(n.bind(n,8460)),"@site/versioned_docs/version-0.2.1/examples.md",8460],b67ba642:[()=>Promise.all([n.e(2176),n.e(4424)]).then(n.bind(n,68)),"@site/versioned_docs/version-0.3.0/getting_started/components/hls.md",68],ba8dacd3:[()=>n.e(8315).then(n.t.bind(n,4684,19)),"/home/runner/work/jellyfish-docs/jellyfish-docs/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",4684],bd4d3e77:[()=>n.e(3624).then(n.bind(n,5044)),"@site/docs/deploying/fly_io.md",5044],caf39a59:[()=>n.e(4916).then(n.bind(n,4932)),"@site/docs/benchmarks.md",4932],cf5003b1:[()=>Promise.all([n.e(2176),n.e(7376)]).then(n.bind(n,5784)),"@site/docs/getting_started/notifications.md",5784],cf9e2847:[()=>n.e(6020).then(n.bind(n,1200)),"@site/versioned_docs/version-0.3.0/deploying/vps.md",1200],dd033c5b:[()=>n.e(5832).then(n.bind(n,5736)),"@site/versioned_docs/version-0.2.1/cluster.md",5736],ddb258f2:[()=>n.e(3560).then(n.bind(n,1032)),"@site/docs/deploying/vps.md",1032],de993eb4:[()=>n.e(8644).then(n.bind(n,76)),"@site/docs/introduction/example_scenarios.md",76],debcebe1:[()=>Promise.all([n.e(2176),n.e(8904)]).then(n.bind(n,1688)),"@site/versioned_docs/version-0.3.0/tutorials/simple-react-app.mdx",1688],e364a627:[()=>Promise.all([n.e(2176),n.e(7492)]).then(n.bind(n,8280)),"@site/versioned_docs/version-0.2.1/tutorials/simple-react-app.mdx",8280],e84b993c:[()=>n.e(7784).then(n.bind(n,4046)),"@site/versioned_docs/version-0.2.1/for_developers/api_reference.md",4046],e8d07e67:[()=>Promise.all([n.e(2176),n.e(4856),n.e(32)]).then(n.bind(n,6576)),"@site/versioned_docs/version-0.3.0/for_developers/api_reference/rest_api.md",6576],f0ad3fbb:[()=>Promise.all([n.e(2176),n.e(4856),n.e(5896)]).then(n.bind(n,5996)),"@theme/ApiDoc",5996],f20ac086:[()=>Promise.all([n.e(2176),n.e(4848)]).then(n.bind(n,2052)),"@site/versioned_docs/version-0.2.1/tutorials/dashboard.mdx",2052],f2711dff:[()=>Promise.all([n.e(2176),n.e(6784)]).then(n.bind(n,7520)),"@site/docs/getting_started/installation.md",7520],f9b08eaa:[()=>n.e(2781).then(n.bind(n,5832)),"@site/docs/cluster.md",5832],fa5b4139:[()=>n.e(5508).then(n.t.bind(n,8140,19)),"/home/runner/work/jellyfish-docs/jellyfish-docs/.docusaurus/docusaurus-plugin-redoc/jellyfish-rest-api/redocApiLayoutV1-jellyfish-rest-api.json",8140],fdcc75fd:[()=>n.e(5420).then(n.t.bind(n,3672,19)),"/home/runner/work/jellyfish-docs/jellyfish-docs/.docusaurus/docusaurus-plugin-redoc/jellyfish-rest-api/plugin-route-context-module-100.json",3672]};var s=n(7624);function l(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(8120),u=n(5548);function d(e,t){if("*"===e)return o()({loading:l,loader:()=>n.e(4552).then(n.bind(n,4552)),modules:["@theme/NotFound"],webpack:()=>[4552],render(e,t){const n=e.default;return(0,s.jsx)(u.Y,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},p=[],f=[],h=(0,c.c)(r);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),o().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let i=o;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;return delete o.__context,(0,s.jsx)(u.Y,{value:i,children:(0,s.jsx)(a,{...o,...n})})}})}const p=[{path:"/jellyfish-docs/examples/using-single-yaml",component:d("/jellyfish-docs/examples/using-single-yaml","021"),exact:!0},{path:"/jellyfish-docs/search",component:d("/jellyfish-docs/search","7e2"),exact:!0},{path:"/jellyfish-docs/",component:d("/jellyfish-docs/","57e"),routes:[{path:"/jellyfish-docs/0.2.1",component:d("/jellyfish-docs/0.2.1","c19"),routes:[{path:"/jellyfish-docs/0.2.1",component:d("/jellyfish-docs/0.2.1","407"),routes:[{path:"/jellyfish-docs/0.2.1",component:d("/jellyfish-docs/0.2.1","9b1"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/cluster",component:d("/jellyfish-docs/0.2.1/cluster","950"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/deploying/fly_io",component:d("/jellyfish-docs/0.2.1/deploying/fly_io","fe4"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/deploying/vps",component:d("/jellyfish-docs/0.2.1/deploying/vps","908"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/examples",component:d("/jellyfish-docs/0.2.1/examples","223"),exact:!0},{path:"/jellyfish-docs/0.2.1/for_developers/api_reference",component:d("/jellyfish-docs/0.2.1/for_developers/api_reference","27e"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/for_developers/api_reference/rest_api",component:d("/jellyfish-docs/0.2.1/for_developers/api_reference/rest_api","200"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/for_developers/design_docs",component:d("/jellyfish-docs/0.2.1/for_developers/design_docs","944"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/architecture",component:d("/jellyfish-docs/0.2.1/getting_started/architecture","338"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/authentication",component:d("/jellyfish-docs/0.2.1/getting_started/authentication","3a6"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/components/hls",component:d("/jellyfish-docs/0.2.1/getting_started/components/hls","b8f"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/components/rtsp",component:d("/jellyfish-docs/0.2.1/getting_started/components/rtsp","823"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/installation",component:d("/jellyfish-docs/0.2.1/getting_started/installation","1c6"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/metrics",component:d("/jellyfish-docs/0.2.1/getting_started/metrics","f75"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/notifications",component:d("/jellyfish-docs/0.2.1/getting_started/notifications","666"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/peers/webrtc",component:d("/jellyfish-docs/0.2.1/getting_started/peers/webrtc","438"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/getting_started/sdks",component:d("/jellyfish-docs/0.2.1/getting_started/sdks","a4f"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/introduction/basic_concepts",component:d("/jellyfish-docs/0.2.1/introduction/basic_concepts","a00"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/introduction/example_scenarios",component:d("/jellyfish-docs/0.2.1/introduction/example_scenarios","460"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/tutorials/dashboard",component:d("/jellyfish-docs/0.2.1/tutorials/dashboard","748"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/tutorials/react-native",component:d("/jellyfish-docs/0.2.1/tutorials/react-native","c46"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/0.2.1/tutorials/simple-react-app",component:d("/jellyfish-docs/0.2.1/tutorials/simple-react-app","55b"),exact:!0,sidebar:"mainSidebar"}]}]},{path:"/jellyfish-docs/next",component:d("/jellyfish-docs/next","8c4"),routes:[{path:"/jellyfish-docs/next",component:d("/jellyfish-docs/next","963"),routes:[{path:"/jellyfish-docs/next",component:d("/jellyfish-docs/next","149"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/benchmarks",component:d("/jellyfish-docs/next/benchmarks","15e"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/benchmarks/hls",component:d("/jellyfish-docs/next/benchmarks/hls","fdb"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/benchmarks/webrtc",component:d("/jellyfish-docs/next/benchmarks/webrtc","6ca"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/cluster",component:d("/jellyfish-docs/next/cluster","096"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/deploying/fly_io",component:d("/jellyfish-docs/next/deploying/fly_io","e1f"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/deploying/vps",component:d("/jellyfish-docs/next/deploying/vps","2b0"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/examples",component:d("/jellyfish-docs/next/examples","200"),exact:!0},{path:"/jellyfish-docs/next/for_developers/api_reference",component:d("/jellyfish-docs/next/for_developers/api_reference","a57"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/for_developers/api_reference/rest_api",component:d("/jellyfish-docs/next/for_developers/api_reference/rest_api","6bc"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/for_developers/design_docs",component:d("/jellyfish-docs/next/for_developers/design_docs","871"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/for_developers/metrics_design",component:d("/jellyfish-docs/next/for_developers/metrics_design","af1"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/architecture",component:d("/jellyfish-docs/next/getting_started/architecture","113"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/authentication",component:d("/jellyfish-docs/next/getting_started/authentication","a5e"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/components/file",component:d("/jellyfish-docs/next/getting_started/components/file","4b8"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/components/hls",component:d("/jellyfish-docs/next/getting_started/components/hls","4e2"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/components/rtsp",component:d("/jellyfish-docs/next/getting_started/components/rtsp","a7f"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/installation",component:d("/jellyfish-docs/next/getting_started/installation","40d"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/metrics",component:d("/jellyfish-docs/next/getting_started/metrics","608"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/notifications",component:d("/jellyfish-docs/next/getting_started/notifications","d82"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/peers/webrtc",component:d("/jellyfish-docs/next/getting_started/peers/webrtc","60a"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/room",component:d("/jellyfish-docs/next/getting_started/room","572"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/getting_started/sdks",component:d("/jellyfish-docs/next/getting_started/sdks","160"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/introduction/basic_concepts",component:d("/jellyfish-docs/next/introduction/basic_concepts","f09"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/introduction/example_scenarios",component:d("/jellyfish-docs/next/introduction/example_scenarios","16b"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/release_notes",component:d("/jellyfish-docs/next/release_notes","831"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/tutorials/dashboard",component:d("/jellyfish-docs/next/tutorials/dashboard","b5f"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/tutorials/react-native",component:d("/jellyfish-docs/next/tutorials/react-native","949"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/next/tutorials/simple-react-app",component:d("/jellyfish-docs/next/tutorials/simple-react-app","2c8"),exact:!0,sidebar:"mainSidebar"}]}]},{path:"/jellyfish-docs/",component:d("/jellyfish-docs/","e83"),routes:[{path:"/jellyfish-docs/",component:d("/jellyfish-docs/","e29"),routes:[{path:"/jellyfish-docs/benchmarks",component:d("/jellyfish-docs/benchmarks","3df"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/benchmarks/hls",component:d("/jellyfish-docs/benchmarks/hls","bda"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/benchmarks/webrtc",component:d("/jellyfish-docs/benchmarks/webrtc","2c2"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/cluster",component:d("/jellyfish-docs/cluster","eda"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/deploying/fly_io",component:d("/jellyfish-docs/deploying/fly_io","ea6"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/deploying/vps",component:d("/jellyfish-docs/deploying/vps","b58"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/examples",component:d("/jellyfish-docs/examples","8e7"),exact:!0},{path:"/jellyfish-docs/for_developers/api_reference",component:d("/jellyfish-docs/for_developers/api_reference","bf5"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/for_developers/api_reference/rest_api",component:d("/jellyfish-docs/for_developers/api_reference/rest_api","a82"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/for_developers/design_docs",component:d("/jellyfish-docs/for_developers/design_docs","545"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/for_developers/metrics_design",component:d("/jellyfish-docs/for_developers/metrics_design","ff8"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/architecture",component:d("/jellyfish-docs/getting_started/architecture","e0a"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/authentication",component:d("/jellyfish-docs/getting_started/authentication","46a"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/components/file",component:d("/jellyfish-docs/getting_started/components/file","626"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/components/hls",component:d("/jellyfish-docs/getting_started/components/hls","979"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/components/rtsp",component:d("/jellyfish-docs/getting_started/components/rtsp","e12"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/installation",component:d("/jellyfish-docs/getting_started/installation","60a"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/metrics",component:d("/jellyfish-docs/getting_started/metrics","79a"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/notifications",component:d("/jellyfish-docs/getting_started/notifications","43e"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/peers/webrtc",component:d("/jellyfish-docs/getting_started/peers/webrtc","47b"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/getting_started/sdks",component:d("/jellyfish-docs/getting_started/sdks","2de"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/introduction/basic_concepts",component:d("/jellyfish-docs/introduction/basic_concepts","9ca"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/introduction/example_scenarios",component:d("/jellyfish-docs/introduction/example_scenarios","8bf"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/release_notes",component:d("/jellyfish-docs/release_notes","bfb"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/tutorials/dashboard",component:d("/jellyfish-docs/tutorials/dashboard","0e2"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/tutorials/react-native",component:d("/jellyfish-docs/tutorials/react-native","414"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/tutorials/simple-react-app",component:d("/jellyfish-docs/tutorials/simple-react-app","946"),exact:!0,sidebar:"mainSidebar"},{path:"/jellyfish-docs/",component:d("/jellyfish-docs/","727"),exact:!0,sidebar:"mainSidebar"}]}]}]},{path:"*",component:d("*")}]},240:(e,t,n)=>{"use strict";n.d(t,{e:()=>a,g:()=>i});var r=n(1504),o=n(7624);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},8808:(e,t,n)=>{"use strict";var r=n(1504),o=n(8352),a=n(440),i=n(2160),s=n(8684);const l=[n(1462),n(5396),n(1976),n(1496),n(7900),n(604)];var c=n(628),u=n(5592),d=n(5464),p=n(7624);function f(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var h=n(6952),m=n(8264),g=n(964),y=n(1824),b=n(5008),v=n(1616),x=n(204),w=n(4456),k=n(5684),_=n(8712);function S(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,m.c)(),r=(0,v.D)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,p.jsxs)(h.c,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function E(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,m.c)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,m.c)(),{pathname:r}=(0,u.IT)();return e+(0,k.applyTrailingSlash)((0,g.c)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,p.jsxs)(h.c,{children:[(0,p.jsx)("meta",{property:"og:url",content:o}),(0,p.jsx)("link",{rel:"canonical",href:o})]})}function j(){const{i18n:{currentLocale:e}}=(0,m.c)(),{metadata:t,image:n}=(0,y.y)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(h.c,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:x.m})]}),n&&(0,p.jsx)(b.U7,{image:n}),(0,p.jsx)(E,{}),(0,p.jsx)(S,{}),(0,p.jsx)(_.c,{tag:w.e6,locale:e}),(0,p.jsx)(h.c,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const C=new Map;function T(e){if(C.has(e.pathname))return{...e,pathname:C.get(e.pathname)};if((0,d.C)(c.c,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}var A=n(240),P=n(136),R=n(5288);function L(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>o.forEach((e=>e?.()))}const N=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,R.c)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),L("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function O(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.C)(c.c,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class I extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=s.default.canUseDOM?L("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=L("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),O(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(N,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(u.kX,{location:t,render:()=>e})})}}const F=I,D="__docusaurus-base-url-issue-banner-container",M="__docusaurus-base-url-issue-banner",$="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${D}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var Q=n(8120);const J=new Set,Z=new Set,X=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!X()&&!Z.has(e)&&!J.has(e))(e))return!1;J.add(e);const t=(0,d.C)(c.c,e).flatMap((e=>{return t=e.route.path,Object.entries(Y).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,Q.c)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?K(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!X()&&!Z.has(e))(e)&&(Z.add(e),O(e))},te=Object.freeze(ee),ne=Boolean(!0);if(s.default.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(i.EN,{children:(0,p.jsx)(a.kn,{children:(0,p.jsx)(G,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(ne)r.startTransition((()=>{o.hydrateRoot(e,t,{onRecoverableError:n})}));else{const a=o.createRoot(e,{onRecoverableError:n});r.startTransition((()=>{a.render(t)}))}};O(window.location.pathname).then(s)}},136:(e,t,n)=>{"use strict";n.d(t,{e:()=>d,y:()=>p});var r=n(1504),o=n(7768);const a=JSON.parse('{"docusaurus-plugin-redoc":{"jellyfish-rest-api":{"url":"https://raw.githubusercontent.com/jellyfish-dev/jellyfish/main/openapi.yaml","themeId":"theme-redoc","isSpecFile":false,"spec":{"components":{"responses":{},"schemas":{"PeerStatus":{"description":"Informs about the peer status","enum":["connected","disconnected"],"example":"disconnected","title":"PeerStatus","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Status"},"HealthReportStatus":{"description":"Informs about the status of Jellyfish or a specific service","enum":["UP","DOWN"],"example":"UP","title":"HealthReportStatus","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport.Status"},"RoomDetailsResponse":{"description":"Response containing room details","properties":{"data":{"$ref":"#/components/schemas/Room"}},"required":["data"],"title":"RoomDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomDetailsResponse"},"ComponentOptionsRTSP":{"description":"Options specific to the RTSP component","properties":{"keepAliveInterval":{"default":15000,"description":"Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source","minimum":0,"type":"integer"},"pierceNat":{"default":true,"description":"Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup","type":"boolean"},"reconnectDelay":{"default":15000,"description":"Delay (in ms) between successive reconnect attempts","minimum":0,"type":"integer"},"rtpPort":{"default":20000,"description":"Local port RTP stream will be received at","maximum":65535,"minimum":1,"type":"integer"},"sourceUri":{"description":"URI of RTSP source stream","example":"rtsp://localhost:554/stream","type":"string"}},"required":["sourceUri"],"title":"ComponentOptionsRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP.Options"},"ComponentPropertiesHLS":{"description":"Properties specific to the HLS component","properties":{"lowLatency":{"description":"Whether the component uses LL-HLS","type":"boolean"},"persistent":{"description":"Whether the video is stored after end of stream","type":"boolean"},"playable":{"description":"Whether the generated HLS playlist is playable","type":"boolean"},"subscribeMode":{"description":"Whether the HLS component should subscribe to tracks automatically or manually","enum":["auto","manual"],"type":"string"},"targetWindowDuration":{"description":"Duration of stream available for viewer","nullable":true,"type":"integer"}},"required":["playable","lowLatency","persistent","targetWindowDuration","subscribeMode"],"title":"ComponentPropertiesHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.Properties"},"Room":{"description":"Description of the room state","properties":{"components":{"description":"List of all components","items":{"$ref":"#/components/schemas/Component"},"type":"array"},"config":{"$ref":"#/components/schemas/RoomConfig"},"id":{"description":"Room ID","example":"room-1","type":"string"},"peers":{"description":"List of all peers","items":{"$ref":"#/components/schemas/Peer"},"type":"array"}},"required":["id","config","components","peers"],"title":"Room","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Room"},"Component":{"description":"Describes component","discriminator":{"mapping":{"file":"#/components/schemas/ComponentFile","hls":"#/components/schemas/ComponentHLS","rtsp":"#/components/schemas/ComponentRTSP"},"propertyName":"type"},"oneOf":[{"$ref":"#/components/schemas/ComponentHLS"},{"$ref":"#/components/schemas/ComponentRTSP"},{"$ref":"#/components/schemas/ComponentFile"}],"title":"Component","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component"},"PeerOptionsWebRTC":{"description":"Options specific to the WebRTC peer","properties":{"enableSimulcast":{"default":true,"description":"Enables the peer to use simulcast","type":"boolean"}},"title":"PeerOptionsWebRTC","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.WebRTC"},"HealthcheckResponse":{"description":"Response containing health report of Jellyfish","properties":{"data":{"$ref":"#/components/schemas/HealthReport"}},"required":["data"],"title":"HealthcheckResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthcheckResponse"},"ComponentHLS":{"description":"Describes the HLS component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesHLS"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"hls","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS"},"HlsSkip":{"description":"Set to \\"YES\\" if delta manifest should be requested","example":"YES","nullable":true,"title":"HlsSkip","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsSkip"},"PeerMetadata":{"description":"Custom metadata set by the peer","example":{"name":"JellyfishUser"},"nullable":true,"title":"PeerMetadata","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.PeerMetadata"},"ComponentPropertiesFile":{"description":"Properties specific to the File component","properties":{"filePath":{"description":"Relative path to track file. Must be either OPUS encapsulated in Ogg or raw h264","type":"string"},"framerate":{"description":"Framerate of video in a file. It is only valid for video track","example":30,"nullable":true,"type":"integer"}},"required":["filePath","framerate"],"title":"ComponentPropertiesFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File.Properties"},"ComponentFile":{"description":"Describes the File component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesFile"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"file","type":"string"}},"required":["id","type","tracks"],"title":"ComponentFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File"},"SubscriptionConfig":{"description":"Subscription config","properties":{"origins":{"description":"List of peers and components ids whose tracks the HLS endpoint will subscribe to","items":{"type":"string"},"type":"array"}},"title":"SubscriptionConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Subscription.Origins"},"HlsMsn":{"description":"Segment sequence number","example":10,"minimum":0,"nullable":true,"title":"HlsMsn","type":"integer","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsMsn"},"ComponentRTSP":{"description":"Describes the RTSP component","properties":{"id":{"description":"Assigned component ID","example":"component-1","type":"string"},"properties":{"$ref":"#/components/schemas/ComponentPropertiesRTSP"},"tracks":{"description":"List of all component\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"description":"Component type","example":"hls","type":"string"}},"required":["id","type","properties","tracks"],"title":"ComponentRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP"},"HlsPart":{"description":"Partial segment sequence number","example":10,"minimum":0,"nullable":true,"title":"HlsPart","type":"integer","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Params.HlsPart"},"ComponentDetailsResponse":{"description":"Response containing component details","properties":{"data":{"$ref":"#/components/schemas/Component"}},"required":["data"],"title":"ComponentDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.ComponentDetailsResponse"},"ComponentOptionsHLS":{"description":"Options specific to the HLS component","properties":{"lowLatency":{"default":false,"description":"Whether the component should use LL-HLS","type":"boolean"},"persistent":{"default":false,"description":"Whether the video is stored after end of stream","type":"boolean"},"s3":{"description":"Credentials to AWS S3 bucket.","nullable":true,"oneOf":[{"$ref":"#/components/schemas/S3Credentials"}],"type":"object"},"subscribeMode":{"default":"auto","description":"Whether the HLS component should subscribe to tracks automatically or manually.","enum":["auto","manual"],"type":"string"},"targetWindowDuration":{"description":"Duration of stream available for viewer","nullable":true,"type":"integer"}},"title":"ComponentOptionsHLS","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.Options"},"S3Credentials":{"description":"An AWS S3 credential that will be used to send HLS stream. The stream will only be uploaded if credentials are provided","properties":{"accessKeyId":{"description":"An AWS access key identifier, linked to your AWS account.","type":"string"},"bucket":{"description":"The name of the S3 bucket where your data will be stored.","type":"string"},"region":{"description":"The AWS region where your bucket is located.","type":"string"},"secretAccessKey":{"description":"The secret key that is linked to the Access Key ID.","type":"string"}},"required":["accessKeyId","secretAccessKey","region","bucket"],"title":"S3Credentials","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.HLS.S3"},"RecordingListResponse":{"description":"Response containing list of all recording","properties":{"data":{"items":{"type":"string"},"type":"array"}},"required":["data"],"title":"RecordingListResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RecordingListResponse"},"ComponentOptions":{"description":"Component-specific options","oneOf":[{"$ref":"#/components/schemas/ComponentOptionsHLS"},{"$ref":"#/components/schemas/ComponentOptionsRTSP"},{"$ref":"#/components/schemas/ComponentOptionsFile"}],"title":"ComponentOptions","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.Options"},"Track":{"description":"Describes media track of a Peer or Component","properties":{"id":{"type":"string"},"metadata":{"nullable":true},"type":{"enum":["audio","video"],"type":"string"}},"title":"Track","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Track"},"HealthReportDistribution":{"description":"Informs about the status of Jellyfish distribution","properties":{"enabled":{"description":"Whether distribution is enabled on this Jellyfish","type":"boolean"},"nodeStatus":{"$ref":"#/components/schemas/HealthReportStatus"},"nodesInCluster":{"description":"Amount of nodes (including this Jellyfish\'s node) in the distribution cluster","type":"integer"}},"required":["nodeStatus","nodesInCluster"],"title":"HealthReportDistribution","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport.Distribution"},"ComponentPropertiesRTSP":{"description":"Properties specific to the RTSP component","properties":{"keepAliveInterval":{"description":"Interval (in ms) in which keep-alive RTSP messages will be sent to the remote stream source","type":"integer"},"pierceNat":{"description":"Whether to attempt to create client-side NAT binding by sending an empty datagram from client to source, after the completion of RTSP setup","type":"boolean"},"reconnectDelay":{"description":"Delay (in ms) between successive reconnect attempts","type":"integer"},"rtpPort":{"description":"Local port RTP stream will be received at","type":"integer"},"sourceUri":{"description":"URI of RTSP source stream","type":"string"}},"required":["sourceUri","rtpPort","reconnectDelay","keepAliveInterval","pierceNat"],"title":"ComponentPropertiesRTSP","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.RTSP.Properties"},"PeerOptions":{"description":"Peer-specific options","oneOf":[{"$ref":"#/components/schemas/PeerOptionsWebRTC"}],"title":"PeerOptions","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Options"},"HealthReport":{"description":"Describes overall Jellyfish health","properties":{"distribution":{"$ref":"#/components/schemas/HealthReportDistribution"},"status":{"$ref":"#/components/schemas/HealthReportStatus"},"uptime":{"description":"Uptime of Jellyfish (in seconds)","type":"integer"}},"required":["status","uptime","distribution"],"title":"HealthReport","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.HealthReport"},"Peer":{"description":"Describes peer status","properties":{"id":{"description":"Assigned peer id","example":"peer-1","type":"string"},"metadata":{"$ref":"#/components/schemas/PeerMetadata"},"status":{"$ref":"#/components/schemas/PeerStatus"},"tracks":{"description":"List of all peer\'s tracks","items":{"$ref":"#/components/schemas/Track"},"type":"array"},"type":{"$ref":"#/components/schemas/PeerType"}},"required":["id","type","status","tracks","metadata"],"title":"Peer","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer"},"ComponentType":{"description":"Component type","example":"hls","title":"ComponentType","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.Type"},"AuthToken":{"description":"Token for authorizing websocket connection","example":"5cdac726-57a3-4ecb-b1d5-72a3d62ec242","title":"AuthToken","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Token"},"RoomsListingResponse":{"description":"Response containing list of all rooms","properties":{"data":{"items":{"$ref":"#/components/schemas/Room"},"type":"array"}},"required":["data"],"title":"RoomsListingResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomsListingResponse"},"PeerDetailsResponse":{"description":"Response containing peer details and their token","properties":{"data":{"properties":{"peer":{"$ref":"#/components/schemas/Peer"},"token":{"$ref":"#/components/schemas/AuthToken"}},"required":["peer","token"],"type":"object"}},"required":["data"],"title":"PeerDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.PeerDetailsResponse"},"HlsResponse":{"description":"Requested file","title":"HlsResponse","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.HLS.Response"},"PeerType":{"description":"Peer type","example":"webrtc","title":"PeerType","type":"string","x-struct":"Elixir.JellyfishWeb.ApiSpec.Peer.Type"},"RoomCreateDetailsResponse":{"description":"Response containing room details","properties":{"data":{"properties":{"jellyfish_address":{"description":"Jellyfish instance address where the room was created. This might be different than the address of Jellyfish where the request was sent only when running a cluster of Jellyfishes.","example":"jellyfish1:5003","type":"string"},"room":{"$ref":"#/components/schemas/Room"}},"required":["room","jellyfish_address"],"type":"object"}},"required":["data"],"title":"RoomCreateDetailsResponse","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.RoomCreateDetailsResponse"},"ComponentOptionsFile":{"description":"Options specific to the File component","properties":{"filePath":{"description":"Path to track file. Must be either OPUS encapsulated in Ogg or raw h264","example":"/root/video.h264","type":"string"},"framerate":{"description":"Framerate of video in a file. It is only valid for video track","example":30,"nullable":true,"type":"integer"}},"required":["filePath"],"title":"ComponentOptionsFile","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Component.File.Options"},"Error":{"description":"Error message","properties":{"errors":{"description":"Error details","example":"Token has expired","type":"string"}},"required":["errors"],"title":"Error","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Error"},"RoomConfig":{"description":"Room configuration","properties":{"maxPeers":{"description":"Maximum amount of peers allowed into the room","example":10,"minimum":1,"nullable":true,"type":"integer"},"roomId":{"description":"Custom id used for identifying room within Jellyfish. Must be unique across all rooms. If not provided, random UUID is generated.","nullable":true,"type":"string"},"videoCodec":{"description":"Enforces video codec for each peer in the room","enum":["h264","vp8"],"nullable":true,"type":"string"},"webhookUrl":{"description":"URL where Jellyfish notifications will be sent","example":"https://backend.address.com/jellyfish-notifications-endpoint","nullable":true,"type":"string"}},"title":"RoomConfig","type":"object","x-struct":"Elixir.JellyfishWeb.ApiSpec.Room.Config"}},"securitySchemes":{"authorization":{"scheme":"bearer","type":"http"}}},"info":{"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0"},"title":"Jellyfish Media Server","version":"0.2.0"},"openapi":"3.0.0","paths":{"/health":{"get":{"callbacks":{},"operationId":"healthcheck","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthcheckResponse"}}},"description":"Healthy"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Describes the health of Jellyfish","tags":["health"]}},"/hls/{room_id}/subscribe":{"post":{"callbacks":{},"operationId":"subscribe_hls_to","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionConfig"}}},"description":"Subscribe configuration","required":false},"responses":{"201":{"description":"Tracks succesfully added."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Subscribe the HLS component to the tracks of peers or components","tags":["hls"]}},"/hls/{room_id}/{filename}":{"get":{"callbacks":{},"operationId":"getHlsContent","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Name of the file","in":"path","name":"filename","required":true,"schema":{"type":"string"}},{"description":"Byte range of partial segment","in":"header","name":"range","required":false,"schema":{"type":"string"}},{"description":"Segment sequence number","in":"query","name":"_HLS_msn","required":false,"schema":{"$ref":"#/components/schemas/HlsMsn"}},{"description":"Partial segment sequence number","in":"query","name":"_HLS_part","required":false,"schema":{"$ref":"#/components/schemas/HlsPart"}},{"description":"Is delta manifest requested","in":"query","name":"_HLS_skip","required":false,"schema":{"$ref":"#/components/schemas/HlsSkip"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HlsResponse"}}},"description":"File was found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid filename"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"File not found"}},"summary":"Retrieve HLS Content","tags":["hls"]}},"/recording":{"get":{"callbacks":{},"operationId":"get_recordings","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordingListResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unable to obtain recordings"}},"summary":"Lists all available recordings","tags":["recording"]}},"/recording/{recording_id}":{"delete":{"callbacks":{},"operationId":"delete_recording","parameters":[{"description":"Recording id","in":"path","name":"recording_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted recording"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid recording"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Recording doesn\'t exist"}},"summary":"Deletes the recording","tags":["recording"]}},"/recording/{recording_id}/{filename}":{"get":{"callbacks":{},"operationId":"getRecordingContent","parameters":[{"description":"Recording id","in":"path","name":"recording_id","required":true,"schema":{"type":"string"}},{"description":"Name of the file","in":"path","name":"filename","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HlsResponse"}}},"description":"File was found"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"File not found"}},"summary":"Retrieve Recording (HLS) Content","tags":["recording"]}},"/room":{"get":{"callbacks":{},"operationId":"get_all_rooms","parameters":[],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomsListingResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Show information about all rooms","tags":["room"]},"post":{"callbacks":{},"operationId":"create_room","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomConfig"}}},"description":"Room configuration","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomCreateDetailsResponse"}}},"description":"Room successfully created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"Creates a room","tags":["room"]}},"/room/{room_id}":{"delete":{"callbacks":{},"operationId":"delete_room","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted room"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Delete the room","tags":["room"]},"get":{"callbacks":{},"operationId":"get_room","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomDetailsResponse"}}},"description":"Success"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Shows information about the room","tags":["room"]}},"/room/{room_id}/component":{"post":{"callbacks":{},"operationId":"add_component","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"options":{"$ref":"#/components/schemas/ComponentOptions"},"type":{"$ref":"#/components/schemas/ComponentType"}},"required":["type"],"type":"object"}}},"description":"Component config","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComponentDetailsResponse"}}},"description":"Successfully added component"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"}},"summary":"Creates the component and adds it to the room","tags":["room"]}},"/room/{room_id}/component/{id}":{"delete":{"callbacks":{},"operationId":"delete_component","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Component ID","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Successfully deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Either component or the room doesn\'t exist"}},"summary":"Delete the component from the room","tags":["room"]}},"/room/{room_id}/peer":{"post":{"callbacks":{},"operationId":"add_peer","parameters":[{"description":"Room id","in":"path","name":"room_id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"options":{"$ref":"#/components/schemas/PeerOptions"},"type":{"$ref":"#/components/schemas/PeerType"}},"required":["type","options"],"type":"object"}}},"description":"Peer specification","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeerDetailsResponse"}}},"description":"Peer successfully created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Invalid request body structure"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room doesn\'t exist"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Peer limit has been reached"}},"summary":"Create peer","tags":["room"]}},"/room/{room_id}/peer/{id}":{"delete":{"callbacks":{},"operationId":"delete_peer","parameters":[{"description":"Room ID","in":"path","name":"room_id","required":true,"schema":{"type":"string"}},{"description":"Peer id","in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Peer successfully deleted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Room ID or Peer ID references a resource that doesn\'t exist"}},"summary":"Delete peer","tags":["room"]}}},"security":[{"authorization":[]}],"servers":[],"tags":[]}}},"docusaurus-theme-redoc":{"theme-redoc":{"lightTheme":{"typography":{"fontFamily":"var(--ifm-font-family-base)","fontSize":"var(--ifm-font-size-base)","lineHeight":"var(--ifm-line-height-base)","fontWeightLight":"var(--ifm-font-weight-light)","fontWeightRegular":"var(--ifm-font-weight-base)","fontWeightBold":"var(--ifm-font-weight-bold)","headings":{"fontFamily":"var(--ifm-heading-font-family)","fontWeight":"var(--ifm-heading-font-weight)","lineHeight":"var(--ifm-heading-line-height)"},"code":{"fontFamily":"var(--ifm-font-family-monospace)","lineHeight":"var(--ifm-pre-line-height)"}},"sidebar":{"width":"300px","backgroundColor":"#ffffff"},"rightPanel":{"backgroundColor":"#303846"},"colors":{"primary":{"main":"#3F57A6"}},"theme":{"prism":{"additionalLanguages":["scala"]}}},"darkTheme":{"typography":{"fontFamily":"var(--ifm-font-family-base)","fontSize":"var(--ifm-font-size-base)","lineHeight":"var(--ifm-line-height-base)","fontWeightLight":"var(--ifm-font-weight-light)","fontWeightRegular":"var(--ifm-font-weight-base)","fontWeightBold":"var(--ifm-font-weight-bold)","headings":{"fontFamily":"var(--ifm-heading-font-family)","fontWeight":"var(--ifm-heading-font-weight)","lineHeight":"var(--ifm-heading-line-height)"},"code":{"fontFamily":"var(--ifm-font-family-monospace)","lineHeight":"var(--ifm-pre-line-height)"}},"sidebar":{"width":"300px","backgroundColor":"rgb(24, 25, 26)","textColor":"#f5f6f7","arrow":{"color":"#f5f6f7"}},"colors":{"text":{"primary":"#f5f6f7","secondary":"rgba(255, 255, 255, 1)"},"gray":{"50":"#FAFAFA","100":"#F5F5F5"},"border":{"dark":"#ffffff","light":"rgba(0,0,0, 0.1)"},"primary":{"main":"#3F57A6"}},"schema":{"nestedBackground":"rgb(24, 25, 26)","typeNameColor":"rgba(255, 255, 255, 1)","typeTitleColor":"rgba(255, 255, 255, 1)"},"theme":{"prism":{"additionalLanguages":["scala"]}}},"options":{"scrollYOffset":"nav.navbar","expandSingleSchemaField":true,"menuToggle":true,"suppressWarnings":true}}},"docusaurus-plugin-content-docs":{"default":{"path":"/jellyfish-docs/","versions":[{"name":"current","label":"Next","isLast":false,"path":"/jellyfish-docs/next","mainDocId":"introduction/what_is_jellyfish","docs":[{"id":"benchmarks","path":"/jellyfish-docs/next/benchmarks","sidebar":"mainSidebar"},{"id":"benchmarks/hls","path":"/jellyfish-docs/next/benchmarks/hls","sidebar":"mainSidebar"},{"id":"benchmarks/webrtc","path":"/jellyfish-docs/next/benchmarks/webrtc","sidebar":"mainSidebar"},{"id":"cluster","path":"/jellyfish-docs/next/cluster","sidebar":"mainSidebar"},{"id":"deploying/fly_io","path":"/jellyfish-docs/next/deploying/fly_io","sidebar":"mainSidebar"},{"id":"deploying/vps","path":"/jellyfish-docs/next/deploying/vps","sidebar":"mainSidebar"},{"id":"examples","path":"/jellyfish-docs/next/examples"},{"id":"for_developers/api_reference","path":"/jellyfish-docs/next/for_developers/api_reference","sidebar":"mainSidebar"},{"id":"for_developers/api_reference/rest_api","path":"/jellyfish-docs/next/for_developers/api_reference/rest_api","sidebar":"mainSidebar"},{"id":"for_developers/design_docs","path":"/jellyfish-docs/next/for_developers/design_docs","sidebar":"mainSidebar"},{"id":"for_developers/metrics_design","path":"/jellyfish-docs/next/for_developers/metrics_design","sidebar":"mainSidebar"},{"id":"getting_started/architecture","path":"/jellyfish-docs/next/getting_started/architecture","sidebar":"mainSidebar"},{"id":"getting_started/authentication","path":"/jellyfish-docs/next/getting_started/authentication","sidebar":"mainSidebar"},{"id":"getting_started/components/file","path":"/jellyfish-docs/next/getting_started/components/file","sidebar":"mainSidebar"},{"id":"getting_started/components/hls","path":"/jellyfish-docs/next/getting_started/components/hls","sidebar":"mainSidebar"},{"id":"getting_started/components/rtsp","path":"/jellyfish-docs/next/getting_started/components/rtsp","sidebar":"mainSidebar"},{"id":"getting_started/installation","path":"/jellyfish-docs/next/getting_started/installation","sidebar":"mainSidebar"},{"id":"getting_started/metrics","path":"/jellyfish-docs/next/getting_started/metrics","sidebar":"mainSidebar"},{"id":"getting_started/notifications","path":"/jellyfish-docs/next/getting_started/notifications","sidebar":"mainSidebar"},{"id":"getting_started/peers/webrtc","path":"/jellyfish-docs/next/getting_started/peers/webrtc","sidebar":"mainSidebar"},{"id":"getting_started/room","path":"/jellyfish-docs/next/getting_started/room","sidebar":"mainSidebar"},{"id":"getting_started/sdks","path":"/jellyfish-docs/next/getting_started/sdks","sidebar":"mainSidebar"},{"id":"introduction/basic_concepts","path":"/jellyfish-docs/next/introduction/basic_concepts","sidebar":"mainSidebar"},{"id":"introduction/example_scenarios","path":"/jellyfish-docs/next/introduction/example_scenarios","sidebar":"mainSidebar"},{"id":"introduction/what_is_jellyfish","path":"/jellyfish-docs/next/","sidebar":"mainSidebar"},{"id":"release_notes","path":"/jellyfish-docs/next/release_notes","sidebar":"mainSidebar"},{"id":"tutorials/dashboard","path":"/jellyfish-docs/next/tutorials/dashboard","sidebar":"mainSidebar"},{"id":"tutorials/react-native","path":"/jellyfish-docs/next/tutorials/react-native","sidebar":"mainSidebar"},{"id":"tutorials/simple-react-app","path":"/jellyfish-docs/next/tutorials/simple-react-app","sidebar":"mainSidebar"}],"draftIds":[],"sidebars":{"mainSidebar":{"link":{"path":"/jellyfish-docs/next/","label":"introduction/what_is_jellyfish"}}}},{"name":"0.3.0","label":"0.3.0","isLast":true,"path":"/jellyfish-docs/","mainDocId":"introduction/what_is_jellyfish","docs":[{"id":"benchmarks","path":"/jellyfish-docs/benchmarks","sidebar":"mainSidebar"},{"id":"benchmarks/hls","path":"/jellyfish-docs/benchmarks/hls","sidebar":"mainSidebar"},{"id":"benchmarks/webrtc","path":"/jellyfish-docs/benchmarks/webrtc","sidebar":"mainSidebar"},{"id":"cluster","path":"/jellyfish-docs/cluster","sidebar":"mainSidebar"},{"id":"deploying/fly_io","path":"/jellyfish-docs/deploying/fly_io","sidebar":"mainSidebar"},{"id":"deploying/vps","path":"/jellyfish-docs/deploying/vps","sidebar":"mainSidebar"},{"id":"examples","path":"/jellyfish-docs/examples"},{"id":"for_developers/api_reference","path":"/jellyfish-docs/for_developers/api_reference","sidebar":"mainSidebar"},{"id":"for_developers/api_reference/rest_api","path":"/jellyfish-docs/for_developers/api_reference/rest_api","sidebar":"mainSidebar"},{"id":"for_developers/design_docs","path":"/jellyfish-docs/for_developers/design_docs","sidebar":"mainSidebar"},{"id":"for_developers/metrics_design","path":"/jellyfish-docs/for_developers/metrics_design","sidebar":"mainSidebar"},{"id":"getting_started/architecture","path":"/jellyfish-docs/getting_started/architecture","sidebar":"mainSidebar"},{"id":"getting_started/authentication","path":"/jellyfish-docs/getting_started/authentication","sidebar":"mainSidebar"},{"id":"getting_started/components/file","path":"/jellyfish-docs/getting_started/components/file","sidebar":"mainSidebar"},{"id":"getting_started/components/hls","path":"/jellyfish-docs/getting_started/components/hls","sidebar":"mainSidebar"},{"id":"getting_started/components/rtsp","path":"/jellyfish-docs/getting_started/components/rtsp","sidebar":"mainSidebar"},{"id":"getting_started/installation","path":"/jellyfish-docs/getting_started/installation","sidebar":"mainSidebar"},{"id":"getting_started/metrics","path":"/jellyfish-docs/getting_started/metrics","sidebar":"mainSidebar"},{"id":"getting_started/notifications","path":"/jellyfish-docs/getting_started/notifications","sidebar":"mainSidebar"},{"id":"getting_started/peers/webrtc","path":"/jellyfish-docs/getting_started/peers/webrtc","sidebar":"mainSidebar"},{"id":"getting_started/sdks","path":"/jellyfish-docs/getting_started/sdks","sidebar":"mainSidebar"},{"id":"introduction/basic_concepts","path":"/jellyfish-docs/introduction/basic_concepts","sidebar":"mainSidebar"},{"id":"introduction/example_scenarios","path":"/jellyfish-docs/introduction/example_scenarios","sidebar":"mainSidebar"},{"id":"introduction/what_is_jellyfish","path":"/jellyfish-docs/","sidebar":"mainSidebar"},{"id":"release_notes","path":"/jellyfish-docs/release_notes","sidebar":"mainSidebar"},{"id":"tutorials/dashboard","path":"/jellyfish-docs/tutorials/dashboard","sidebar":"mainSidebar"},{"id":"tutorials/react-native","path":"/jellyfish-docs/tutorials/react-native","sidebar":"mainSidebar"},{"id":"tutorials/simple-react-app","path":"/jellyfish-docs/tutorials/simple-react-app","sidebar":"mainSidebar"}],"draftIds":[],"sidebars":{"mainSidebar":{"link":{"path":"/jellyfish-docs/","label":"introduction/what_is_jellyfish"}}}},{"name":"0.2.1","label":"0.2.1","isLast":false,"path":"/jellyfish-docs/0.2.1","mainDocId":"introduction/what_is_jellyfish","docs":[{"id":"cluster","path":"/jellyfish-docs/0.2.1/cluster","sidebar":"mainSidebar"},{"id":"deploying/fly_io","path":"/jellyfish-docs/0.2.1/deploying/fly_io","sidebar":"mainSidebar"},{"id":"deploying/vps","path":"/jellyfish-docs/0.2.1/deploying/vps","sidebar":"mainSidebar"},{"id":"examples","path":"/jellyfish-docs/0.2.1/examples"},{"id":"for_developers/api_reference","path":"/jellyfish-docs/0.2.1/for_developers/api_reference","sidebar":"mainSidebar"},{"id":"for_developers/api_reference/rest_api","path":"/jellyfish-docs/0.2.1/for_developers/api_reference/rest_api","sidebar":"mainSidebar"},{"id":"for_developers/design_docs","path":"/jellyfish-docs/0.2.1/for_developers/design_docs","sidebar":"mainSidebar"},{"id":"getting_started/architecture","path":"/jellyfish-docs/0.2.1/getting_started/architecture","sidebar":"mainSidebar"},{"id":"getting_started/authentication","path":"/jellyfish-docs/0.2.1/getting_started/authentication","sidebar":"mainSidebar"},{"id":"getting_started/components/hls","path":"/jellyfish-docs/0.2.1/getting_started/components/hls","sidebar":"mainSidebar"},{"id":"getting_started/components/rtsp","path":"/jellyfish-docs/0.2.1/getting_started/components/rtsp","sidebar":"mainSidebar"},{"id":"getting_started/installation","path":"/jellyfish-docs/0.2.1/getting_started/installation","sidebar":"mainSidebar"},{"id":"getting_started/metrics","path":"/jellyfish-docs/0.2.1/getting_started/metrics","sidebar":"mainSidebar"},{"id":"getting_started/notifications","path":"/jellyfish-docs/0.2.1/getting_started/notifications","sidebar":"mainSidebar"},{"id":"getting_started/peers/webrtc","path":"/jellyfish-docs/0.2.1/getting_started/peers/webrtc","sidebar":"mainSidebar"},{"id":"getting_started/sdks","path":"/jellyfish-docs/0.2.1/getting_started/sdks","sidebar":"mainSidebar"},{"id":"introduction/basic_concepts","path":"/jellyfish-docs/0.2.1/introduction/basic_concepts","sidebar":"mainSidebar"},{"id":"introduction/example_scenarios","path":"/jellyfish-docs/0.2.1/introduction/example_scenarios","sidebar":"mainSidebar"},{"id":"introduction/what_is_jellyfish","path":"/jellyfish-docs/0.2.1/","sidebar":"mainSidebar"},{"id":"tutorials/dashboard","path":"/jellyfish-docs/0.2.1/tutorials/dashboard","sidebar":"mainSidebar"},{"id":"tutorials/react-native","path":"/jellyfish-docs/0.2.1/tutorials/react-native","sidebar":"mainSidebar"},{"id":"tutorials/simple-react-app","path":"/jellyfish-docs/0.2.1/tutorials/simple-react-app","sidebar":"mainSidebar"}],"draftIds":[],"sidebars":{"mainSidebar":{"link":{"path":"/jellyfish-docs/0.2.1/","label":"introduction/what_is_jellyfish"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(144);const l=JSON.parse('{"docusaurusVersion":"3.1.1","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.1.1"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.1.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.1.1"},"docusaurus-plugin-redoc":{"type":"package","name":"docusaurus-plugin-redoc","version":"2.0.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.1.1"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.1.1"},"docusaurus-theme-redoc":{"type":"package","name":"docusaurus-theme-redoc","version":"2.0.1"}}}');var c=n(7624);const u={siteConfig:o.default,siteMetadata:l,globalData:a,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},5852:(e,t,n)=>{"use strict";n.d(t,{c:()=>f});var r=n(1504),o=n(8684),a=n(6952),i=n(5684),s=n(7468),l=n(7624);function c(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function d(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)(f,{fallback:()=>(0,l.jsx)(c,{error:t,tryAgain:n}),children:[(0,l.jsx)(a.c,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(s.c,{children:(0,l.jsx)(c,{error:t,tryAgain:n})})]})}const p=e=>(0,l.jsx)(d,{...e});class f extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.default.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??p)(e)}return e??null}}},8684:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},6952:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);var r=n(2160),o=n(7624);function a(e){return(0,o.jsx)(r.So,{...e})}},867:(e,t,n)=>{"use strict";n.d(t,{c:()=>f});var r=n(1504),o=n(440),a=n(5684),i=n(8264),s=n(8136),l=n(8684),c=n(5976),u=n(964),d=n(7624);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:h,isActive:m,"data-noBrokenLinkCheck":g,autoAddBaseUrl:y=!0,...b}=e;const{siteConfig:{trailingSlash:v,baseUrl:x}}=(0,i.c)(),{withBaseUrl:w}=(0,u.E)(),k=(0,c.c)(),_=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>_.current));const S=p||f;const E=(0,s.c)(S),j=S?.replace("pathname://","");let C=void 0!==j?(T=j,y&&(e=>e.startsWith("/"))(T)?w(T):T):void 0;var T;C&&E&&(C=(0,a.applyTrailingSlash)(C,{trailingSlash:v,baseUrl:x}));const A=(0,r.useRef)(!1),P=n?o.Af:o.cH,R=l.default.canUseIntersectionObserver,L=(0,r.useRef)(),N=()=>{A.current||null==C||(window.docusaurus.preload(C),A.current=!0)};(0,r.useEffect)((()=>(!R&&E&&null!=C&&window.docusaurus.prefetch(C),()=>{R&&L.current&&L.current.disconnect()})),[L,C,R,E]);const O=C?.startsWith("#")??!1,I=!b.target||"_self"===b.target,F=!C||!E||!I||O;return g||!O&&F||k.collectLink(C),b.id&&k.collectAnchor(b.id),F?(0,d.jsx)("a",{ref:_,href:C,...S&&!E&&{target:"_blank",rel:"noopener noreferrer"},...b}):(0,d.jsx)(P,{...b,onMouseEnter:N,onTouchStart:N,innerRef:e=>{_.current=e,R&&e&&E&&(L.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(L.current.unobserve(e),L.current.disconnect(),null!=C&&window.docusaurus.prefetch(C))}))})),L.current.observe(e))},to:C,...n&&{isActive:m,activeClassName:h}})}const f=r.forwardRef(p)},4357:(e,t,n)=>{"use strict";n.d(t,{c:()=>c,G:()=>l});var r=n(1504),o=n(7624);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(144);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return a(s({message:n,id:r}),t)}function c(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=s({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},2488:(e,t,n)=>{"use strict";n.d(t,{M:()=>r});const r="default"},8136:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{_:()=>r,c:()=>o})},964:(e,t,n)=>{"use strict";n.d(t,{E:()=>i,c:()=>s});var r=n(1504),o=n(8264),a=n(8136);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,o.c)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a._)(n))return n;if(o)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},5976:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(1504);n(7624);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},8264:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});var r=n(1504),o=n(136);function a(){return(0,r.useContext)(o.e)}},3160:(e,t,n)=>{"use strict";n.d(t,{MP:()=>i,mm:()=>a});var r=n(8264),o=n(2488);function a(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.c)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}function i(e,t,n){void 0===t&&(t=o.M),void 0===n&&(n={});const r=a(e),i=r?.[t];if(!i&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return i}},3664:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});var r=n(1504),o=n(240);function a(){return(0,r.useContext)(o.e)}},5288:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});var r=n(1504);const o=n(8684).default.canUseDOM?r.useLayoutEffect:r.useEffect},8120:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const s=o?`${o}.${a}`:a;r(i)?e(i,s):t[s]=i}))}(e),t}},5548:(e,t,n)=>{"use strict";n.d(t,{Y:()=>i,e:()=>a});var r=n(1504),o=n(7624);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),s=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:s,children:t})}},5172:(e,t,n)=>{"use strict";n.d(t,{wB:()=>m,UF:()=>d,mU:()=>p,L0:()=>c,i8:()=>g,OK:()=>u,aA:()=>h,gN:()=>f});var r=n(5592),o=n(3160);const a=e=>e.versions.find((e=>e.isLast));function i(e,t){const n=a(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.ot)(t,{path:e.path,exact:!1,strict:!1})))}function s(e,t){const n=i(e,t),o=n?.docs.find((e=>!!(0,r.ot)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const l={},c=()=>(0,o.mm)("docusaurus-plugin-content-docs")??l,u=e=>(0,o.MP)("docusaurus-plugin-content-docs",e,{failfast:!0});function d(e){void 0===e&&(e={});const t=c(),{pathname:n}=(0,r.IT)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.ot)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return a}(t,n,e)}function p(e){void 0===e&&(e={});const t=d(e),{pathname:n}=(0,r.IT)();if(!t)return;return{activePlugin:t,activeVersion:i(t.pluginData,n)}}function f(e){return u(e).versions}function h(e){const t=u(e);return a(t)}function m(e){const t=u(e),{pathname:n}=(0,r.IT)();return s(t,n)}function g(e){const t=u(e),{pathname:n}=(0,r.IT)();return function(e,t){const n=a(e);return{latestDocSuggestion:s(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},1976:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(2272),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},5396:(e,t,n)=>{"use strict";n.r(t);var r=n(4728),o=n(7768);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(1808),n(4164)(`./prism-${e}`)})),delete globalThis.Prism}(r.sp)},6448:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});n(1504);var r=n(4064),o=n(4357),a=n(1824),i=n(867),s=n(5976);const l={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var c=n(7624);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.c)(),{navbar:{hideOnScroll:p}}=(0,a.y)();if("h1"===t||!n)return(0,c.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,o.G)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,c.jsxs)(t,{...u,className:(0,r.c)("anchor",p?l.anchorWithHideOnScrollNavbar:l.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,c.jsx)(i.c,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},3232:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(7624);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},7468:(e,t,n)=>{"use strict";n.d(t,{c:()=>Lt});var r=n(1504),o=n(4064),a=n(5852),i=n(5008),s=n(5592),l=n(4357),c=n(7124),u=n(7624);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.Uz)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.c)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const h=(0,l.G)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function m(e){const t=e.children??h,{containerRef:n,onClick:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":h,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var g=n(5864),y=n(204);const b={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(m,{className:b.skipToContent})}var x=n(1824),w=n(3868);function k(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const _={closeButton:"closeButton_CVFx"};function S(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,l.G)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.c)("clean-btn close",_.closeButton,e.className),children:(0,u.jsx)(k,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_knG7"};function j(e){const{announcementBar:t}=(0,x.y)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.c)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const C={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function T(){const{announcementBar:e}=(0,x.y)(),{isActive:t,close:n}=(0,w.el)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:C.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:C.announcementBarPlaceholder}),(0,u.jsx)(j,{className:C.announcementBarContent}),a&&(0,u.jsx)(S,{onClick:n,className:C.announcementBarClose})]})}var A=n(8200),P=n(3943);var R=n(1100),L=n(5168);const N=r.createContext(null);function O(e){let{children:t}=e;const n=function(){const e=(0,A.q)(),t=(0,L.MF)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,R.i0)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(N.Provider,{value:n,children:t})}function I(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function F(){const e=(0,r.useContext)(N);if(!e)throw new R.AH("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,L.MF)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:I(a)})),[o,a,t])}function D(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=F();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.c)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var M=n(6528),$=n(3664);function B(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function z(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function H(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,$.c)(),s=(0,l.G)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,l.G)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.G)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.c)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.c)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(B,{className:(0,o.c)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)(z,{className:(0,o.c)(U.toggleIcon,U.darkToggleIcon)})]})})}const W=r.memo(H),q={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function V(e){let{className:t}=e;const n=(0,x.y)().navbar.style,r=(0,x.y)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,M.U)();return r?null:(0,u.jsx)(W,{className:t,buttonClassName:"dark"===n?q.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var G=n(8164);function Y(){return(0,u.jsx)(G.c,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function K(){const e=(0,A.q)();return(0,u.jsx)("button",{type:"button","aria-label":(0,l.G)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(k,{color:"var(--ifm-color-emphasis-600)"})})}function Q(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(Y,{}),(0,u.jsx)(V,{className:"margin-right--md"}),(0,u.jsx)(K,{})]})}var J=n(867),Z=n(964),X=n(8136),ee=n(1064),te=n(3232);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:s,prependBaseUrlToHref:l,...c}=e;const d=(0,Z.c)(r),p=(0,Z.c)(t),f=(0,Z.c)(o,{forcePrependBaseUrl:!0}),h=a&&o&&!(0,X.c)(o),m=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,h&&(0,u.jsx)(te.c,{...s&&{width:12,height:12}})]})};return o?(0,u.jsx)(J.c,{href:l?f:o,...c,...m}):(0,u.jsx)(J.c,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee._)(n,t.pathname):t.pathname.startsWith(p)},...c,...m})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.c)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.c)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(8448),se=n(3376),le=n(8264);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.Sc)(e.to,t)||!!(0,ee._)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:i,...s}=e;const l=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{l.current&&!l.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,o.c)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,o.c)("navbar__link",a),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(We,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:a,onClick:i,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.c)(),{pathname:t}=(0,s.IT)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:h}=(0,ie.a)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&h(!d)}),[c,d,h]),(0,u.jsxs)("li",{className:(0,o.c)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.c)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,u.jsx)(ie.U,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(We,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var he=n(1616);function me(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const ge="iconLanguage_nlXk";var ye=n(7104);function be(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var ve=n(5052),xe=["translations"];function we(){return we=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var Ee="Ctrl";var je=r.forwardRef((function(e,t){var n=e.translations,o=void 0===n?{}:n,a=Se(e,xe),i=o.buttonText,s=void 0===i?"Search":i,l=o.buttonAriaLabel,c=void 0===l?"Search":l,u=ke((0,r.useState)(null),2),d=u[0],p=u[1];return(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?p("\u2318"):p(Ee))}),[]),r.createElement("button",we({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},a,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(ve.I,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&r.createElement(r.Fragment,null,r.createElement("kbd",{className:"DocSearch-Button-Key"},d===Ee?r.createElement(be,null):d),r.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),Ce=n(6952),Te=n(7092),Ae=n(9032),Pe=n(4456);const Re={button:{buttonText:(0,l.G)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,l.G)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,l.G)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,l.G)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,l.G)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,l.G)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,l.G)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,l.G)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,l.G)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,l.G)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,l.G)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,l.G)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,l.G)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,l.G)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,l.G)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,l.G)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,l.G)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,l.G)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,l.G)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,l.G)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,l.G)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,l.G)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,l.G)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,l.G)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,l.G)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,l.G)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,l.G)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Le=null;function Ne(e){let{hit:t,children:n}=e;return(0,u.jsx)(J.c,{to:t.url,children:n})}function Oe(e){let{state:t,onClose:n}=e;const r=(0,Te.Y)();return(0,u.jsx)(J.c,{to:r(t.query),onClick:n,children:(0,u.jsx)(l.c,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Ie(e){let{contextualSearch:t,externalUrlRegex:o,...a}=e;const{siteMetadata:i}=(0,le.c)(),l=(0,Ae.Q)(),c=function(){const{locale:e,tags:t}=(0,Pe.mY)();return[`language:${e}`,t.map((e=>`docusaurus_tag:${e}`))]}(),d=a.searchParameters?.facetFilters??[],p=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(c,d):d,f={...a.searchParameters,facetFilters:p},h=(0,s.Uz)(),m=(0,r.useRef)(null),g=(0,r.useRef)(null),[y,b]=(0,r.useState)(!1),[v,x]=(0,r.useState)(void 0),w=(0,r.useCallback)((()=>Le?Promise.resolve():Promise.all([n.e(2528).then(n.bind(n,2528)),Promise.all([n.e(2176),n.e(1676)]).then(n.bind(n,9296)),Promise.all([n.e(2176),n.e(8879)]).then(n.bind(n,8879))]).then((e=>{let[{DocSearchModal:t}]=e;Le=t}))),[]),k=(0,r.useCallback)((()=>{w().then((()=>{m.current=document.createElement("div"),document.body.insertBefore(m.current,document.body.firstChild),b(!0)}))}),[w,b]),_=(0,r.useCallback)((()=>{b(!1),m.current?.remove()}),[b]),S=(0,r.useCallback)((e=>{w().then((()=>{b(!0),x(e.key)}))}),[w,b,x]),E=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee._)(o,t)?window.location.href=t:h.push(t)}}).current,j=(0,r.useRef)((e=>a.transformItems?a.transformItems(e):e.map((e=>({...e,url:l(e.url)}))))).current,C=(0,r.useMemo)((()=>e=>(0,u.jsx)(Oe,{...e,onClose:_})),[_]),T=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,o=e.onClose,a=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){var r;(27===e.keyCode&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?o():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&a&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&a(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,o,a,i])}({isOpen:y,onOpen:k,onClose:_,onInput:S,searchButtonRef:g}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Ce.c,{children:(0,u.jsx)("link",{rel:"preconnect",href:`https://${a.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})}),(0,u.jsx)(je,{onTouchStart:w,onFocus:w,onMouseOver:w,onClick:k,ref:g,translations:Re.button}),y&&Le&&m.current&&(0,ye.createPortal)((0,u.jsx)(Le,{onClose:_,initialScrollY:window.scrollY,initialQuery:v,navigator:E,transformItems:j,hitComponent:Ne,transformSearchClient:T,...a.searchPagePath&&{resultsFooterComponent:C},...a,searchParameters:f,placeholder:Re.placeholder,translations:Re.modal}),m.current)]})}function Fe(){const{siteConfig:e}=(0,le.c)();return(0,u.jsx)(Ie,{...e.themeConfig.algolia})}const De={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Me(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.c)(n,De.navbarSearchContainer),children:t})}var $e=n(5172),Be=n(5492);var ze=n(4592);const Ue=e=>e.docs.find((t=>t.id===e.mainDocId));const He={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.c)(),p=(0,he.D)(),{search:f,hash:h}=(0,s.IT)(),m=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${h}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],g=t?(0,l.G)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(me,{className:ge}),g]}),items:m})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Me,{className:n,children:(0,u.jsx)(Fe,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.c)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,$e.wB)(r),i=(0,Be.Qf)(t,r),s=a?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>s||!!a?.sidebar&&a.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,$e.wB)(r),i=(0,Be.Ab)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,Be.b7)(r)[0],i=t??a.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:c,hash:d}=(0,s.IT)(),p=(0,$e.wB)(n),f=(0,$e.gN)(n),{savePreferredVersionName:h}=(0,ze.iy)(n),m=[...o,...f.map((e=>{const t=p.alternateDocVersions[e.name]??Ue(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>h(e.name)}})),...a],g=(0,Be.b7)(n)[0],y=t&&m.length>1?(0,l.G)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,b=t&&m.length>1?void 0:Ue(g).path;return m.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:y,to:b,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:y,to:b,items:m,isActive:r?()=>!1:void 0})}};function We(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=He[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function qe(){const e=(0,A.q)(),t=(0,x.y)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(We,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Ve(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(l.c,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function Ge(){const e=0===(0,x.y)().navbar.items.length,t=F();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(Ve,{onClick:()=>t.hide()}),t.content]})}function Ye(){const e=(0,A.q)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(D,{header:(0,u.jsx)(Q,{}),primaryMenu:(0,u.jsx)(qe,{}),secondaryMenu:(0,u.jsx)(Ge,{})}):null}const Ke={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Qe(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.c)("navbar-sidebar__backdrop",e.className)})}function Je(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,x.y)(),i=(0,A.q)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,P.SM)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,l.G)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.c)("navbar","navbar--fixed-top",n&&[Ke.navbarHideable,!d&&Ke.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(Qe,{onClick:i.toggle}),(0,u.jsx)(Ye,{})]})}var Ze=n(5684);const Xe={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function et(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(l.c,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function tt(e){let{error:t}=e;const n=(0,Ze.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Xe.errorBoundaryError,children:n})}class nt extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const rt="right";function ot(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function at(){const{toggle:e,shown:t}=(0,A.q)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,l.G)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(ot,{})})}const it={colorModeToggle:"colorModeToggle_DEke"};function st(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(nt,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(We,{...e})},t)))})}function lt(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function ct(){const e=(0,A.q)(),t=(0,x.y)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??rt)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(lt,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(at,{}),(0,u.jsx)(Y,{}),(0,u.jsx)(st,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(st,{items:r}),(0,u.jsx)(V,{className:it.colorModeToggle}),!o&&(0,u.jsx)(Me,{children:(0,u.jsx)(Fe,{})})]})})}function ut(){return(0,u.jsx)(Je,{children:(0,u.jsx)(ct,{})})}function dt(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,s=(0,Z.c)(n),l=(0,Z.c)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(J.c,{className:"footer__link-item",...r?{href:a?l:r}:{to:s},...i,children:[o,r&&!(0,X.c)(r)&&(0,u.jsx)(te.c,{})]})}function pt(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(dt,{item:t})},t.href??t.to)}function ft(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(pt,{item:e},t)))})]})}function ht(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(ft,{column:e},t)))})}function mt(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function gt(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(dt,{item:t})}function yt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(gt,{item:e}),t.length!==n+1&&(0,u.jsx)(mt,{})]},n)))})})}function bt(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(ht,{columns:t}):(0,u.jsx)(yt,{links:t})}var vt=n(1964);const xt={footerLogoLink:"footerLogoLink_BH7S"};function wt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,Z.E)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(vt.c,{className:(0,o.c)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function kt(e){let{logo:t}=e;return t.href?(0,u.jsx)(J.c,{href:t.href,className:xt.footerLogoLink,target:t.target,children:(0,u.jsx)(wt,{logo:t})}):(0,u.jsx)(wt,{logo:t})}function _t(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function St(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.c)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function Et(){const{footer:e}=(0,x.y)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(St,{style:o,links:n&&n.length>0&&(0,u.jsx)(bt,{links:n}),logo:r&&(0,u.jsx)(kt,{logo:r}),copyright:t&&(0,u.jsx)(_t,{copyright:t})})}const jt=r.memo(Et),Ct=(0,R.qY)([M.C,w.qu,P.S2,ze.gc,i.w7,function(e){let{children:t}=e;return(0,u.jsx)(L.Ub,{children:(0,u.jsx)(A.y,{children:(0,u.jsx)(O,{children:t})})})}]);function Tt(e){let{children:t}=e;return(0,u.jsx)(Ct,{children:t})}var At=n(6448);function Pt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(At.c,{as:"h1",className:"hero__title",children:(0,u.jsx)(l.c,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(et,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(tt,{error:t})})]})})})}const Rt={mainWrapper:"mainWrapper_z2l0"};function Lt(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:l}=e;return(0,y.W)(),(0,u.jsxs)(Tt,{children:[(0,u.jsx)(i.U7,{title:s,description:l}),(0,u.jsx)(v,{}),(0,u.jsx)(T,{}),(0,u.jsx)(ut,{}),(0,u.jsx)("div",{id:d,className:(0,o.c)(g.W.wrapper.main,Rt.mainWrapper,r),children:(0,u.jsx)(a.c,{fallback:e=>(0,u.jsx)(Pt,{...e}),children:t})}),!n&&(0,u.jsx)(jt,{})]})}},8164:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});n(1504);var r=n(867),o=n(964),a=n(8264),i=n(1824),s=n(1964),l=n(7624);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.c)(t.src),dark:(0,o.c)(t.srcDark||t.src)},i=(0,l.jsx)(s.c,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,l.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,a.c)(),{navbar:{title:n,logo:s}}=(0,i.y)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,o.c)(s?.href||"/"),h=n?"":t,m=s?.alt??h;return(0,l.jsxs)(r.c,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,l.jsx)(c,{logo:s,alt:m,imageClassName:u}),null!=n&&(0,l.jsx)("b",{className:d,children:n})]})}},8712:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);var r=n(6952),o=n(7624);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.c,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},1964:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});var r=n(1504),o=n(5420),a=n(3664),i=n(6528);const s={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var l=n(7624);function c(e){let{className:t,children:n}=e;const c=(0,a.c)(),{colorMode:u}=(0,i.U)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.c)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,l.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,l.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},8448:(e,t,n)=>{"use strict";n.d(t,{U:()=>y,a:()=>c});var r=n(1504),o=n(8684),a=n(5288),i=n(3856),s=n(7624);const l="ease-in-out";function c(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,i.I)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??l}`,height:`${t}px`}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return p(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function h(e){if(!o.default.canUseDOM)return e?u:d}function m(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:l,disableSSRStyle:c}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:a}),(0,s.jsx)(t,{ref:u,style:c?void 0:h(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:l,children:o})}function g(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[l,c]=(0,r.useState)(t);return(0,a.c)((()=>{t||i(!0)}),[t]),(0,a.c)((()=>{o&&c(t)}),[o,t]),o?(0,s.jsx)(m,{...n,collapsed:l}):null}function y(e){let{lazy:t,...n}=e;const r=t?g:m;return(0,s.jsx)(r,{...n})}},3868:(e,t,n)=>{"use strict";n.d(t,{el:()=>m,qu:()=>h});var r=n(1504),o=n(3664),a=n(1148),i=n(1100),s=n(1824),l=n(7624);const c=(0,a.GS)("docusaurus.announcement.dismiss"),u=(0,a.GS)("docusaurus.announcement.id"),d=()=>"true"===c.get(),p=e=>c.set(String(e)),f=r.createContext(null);function h(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.y)(),t=(0,o.c)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function m(){const e=(0,r.useContext)(f);if(!e)throw new i.AH("AnnouncementBarProvider");return e}},6528:(e,t,n)=>{"use strict";n.d(t,{C:()=>g,U:()=>y});var r=n(1504),o=n(8684),a=n(1100),i=n(1148),s=n(1824),l=n(7624);const c=r.createContext(void 0),u="theme",d=(0,i.GS)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,h=e=>o.default.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),m=e=>{d.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.y)(),[o,a]=(0,r.useState)(h(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&m(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:i,get isDarkTheme(){return o===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[o,i])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function y(){const e=(0,r.useContext)(c);if(null==e)throw new a.AH("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},4592:(e,t,n)=>{"use strict";n.d(t,{eM:()=>x,gc:()=>y,iy:()=>v});var r=n(1504),o=n(5172),a=n(2488),i=n(1824),s=n(5492),l=n(1100),c=n(1148),u=n(7624);const d=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.GS)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.GS)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.GS)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const h=r.createContext(null);function m(){const e=(0,o.L0)(),t=(0,i.y)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=p.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return(0,u.jsx)(h.Provider,{value:n,children:t})}function y(e){let{children:t}=e;return s.c1?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function b(){const e=(0,r.useContext)(h);if(!e)throw new l.AH("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=a.M);const t=(0,o.OK)(e),[n,i]=b(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function x(){const e=(0,o.L0)(),[t]=b();function n(n){const r=e[n],{preferredVersionName:o}=t[n];return r.versions.find((e=>e.name===o))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},6192:(e,t,n)=>{"use strict";n.d(t,{m:()=>c,y:()=>l});var r=n(1504),o=n(1100),a=n(7624);const i=Symbol("EmptyContext"),s=r.createContext(i);function l(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(s.Provider,{value:i,children:t})}function c(){const e=(0,r.useContext)(s);if(e===i)throw new o.AH("DocsSidebarProvider");return e}},9920:(e,t,n)=>{"use strict";n.d(t,{E:()=>l,Q:()=>s});var r=n(1504),o=n(1100),a=n(7624);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(null===e)throw new o.AH("DocsVersionProvider");return e}},8200:(e,t,n)=>{"use strict";n.d(t,{q:()=>f,y:()=>p});var r=n(1504),o=n(5168),a=n(1432),i=n(632),s=n(1824),l=n(1100),c=n(7624);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.MF)(),{items:t}=(0,s.y)().navbar;return 0===t.length&&!e.component}(),t=(0,a.U)(),n=!e&&"mobile"===t,[l,c]=(0,r.useState)(!1);(0,i.a4)((()=>{if(l)return c(!1),!1}));const u=(0,r.useCallback)((()=>{c((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function p(e){let{children:t}=e;const n=d();return(0,c.jsx)(u.Provider,{value:n,children:t})}function f(){const e=r.useContext(u);if(void 0===e)throw new l.AH("NavbarMobileSidebarProvider");return e}},5168:(e,t,n)=>{"use strict";n.d(t,{MF:()=>l,Mx:()=>c,Ub:()=>s});var r=n(1504),o=n(1100),a=n(7624);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(!e)throw new o.AH("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.AH("NavbarSecondaryMenuContentProvider");const[,s]=a,l=(0,o.Mh)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},204:(e,t,n)=>{"use strict";n.d(t,{m:()=>o,W:()=>a});var r=n(1504);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},7092:(e,t,n)=>{"use strict";n.d(t,{Y:()=>l,a:()=>s});var r=n(1504),o=n(8264),a=n(632);const i="q";function s(){return(0,a.E9)(i)}function l(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,o.c)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>`${e}${n}?${i}=${encodeURIComponent(t)}`),[e,n])}},1432:(e,t,n)=>{"use strict";n.d(t,{U:()=>s});var r=n(1504),o=n(8684);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!o.default.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},5864:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},3856:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{I:()=>r})},5492:(e,t,n)=>{"use strict";n.d(t,{Ab:()=>k,Gw:()=>f,Md:()=>g,Qf:()=>_,Uj:()=>S,b7:()=>w,c1:()=>p,js:()=>x,mg:()=>b});var r=n(1504),o=n(5592),a=n(5464),i=n(5172),s=n(4592),l=n(9920),c=n(6192),u=n(7128),d=n(3376);const p=!!i.L0;function f(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=f(t);if(e)return e}}(e):void 0:e.href}const h=(e,t)=>void 0!==e&&(0,d.Sc)(e,t),m=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?h(e.href,t):"category"===e.type&&(h(e.href,t)||m(e.items,t))}function y(e,t){switch(e.type){case"category":return g(e,t)||e.items.some((e=>y(e,t)));case"link":return!e.unlisted||g(e,t);default:return!0}}function b(e,t){return(0,r.useMemo)((()=>e.filter((e=>y(e,t)))),[e,t])}function v(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,d.Sc)(a.href,n)||e(a.items))||"link"===a.type&&(0,d.Sc)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function x(){const e=(0,c.m)(),{pathname:t}=(0,o.IT)(),n=(0,i.UF)()?.pluginData.breadcrumbs;return!1!==n&&e?v({sidebarItems:e.items,pathname:t}):null}function w(e){const{activeVersion:t}=(0,i.wB)(e),{preferredVersion:n}=(0,s.iy)(e),o=(0,i.aA)(e);return(0,r.useMemo)((()=>(0,u.U)([t,n,o].filter(Boolean))),[t,n,o])}function k(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function _(e,t){const n=w(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,u.U)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function S(e){let{route:t}=e;const n=(0,o.IT)(),r=(0,l.E)(),i=t.routes,s=i.find((e=>(0,o.ot)(n.pathname,e)));if(!s)return null;const c=s.sidebar,u=c?r.docsSidebars[c]:void 0;return{docElement:(0,a.k)(i),sidebarName:c,sidebarItems:u}}},8648:(e,t,n)=>{"use strict";n.d(t,{g:()=>o});var r=n(8264);function o(e){const{siteConfig:t}=(0,r.c)(),{title:n,titleDelimiter:o}=t;return e?.trim().length?`${e.trim()} ${o} ${n}`:n}},632:(e,t,n)=>{"use strict";n.d(t,{E9:()=>l,_M:()=>s,a4:()=>i});var r=n(1504),o=n(5592),a=n(1100);function i(e){!function(e){const t=(0,o.Uz)(),n=(0,a.yA)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function s(e){return function(e){const t=(0,o.Uz)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function l(e){const t=s(e)??"",n=function(){const e=(0,o.Uz)();return(0,r.useCallback)(((t,n,r)=>{const o=new URLSearchParams(e.location.search);n?o.set(t,n):o.delete(t),(r?.push?e.push:e.replace)({search:o.toString()})}),[e])}();return[t,(0,r.useCallback)(((t,r)=>{n(e,t,r)}),[n,e])]}},7128:(e,t,n)=>{"use strict";function r(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,r)=>e.findIndex((e=>t(e,n)))!==r))}function o(e){return Array.from(new Set(e))}n.d(t,{U:()=>o,w:()=>r})},5008:(e,t,n)=>{"use strict";n.d(t,{cr:()=>f,U7:()=>d,w7:()=>h});var r=n(1504),o=n(5420),a=n(6952),i=n(5548);function s(){const e=r.useContext(i.e);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(964),c=n(8648),u=n(7624);function d(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const s=(0,c.g)(t),{withBaseUrl:d}=(0,l.E)(),p=o?d(o,{absolute:!0}):void 0;return(0,u.jsxs)(a.c,{children:[t&&(0,u.jsx)("title",{children:s}),t&&(0,u.jsx)("meta",{property:"og:title",content:s}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,u.jsx)("meta",{property:"og:image",content:p}),p&&(0,u.jsx)("meta",{name:"twitter:image",content:p}),i]})}const p=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(p),s=(0,o.c)(i,t);return(0,u.jsxs)(p.Provider,{value:s,children:[(0,u.jsx)(a.c,{children:(0,u.jsx)("html",{className:s})}),n]})}function h(e){let{children:t}=e;const n=s(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(f,{className:(0,o.c)(r,a),children:t})}},1100:(e,t,n)=>{"use strict";n.d(t,{AH:()=>l,Mh:()=>c,i0:()=>s,qY:()=>u,yA:()=>i});var r=n(1504),o=n(5288),a=n(7624);function i(e){const t=(0,r.useRef)(e);return(0,o.c)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,o.c)((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},1064:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{_:()=>r})},3376:(e,t,n)=>{"use strict";n.d(t,{Sc:()=>i,Y5:()=>s});var r=n(1504),o=n(628),a=n(8264);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,a.c)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.c,baseUrl:e})),[e])}},3943:(e,t,n)=>{"use strict";n.d(t,{MV:()=>h,S2:()=>u,SM:()=>f,yI:()=>m});var r=n(1504),o=n(8684),a=n(3664),i=n(5288),s=n(1100),l=n(7624);const c=r.createContext(void 0);function u(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function d(){const e=(0,r.useContext)(c);if(null==e)throw new s.AH("ScrollControllerProvider");return e}const p=()=>o.default.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function f(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=d(),o=(0,r.useRef)(p()),a=(0,s.yA)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=p();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function h(){const e=d(),t=function(){const e=(0,r.useRef)({elem:null,top:0}),t=(0,r.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,r.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const r=t.getBoundingClientRect().top-n;return r&&window.scrollBy({left:0,top:r}),e.current={elem:null,top:0},{restored:0!==r}}),[]);return(0,r.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,r.useRef)(void 0),o=(0,r.useCallback)((r=>{t.save(r),e.disableScrollEvents(),n.current=()=>{const{restored:r}=t.restore();if(n.current=void 0,r){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,i.c)((()=>{queueMicrotask((()=>n.current?.()))})),{blockElementScrollPositionUntilNextRender:o}}function m(){const e=(0,r.useRef)(null),t=(0,a.c)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},4456:(e,t,n)=>{"use strict";n.d(t,{SE:()=>s,e6:()=>i,mY:()=>l});var r=n(5172),o=n(8264),a=n(4592);const i="default";function s(e,t){return`docs-${e}-${t}`}function l(){const{i18n:e}=(0,o.c)(),t=(0,r.L0)(),n=(0,r.mU)(),l=(0,a.eM)();const c=[i,...Object.keys(t).map((function(e){const r=n?.activePlugin.pluginId===e?n.activeVersion:void 0,o=l[e],a=t[e].versions.find((e=>e.isLast));return s(e,(r??o??a).name)}))];return{locale:e.currentLocale,tags:c}}},1148:(e,t,n)=>{"use strict";n.d(t,{GS:()=>c,IN:()=>u});var r=n(1504);const o="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,s||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),s=!0),null}var t}let s=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=i(t?.persistence);return null===n?l:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}function u(e,t){const n=(0,r.useRef)((()=>null===e?l:c(e,t))).current(),o=(0,r.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,r.useSyncExternalStore)(o,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},1616:(e,t,n)=>{"use strict";n.d(t,{D:()=>i});var r=n(8264),o=n(5592),a=n(5684);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.c)(),{pathname:l}=(0,o.IT)(),c=(0,a.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},7124:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(1504),o=n(5592),a=n(1100);function i(e){const t=(0,o.IT)(),n=(0,a.i0)(t),i=(0,a.yA)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},1824:(e,t,n)=>{"use strict";n.d(t,{y:()=>o});var r=n(8264);function o(){return(0,r.c)().siteConfig.themeConfig}},8589:(e,t,n)=>{"use strict";n.d(t,{E:()=>o});var r=n(8264);function o(){const{siteConfig:{themeConfig:e}}=(0,r.c)();return e}},9032:(e,t,n)=>{"use strict";n.d(t,{Q:()=>s});var r=n(1504),o=n(1064),a=n(964),i=n(8589);function s(){const{withBaseUrl:e}=(0,a.E)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.E)();return(0,r.useCallback)((r=>{const a=new URL(r);if((0,o._)(t,a.href))return r;const i=`${a.pathname+a.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},1600:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[o]=e.split(/[#?]/),a="/"===o||o===r?o:(i=o,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(o,a)}},4292:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},5684:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var o=n(1600);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(o).default}});var a=n(4292);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return a.getErrorCausalChain}})},604:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});r(n(8684)).default.canUseDOM&&(window.Prism=window.Prism||{},window.Prism.manual=!0)},8064:(e,t,n)=>{"use strict";n.d(t,{iU:()=>x,Yf:()=>j,gh:()=>f,Wi:()=>T,Ep:()=>p});var r=n(5072);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&o(i[0])||i.unshift("");var h=i.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};var s=n(4812);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.c)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function h(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,m(),x.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(x.entries[x.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=x.index+e;return t>=0&&t{"use strict";var r=n(2168),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||o}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var o=f(n);o&&o!==h&&e(t,o,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),m=l(n),g=0;g{"use strict";e.exports=function(e,t,n,r,o,a,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,a,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},9600:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},7900:(e,t,n)=>{"use strict";n.r(t)},1462:(e,t,n)=>{"use strict";n.r(t)},1496:(e,t,n)=>{"use strict";n.r(t)},2272:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),c=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){l(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,i=t.querySelector(r.barSelector),s=e?"-100":a(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},6872:(e,t,n)=>{var r=n(9600);e.exports=f,e.exports.parse=a,e.exports.compile=function(e,t){return s(a(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=p;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,i=0,s="",u=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],p=n[1],f=n.index;if(s+=e.slice(i,f),i=f+d.length,p)s+=p[1];else{var h=e[i],m=n[2],g=n[3],y=n[4],b=n[5],v=n[6],x=n[7];s&&(r.push(s),s="");var w=null!=m&&null!=h&&h!==m,k="+"===v||"*"===v,_="?"===v||"*"===v,S=n[2]||u,E=y||b;r.push({name:g||a++,prefix:m||"",delimiter:S,optional:_,repeat:k,partial:w,asterisk:!!x,pattern:E?c(E):x?".*":"[^"+l(S)+"]+?"})}}return i{Prism.languages.elixir={doc:{pattern:/@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,inside:{attribute:/^@\w+/,string:/['"][\s\S]+/}},comment:{pattern:/#.*/,greedy:!0},regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},module:{pattern:/\b[A-Z]\w*\b/,alias:"class-name"},"attr-name":/\b\w+\??:(?!:)/,argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},function:/\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d))/,number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|delegate|exception|impl|macro|module|n|np|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|quote|raise|require|rescue|try|unless|unquote|use|when)\b/,boolean:/\b(?:false|nil|true)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach((function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}))},1808:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,s=i.length;-1!==n.code.indexOf(o=t(r,s));)++s;return i[s]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=a.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=a[o],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(r,u),h=p.indexOf(f);if(h>-1){++o;var m=p.substring(0,h),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),y=p.substring(h+f.length),b=[];m&&b.push.apply(b,i([m])),b.push(g),y&&b.push.apply(b,i([y])),"string"==typeof c?s.splice.apply(s,[l,1].concat(b)):c.content=b}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(Prism)},4164:(e,t,n)=>{var r={"./prism-elixir":7948};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=4164},9776:(e,t,n)=>{"use strict";var r=n(9143);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},3268:(e,t,n)=>{e.exports=n(9776)()},9143:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},9516:(e,t,n)=>{"use strict";var r=n(1504),o=n(4712);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n