diff --git a/docusaurus/video/docusaurus/docs/api/_common_/broadcast.mdx b/docusaurus/video/docusaurus/docs/api/_common_/broadcast.mdx new file mode 100644 index 00000000..e19a8bef --- /dev/null +++ b/docusaurus/video/docusaurus/docs/api/_common_/broadcast.mdx @@ -0,0 +1,33 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +```js +call.startHLSBroadcasting(); + +// to end broadcasting +call.stopHLSBroadcasting(); +``` + + + + +```py +call.start_broadcasting() + +// to end broadcasting +call.stop_broadcasting() +``` + + + + +```bash +curl -X POST "https://video.stream-io-api.com/video/call/default/${CALL_ID}/start_broadcasting?api_key=${API_KEY}" \ +-H "Authorization: ${JWT_TOKEN}" +``` + + + diff --git a/docusaurus/video/docusaurus/docs/api/_common_/go_live.mdx b/docusaurus/video/docusaurus/docs/api/_common_/go_live.mdx index 1c41b638..2e560a19 100644 --- a/docusaurus/video/docusaurus/docs/api/_common_/go_live.mdx +++ b/docusaurus/video/docusaurus/docs/api/_common_/go_live.mdx @@ -6,6 +6,9 @@ import TabItem from '@theme/TabItem'; ```js call.goLive(); + +// optionally start HLS broadcast and/or recording +call.goLive({ start_hls: true, start_recording: true }); ``` @@ -16,4 +19,4 @@ call.go_live() ``` - \ No newline at end of file + diff --git a/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx b/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx index 5035cf30..da3ae4dc 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/authentication.mdx @@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'; ## Creating users -Stream Users require only an id to be created. Users can be created with role of user or admin. The role will be set to user if a value is not provided in the request. There are additional properties you can provide to further describe your users. +Stream Users require only an ID to be created. Users can be created with the role of user or admin. The role will be set to user if a value is not provided in the request. There are additional properties you can provide to further describe your users. The `name` and `image` fields are special fields that are supported by client-side SDKs. @@ -36,6 +36,18 @@ await client.upsertUsers({ }); ``` + + + +```py +users = {} +user = UserRequest( +id='user_id', role="user", custom={"color": "red"}, name="This is a test user",image= "link/to/profile/image", +) +users[user.id] = user +client.upsert_users(users=users) +``` + @@ -44,7 +56,7 @@ await client.upsertUsers({ There are two ways to update user objects: - Updating will replace the existing user object -- Partial update will let you choose which fields you want to chage/unset +- Partial update will let you choose which fields you want to change/unset @@ -79,6 +91,38 @@ client.updateUsersPartial({ }); ``` + + + +```py +users = {} +user = UserRequest( + id= 'userid', + role= 'user', + custom= { + "color": 'red', + }, + name= 'This is a test user', + image= 'link/to/profile/image', +) + +users[user.id] = user +client.upsert_users(users=users) + +// or +client.update_users_partial( + users= [ + { + id: user.id, + set: { + color: 'blue', + }, + unset: ['name'], + }, + ], +) +``` + @@ -88,7 +132,7 @@ Anonymous users are users that are not authenticated. It's common to use this fo ## Guest users -Guest users are temporary user accounts. You can use it to temporarily give someone a name and image when joining a call. Guest users can aslso be created cliend-side. +Guest users are temporary user accounts. You can use it to temporarily give someone a name and image when joining a call. Guest users can aslso be created client-side. @@ -105,6 +149,21 @@ const guest: UserObjectRequest = { const guest = (await client.createGuest({ user: guest })).user; ``` + + + +```py +guest = UserRequest( + id = '', + name= '', + custom= { + "color": 'red', + }, +) + +guest = (client.video.create_guest(user=guest)).user +``` + @@ -112,7 +171,10 @@ const guest = (await client.createGuest({ user: guest })).user; While it is usually safer for data retention to deactivate a user, some use cases require completely deleting a user and their data. -Once a user has been deleted, it cannot be un-deleted and the user_id cannot be used again. +Once a user has been deleted, it cannot be un-deleted, and the user_id cannot be used again. + + + ```js client.deactivateUser({ @@ -122,14 +184,29 @@ client.deactivateUser({ client.deleteUser({ userId: '' }); ``` + + + + +```py +client.deactivate_user( + user_id= '', +) + +client.delete_user( user_id= '' ) +``` + + + + ## User tokens -Stream uses JWT (JSON Web Tokens) to authenticate chat users, enabling them to login. Knowing whether a user is authorized to perform certain actions is managed separately via a role based permissions system. Tokens need to be generated server-side. +Stream uses JWT (JSON Web Tokens) to authenticate chat users, enabling them to log in. Knowing whether a user is authorized to perform certain actions is managed separately via a role-based permissions system. Tokens need to be generated server-side. You can optionally provide -- expiration time -- issued at date which is necessary if you manually wan to revoke tokens +- Expiration time. By default tokens don't have an expiration date. +- Issued at date, which is necessary if you manually want to revoke tokens. By default, the issued at date is set to the current date. @@ -179,12 +256,7 @@ const iat = Math.round(new Date().getTime() / 1000); const call_cids = ['default:call1', 'livestream:call2']; -client.createToken( - (user_id = user_id), - (exp = exp), - (iat = iat), - (call_cids = call_cids), -); +client.createCallToken(userId, call_cids, exp, iat); ``` @@ -209,5 +281,5 @@ client.create_token(user_id=user_id, exp, iat, call_cids) ## Provisioning token in production -Your authentication service is responsible for generating token for your users. It is highly recommended to always create tokens with an expiration. -All SDK make it easy to automatically re-fetch tokens from your backend servers with token providers when they expire. +Your authentication service is responsible for generating tokens for your users. It is highly recommended to always create tokens with an expiration. +All SDKs make it easy to automatically re-fetch tokens from your backend servers with token providers when they expire. diff --git a/docusaurus/video/docusaurus/docs/api/basics/calls.mdx b/docusaurus/video/docusaurus/docs/api/basics/calls.mdx index bf2246a6..acc81029 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/calls.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/calls.mdx @@ -12,7 +12,7 @@ import TabItem from '@theme/TabItem'; You can create a call by providing the call type and an ID: -- The [call type](call_types/builtin) controls which features are enabled, and sets up permissions. +- The [call type](call_types/builtin) controls which features are enabled and sets up permissions. - Calls IDs can be reused, which means they can be joined multiple times, so it's possible to set up recurring calls. You can optionally restrict call access by providing a list of users. @@ -43,13 +43,13 @@ call.create({ ```py # create a call -call.get_or_create_call( +call.create( data=CallRequest( created_by_id='john' ) ) # create a call with more data -call.get_or_create_call( +call.create( data=CallRequest( created_by_id='john', members=[ @@ -109,7 +109,7 @@ call.update({ custom: { color: 'red' } }); ```py # update call settings -call.update_call( +call.update( settings_override=CallSettingsRequest( audio=AudioSettingsRequest( mic_default_on=True, @@ -118,7 +118,7 @@ call.update_call( ) # update call with custom data -call.update_call( +call.update( custom={'color': 'red'} ) ``` @@ -145,7 +145,7 @@ curl -X PUT "https://video.stream-io-api.com/video/call/default/${CALL_ID}?api_k ## Manage call members -Call members can be added and removed as necessary. Their role's can also be changed. +Call members can be added and removed as necessary. Their roles can also be changed. @@ -168,7 +168,7 @@ call.updateCallMembers({ ```py # update or add call members -call.update_call( +call.update_members( members=[ MemberRequest(user_id: 'sara'), MemberRequest(user_id: 'jack', role: 'admin') @@ -177,7 +177,7 @@ call.update_call( # remove call members # Assuming the updated call members are 'sara' and 'jack' -call.update_call( +call.update_members( members=[ MemberRequest(user_id: 'jack', role: 'admin') ] @@ -210,7 +210,7 @@ For many video calling, live stream, or audio rooms apps, you'll want to show: - Calls that are currently live - Popular live streams / audio rooms with a link to the recording -Below you can find a few examples of different quieries: +Below you can find a few examples of different queries: @@ -244,23 +244,23 @@ client.video.queryCalls({ ```py # default sorting -call.query_calls(data=QueryCallsRequest()) +client.query_calls() # sorting and pagination -response = call.query_calls( +response = client.query_calls( sort= [SortParamRequest(field: 'starts_at', direction: -1)], limit=2, ) # loading next page -call.query_calls( +client.query_calls( sort= [SortParamRequest(field: 'starts_at', direction: -1)], limit=2, next=response.data().next ) # filtering -call.query_calls( +client.query_calls( filter_conditions={'backstage': {'$eq': False}} ) ``` @@ -268,7 +268,7 @@ call.query_calls( -Filter expressions support multiple match criteria and it's also possible to combine filters. For more information visit the [filter operators](https://getstream.io/chat/docs/node/query_syntax_operators/?language=javascript) guide. +Filter expressions support multiple match criteria, and it's also possible to combine filters. For more information, visit the [filter operators](https://getstream.io/chat/docs/node/query_syntax_operators/?language=javascript) guide. ## Query call members @@ -328,4 +328,4 @@ call.query_members( -Filter expressions support multiple match criteria and it's also possible to combine filters. For more information visit the [filter operators](https://getstream.io/chat/docs/node/query_syntax_operators/?language=javascript) guide. +Filter expressions support multiple match criteria, and it's also possible to combine filters. For more information, visit the [filter operators](https://getstream.io/chat/docs/node/query_syntax_operators/?language=javascript) guide. diff --git a/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx b/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx index d72021f7..a56845da 100644 --- a/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx +++ b/docusaurus/video/docusaurus/docs/api/basics/get_started.mdx @@ -8,16 +8,17 @@ title: Get started import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import RTMP from '../_common_/rtmp.mdx'; +import Broadcast from '../_common_/broadcast.mdx'; -For the average Stream integration, the development work focuses on code that executes in the client. However, some tasks must be executed from the server for safety (for example token generation). +For the average Stream integration, the development work focuses on code that executes in the client. However, some tasks must be executed from the server for safety (for example, token generation). -Stream provides server-side SDKs to help executing these tasks. +Stream provides server-side SDKs to help execute these tasks. You can reference our [development roadmap](https://github.com/GetStream/protocol/discussions/177) to know which languages and features are supported. ## Installation -All official SDK are available on package managers, full source code is available on the GetStream Github organization. +All official SDKs are available on package managers, full source code is available on the GetStream Github organization. @@ -40,7 +41,7 @@ pip install getstream ## Creating client -To create a server-side client you'll need your **API key** and **secret**, both of them can be found in your [Stream Dashboard](https://dashboard.getstream.io/). +To create a server-side client, you'll need your **API key** and **secret**. Both of them can be found in your [Stream Dashboard](https://dashboard.getstream.io/). @@ -65,7 +66,7 @@ client = Stream(api_key="your_api_key", api_secret="your_api_secret") ## Creating user tokens -Tokens need to be generated server-side. Typically you integrate this into the part of your codebase where you login or register users. The tokens provide a way to authenticate a user or give access to a specific set of video/audio calls. +Tokens need to be generated server-side. Typically, you integrate this into the part of your codebase where you log in or register users. The tokens provide a way to authenticate a user or give access to a specific set of video/audio calls. @@ -78,10 +79,6 @@ const exp = Math.round(new Date().getTime() / 1000) + 60 * 60; const iat = Math.round(new Date().getTime() / 1000); client.createToken(userId, exp, iat); - -// optionally provide call cids -const call_cids = ['default:call1', 'livestream:call2']; -client.createToken(userId, exp, iat, call_cids); ``` @@ -98,7 +95,7 @@ token = client.create_token("admin-user") You can create a call by providing the call type and an ID: -- The [call type](call_types/builtin) controls which features are enabled, and sets up permissions. +- The [call type](call_types/builtin) controls which features are enabled and sets up permissions. - Calls IDs can be reused, which means they can be joined multiple times, so it's possible to set up recurring calls. You can optionally restrict call access by providing a list of users. @@ -129,7 +126,7 @@ call.create({ from getstream.models.call_request import CallRequest call = client.video.call("default", "id") -response = call.get_or_create_call( +response = call.create( data=CallRequest( created_by_id="sacha", ), @@ -171,7 +168,7 @@ call.updateCallMembers({ ```py -call.update_call_members(update_members=[ +call.update_members(update_members=[ MemberRequest(user_id: "sara"), MemberRequest(user_id: "emily", role: "admin")]) ``` @@ -196,7 +193,7 @@ curl -X PUT "https://video.stream-io-api.com/video/call/default/${CALL_ID}/membe ## Updating a call -- Most of the call type settings can be overriden on a call level. +- Most of the call type settings can be overridden on a call level. - Custom data can also be stored for calls. @@ -251,7 +248,7 @@ curl -X PUT "https://video.stream-io-api.com/video/call/default/${CALL_ID}?api_k -## Start HLS broadcasting +## Streaming Broadcasting serves are a means of transmitting live or pre-recorded content to a wide audience. @@ -264,48 +261,23 @@ It is up to the integrators to decide, what approach will be used in their apps For more information see the [Streaming section](streaming/overview/). - - - -```js -call.startHLSBroadcasting(); - -// to end broadcasting -call.stopHLSBroadcasting(); -``` - - - - -```py -call.start_broadcasting() - -// to end broadcasting -call.stop_broadcasting() -``` - - - - -```bash -curl -X POST "https://video.stream-io-api.com/video/call/default/${CALL_ID}/start_broadcasting?api_key=${API_KEY}" \ --H "Authorization: ${JWT_TOKEN}" -``` +The following example shows how to start and stop HLS broadcasting: - - + -## Set up a call for RTMP +Almost all livestream software and hardware supports RTMPS. Our API supports using third-party software for streaming using RTMPS. For more information, reference the [Streaming section](streaming/overview/). -Almost all livestream software and hardware supports RTMPS. Our API supports using a third-party software for streaming using RTMPS. For more information reference the [Streaming section](streaming/overview/). +The following example shows how to get the RTMP address that you need to provide for the third-party software: -## Start call recording +## Recording Calls can be recorded for later use. Calls recording can be started/stopped via API calls or configured to start automatically when the first user joins the call. -For more information see the [Recordings section](recording/calls/). +For more information, see the [Recordings section](recording/calls/). + +The following example shows how to start and stop recording: @@ -338,7 +310,7 @@ curl -X POST "https://video.stream-io-api.com/video/call/default/${CALL_ID}/star -## List recordings for a call +The following example shows how to query existing recordings: @@ -351,7 +323,7 @@ call.listRecordings(); ```py -recordings = call.list_recordings(session="your_session_id") +recordings = call.list_recordings() ``` diff --git a/docusaurus/video/docusaurus/docs/api/call_types/CustomStyle.jsx b/docusaurus/video/docusaurus/docs/api/call_types/CustomStyle.jsx new file mode 100644 index 00000000..faeb1688 --- /dev/null +++ b/docusaurus/video/docusaurus/docs/api/call_types/CustomStyle.jsx @@ -0,0 +1,10 @@ +import React from 'react'; + +// Workaround for hiding SDK tutorial links on the call types shared page +const css = `.theme-admonition { + display: none +}`; + +const CustomStyle = () => ; + +export default CustomStyle; \ No newline at end of file diff --git a/docusaurus/video/docusaurus/docs/api/call_types/builtin_types.mdx b/docusaurus/video/docusaurus/docs/api/call_types/builtin_types.mdx index 6924ea5b..e34b2760 100644 --- a/docusaurus/video/docusaurus/docs/api/call_types/builtin_types.mdx +++ b/docusaurus/video/docusaurus/docs/api/call_types/builtin_types.mdx @@ -4,3 +4,9 @@ sidebar_position: 1 slug: /call_types/builtin title: Built-in Types --- + +import CallTypesPage from '../../../shared/video/_call-types.md'; +import CustomStyle from './CustomStyle'; + + + diff --git a/docusaurus/video/docusaurus/docs/api/call_types/geofencing.mdx b/docusaurus/video/docusaurus/docs/api/call_types/geofencing.mdx index 370574f9..95b4c445 100644 --- a/docusaurus/video/docusaurus/docs/api/call_types/geofencing.mdx +++ b/docusaurus/video/docusaurus/docs/api/call_types/geofencing.mdx @@ -6,21 +6,20 @@ title: Geofencing --- With geofencing, you can define which edge nodes are utilized for video calls within specific geo-fenced areas. -You can set geo-fences to a call type or specify when creating a new call. Multiple geo-fences can be used at the same time. +You can set geofences to a call type or specify when creating a new call. Multiple geo-fences can be used at the same time. +At this present, you can only select from a predefined list of geofences: -At this present you can only select from a predefined list of geo-fences: - -| Name | Description | -|-------------------|-----------------------------------------------------------------------------------------------------------------| -| european_union | The list of countries that are part of european union | -| united_states | Only selects edges in US | -| canada | Only selects edges in Canada | -| united_kingdom | Only selects edges in the United Kingdom | -| india | Only selects edges in India | -| china_exclusion | Excludes edges running in mainland China (currently Stream edge infrastructure does not have any edge in China) | -| russia_exclusion | Excludes edges running in Russia | -| belarus_exclusion | Excludes edges running in Belarus | +| Name | Description | +| ----------------- | ---------------------------------------------------------------------------------------------------------------- | +| european_union | The list of countries that are part of european union | +| united_states | Only selects edges in US | +| canada | Only selects edges in Canada | +| united_kingdom | Only selects edges in the United Kingdom | +| india | Only selects edges in India | +| china_exclusion | Excludes edges running in mainland China (currently, Stream edge infrastructure does not have any edge in China) | +| russia_exclusion | Excludes edges running in Russia | +| belarus_exclusion | Excludes edges running in Belarus | import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; @@ -52,4 +51,29 @@ call.create({ ``` - \ No newline at end of file + + +```py +client.video.create_call_type( + name= '', + settings= CallSettingsRequest( + geofencing= GeofenceSettingsRequest( + names= ['european_union'], + ), + ), +) + +//override settings on call level +call.create( + data = CallRequest( + created_by_id= 'john', + settings_override= CallSettingsRequest( + geofencing= GeofenceSettingsRequest( + names= ['european_union', 'united_states'], + ), + ), + ), +) +``` + + diff --git a/docusaurus/video/docusaurus/docs/api/call_types/manage-types.mdx b/docusaurus/video/docusaurus/docs/api/call_types/manage-types.mdx index 01d3bad3..9af84900 100644 --- a/docusaurus/video/docusaurus/docs/api/call_types/manage-types.mdx +++ b/docusaurus/video/docusaurus/docs/api/call_types/manage-types.mdx @@ -20,6 +20,15 @@ client.video.listCallTypes(); client.getCallType({name: 'livestream'}); ``` + + + +```py +client.video.list_call_types() + +//or +client.get_call_type(name= 'livestream') +``` @@ -46,6 +55,27 @@ client.video.createCallType({ ``` + + +```py +client.video.create_call_type( + name= 'allhands', + settings = CallSettingsRequest( + audio=AudioSettingsRequest( mic_default_on= True, default_device ='speaker' ), + ), + grants = { + "admin": [ + OwnCapability.SEND_AUDIO.to_str(), + OwnCapability.SEND_VIDEO.to_str(), + OwnCapability.MUTE_USERS.to_str(), + ], + "user": [OwnCapability.SEND_AUDIO.to_str(), OwnCapability.SEND_VIDEO.to_str()], + }, +) + +``` + + ## Update call type @@ -61,6 +91,16 @@ client.video.updateCallType('allhands', { }); ``` + + + +```py +client.video.update_call_type(name='allhands', + settings= CallSettingsRequest( + audio=AudioSettingsRequest( mic_default_on= False, default_device= 'earpiece' ), + ), +) +``` @@ -73,5 +113,12 @@ client.video.updateCallType('allhands', { client.video.deleteCallType({name: 'allhands'}); ``` + + + +```py +client.video.delete_call_type(name= 'allhands') + +``` \ No newline at end of file diff --git a/docusaurus/video/docusaurus/docs/api/call_types/permissions.mdx b/docusaurus/video/docusaurus/docs/api/call_types/permissions.mdx index 4bc83f67..d5c0aa41 100644 --- a/docusaurus/video/docusaurus/docs/api/call_types/permissions.mdx +++ b/docusaurus/video/docusaurus/docs/api/call_types/permissions.mdx @@ -5,9 +5,27 @@ slug: /call_types/permissions title: Permissions --- +import CallCapabilities from '../../../shared/video/_call-capabilities.md'; + import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +## Introduction + +This page shows how you can create or update roles for a call type. + +Stream has a role-based permission system. Each user has an application-level role, and also channel (chat product) and call (video product) level roles. Every role (be it application or call/channel level) contains a list of capabilities. A capability is an action (for example, create a call). The list of capabilities assigned to a role defines what a user is allowed to do. Call roles are defined on the call type level. + +## Configuring roles + +When you create a call type, you can specify your role configurations. A role configuration consists of a role name and the list of capabilities that are enabled for that role. + +When you create a call type, it comes with a default set of configurations. You can override or extend that. + +The following example overrides the capabilities of the built-in `admin` role and defines the `customrole`. + +Please note that for the below code to work, you need to create the `customrole` beforehand. You can do that in your [Stream Dashboard](https://dashboard.getstream.io/). + @@ -20,10 +38,64 @@ client.video.createCallType({ VideoOwnCapability.SEND_VIDEO, VideoOwnCapability.MUTE_USERS, ], - user: [VideoOwnCapability.SEND_AUDIO, VideoOwnCapability.SEND_VIDEO], + ['customrole']: [ + VideoOwnCapability.SEND_AUDIO, + VideoOwnCapability.SEND_VIDEO, + ], + }, +}); + +// or edit a built-in call type +client.video.updateCallType('default', { + grants: { + /* ... */ }, }); ``` - \ No newline at end of file + + + +```py +client.video.create_call_type( + name= '', + grants={ + "admin": [ + OwnCapability.SEND_AUDIO.to_str(), + OwnCapability.SEND_VIDEO.to_str(), + OwnCapability.MUTE_USERS.to_str(), + ], + "customrole": [ + OwnCapability.SEND_AUDIO.to_str(), + OwnCapability.SEND_VIDEO.to_str(), + ], + }, +) + +client.video.update_call_type(name = 'default', + grants= { + /* ... */ + }, +) +``` + + + +### Built-in roles + +There are 5 pre-defined call roles, these are: + +- `user` +- `moderator` +- `host` +- `admin` +- `call-member` + +You can access the default roles and their capabilities in your [Stream Dashboard](https://dashboard.getstream.io/). + +### Capabilities + +The list of call capabilities that you can include in your role configurations: + + diff --git a/docusaurus/video/docusaurus/docs/api/call_types/settings.mdx b/docusaurus/video/docusaurus/docs/api/call_types/settings.mdx index 28b976e3..b5747e1d 100644 --- a/docusaurus/video/docusaurus/docs/api/call_types/settings.mdx +++ b/docusaurus/video/docusaurus/docs/api/call_types/settings.mdx @@ -5,10 +5,23 @@ slug: /call_types/settings title: Settings --- +import CallTypeSettings from '../../../shared/video/_call-type-settings.md'; + import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -## Settings +## Configuration options + +The Stream API provides multiple configuration options on the call type level. + + + +- You can provide the settings when creating or updating a call type +- For maximum flexibility, you can override the settings on the call level when creating or updating a call + +## Code examples + +### Settings @@ -38,9 +51,37 @@ call.create({ ``` + + + +```py +client.video.create_call_type( + name= '', + settings= CallSettingsRequest( + screensharing=ScreensharingSettingsRequest( + access_request_enabled= False, + enabled= True, + ), + ), +) + +// override settings on call level +call.create( + data=CallRequest( + created_by_id= 'john', + settings_override= CallSettingsRequest( + screensharing= ScreensharingSettingsRequest( + enabled= False, + ), + ), + ), +) +``` + + -## Notification settings +### Notification settings @@ -64,4 +105,25 @@ client.video.createCallType({ ``` - \ No newline at end of file + + +```py +client.video.create_call_type( + name= '', + notification_settings= NotificationSettingsRequest( + enabled= True, + call_notification= EventNotificationSettingsRequest( + apns=Apnsrequest( + title= '{{ user.display_name }} invites you to a call', + ), + enabled= True, + ), + session_started= EventNotificationSettingsRequest( + enabled: False, + ), + ), +) +``` + + + diff --git a/docusaurus/video/docusaurus/docs/api/moderation/capabilities.mdx b/docusaurus/video/docusaurus/docs/api/moderation/capabilities.mdx deleted file mode 100644 index 1ce790c8..00000000 --- a/docusaurus/video/docusaurus/docs/api/moderation/capabilities.mdx +++ /dev/null @@ -1,6 +0,0 @@ ---- -id: moderation_capabilities -sidebar_position: 2 -slug: /moderation/capabilities -title: Capabilities ---- diff --git a/docusaurus/video/docusaurus/docs/api/moderation/overview.mdx b/docusaurus/video/docusaurus/docs/api/moderation/overview.mdx new file mode 100644 index 00000000..f18d9703 --- /dev/null +++ b/docusaurus/video/docusaurus/docs/api/moderation/overview.mdx @@ -0,0 +1,203 @@ +--- +id: moderation_index +sidebar_position: 1 +slug: /moderation/overview +title: Overview +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +When running calls with a larger audience, you’ll often need moderation features to prevent abuse. Participants can share inappropriate content via + +- The video feed +- Audio +- Screen share +- Chat messages +- Username + +Stream has tools to help you manage these issues while on a call. + +### Removing & Blocking a member from a call + +Call can be configured to only be accessible to their members. To remove a user from a call and prevent from accessing again: + + + + +```js +// Block user +call.blockUser({ user_id: 'sara' }); + +// Unblock user +call.unblockUser({ user_id: 'sara' }); +``` + + + + +```py +// Block user +call.block_user( user_id='sara' ) + +// Unblock user +call.unblock_user( user_id= 'sara' ) +``` + + + + +### Call permissions + +You can configure if a screen share is enabled, disabled or requires requesting permission + + + + +```js +call.update({ + settings_override: { + screensharing: { enabled: true, access_request_enabled: true }, + }, +}); +``` + + + + +```py +call.update( + settings_override = CallSettingsRequest( + screensharing= ScreensharingSettingsRequest( enabled= True, access_request_enabled= True ), + ), +) +``` + + + + +### Muting everyone + +You can also mute every other participant’s video or audio. + + + + +```js +// You can specify which kind of stream(s) to mute +call.muteUsers({ + mute_all_users: true, + audio: true, +}); +``` + + + + +```py +// You can specify which kind of stream(s) to mute +call.mute_users( + mute_all_users= True, + audio=True, +) +``` + + + + +### Muting one participant's video or audio (or both) + + + + +```js +call.muteUsers({ + user_ids: ['sara'], + audio: true, + video: true, + screenshare: true, + screenshare_audio: true, +}); +``` + + + + +```py +call.mute_users( + user_ids= ['sara'], + audio= True, + video= True, + screenshare= True, + screenshare_audio = True, +) +``` + + + + +### Granting and revoking permissions + +It's possible for users to ask for any of the following permissions: + +- Sending audio +- Sending video +- Sharing their screen + +These requests will trigger the `call.permission_request` webhook. + +This is how these requests can be accepted: + + + + +```js +call.updateUserPermissions({ + user_id: 'sara', + grant_permissions: [VideoOwnCapability.SEND_AUDIO], +}); +``` + + + + +```py +call.update_user_permissions( + user_id= 'sara', + grant_permissions= [OwnCapability.SEND_AUDIO.to_str()], +) +``` + + + + +For moderation purposes any user's permission to + +- send audio +- send video +- share their screen + +can be revoked at any time. This is how it can be done: + + + + +```js +call.updateUserPermissions({ + user_id: 'sara', + revoke_permissions: [VideoOwnCapability.SEND_AUDIO], +}); +``` + + + + +```py +call.update_user_permissions( + user_id= 'sara', + revoke_permissions= [OwnCapability.SEND_AUDIO.to_str()], +) +``` + + + diff --git a/docusaurus/video/docusaurus/docs/api/moderation/permissions.mdx b/docusaurus/video/docusaurus/docs/api/moderation/permissions.mdx deleted file mode 100644 index a3857336..00000000 --- a/docusaurus/video/docusaurus/docs/api/moderation/permissions.mdx +++ /dev/null @@ -1,6 +0,0 @@ ---- -id: moderation_permissions -sidebar_position: 1 -slug: /moderation/permissions -title: Permissions ---- diff --git a/docusaurus/video/docusaurus/docs/api/recording/recording_calls.mdx b/docusaurus/video/docusaurus/docs/api/recording/recording_calls.mdx index b10b45b0..530bde6d 100644 --- a/docusaurus/video/docusaurus/docs/api/recording/recording_calls.mdx +++ b/docusaurus/video/docusaurus/docs/api/recording/recording_calls.mdx @@ -9,11 +9,11 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; Calls can be recorded for later use. Calls recording can be started/stopped via API calls or configured to start automatically when the first user joins the call. -Call recording is done by Stream server-side and later stored on AWS S3, you can also configure your Stream application to have files stored on your own S3 bucket (in that case storage costs will not apply). +Call recording is done by Stream server-side and later stored on AWS S3. You can also configure your Stream application to have files stored on your own S3 bucket (in that case, storage costs will not apply). -By default, calls will be recorded as mp4 video files, you can configure recording to only capture the audio. +By default, calls will be recorded as mp4 video files. You can configure recording to only capture the audio. -Note: by default recordings contain all tracks mixed in a single file, you can follow the discussion [here](https://github.com/GetStream/protocol/discussions/247) if you are interested in different ways to record calls. +Note: by default, recordings contain all tracks mixed in a single file. You can follow the discussion [here](https://github.com/GetStream/protocol/discussions/247) if you are interested in different ways to record calls. ## Start and stop call recording @@ -151,52 +151,52 @@ call.update({ ```py # Disable on call level -call.update_call(UpdateCallRequest( +call.update( settings_override=CallSettingsRequest( recording=RecordSettingsRequest( mode='disabled', ), ), -)) +) # Disable on call type level call_type_name = 'default' -call.update_call_type(call_type_name, UpdateCallTypeRequest( +client.video.update_call_type(call_type_name, settings=CallSettingsRequest( recording=RecordSettingsRequest( mode='disabled', ), ), -)) +) # Automatically record calls -call.update_call_type(UpdateCallTypeRequest( +client.video.update_call_type( settings=CallSettingsRequest( recording=RecordSettingsRequest( mode='auto', ), ), -)) +) # Enable -call.update_call(UpdateCallRequest( +client.update( settings_override=CallSettingsRequest( recording=RecordSettingsRequest( mode='available', ), ), -)) +) # Other settings -call.update_call(UpdateCallRequest( +call.update( settings_override=CallSettingsRequest( recording=RecordSettingsRequest( mode='available', quality='1080p', ), ), -)) +) ``` @@ -226,14 +226,14 @@ call.update({ ```py # Enable recording -call.update_call(UpdateCallRequest( +call.update( settings_override=CallSettingsRequest( recording=RecordSettingsRequest( mode='available', audio_only=True ), ), -)) +) ``` @@ -244,14 +244,14 @@ call.update_call(UpdateCallRequest( Recording can be customized in several ways: - You can pick one of the built-in layouts and pass some options to it -- You can customize more in detail the style of the call by providing your own CSS file +- You can further customize the style of the call by providing your own CSS file - You can use your own recording application There are three available layouts you can use for your calls: `"single_participant"`, `"grid"` and `"spotlight"` ### Single Participant -This layout shows only one participant video at the time, other video tracks are hidden. +This layout shows only one participant video at a time, other video tracks are hidden. ```py -def hello_world(): - print("Hello, world!") +layout_options = { + 'logo.image_url': + 'https://theme.zdassets.com/theme_assets/9442057/efc3820e436f9150bc8cf34267fff4df052a1f9c.png', + 'logo.horizontal_position': 'center', + 'title.text': 'Building Stream Video Q&A', + 'title.horizontal_position': 'center', + 'title.color': 'black', + 'participant_label.border_radius': '0px', + 'participant.border_radius': '0px', + 'layout.spotlight.participants_bar_position': 'top', + 'layout.background_color': '#f2f2f2', + 'participant.placeholder_background_color': '#1f1f1f', + 'layout.single-participant.padding_inline': '20%', + 'participant_label.background_color': 'transparent', + } + + client.video.update_call_type(CALL_TYPE_NAME, settings=CallSettingsRequest( + recording=RecordSettingsRequest( + mode='available', + audio_only=False, + quality='1080p', + layout=LayoutSettingsRequest( + name='spotlight', + options=layout_options, + ), + ), + ), + ) ``` @@ -401,40 +427,40 @@ Here you can find the complete list of options available to each layout. ### Grid -| Option | Type | Default | Allowed Values | Description | -| ---------------------------------------- | ------- | ----------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| logo.image_url | string | `` | | add a logo image to the video layout | -| logo.vertical_position | string | `top` | `[top bottom center]` | vertical position of the logo | -| participant.label_horizontal_position | string | `left` | `[center left right]` | horizontal position for the participant label | -| participant.placeholder_background_color | color | `#000000` | | Sets the background color for video placeholder tile | -| video.scale_mode | string | `fill` | `[fit fill]` | How source video is displayed inside a box when aspect ratio does not match. 'fill' crops the video to fill the entire box, 'fit' ensures the video fits inside the box by padding necessary padding | -| logo.horizontal_position | string | `center` | `[center left right]` | horizontal position of the logo | -| participant.video_border_rounded | boolean | `true` | | Render the participant video border rounded | -| participant.label_display_border | boolean | `true` | | Render label border | -| participant.label_border_color | color | `#CCCCCC` | | Label border color | -| grid.cell_padding | size | `10` | | padding between cells | -| video.screenshare_scale_mode | string | `fit` | `[fit fill]` | How source video is displayed inside a box when aspect ratio does not match. 'fill' crops the video to fill the entire box, 'fit' ensures the video fits inside the box by padding necessary padding | -| video.background_color | color | `#000000` | | The background color | -| participant.label_border_radius | number | `1.2` | | The corner radius used for the label border | -| grid.size_percentage | number | `90` | | The percentage of the screen the grid should take up | -| grid.margin | size | `10` | | the margin between grid and spotlight | -| grid.columns | number | `5` | | how many column to use in grid mode | -| participant.label_vertical_position | string | `bottom` | `[top bottom center]` | vertical position for the participant label | -| participant.label_display | boolean | `true` | | Show the participant label | -| participant.video_border_color | color | `#CCCCCC` | | The color used for the participant video border | -| participant.video_border_width | boolean | `true` | | The stroke width used to render a participant border | -| screenshare_layout | string | `spotlight` | `[grid spotlight single-participant]` | The layout to use when entering screenshare mode | -| participant.label_text_color | color | `#000000` | | Text color of the participant label | -| participant.label_background_color | color | `#00000000` | | Background color of the participant label | -| participant.label_border_rounded | boolean | `true` | | Render the label border rounded | -| participant.video_border_radius | number | `1.2` | | The corner radius used for the participant video border | -| participant.video_highlight_border_color | color | `#7CFC00` | | The color used for highlighted participants video border | -| grid.rows | number | `4` | | how many rows to use in grid mode | +| Option | Type | Default | Allowed Values | Description | +| ---------------------------------------- | ------- | ----------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| logo.image_url | string | `` | | add a logo image to the video layout | +| logo.vertical_position | string | `top` | `[top bottom center]` | vertical position of the logo | +| participant.label_horizontal_position | string | `left` | `[center left right]` | horizontal position for the participant label | +| participant.placeholder_background_color | color | `#000000` | | Sets the background color for video placeholder tile | +| video.scale_mode | string | `fill` | `[fit fill]` | How source video is displayed inside a box when the aspect ratio does not match. 'fill' crops the video to fill the entire box, 'fit' ensures the video fits inside the box by padding necessary padding | +| logo.horizontal_position | string | `center` | `[center left right]` | horizontal position of the logo | +| participant.video_border_rounded | boolean | `true` | | Render the participant video border rounded | +| participant.label_display_border | boolean | `true` | | Render label border | +| participant.label_border_color | color | `#CCCCCC` | | Label border color | +| grid.cell_padding | size | `10` | | padding between cells | +| video.screenshare_scale_mode | string | `fit` | `[fit fill]` | How source video is displayed inside a box when the aspect ratio does not match. 'fill' crops the video to fill the entire box, 'fit' ensures the video fits inside the box by padding necessary padding | +| video.background_color | color | `#000000` | | The background color | +| participant.label_border_radius | number | `1.2` | | The corner radius used for the label border | +| grid.size_percentage | number | `90` | | The percentage of the screen the grid should take up | +| grid.margin | size | `10` | | the margin between grid and spotlight | +| grid.columns | number | `5` | | how many column to use in grid mode | +| participant.label_vertical_position | string | `bottom` | `[top bottom center]` | vertical position for the participant label | +| participant.label_display | boolean | `true` | | Show the participant label | +| participant.video_border_color | color | `#CCCCCC` | | The color used for the participant video border | +| participant.video_border_width | boolean | `true` | | The stroke width used to render a participant border | +| screenshare_layout | string | `spotlight` | `[grid spotlight single-participant]` | The layout to use when entering screen share mode | +| participant.label_text_color | color | `#000000` | | Text color of the participant label | +| participant.label_background_color | color | `#00000000` | | Background color of the participant label | +| participant.label_border_rounded | boolean | `true` | | Render the label border rounded | +| participant.video_border_radius | number | `1.2` | | The corner radius used for the participant video border | +| participant.video_highlight_border_color | color | `#7CFC00` | | The color used for highlighted participants video border | +| grid.rows | number | `4` | | how many rows to use in grid mode | ## Custom recording styling using external CSS -You can customize how recorded calls look like by providing an external CSS file, the CSS file needs to be publicly available and ideally hosted on a CDN to ensure best performance. -The best way to find the right CSS setup is by running the layout app directly, the application is [publicly available on Github here](https://github.com/GetStream/stream-video-js/tree/main/sample-apps/react/egress-composite) and contains instructions on how to be used. +You can customize how recorded calls look by providing an external CSS file. The CSS file needs to be publicly available and ideally hosted on a CDN to ensure the best performance. +The best way to find the right CSS setup is by running the layout app directly. The application is [publicly available on Github here](https://github.com/GetStream/stream-video-js/tree/main/sample-apps/react/egress-composite) and contains instructions on how to be used. @@ -459,8 +485,18 @@ client.video.updateCallType(callTypeName, { ```py -def hello_world(): - print("Hello, world!") +client.video.update_call_type(CALL_TYPE_NAME, settings=CallSettingsRequest( + recording=RecordSettingsRequest( + mode="available", + audio_only=False, + quality="1080p", + layout=LayoutSettingsRequest( + name="spotlight", + external_css_url='https://path/to/custom.css', + ), + ), + ), + ) ``` @@ -470,7 +506,7 @@ def hello_world(): If needed, you can use your own custom application to record a call. This is the most flexible and complex approach to record calls, make sure to reach out to our customer support before going with this approach. -The layout app used to record calls is available on Github and is a good starting point, the repository also includes information on how to build your own. +The layout app used to record calls is available on GitHub and is a good starting point. The repository also includes information on how to build your own. @@ -495,8 +531,18 @@ client.video.updateCallType(callTypeName, { ```py -def hello_world(): - print("Hello, world!") +client.video.update_call_type(CALL_TYPE_NAME, settings=CallSettingsRequest( + recording=RecordSettingsRequest( + mode="available", + audio_only=False, + quality="1080p", + layout=LayoutSettingsRequest( + name="custom", + external_app_url='https://path/to/layout/app', + ), + ), + ), + ) ``` @@ -504,4 +550,4 @@ def hello_world(): ## Client-side recording -Unfortunately there is no direct support for client-side recording at the moment. Call recording at the moment is done by Stream server-side. If client-side recording is important for you please make sure to follow the conversation [here](https://github.com/GetStream/protocol/discussions/249). +Unfortunately, there is no direct support for client-side recording at the moment. Call recording at the moment is done by Stream server-side. If client-side recording is important for you please make sure to follow the conversation [here](https://github.com/GetStream/protocol/discussions/249). diff --git a/docusaurus/video/docusaurus/docs/api/streaming/backstage.mdx b/docusaurus/video/docusaurus/docs/api/streaming/backstage.mdx index d7a56b77..860ffd7d 100644 --- a/docusaurus/video/docusaurus/docs/api/streaming/backstage.mdx +++ b/docusaurus/video/docusaurus/docs/api/streaming/backstage.mdx @@ -7,12 +7,17 @@ title: Backstage import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -import GoLive from '../_common_/go_live.mdx' +import GoLive from '../_common_/go_live.mdx'; ## Introduction +By default, livestreams are created in backstage mode, while in backstage mode, streams can only be accessed by admin-like users. +This is necessary because it makes it possible to create the setup in advance and to notify and grant access to viewers when the event starts. + ## Configuration +You change the backstage mode settings on the call type or on the call level. + @@ -41,7 +46,7 @@ client.video.updateCallType('', { ```py # call level update -call.update_call( +call.update( settings_override=CallSettingsRequest( backstage=BackstageSettingsRequest( enabled=True, @@ -51,7 +56,7 @@ call.update_call( # call type level update call_type_name = '' -call.update_call_type( +client.video.update_call_type( settings=CallSettingsRequest( backstage=BackstageSettingsRequest( enabled=True, @@ -63,8 +68,12 @@ call.update_call_type( +Setting the backstage mode to `false` means that calls won't be created in backstage mode, and anyone can join the call. + ## Backstage Permissions +When a call is in backstage mode, only users with the `join-backstage` capability are allowed to join. + @@ -81,7 +90,7 @@ client.video.updateCallType('', { ```py callTypeName = '' -call.update_call_type( +client.video.update_call_type( grants={"host": [OwnCapability.JOIN_BACKSTAGE.to_str()]}, ) ``` @@ -89,12 +98,22 @@ call.update_call_type( +With this approach you can add multiple members that have the `join-backstage` capability, which allows you to have multiple hosts. + ## Go Live +When the hosts are ready to start the stream and allow viewers to join, you can call the `GoLive` method. + +Optionally, you can start the HLS broadcast and/or recording at the same time as going live. + ## Stop Live +When the stream ends the `StopLive` endpoint will remove the viewers that are still in the call, and prevent from new viewers to join. + +A call can enter and leave backstage mode multiple times. + diff --git a/docusaurus/video/docusaurus/docs/api/streaming/hls.mdx b/docusaurus/video/docusaurus/docs/api/streaming/hls.mdx index 31efff34..e11611cf 100644 --- a/docusaurus/video/docusaurus/docs/api/streaming/hls.mdx +++ b/docusaurus/video/docusaurus/docs/api/streaming/hls.mdx @@ -4,3 +4,81 @@ sidebar_position: 2 slug: /streaming/hls title: HLS --- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Broadcast from '../_common_/broadcast.mdx'; +import GoLive from '../_common_/go_live.mdx'; + +[HLS streaming](https://en.wikipedia.org/wiki/HTTP_Live_Streaming) provides better buffering than WebRTC, at the cost having a slight delay in your livestreams. + +## Start and stop HLS broadcast + +There are two ways to start/stop HLS broadcast: + + + +Or, if you're using backstage mode, you can do that when going live: + + + +Once the live ended, the HLS broadcast will be stopped as well. + +## User permissions + +To perform these operations, users need the following capabilities: + +- `start-broadcast-call` +- `stop-broadcast-call` + +## Broadcast state + +You can check if the call is being broadcasted like this: + + + + +```js +const resp = await call.getOrCreate(); +const isBroadcasting = resp.call.egress.broadcasting; +``` + + + + +```py +resp = call.get() +isBroadcasting = resp.data().call.egress.broadcasting +``` + + + +## Events + +These events are sent to users connected to the call and your webhook/SQS: + +- `call.broadcasting_started` +- `call.broadcasting_stopped` +- `call.broadcasting_failed` + +## Consuming HLS broadcast + +Users don't need to join the call to consume the HLS broadcast, but they need to have the URL of the broadcast: + + + + +```js +const resp = await call.getOrCreate(); +const URL = resp.call.egress.hls?.playlist_url; +``` + + + + +```py +resp = call.get() +URL = resp.data().call.egress.hls.playlist_url +``` + + diff --git a/docusaurus/video/docusaurus/docs/api/streaming/overview.mdx b/docusaurus/video/docusaurus/docs/api/streaming/overview.mdx index 0ed7df57..507755bd 100644 --- a/docusaurus/video/docusaurus/docs/api/streaming/overview.mdx +++ b/docusaurus/video/docusaurus/docs/api/streaming/overview.mdx @@ -11,9 +11,9 @@ import TabItem from '@theme/TabItem'; import GoLive from '../_common_/go_live.mdx'; import RTMP from '../_common_/rtmp.mdx'; -In this section we are going to explain how you can use Stream to power different livestream use-cases. +In this section, we are going to explain how you can use Stream to power different livestream use cases. -Stream video allows you to power ultra low-latency streaming (hundreds of milliseconds). This is made possible by our worldwide edge infrastructure which support WebRTC for consuming and sending video. +Stream video allows you to power ultra-low-latency streaming (hundreds of milliseconds). This is made possible by our worldwide edge infrastructure, which supports WebRTC for consuming and sending video. Other important features related to livestream that are discussed in this section: @@ -36,55 +36,76 @@ call = client.video.call('livestream', callId); const response = await call.getOrCreate({ data: { created_by_id: 'john', + // You can add multiple hosts if you want to members: [{ user_id: 'john', role: 'host' }], }, }); ``` + + + +```py +call = client.video.call('livestream', callId) +response = call.create( + data= CallRequest( + created_by_id= 'john', + // You can add multiple hosts if you want to + members= [MemberRequest( user_id= 'john', role= 'host' )], + ), +) +``` -By default livestreams are created in backstage mode, when in backstage mode streams can only be accessed by admin-like users. +The built-in `livestream` call type has sensible defaults for livestreaming. However, you can customize that call type or create your own to better match your requirements. More information on this topic can be found in the [Call Types section](../../call_types/builtin). + +### Set the call live + +By default, livestreams are created in backstage mode. When in backstage mode, streams can only be accessed by admin-like users. This is necessary because it makes it possible to create the setup in advance and to notify and grant access to viewers when the event starts. -All we need to do in this case is call the `GoLive` method on the call object and that will make it accessible to viewers. +All we need to do in this case is call the `GoLive` method on the call object, and that will make it accessible to viewers. -### Create a simple test app using the livestream video player +For more information, see the [Backstage page](../backstage). + +### Test watching the stream + +The Stream API supports two different kinds of streams: -TODO: point to a simple webapp where you can run our video player, OK to use something like Codesanbox +- [WebRTC](../webrtc) +- [HLS](../hls) -### Test sending video using WebRTC +For testing purposes, you can use this [simple example application](https://codesandbox.io/s/javascript-livestream-viewer-lwzgmw) that can play WebRTC and HLS streams as well. Don't forget to provide the necessary credentials before testing. -You can refer to this [CodeSandbox](https://codesandbox.io/s/livestream-tutorial-mlqtrd?file=/src/App.tsx) - where you can send videos via WebRTC +### Test sending video via WebRTC + +For testing purposes, you can use this [simple example host application](https://codesandbox.io/s/javascript-livestream-host-3hs4vt). You can open the application multiple times which allows you to have multiple hosts, who can send multiple audio/video streams. Don't forget to provide the necessary credentials before testing. ### Test sending video via RTMP using OBS +Almost all livestream software and hardware supports RTMP. Our API supports using third-party software for streaming using RTMP. + Let's keep the demo app open and try to send video to the same call using RTMP. #### Log the URL & Stream Key -​ - #### Open OBS and go to settings -> stream -​ Select "custom" service Server: equal to the rtmpURL from the log Stream key: equal to the streamKey from the log Press start streaming in OBS. The RTMP stream will now show up in your call just like a regular video participant. -Now that we've learned to publish using WebRTC or RTMP let's talk about watching the livestream. +You can test the livestream with the test application linked above. -### Set the call live +For more information on this topic, see the [RTMP page](../rtmp). -Until now we connected to the call as the host user. By default livestream calls are configured to only allow hosts to send audio/video tracks. -Viewers on the other hand are not +## Recording -``` -// TODO: ... -``` +Liverstreams (and any other calls) can be recorded for later use. For more information see the [Recording section](../../recording/calls). diff --git a/docusaurus/video/docusaurus/docs/api/streaming/rtmp.mdx b/docusaurus/video/docusaurus/docs/api/streaming/rtmp.mdx index d5d0ce7f..90637567 100644 --- a/docusaurus/video/docusaurus/docs/api/streaming/rtmp.mdx +++ b/docusaurus/video/docusaurus/docs/api/streaming/rtmp.mdx @@ -10,8 +10,12 @@ import TabItem from '@theme/TabItem'; ## RTMP support overview +Almost all livestream software and hardware supports RTMP. Our API supports using third-party software for streaming using RTMP. + ## RTMP publishing +This is how you can acquire the necessary information for publishing RTMP using a third-party software. + @@ -31,9 +35,8 @@ const address = resp.call.ingress.rtmp.address.replace( ```py - # create or get the call -response = call.get_or_create_call( +response = call.create( data=CallRequest( created_by_id='john' ) @@ -50,4 +53,6 @@ address = response.data().call.ingress.rtmp.address.replace('', -## RTMP relay +The user(s) streaming from the third-party software will show up as regular users in the call. + +You can see an example in the [Quickstart](../../streaming/overview/#test-sending-video-via-rtmp-using-obs). diff --git a/docusaurus/video/docusaurus/docs/api/streaming/webrtc.mdx b/docusaurus/video/docusaurus/docs/api/streaming/webrtc.mdx index 3aa301f5..0159f887 100644 --- a/docusaurus/video/docusaurus/docs/api/streaming/webrtc.mdx +++ b/docusaurus/video/docusaurus/docs/api/streaming/webrtc.mdx @@ -5,4 +5,12 @@ slug: /streaming/webrtc title: WebRTC --- -## Low-latency streaming with WebRTC +[WebRTC](https://webrtc.org/) allows you to have low-latency streaming (hundreds of milliseconds). + +## Start and stop WebRTC broadcast + +The WebRTC broadcast is always on. Viewers can access it by joining the call. You can control who can join the call with [backstage mode](../../streaming/backstage). + +## Consuming WebRTC broadcast + +Your viewers must join the call to access the stream. You can use regular, guest or anonymous users to join the livestream. It's also possible to create call tokens that only allow access for specific calls. For more information, see the [authentication page](../../authentication). diff --git a/docusaurus/video/docusaurus/docs/api/webhooks/events.mdx b/docusaurus/video/docusaurus/docs/api/webhooks/events.mdx index 2567b21d..5ac85e79 100644 --- a/docusaurus/video/docusaurus/docs/api/webhooks/events.mdx +++ b/docusaurus/video/docusaurus/docs/api/webhooks/events.mdx @@ -9,9 +9,11 @@ Here you can find the list of events are sent to Webhook and SQS. | Event Type | Description | |---------------------------------|---------------------------------------------------| +| custom | Sent when a custom event is triggered | | call.accepted | Sent when a user accepts an incoming call | | call.blocked_user | Sent when a user is blocked | | call.broadcasting_started | Sent when HLS broadcasting has started | +| call.broadcasting_failed | Sent when HLS broadcasting has failed | | call.broadcasting_stopped | Sent when HLS broadcasting is stopped | | call.created | Sent when a call is created | | call.ended | Sent when a call is marked as ended | @@ -23,14 +25,15 @@ Here you can find the list of events are sent to Webhook and SQS. | call.permission_request | Sent when a user requests access on a call | | call.permissions_updated | Sent when permissions are updated on a call | | call.reaction_new | Sent when a reaction is sent on a call | -| call.recording_started | Sent when call recording starts | -| call.recording_stopped | Sent when call recording is stopped | | call.rejected | Sent when a user rejects an incoming call | | call.session_ended | Sent when the session has ended | | call.session_participant_joined | Sent when a user joins a call | | call.session_participant_left | Sent when a user leaves a call | | call.session_started | Sent when a call session starts | | call.unblocked_user | Sent when a user is unblocked | +| call.user_muted | Sent when a call member is muted | +| call.ring | Sent when a user rings others to join a call | +| call.notification | Sent when a user notifies others to join a call | | call.updated | Sent when a call is updated | | call.recording_started | Sent when call recording has started | | call.recording_stopped | Sent when call recording has stopped |