From 93999b9ff2aae1fd22aeca593785e3a4d6b1b259 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Fri, 2 Jul 2021 13:21:31 +0200 Subject: [PATCH 01/36] Add RFC: Service Overhaul --- text/0039-service-overhaul.md | 425 ++++++++++++++++++++++++++++++++++ 1 file changed, 425 insertions(+) create mode 100644 text/0039-service-overhaul.md diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md new file mode 100644 index 0000000..e7797a2 --- /dev/null +++ b/text/0039-service-overhaul.md @@ -0,0 +1,425 @@ +***This RFC is dependent on [RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md).*** + +# Summary + +- Make OBS able to accept third-party service plugins +- Register services with a unique id rather than a common one +- A service can be provided with multiple protocols +- Separate Twitch, Restream and YouTube integration and make them plugins + +# Motivation + +Actually even if OBS has the service API, developer can't create third-party service plugin because there is no mechanism to list those and show their own property view. + +Before in OBS, in the Stream settings page, there was a combobox with two choice: +- Streaming Services +- Custom Streaming Server + +Each one had his own property view because those two are the two actual registered official services. +This behavior could enable third-party service plugin to exist. + +Nowadays in OBS, this page show the list of services with many new elements showed of hidden depending of the selection (like recommended settings). With also Twitch and Restream OAuth integrations. And no use of the property views provided by `rtmp-services`. + +We need to restore the usage of property views and the possibility to create and use service plugin. + +It will also provide the ability for some stream services to be able to made their own plugin. + +*Since using the service API was not possible with the actual OBS, any breaking change in it (if there are) will not impact any plugin for OBS.* + +# Design + +## UI +The Stream settings page and the auto-wizard will only contain a combo box listing registered services with also the "Show All" option. And the property view of the service will be shown under it. + +A "common" service is a service that is shown that is shown in the default service list. To keep this attributes with the UI, a flag will be added to Service API to allow services to not be in this list, so by default third-party plugins will be shown without the need to click on the "Show all" option. + +Service with an VOD/archive track feature will also under a flag. So this option will only be shown if the combo service-protocol is compatible with this feature. +This feature should be considered different from a multi-track feature. + +Many elements will be moved inside properties views like: +- Stream key field +- Username and password fields +- OAuth connect disconnect button +- Text with clickable link +- Maximum and recommended settings label (and maybe their ignore checkboxes) +- "Get Stream Key" button +- "More Info" button + +## Service plugins +### Issue +#### `rtmp-services` +This plugin provide services with only one protocol, so it needs to "register" service like YouTube multiple times (HLS & RTMPS). + +And also OBS is too heavily dependent of it. + +#### Service integrations +Those integrations are added and use `rtmp-services` in a hacky way and not as plugins. + +### Idea for new services plugins +#### `rtmp-services` +This plugin will be put in a state of deprecation. And be replaced and finally removed after one major release cycle. + +Since OBS is heavily dependent of this plugin, many changes will be needed to remove this dependency. + +##### Conversion `rtmp_common` and `rtmp_custom` to new services +A way to convert user service config to a new one will be added. More detail below. + +#### Service integrations + +Twitch, YouTube and Restream have their own integration in OBS with OAuth. But those need to be isolated as plugins (frontend if needed). + +Those will plugins will provide the basic and OAuth version of the services as one services. + +If OBS is built without client ids and hashes, those plugins will be built without their integration. + +##### Conversion to new plugins +Everything related to auth in `basic.ini` will moved elsewhere. More detail below. + +##### About dock additions (idea/draft) +A new function in the Service API to load UI additions when starting OBS or applying setting. An unload may be needed or added to the destroy function. + +##### About "Manage Broadcast" in YouTube integration About dock additions (idea/draft) +YouTube adds a "broadcast manager", some services could also have the same need (e.g. PeerTube) so the button will be kept and a new function and a flag to the service API allowing this behavior will be added. + +#### `custom-service` +This plugin is meant to provide a replacement for `rtmp_custom` type. + +If OBS need to be heavily dependent to one plugin, it shall be this one. + +The protocol will be detected (or maybe forced set by the user). +Maybe properties will show depending of the protocol. + +#### `obs-services` +This plugin is meant to provide a replacements for `rtmp_common` type for services who doesn't have custom behavior or integration. + +This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `rtmp-common` id. + +Those services will be able to provide multiple protocols so no more "Service - HLS" and "Service - FTL". + +If a certain protocol is not available, the plugin will not register the service if the service doesn't use another protocol. +If it does, the missing protocol will not be shown. [Thanks to RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md). + +The notion of maximum and recommended shall be distinguished. +Maximum, supported resolutions, recommended settings will be ignorable with their respective checkboxes. + +Those services should have no specific behavior like ingest management. + +But can list with which codec they are compatible if needed. [Thanks to RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md) + +In the end, adding streaming service will only be a JSON addition for this plugin. +Only improvements will be accepted in the code of this plugin. + +#### A plugin per special case +This/Those plugin(s) is/are meant to provide replacements for `rtmp_common` type for services which need a custom behavior. + +This/Those plugin(s) is/are meant to have implemented and register services which need a specific behavior like custom ingest with a unique id for each one. + +#### Note about the plugins +- Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new plugin and keep the same id. The change will be seamless for the user. + +### Conversion of services +**Downgrade will break service configuration** +A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the `service.json` to a new one. + +Auth integration config inside `basic.ini` will be also transfered to the new file. + +## Other changes + +### Service API changes +- Add missing get_properties2 and get_default2 functions for service + +### Property API addition +- Add a property to be able to show information with text label + +Since the service API is in a way unusable by third-party, any breakage will only impact OBS built-in service plugins ( so only `rtmp-services`). + +### Service integrations new flow + +#### How docks and CEF widget for OAuth will be created +The front-end API will need to have a way to access and use `cef` and `panel_cookies` from the main window. + +#### How docks will be added + +`OBS_FRONTEND_EVENT_FINISHED_LOADING` can be used when OBS startup to enable docks. + +Three new front-end event will be added: +- `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id). +- `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change). + +Each service integration plugin will react to at least the two first to add or remove his related docks. + +#### Manage Broadcast +YouTube is not the only service that could have or need a "Manage Broadcast" button. So adding a way to make other service plugin able to use it. + +- Add a unique callback meant to be called when the "Manage Broadcast" button is clicked. +- Add a callback setter in the frontend-api which will make the button show up. This setter will always override the previous callback. +- Add a callback unsetter in the frontend-api which will make the button hide. This unsetter will have the callback as a parameter to check if the set callback should really be unset. + +### Service JSON format + +#### Old version + +The old actually looks like this: +```json +{ + "format_version": 3, + "services": [ + { + "name": "Example", + "common": false, + "more_info_link": "https://example.com/more_info", + "stream_key_link": "https://example.com/stream_key", + "alt_names": [ + "Example with a FTL server" + ], + "servers": [ + { + "name": "Server", + "url": "ftl://example.com" + } + ], + "recommended": { + "keyint": 2, + "profile": "main", + "output": "ftl_output", + "max video bitrate": 4321, + "max audio bitrate": 321, + "supported resolutions": [ + "1600x900", + "1280x720" + ], + "max fps": 24, + "bframes": 2, + "x264opts": "scenecut=0 tune=zerolatency", + "bitrate matrix": [ + { + "res": "1280x720", + "fps": 24, + "max bitrate": 3210 + }, + { + "res": "1600x900", + "fps": 24, + "max bitrate": 4321 + } + ], + } + } + ] +} +``` + +- `"format_version"`: the format version, changed when the JSON is no longer backward compatible. +- `"services"`: array of services. + - `"name"`: name showed in OBS. + - `"common"` (optional): is the service only shown when the user has clicked on `Show all`. + - `"more_info_link"` (optional): link with more info about the service. + - `"stream_key_link"` (optional): link where the user can find his stream key. + - `"alt_names"` (optional): alternative service name. + - `"servers"`: array of servers. + - `"name"`: name of the server. + - `"url"`: url of the server. + - `"recommended"` (it depends): "recommended" settings that become the default when using this service. + - `"output"` (not optional if using a protocol different from RTMP(S)): indicates which output **shall** be used because the service use a protocol different from RTMP(S). + - `"keyint"` (optional): default keyframe interval for this service. + - `"bframes"` (optional): default b-frames for this service. + - `"profile"` (optional): default H264 encoder profile for this service. + - `"x264opts"` (optional): default option for x264 for this service. + - `"max video bitrate"` (optional): maximum video bitrate for this service. + - `"max audio bitrate"` (optional): maximum audio bitrate for this service. + - `"max fps"` (optional): maximum frame per second for this service. + - `"supported resolutions"` (optional): array of supported resolutions for this service. + - `"bitrate matrix"` (optional): array of maximum bitrate for a certain resolution/FPS combo for this service. + - `"res"`: resolution. + - `"fps"`: frame per seconds. + - `"max bitrate"`: maximum video bitrate. + +##### Issues with this format +- The naming scheme is a mix of object name with space and some with underscores. +- About `"output"`, OBS consider every service as RTMP if not added and it's not a recommended settings at all. It makes OBS use the right protocol for the service. Also this prevent a service of being multi-protocol. +- About `"recommended"`, most of the options seems to H264 related +- `"common"`, the name makes it not understandable at the first sight maybe adding some documention would be good thing. + +#### New format (draft) +Here is a example: +```json +{ + "format_version": 1, + "services": [ + { + "id": "example", + "name": "Example of stream services", + "common": false, + "more_info_link": "https://example.com/more_info", + "stream_key_link": "https://example.com/stream_key", + "servers": [ + { + "name": "SRT Server", + "url": "srt://example.com" + }, + { + "name": "RTMPS Server", + "url": "rtmps://example.com/server" + }, + { + "name": "FTL Server", + "url": "ftl://example.com/" + }, + { + "name": "HLS Server", + "protocol": "HLS", + "url": "https://example.com/http_upload_hls?cid={stream_key}©=0&file=out.m3u8" + } + ], + "supported_codecs": { + "video": { + "any_protocol": [ + "h264" + ], + "SRT": [ + "av1" + ] + }, + "audio": { + "any_protocol": [ + "aac" + ], + "SRT": [ + "opus" + ] + } + }, + "supported_resolutions": { + "with_framerate": true, + "array": [ + "1920x1080@60", + "1920x1080@30", + "1280x720@60", + "1280x720@30" + ] + }, + "maximums": { + "fps": 60, + "video_bitrate": { + "any_codec": 9000, + "av1": 8000, + }, + "audio_bitrate": { + "any_codec": 320, + "opus": 640, + }, + "video_bitrate_matrix": { + "1920x1080@60": { + "any_codec": 9000, + "av1": 8000 + }, + "1920x1080@30": { + "any_codec": 6000, + "av1": 5000 + }, + "1280x720@60": { + "any_codec": 6000, + "av1": 5000 + }, + "1280x720@30": { + "any_codec": 4000, + "av1": 3000 + } + }, + }, + "recommended": { + "video": {}, + "video_bitrate_matrix": {}, + "audio": {}, + } + } + ] +} +``` + +- `"format_version"`: no change. +- `"services"`: array of services. + - **`"id"`**: service identifier, services are no longer identified by their name. + - `"name"` (if multiple servers): no change. + - `"common"` (optional): no change. + - `"more_info_link"` (optional): no change. + - `"stream_key_link"` (optional): no change. + - ~~`"alt_names"`~~: removed. + - `"servers"`: array of servers. + - `"name"`: no change. + - **`"protocol"`** (optional): needed if the url prefix can't help identify the protocol. + - `"url"`: no change. + - **`"supported_codecs"`** (optional): codec not supported by a protocol will not be used. If not set, fallback to what the protocol support. + - **`"video"`** (optional): video codecs supported by the service. + - **`"any_protocol"`** (optional): array of strings with codecs' name supported by the service for any protocol. + - ***`"protocol name"`*** (optional): (e.g. `"HLS":`) array of strings with codecs' name supported by only this protocol. This array is merged with `"any_protocol"`. + - **`"audio"`** (optional): audio codecs supported by the service. + - **`"any_protocol"`** (optional): array of strings with codecs' name supported by the service for any protocol. + - ***`"protocol name"`*** (optional): (e.g. `"HLS":`) array of strings with codecs' name only supported by this protocol. This array is merged with `"any_protocol"`. + - **`"supported_resolutions"`** (optional): array of strings with resolutions (e.g. `"1280x720"`) supported by the service for any protocol. + - **`"with_framerates"`** (optional): default to false. If false each entry shall be put as this "1920x1080", if true it will be put with a framerate as this "1920x1080@30". Only those framerate will be be considered supported. + - **`"array"`**: Array of resolutions + - **`"maximums"`** (optional): maximums allowed by the service. + - **`"fps"`** (optional): maximum framerate allowed by the service. May be overrided if `"supported_resolutions"` is set with framerates (if 1080p is limited to 30 FPS and 720p to 60, the maximum will change depending on the resolution). + - **`"video_bitrate"`** (optional): maximum video bitrate. Can be set per codec. Unused if `"video_bitrate_matrix"` is set. + - **`"any_codec"`** (optional): bitrate for any codec. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) bitrate for this codec. It overrides `"any_codec"`. + - **`"video_bitrate_matrix"`** (optional but requires `"supported_resolutions"` with framerates): maximum bitrate based on resolutions and framerates from `"supported_resolutions"`. + - ***`"CX x CY @ FPS"`*** (one per resolution): (e.g. `"1280x720@60":`) maximum bitrate for supported resolution of this service. Can be set per codec. + - **`"any_codec"`** (optional): bitrate for any codec. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. + - **`"audio_bitrate"`** (optional): maximum audio bitrate. Can be set per codec. + - **`"any_codec"`** (optional): bitrate for any codecs. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. + - `"recommended"` (optional): recommended settings that become the defaults when using this service. + - ~~`"output"`~~: removed and replaced by the `"url"` prefix or `"protocol"` in `"servers"`. + - `"keyint"` (optional): is now per video codec. + - **`"any_codec"`** (optional): keyframe interval for any codec. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) keyframe interval for this codec. It overrides `"any_codec"`. + - `"bframes"` (optional): is now per video codec. + - **`"any_codec"`** (optional): b-frames for any codec. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) b-frames for this codec. It overrides `"any_codec"`. + - `"profile"` (optional): is now per video codec. + - No `"any_codec"` because profile is surely different between codecs. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) profile for this codec if available. It overrides `"any_codec"`. + - `"x264opts"`: no change. + - ~~`"max video bitrate"`~~: replaced. + - ~~`"max audio bitrate"`~~: replaced. + - ~~`"max fps"`~~: replaced + - ~~`"supported resolutions"`~~: replaced. + - ~~`"bitrate matrix"`~~: replaced. + - ~~`"res"`~~: replaced. + - ~~`"fps"`~~: replaced. + - ~~`"max bitrate"`~~: replaced. + - **`"fps"`** (optional): recommended framerate for this service. Unused if `"supported_resolutions"` is set with framerates. + - **`"video_bitrate"`** (optional): recommended video bitrate. Can be set per codec. Unused if `"video_bitrate_matrix"` is set. + - **`"any_codec"`** (optional): bitrate for any codec. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) bitrate for this codec. It overrides `"any_codec"`. + - **`"video_bitrate_matrix"`** (optional but requires `"supported_resolutions"` with with framerates): recommended bitrate based on resolutions and framerates from `"supported_resolutions"`. + - ***`"CX x CY @ FPS"`*** (one per resolution): (e.g. `"1280x720@60":`) recommended bitrate for supported resolution of this service. + - **`"any_codec"`** (optional): bitrate for any codec. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) for this codec. It overrides `"any_codec"`. + - **`"audio_bitrate"`** (optional): maximum audio bitrate. Can be set per codec. + - **`"any_codec"`** (optional): bitrate for any codecs. + - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. + +##### Advantages of this format + +- Recommended settings are really recommended settings. +- Recommendation and maximums are two separated thing. +- Some settings are now per protocol or per codec, this allow multi-protocol service to be registered under only one id. This will also need to a way to know which codec is used when applying settings. +- Name can be changed without consequences. + +### Service ID naming scheme +- Only lower case letter +- Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). + +### Things to be reworked +- Verification with video and output settings to see (if not ignored) if the settings for the service are respected. + +### About codecs +Some services could support a protocol without supporting all the compatible codecs, so adding a new field like `supported_codecs` for audio and video may be needed. + +# Drawbacks + +# Additional Information From 91d00456ac5bea5d125d2786496030b6a28a787b Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 9 Jan 2022 21:29:37 +0100 Subject: [PATCH 02/36] WIP update new JSON format --- text/0039-service-overhaul.md | 181 ++++++++++++++++++++-------------- 1 file changed, 109 insertions(+), 72 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index e7797a2..59eb8fd 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -31,7 +31,7 @@ It will also provide the ability for some stream services to be able to made the ## UI The Stream settings page and the auto-wizard will only contain a combo box listing registered services with also the "Show All" option. And the property view of the service will be shown under it. -A "common" service is a service that is shown that is shown in the default service list. To keep this attributes with the UI, a flag will be added to Service API to allow services to not be in this list, so by default third-party plugins will be shown without the need to click on the "Show all" option. +A "common" service is a service that is shown in the default service list. To keep this attributes with the UI, a flag will be added to Service API to allow services to not be in this list, so by default third-party plugins will be shown without the need to click on the "Show all" option. Service with an VOD/archive track feature will also under a flag. So this option will only be shown if the combo service-protocol is compatible with this feature. This feature should be considered different from a multi-track feature. @@ -136,7 +136,13 @@ Since the service API is in a way unusable by third-party, any breakage will onl ### Service integrations new flow #### How docks and CEF widget for OAuth will be created -The front-end API will need to have a way to access and use `cef` and `panel_cookies` from the main window. +For the docks we could add the possibility to add them through the frontend API. + +Adding to the frontend API the possibility to generate the browser widget neutral on the system use (CEF). Also need to add a function asking OBS Studio is browser features are availlable. + +OR + +Maybe adding an API to `obs-browser` to allow plugins to create widget and docks it without using the frontend API as a bridge. #### How docks will be added @@ -240,16 +246,110 @@ The old actually looks like this: - About `"recommended"`, most of the options seems to H264 related - `"common"`, the name makes it not understandable at the first sight maybe adding some documention would be good thing. -#### New format (draft) -Here is a example: +#### New format (WIP) +The new format will be parsable with a new interface library named `service-json-parser` to allow first-party plugins to read this format rather than recreating the wheel. + +The new format will be considered as the version 4. + +This format allow some specific additions parsed by getter added to the concerned plugin. + +Multi-service plugins should have a JSON root that look like this: +```json +{ + "format_version": 4, + "services": [] +} +``` +`"services"` is an array of service objects. + +Service plugin like integrations one should have a JSON root that look like this: +```json +{ + "format_version": 4, + "service": {} +} +``` +`"service"` is the service object itself. + +##### Plugins specific additions +Those additions are added like extensions to the service object format. + +Getters for those customisations are implemented in the plugin itself. +- In `obs-services`: + - `"id"` (required): service identifier, services are no longer identified by their name. Added because this plugin is multi-services. + - `"name"` (required): name of the service. Added because this plugin is multi-services. + - `"common"` (optional, false by default): this object is added in service objects of this plugin to identify which service in "common" or not. No third-party plugin should have this behavior. +- In `obs-youtube`: + - Servers name are translated. + - `"name_suffix"` in `"servers"` (optional): suffix added to the server name after being translated. + +Specific documentations about adding service in `obs-services` should be made. + +##### Service object format +S: Should be required by any first-party plugin + +O: Optional in `obs-services`, can be required or not used at all in first-party one-service plugins depending on their implementations. + +- `"more_info_link"`O: link with more info about the service. +- `"stream_key_link"`O: link where the user can find his stream key. +- `"servers"`S: array of servers. + - `"name"` (required): name of the server. + - `"protocol"` (required if if the url prefix can't help identify the protocol, like HLS protocol): protocol identifier (e.g. RTMP, SRT, RIST). + - `"url"` (required): url of the server. +- `"supported_codecs"`O: codec not supported by a protocol will not be used. If not set, fallback to what the protocol can support. + - `"video"`O: video codecs supported by the service. + - `"any_protocol"`O: array of strings with codecs' name supported by the service for any protocol. + - *`"protocol name"`*O: (e.g. `"HLS":`) array of strings with codecs' name supported by only this protocol. This array is merged with `"any_protocol"`. + - `"audio"`: audio codecs supported by the service. + - `"any_protocol"`O: array of strings with codecs' name supported by the service for any protocol. + - *`"protocol name"`*O: (e.g. `"HLS":`) array of strings with codecs' name only supported by this protocol. This array is merged with `"any_protocol"`. +- `"supported_resolutions"`O: array of strings with resolutions (e.g. `"1280x720"`) supported by the service for any protocol. + - `"with_framerates"`O: default to false. If false each entry shall be put as this "1920x1080", if true it will be put with a framerate as this "1920x1080@30". Only those framerate will be be considered supported. + - `"array"`(required): Array of resolutions +- `"maximums"`O: maximums allowed by the service. + - `"fps"`O: maximum framerate allowed by the service. May be overrided if `"supported_resolutions"` is set with framerates (if 1080p is limited to 30 FPS and 720p to 60, the maximum will change depending on the resolution). + - `"video_bitrate"`O: maximum video bitrate. Can be set per codec. Unused if `"video_bitrate_matrix"` is set. + - `"any_codec"`O: bitrate for any codec. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) bitrate for this codec. It overrides `"any_codec"`. + - `"video_bitrate_matrix"`O (requires `"supported_resolutions"` with framerates): maximum bitrate based on resolutions and framerates from `"supported_resolutions"`. + - *`"CX x CY @ FPS"`*O (**one per resolution**): (e.g. `"1280x720@60":`) maximum bitrate for supported resolution of this service. Can be set per codec. + - `"any_codec"`O: bitrate for any codec. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. + - `"audio_bitrate"`O: maximum audio bitrate. Can be set per codec. + - `"any_codec"`O: bitrate for any codecs. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. +- `"recommended"`O: recommended settings that become the defaults when using this service. + - `"keyint"`O: is now per video codec. + - `"any_codec"`O: keyframe interval for any codec. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) keyframe interval for this codec. It overrides `"any_codec"`. + - `"bframes"`O: is now per video codec. + - `"any_codec"`O: b-frames for any codec. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) b-frames for this codec. It overrides `"any_codec"`. + - `"profile"`O: is now per video codec. + - No `"any_codec"` because profile is surely different between codecs. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) profile for this codec if available. It overrides `"any_codec"`. + - `"x264opts"`O: no change. + - `"fps"`O: recommended framerate for this service. Unused if `"supported_resolutions"` is set with framerates. + - `"video_bitrate"`O: recommended video bitrate. Can be set per codec. Unused if `"video_bitrate_matrix"` is set. + - `"any_codec"`O: bitrate for any codec. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) bitrate for this codec. It overrides `"any_codec"`. + - `"video_bitrate_matrix"`O (requires `"supported_resolutions"` with with framerates): recommended bitrate based on resolutions and framerates from `"supported_resolutions"`. + - *`"CX x CY @ FPS"`*O (**one per resolution**): (e.g. `"1280x720@60":`) recommended bitrate for supported resolution of this service. + - `"any_codec"`O: bitrate for any codec. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) for this codec. It overrides `"any_codec"`. + - `"audio_bitrate"`O: maximum audio bitrate. Can be set per codec. + - `"any_codec"`O: bitrate for any codecs. + - *`"codec name"`*O (requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. + +##### Example +Here is a example with `obs-services` in mind: ```json { - "format_version": 1, + "format_version": 4, "services": [ { "id": "example", "name": "Example of stream services", - "common": false, "more_info_link": "https://example.com/more_info", "stream_key_link": "https://example.com/stream_key", "servers": [ @@ -337,72 +437,6 @@ Here is a example: } ``` -- `"format_version"`: no change. -- `"services"`: array of services. - - **`"id"`**: service identifier, services are no longer identified by their name. - - `"name"` (if multiple servers): no change. - - `"common"` (optional): no change. - - `"more_info_link"` (optional): no change. - - `"stream_key_link"` (optional): no change. - - ~~`"alt_names"`~~: removed. - - `"servers"`: array of servers. - - `"name"`: no change. - - **`"protocol"`** (optional): needed if the url prefix can't help identify the protocol. - - `"url"`: no change. - - **`"supported_codecs"`** (optional): codec not supported by a protocol will not be used. If not set, fallback to what the protocol support. - - **`"video"`** (optional): video codecs supported by the service. - - **`"any_protocol"`** (optional): array of strings with codecs' name supported by the service for any protocol. - - ***`"protocol name"`*** (optional): (e.g. `"HLS":`) array of strings with codecs' name supported by only this protocol. This array is merged with `"any_protocol"`. - - **`"audio"`** (optional): audio codecs supported by the service. - - **`"any_protocol"`** (optional): array of strings with codecs' name supported by the service for any protocol. - - ***`"protocol name"`*** (optional): (e.g. `"HLS":`) array of strings with codecs' name only supported by this protocol. This array is merged with `"any_protocol"`. - - **`"supported_resolutions"`** (optional): array of strings with resolutions (e.g. `"1280x720"`) supported by the service for any protocol. - - **`"with_framerates"`** (optional): default to false. If false each entry shall be put as this "1920x1080", if true it will be put with a framerate as this "1920x1080@30". Only those framerate will be be considered supported. - - **`"array"`**: Array of resolutions - - **`"maximums"`** (optional): maximums allowed by the service. - - **`"fps"`** (optional): maximum framerate allowed by the service. May be overrided if `"supported_resolutions"` is set with framerates (if 1080p is limited to 30 FPS and 720p to 60, the maximum will change depending on the resolution). - - **`"video_bitrate"`** (optional): maximum video bitrate. Can be set per codec. Unused if `"video_bitrate_matrix"` is set. - - **`"any_codec"`** (optional): bitrate for any codec. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) bitrate for this codec. It overrides `"any_codec"`. - - **`"video_bitrate_matrix"`** (optional but requires `"supported_resolutions"` with framerates): maximum bitrate based on resolutions and framerates from `"supported_resolutions"`. - - ***`"CX x CY @ FPS"`*** (one per resolution): (e.g. `"1280x720@60":`) maximum bitrate for supported resolution of this service. Can be set per codec. - - **`"any_codec"`** (optional): bitrate for any codec. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. - - **`"audio_bitrate"`** (optional): maximum audio bitrate. Can be set per codec. - - **`"any_codec"`** (optional): bitrate for any codecs. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. - - `"recommended"` (optional): recommended settings that become the defaults when using this service. - - ~~`"output"`~~: removed and replaced by the `"url"` prefix or `"protocol"` in `"servers"`. - - `"keyint"` (optional): is now per video codec. - - **`"any_codec"`** (optional): keyframe interval for any codec. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) keyframe interval for this codec. It overrides `"any_codec"`. - - `"bframes"` (optional): is now per video codec. - - **`"any_codec"`** (optional): b-frames for any codec. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) b-frames for this codec. It overrides `"any_codec"`. - - `"profile"` (optional): is now per video codec. - - No `"any_codec"` because profile is surely different between codecs. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) profile for this codec if available. It overrides `"any_codec"`. - - `"x264opts"`: no change. - - ~~`"max video bitrate"`~~: replaced. - - ~~`"max audio bitrate"`~~: replaced. - - ~~`"max fps"`~~: replaced - - ~~`"supported resolutions"`~~: replaced. - - ~~`"bitrate matrix"`~~: replaced. - - ~~`"res"`~~: replaced. - - ~~`"fps"`~~: replaced. - - ~~`"max bitrate"`~~: replaced. - - **`"fps"`** (optional): recommended framerate for this service. Unused if `"supported_resolutions"` is set with framerates. - - **`"video_bitrate"`** (optional): recommended video bitrate. Can be set per codec. Unused if `"video_bitrate_matrix"` is set. - - **`"any_codec"`** (optional): bitrate for any codec. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1"`) bitrate for this codec. It overrides `"any_codec"`. - - **`"video_bitrate_matrix"`** (optional but requires `"supported_resolutions"` with with framerates): recommended bitrate based on resolutions and framerates from `"supported_resolutions"`. - - ***`"CX x CY @ FPS"`*** (one per resolution): (e.g. `"1280x720@60":`) recommended bitrate for supported resolution of this service. - - **`"any_codec"`** (optional): bitrate for any codec. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) for this codec. It overrides `"any_codec"`. - - **`"audio_bitrate"`** (optional): maximum audio bitrate. Can be set per codec. - - **`"any_codec"`** (optional): bitrate for any codecs. - - ***`"codec name"`*** (optional, requires to be put in `"supported_codecs"` firstly): (e.g. `"av1":`) bitrate for this codec. It overrides `"any_codec"`. - ##### Advantages of this format - Recommended settings are really recommended settings. @@ -410,6 +444,9 @@ Here is a example: - Some settings are now per protocol or per codec, this allow multi-protocol service to be registered under only one id. This will also need to a way to know which codec is used when applying settings. - Name can be changed without consequences. +##### Possible evolution +Add to the service object an url that lead to an updated service object hosted by the stream service itself. + ### Service ID naming scheme - Only lower case letter - Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). From 08eba1c412c1c6f1ad0d6380431d88be3209e3bc Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 2 Feb 2022 17:43:04 +0100 Subject: [PATCH 03/36] WIP Browser Dock API additons and other things --- text/0039-service-overhaul.md | 95 ++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 13 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 59eb8fd..b0de3a0 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -33,9 +33,21 @@ The Stream settings page and the auto-wizard will only contain a combo box listi A "common" service is a service that is shown in the default service list. To keep this attributes with the UI, a flag will be added to Service API to allow services to not be in this list, so by default third-party plugins will be shown without the need to click on the "Show all" option. -Service with an VOD/archive track feature will also under a flag. So this option will only be shown if the combo service-protocol is compatible with this feature. +Note: every service that are not common will have the flag added in first-party plugins so they will not be shown by default. + +The notion of maximum and recommended shall be distinguished by using them differently: + +1. Maximums became limits that can't be bypassed and recommendations can be disabled. +2. Recommendations are used to set settings with the Auto-wizard and maximums can be disabled. +3. Maximum, recommended settings will be ignorable with their respective checkboxes. + +Supported resolutions should be enforced by default and shall not be disabled. + +Service with an VOD/archive track feature will also have a flag. So this option will only be shown if the combo service-protocol is compatible with this feature. This feature should be considered different from a multi-track feature. +*Personal note: Some thought about also adding a flag for bandwidth test mode are also on my mind.* + Many elements will be moved inside properties views like: - Stream key field - Username and password fields @@ -99,9 +111,6 @@ Those services will be able to provide multiple protocols so no more "Service - If a certain protocol is not available, the plugin will not register the service if the service doesn't use another protocol. If it does, the missing protocol will not be shown. [Thanks to RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md). -The notion of maximum and recommended shall be distinguished. -Maximum, supported resolutions, recommended settings will be ignorable with their respective checkboxes. - Those services should have no specific behavior like ingest management. But can list with which codec they are compatible if needed. [Thanks to RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md) @@ -136,21 +145,82 @@ Since the service API is in a way unusable by third-party, any breakage will onl ### Service integrations new flow #### How docks and CEF widget for OAuth will be created -For the docks we could add the possibility to add them through the frontend API. +The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks and generating widgets. + +Note: Free functions for each structure that requires it because of a "dynamic" will be also added. + +##### Check availability +- `bool obs_frontend_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. +- `bool obs_frontend_browser_initialised()` will indicate if the CEF was initialised when the function is called. +##### Browser Widget +Internal OAuth (like Twitch and Restream) require that the Front-end API allow to add a browser widget to show the OAuth login page. + +This structure will be used to send everything needed to create this widget through the API. +```C++ +struct obs_frontend_browser_widget { + /* takes QLayout */ + void *layout; + const char *url; + bool enable_cookie; + DARRAY(struct obs_frontend_browser_connect) connection; +}; +``` +- `void *layout` will contain a `QLayout` pointer which will receive the browser widget. +- `const char *url` will contain the URL af the widget. +- `bool enable_cookie`, if true `panel_cookie` will be set on the widget rather than a `nullptr`. This will allow to keep cookie which is required. +- `DARRAY(struct obs_frontend_browser_connect) connection` is a array that will contain signal-slot connections that will be created on OBS Studio side. + +```C++ +struct obs_frontend_browser_connect { + const char *signal; + /* takes QObject */ + void *signal_receiver; + const char *slot; +}; +``` + +`obs_frontend_add_browser_widget(struct obs_frontend_browser_widget *params)` is the fucntion that will add a browser widget to the QLayout put in the structure. + +##### Browser dock +Twitch and Restream adds browser docks, so the Front-end API needs to allow this with many parameters. + +This structure will be used to send everything needed to create those docks through the API. +```C++ +struct obs_frontend_browser_dock { + const char *id; + const char *title; + const char *url; + int width; + int height; + int min_width; + int min_height; + bool enable_cookie; + struct dstr startup_script; + DARRAY(char *) force_popup_url; +}; +``` +- `const char *id`, ID of the dock. +- `const char *title`, title of the dock. +- `const char *url`, URL of the dock. +- Dock default and minimum dimensions, every parameter under 80 is not used because 80 is the minimum set by OBS Studio. +- `bool enable_cookie`, if true `panel_cookie` will be set on the dock rather than a `nullptr`. This will allow to keep cookie which is required. +- `struct dstr startup_script` allow to set a startup script for the dock. +- `DARRAY(char *) force_popup_url` allow to set a list of URL to force those to popup. -Adding to the frontend API the possibility to generate the browser widget neutral on the system use (CEF). Also need to add a function asking OBS Studio is browser features are availlable. +`void * obs_frontend_add_browser_dock(struct obs_frontend_browser_dock *params)` is the function that will add those browser docks. It returns a `QDockWidget`. For now those docks or not shown by default. -OR +`void obs_frontend_remove_browser_dock(void *dock)` is the function meant to remove a browser dock. Need when disconnecting from a service. It takes QDockWidget, calls delete on dock and its corresponding QAction. -Maybe adding an API to `obs-browser` to allow plugins to create widget and docks it without using the frontend API as a bridge. +##### Other functions +`void obs_frontend_delete_browser_cookie(const char *url)` will remove cookies related to the given URL. #### How docks will be added `OBS_FRONTEND_EVENT_FINISHED_LOADING` can be used when OBS startup to enable docks. Three new front-end event will be added: -- `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id). -- `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change). +- `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id) like when a user switches between services. +- `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. Each service integration plugin will react to at least the two first to add or remove his related docks. @@ -241,12 +311,11 @@ The old actually looks like this: - `"max bitrate"`: maximum video bitrate. ##### Issues with this format -- The naming scheme is a mix of object name with space and some with underscores. - About `"output"`, OBS consider every service as RTMP if not added and it's not a recommended settings at all. It makes OBS use the right protocol for the service. Also this prevent a service of being multi-protocol. - About `"recommended"`, most of the options seems to H264 related - `"common"`, the name makes it not understandable at the first sight maybe adding some documention would be good thing. -#### New format (WIP) +#### New format (conversion in JSON Schema with changes is in WIP) The new format will be parsable with a new interface library named `service-json-parser` to allow first-party plugins to read this format rather than recreating the wheel. The new format will be considered as the version 4. @@ -281,7 +350,7 @@ Getters for those customisations are implemented in the plugin itself. - `"common"` (optional, false by default): this object is added in service objects of this plugin to identify which service in "common" or not. No third-party plugin should have this behavior. - In `obs-youtube`: - Servers name are translated. - - `"name_suffix"` in `"servers"` (optional): suffix added to the server name after being translated. + - `"name_suffix"` in `"servers"` (optional): suffix added to the server name after being translated. In this case "(legacy RTMP)" is the suffix added to translated server names to avoid creating more than 2 translation entries. Specific documentations about adding service in `obs-services` should be made. From 703f2f195c292706170b601b3273a66d127674bb Mon Sep 17 00:00:00 2001 From: tytan652 Date: Fri, 4 Feb 2022 16:15:13 +0100 Subject: [PATCH 04/36] WIP Some changes --- text/0039-service-overhaul.md | 49 ++++++++++++++++------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index b0de3a0..da8438e 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -35,13 +35,13 @@ A "common" service is a service that is shown in the default service list. To ke Note: every service that are not common will have the flag added in first-party plugins so they will not be shown by default. -The notion of maximum and recommended shall be distinguished by using them differently: +- Maximums are limits and one of those 3 choices: + 1. No option at all to bypass it + 2. Add a secret option that shall be added in `basic.ini` to bypass it + 3. Add a checkbox in the Advanced tab to bypass it +- Recommended settings will not provide bitrates and will be ignore-able through a checkbox in the service property. -1. Maximums became limits that can't be bypassed and recommendations can be disabled. -2. Recommendations are used to set settings with the Auto-wizard and maximums can be disabled. -3. Maximum, recommended settings will be ignorable with their respective checkboxes. - -Supported resolutions should be enforced by default and shall not be disabled. +Supported resolutions should be enforced by default and can not be disabled. Service with an VOD/archive track feature will also have a flag. So this option will only be shown if the combo service-protocol is compatible with this feature. This feature should be considered different from a multi-track feature. @@ -53,7 +53,8 @@ Many elements will be moved inside properties views like: - Username and password fields - OAuth connect disconnect button - Text with clickable link -- Maximum and recommended settings label (and maybe their ignore checkboxes) +- Maximum and recommended settings information +- Ignore "recommended setting" checkbox - "Get Stream Key" button - "More Info" button @@ -168,7 +169,7 @@ struct obs_frontend_browser_widget { - `void *layout` will contain a `QLayout` pointer which will receive the browser widget. - `const char *url` will contain the URL af the widget. - `bool enable_cookie`, if true `panel_cookie` will be set on the widget rather than a `nullptr`. This will allow to keep cookie which is required. -- `DARRAY(struct obs_frontend_browser_connect) connection` is a array that will contain signal-slot connections that will be created on OBS Studio side. +- `DARRAY(struct obs_frontend_browser_connect) connection` is a array that will contain signal-slot connections that will be created on OBS Studio side. Required to allow url changed detection. ```C++ struct obs_frontend_browser_connect { @@ -179,7 +180,7 @@ struct obs_frontend_browser_connect { }; ``` -`obs_frontend_add_browser_widget(struct obs_frontend_browser_widget *params)` is the fucntion that will add a browser widget to the QLayout put in the structure. +`obs_frontend_add_browser_widget(struct obs_frontend_browser_widget *params)` is the function that will add a browser widget to the QLayout put in the structure. ##### Browser dock Twitch and Restream adds browser docks, so the Front-end API needs to allow this with many parameters. @@ -442,7 +443,7 @@ Here is a example with `obs-services` in mind: ], "supported_codecs": { "video": { - "any_protocol": [ + "*": [ "h264" ], "SRT": [ @@ -450,7 +451,7 @@ Here is a example with `obs-services` in mind: ] }, "audio": { - "any_protocol": [ + "*": [ "aac" ], "SRT": [ @@ -458,15 +459,12 @@ Here is a example with `obs-services` in mind: ] } }, - "supported_resolutions": { - "with_framerate": true, - "array": [ - "1920x1080@60", - "1920x1080@30", - "1280x720@60", - "1280x720@30" - ] - }, + "supported_resolutions": [ + "1920x1080@60", + "1920x1080@30", + "1280x720@60", + "1280x720@30" + ], "maximums": { "fps": 60, "video_bitrate": { @@ -479,27 +477,24 @@ Here is a example with `obs-services` in mind: }, "video_bitrate_matrix": { "1920x1080@60": { - "any_codec": 9000, + "h264": 9000, "av1": 8000 }, "1920x1080@30": { - "any_codec": 6000, + "h264": 6000, "av1": 5000 }, "1280x720@60": { - "any_codec": 6000, + "h264": 6000, "av1": 5000 }, "1280x720@30": { - "any_codec": 4000, + "h264": 4000, "av1": 3000 } }, }, "recommended": { - "video": {}, - "video_bitrate_matrix": {}, - "audio": {}, } } ] From d7c22fde49bb9be3174b7a68aae8292fe0eb12ed Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 6 Feb 2022 10:39:21 +0100 Subject: [PATCH 05/36] WIP JSON Schemas --- .../commonPattern.schema.json | 23 ++++ .../obs-services.schema.json | 45 ++++++ .../protocolCodecsMap.schema.json | 48 +++++++ .../protocolDefs.schema.json | 24 ++++ text/0039-json-schemas/service.schema.json | 128 ++++++++++++++++++ text/0039-service-overhaul.md | 24 +++- 6 files changed, 286 insertions(+), 6 deletions(-) create mode 100644 text/0039-json-schemas/commonPattern.schema.json create mode 100644 text/0039-json-schemas/obs-services.schema.json create mode 100644 text/0039-json-schemas/protocolCodecsMap.schema.json create mode 100644 text/0039-json-schemas/protocolDefs.schema.json create mode 100644 text/0039-json-schemas/service.schema.json diff --git a/text/0039-json-schemas/commonPattern.schema.json b/text/0039-json-schemas/commonPattern.schema.json new file mode 100644 index 0000000..fd34bf7 --- /dev/null +++ b/text/0039-json-schemas/commonPattern.schema.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Common Pattern", + "description": "Pattern used multiple times in OBS JSON Schemas", + "$defs": { + "linkPattern": { + "description": "Pattern to enforce HTTP(S) links", + "pattern": "^https?://" + }, + "codecPattern": { + "description": "Pattern to enforce lowercase and no whitecase on codec naming", + "pattern": "^[a-z0-9]+$" + }, + "resolutionPattern": { + "description": "Pattern for resolution without framerate", + "pattern": "^[0-9]+x[0-9]+$" + }, + "resolutionFrameratePattern": { + "description": "Pattern for resolution with framerate", + "pattern": "^[0-9]+x[0-9]+@[0-9]+$" + } + } +} diff --git a/text/0039-json-schemas/obs-services.schema.json b/text/0039-json-schemas/obs-services.schema.json new file mode 100644 index 0000000..ad4445e --- /dev/null +++ b/text/0039-json-schemas/obs-services.schema.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "OBS Services Plugin JSON Schema", + "type": "object", + "required": ["format_version", "services"], + "properties": { + "format_version": { + "type": "integer", + "const": 4 + }, + "services": { + "type": "array", + "minItems": 1, + "items": { + "$comment": "Import common service object as a base, and then add new properties", + "$ref": "service.schema.json", + "required": ["id","name"], + "properties": { + "id": { + "title": "Service identifier", + "description": "Human readable identifier used to register the service in OBS", + "$comment": "Making it human readable is meant to allow users to use it through scripts and plugins, like service detection", + "type": "string", + "pattern": "^[a-z0-9_\\-]+$" + }, + "name": { + "title": "Name of the service", + "description": "Name showed in the OBS when choosing a service", + "type": "string" + }, + "common": { + "title": "Property reserved to OBS Project developers", + "description": "If not set, this value is considered as false", + "type": "boolean", + "default": false, + "$comment": "Set as a constant to true to avoid adding uselessly this property set to false", + "const": true + } + }, + "unevaluatedProperties": false + }, + "additionalItems": false + } + } +} diff --git a/text/0039-json-schemas/protocolCodecsMap.schema.json b/text/0039-json-schemas/protocolCodecsMap.schema.json new file mode 100644 index 0000000..c8ab776 --- /dev/null +++ b/text/0039-json-schemas/protocolCodecsMap.schema.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Protocol Codecs Map", + "description": "Hashmap of supported codecs per protocol supported by the service", + "type": "object", + "propertyNames": { + "$comment": "This hashmap can only contain properties where the name match the following pattern", + "$ref": "protocolDefs.schema.json#/$defs/protocolPattern" + }, + "properties": { + "*": { + "title": "Any protocol supported codecs", + "description": "List of supported codecs for any protocol supported by the service", + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "$comment": "Codec name shall match the following pattern", + "$ref": "commonPattern.schema.json#/$defs/codecPattern", + "examples": ["aac"] + }, + "examples": [ + { "*": ["h264"] } + ] + } + }, + "additionalProperties": { + "description": "Additional list of supported codecs for a specific protocol supported by the service", + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "$comment": "Codec name shall match the following pattern", + "$ref": "commonPattern.schema.json#/$defs/codecPattern", + "examples": ["opus"] + }, + "examples": [ + { "HLS": ["av1", "vp9"] } + ] + }, + "examples": [ + { + "*": ["aac"], + "SRT": ["opus"] + } + ], + "unevaluatedProperties": false +} diff --git a/text/0039-json-schemas/protocolDefs.schema.json b/text/0039-json-schemas/protocolDefs.schema.json new file mode 100644 index 0000000..7d7fbb4 --- /dev/null +++ b/text/0039-json-schemas/protocolDefs.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Protocol Enum and Pattern", + "description": "Protocol-related enum and pattern used in OBS JSON Schemas", + "$comment": "Made to allow an easy way to add protocol to schemas", + "$defs": { + "protocolEnum": { + "description": "Enumeration of protocols", + "enum": ["RTMP","RTMPS","HLS","SRT","RIST","SRT","FTL"] + }, + "protocolPattern": { + "description": "Pattern to enforce properties to named with a protocol or '*'", + "pattern": "^(\\*|RTMPS?|HLS|SRT|RIST|FTL)$" + }, + "serverPattern": { + "description": "Pattern to enforce a supported server URL", + "pattern": "^(rtmps?|https?|srt|rist|ftl)://" + }, + "requireProtocolPattern": { + "description": "Pattern meant to match with protocol that have a unique link prefix", + "pattern": "^(rtmps?|srt|rist|ftl)://" + } + } +} diff --git a/text/0039-json-schemas/service.schema.json b/text/0039-json-schemas/service.schema.json new file mode 100644 index 0000000..300aa67 --- /dev/null +++ b/text/0039-json-schemas/service.schema.json @@ -0,0 +1,128 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "OBS Common Service Object Schema", + "description": "Common structure shared among OBS first-party service plugins", + "type": "object", + "required": ["servers"], + "properties": { + "more_info_link": { + "description": "Link to a web page that show more info about the streaming service", + "type": "string", + "format": "uri", + "$comment": "Add a restriction to the URI format", + "$ref": "commonPattern.schema.json#/$defs/linkPattern" + }, + "stream_key_link": { + "description": "Link to a web page that allow the user to obtain streaming service stream key", + "type": "string", + "format": "uri", + "$comment": "Add a restriction to the URI format", + "$ref": "commonPattern.schema.json#/$defs/linkPattern" + }, + "servers": { + "description": "Array of server objects", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["name","url"], + "properties": { + "name": { + "title": "Server given name", + "type": "string" + }, + "protocol": { + "description": "Protocol used by the server. Required if the prefix can't help identify the streaming protocol (e.g. HLS).", + "type": "string", + "$ref": "protocolDefs.schema.json#/$defs/protocolEnum" + }, + "url": { + "title": "Server URL", + "type": "string", + "format": "uri", + "$comment": "Add a restriction to the URI format based on protocols supported by OBS", + "$ref": "protocolDefs.schema.json#/$defs/serverPattern" + } + }, + "additionalProperties": false, + "$comment": "Making 'protocol' required if no unique prefix is found (e.g. HLS will require 'protocol')", + "if": { "not": { "properties": { "url": { "$ref": "protocolDefs.schema.json#/$defs/requireProtocolPattern" } } } }, + "then": { "required": ["protocol"] } + }, + "additionalItems": false + }, + "supported_codecs": { + "description": "Supported video and audio codecs by the service per protocol", + "type": "object", + "properties": { + "video": { "$ref": "protocolCodecsMap.schema.json" }, + "audio": { "$ref": "protocolCodecsMap.schema.json" } + }, + "additionalProperties": false + }, + "supported_resolutions": { + "title": "Resolutions supported by the service", + "description": "All resolutions shall follow the same pattern between two possibility, with or without framerate. Check examples below.", + "type": "array", + "minItems": 1, + "items": { + "type": "string", + "pattern": "^[0-9]+x[0-9]+", + "examples": [ + "1920x1080", + "1280x720@60" + ] + }, + "additionalItems": false, + "$comment": "Detect if resolutions contain a framerate, if true force every resolutions to have it and vice-versa", + "if": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionFrameratePattern" } }, + "then": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionFrameratePattern" } }, + "else": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionPattern" } } + }, + "maximums": { + "type": "object", + "properties": { + "video_bitrate_matrix": { + "description": "Video bitrate per resolution with framerate", + "type": "object", + "propertyNames": { + "$comment": "This object can only contain properties where the name that match the following pattern", + "$ref": "commonPattern.schema.json#/$defs/resolutionFrameratePattern" + }, + "additionalProperties": { + "type": "object", + "propertyNames": { "$ref": "commonPattern.schema.json#/$defs/codecPattern" }, + "additionalProperties": { "type": "integer" }, + "unevaluatedProperties": false + }, + "examples": [ + { + "1280x720@60": { + "h264": 6000, + "av1": 5000 + } + } + ], + "unevaluatedProperties": false + } + } + }, + "recommended": { "type": "object" } + }, + "allOf": [ + { + "if": { + "$comment": "Forbid 'video_bitrate_matrix' objects from being set if 'supported_resolutions' is not set with framerate", + "properties": { "supported_resolutions": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionPattern" } } } + }, + "then": { "properties": { + "maximums": { "not": { "required": ["video_bitrate_matrix"] } }, + "recommended": { "not": { "required": ["video_bitrate_matrix"] } } + } }, + "else": { + "$comment": "Otherwise forbid 'maximums/fps' from being set if 'supported_resolutions' is set with framerate", + "properties": { "maximums": { "not": { "required": ["fps"] } } } + } + } + ] +} \ No newline at end of file diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index da8438e..9443bca 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -319,11 +319,23 @@ The old actually looks like this: #### New format (conversion in JSON Schema with changes is in WIP) The new format will be parsable with a new interface library named `service-json-parser` to allow first-party plugins to read this format rather than recreating the wheel. -The new format will be considered as the version 4. +The new format can be considered as the version 4. -This format allow some specific additions parsed by getter added to the concerned plugin. +This format will be defined by JSON Schemas (Draft 2020-12): +- `commonPattern.schema.json`: regex pattern use multiple times +- `protocolDefs.schema.json`: regex pattern and enum about protocols to ease protocol additions or removals in schemas +- `service.schema.json`: define the service object itself (*still in WIP*) +- `obs-services.schema.json`: `obs-services` JSON Schema -Multi-service plugins should have a JSON root that look like this: +Those are all present in `0039-json-schemas` folder. + +*Documention in schemas are in progress, and a schema for integration plugin should also be made.* + +JSON Schema allows to validate `services.json` (in `obs-services` case) when a PR is made against it. *Draft python script already made.* + +The use of JSON Schema allows to create specific additions for a specific plugin by creating a unique schema for it. + + -##### Plugins specific additions + ##### Example Here is a example with `obs-services` in mind: From f9a9d5b77d4b574edf4caae76e60ec3d95d5e118 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 9 Feb 2022 14:38:13 +0100 Subject: [PATCH 06/36] WIP More event --- text/0039-service-overhaul.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 9443bca..7799894 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -220,7 +220,9 @@ struct obs_frontend_browser_dock { `OBS_FRONTEND_EVENT_FINISHED_LOADING` can be used when OBS startup to enable docks. Three new front-end event will be added: +- `OBS_FRONTEND_EVENT_SERVICE_CHANGING` emitted before the service got changed (new id) like when a user switches between services. - `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id) like when a user switches between services. +- `OBS_FRONTEND_EVENT_SERVICE_UPDATING` emitted before the service got a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. - `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. Each service integration plugin will react to at least the two first to add or remove his related docks. From cb49ee6e5949d714e27c17e3dfba619455d0caf5 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 9 Feb 2022 15:50:03 +0100 Subject: [PATCH 07/36] WIP More about docks and events --- text/0039-service-overhaul.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 7799894..d3a8d26 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -217,7 +217,10 @@ struct obs_frontend_browser_dock { #### How docks will be added -`OBS_FRONTEND_EVENT_FINISHED_LOADING` can be used when OBS startup to enable docks. +`OBS_FRONTEND_EVENT_FINISHED_LOADING` can be used when OBS startup to add docks. +`OBS_FRONTEND_EVENT_EXIT` to unload docks that need to be removed before exit. +`OBS_FRONTEND_EVENT_PROFILE_CHANGING` to unload dock before profile got changed. +`OBS_FRONTEND_EVENT_PROFILE_CHANGED` to load integration from the new loaded profile. Three new front-end event will be added: - `OBS_FRONTEND_EVENT_SERVICE_CHANGING` emitted before the service got changed (new id) like when a user switches between services. @@ -227,6 +230,22 @@ Three new front-end event will be added: Each service integration plugin will react to at least the two first to add or remove his related docks. +#### How docks will keep their state between session and profile +Actually the dock state is global in the config, but with docks that appear depending on the service which is per profile which is still the case with "old" integrations. + +This which can lead to dock state losses between profile switching and exiting. The "old" integration actually store a dock state in the profile config and restore it after being the integration loaded is loaded. + +But making restoring a dock state from a plugin should be the last resort. +Making it per profile could avoid this. + +Integrations docks will be added after specific frontend event. +So after each of them the dock state needs to be restored. + +`OBS_FRONTEND_EVENT_FINISHING_LOADING` (finishing not finished) needs to be created +to allow adding docks and restore dock state before `OBS_FRONTEND_EVENT_FINISHED_LOADING` is emitted. + +Like this `OBS_FRONTEND_EVENT_FINISHED_LOADING` keep his meaning and does not get a restore dock state after it. + #### Manage Broadcast YouTube is not the only service that could have or need a "Manage Broadcast" button. So adding a way to make other service plugin able to use it. @@ -536,5 +555,6 @@ Add to the service object an url that lead to an updated service object hosted b Some services could support a protocol without supporting all the compatible codecs, so adding a new field like `supported_codecs` for audio and video may be needed. # Drawbacks +Dockstate from integration are not recoverable. # Additional Information From 1209d4e168e4f70ab7d08fb2d99e749c1276107c Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sat, 22 Oct 2022 22:01:13 +0200 Subject: [PATCH 08/36] Rework browser in frontend API --- text/0039-service-overhaul.md | 56 ++++++++--------------------------- 1 file changed, 12 insertions(+), 44 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index d3a8d26..fec00ca 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -150,67 +150,35 @@ The Front-end API needs to enable the possibility to access some `obs-browser` r Note: Free functions for each structure that requires it because of a "dynamic" will be also added. -##### Check availability -- `bool obs_frontend_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. -- `bool obs_frontend_browser_initialised()` will indicate if the CEF was initialised when the function is called. -##### Browser Widget -Internal OAuth (like Twitch and Restream) require that the Front-end API allow to add a browser widget to show the OAuth login page. - -This structure will be used to send everything needed to create this widget through the API. -```C++ -struct obs_frontend_browser_widget { - /* takes QLayout */ - void *layout; - const char *url; - bool enable_cookie; - DARRAY(struct obs_frontend_browser_connect) connection; -}; -``` -- `void *layout` will contain a `QLayout` pointer which will receive the browser widget. -- `const char *url` will contain the URL af the widget. -- `bool enable_cookie`, if true `panel_cookie` will be set on the widget rather than a `nullptr`. This will allow to keep cookie which is required. -- `DARRAY(struct obs_frontend_browser_connect) connection` is a array that will contain signal-slot connections that will be created on OBS Studio side. Required to allow url changed detection. +`bool obs_frontend_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. +`bool obs_frontend_browser_initialised()` will indicate if the CEF was initialised when the function is called required for OAuth through CEF. ```C++ struct obs_frontend_browser_connect { - const char *signal; - /* takes QObject */ - void *signal_receiver; - const char *slot; + void *qobject; // QObject + const char *slot; // SLOT() }; -``` - -`obs_frontend_add_browser_widget(struct obs_frontend_browser_widget *params)` is the function that will add a browser widget to the QLayout put in the structure. - -##### Browser dock -Twitch and Restream adds browser docks, so the Front-end API needs to allow this with many parameters. -This structure will be used to send everything needed to create those docks through the API. -```C++ -struct obs_frontend_browser_dock { - const char *id; - const char *title; +struct obs_frontend_browser_params { const char *url; - int width; - int height; - int min_width; - int min_height; bool enable_cookie; struct dstr startup_script; DARRAY(char *) force_popup_url; + DARRAY(struct obs_frontend_browser_connect) title_changed; + DARRAY(struct obs_frontend_browser_connect) url_changed; }; ``` -- `const char *id`, ID of the dock. -- `const char *title`, title of the dock. + - `const char *url`, URL of the dock. -- Dock default and minimum dimensions, every parameter under 80 is not used because 80 is the minimum set by OBS Studio. - `bool enable_cookie`, if true `panel_cookie` will be set on the dock rather than a `nullptr`. This will allow to keep cookie which is required. - `struct dstr startup_script` allow to set a startup script for the dock. - `DARRAY(char *) force_popup_url` allow to set a list of URL to force those to popup. +- `DARRAY(struct obs_frontend_browser_connect) title_changed` allow to connect QCefWidget `titleChanged()` signal to a slot +- `DARRAY(struct obs_frontend_browser_connect) url_changed` allow to connect QCefWidget `urlChanged()` signal to a slot -`void * obs_frontend_add_browser_dock(struct obs_frontend_browser_dock *params)` is the function that will add those browser docks. It returns a `QDockWidget`. For now those docks or not shown by default. +`bool obs_frontend_add_browser_dock(const char *id, struct obs_frontend_browser_dock *params)` is the function that will add those browser docks to the UI. -`void obs_frontend_remove_browser_dock(void *dock)` is the function meant to remove a browser dock. Need when disconnecting from a service. It takes QDockWidget, calls delete on dock and its corresponding QAction. +`void *obs_frontend_create_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). ##### Other functions `void obs_frontend_delete_browser_cookie(const char *url)` will remove cookies related to the given URL. From 21c999b38c21416b74959c7d0275b11954868305 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 23 Oct 2022 13:44:48 +0200 Subject: [PATCH 09/36] WIP --- text/0039-service-overhaul.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index fec00ca..ceee9b8 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -1,5 +1,3 @@ -***This RFC is dependent on [RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md).*** - # Summary - Make OBS able to accept third-party service plugins @@ -15,7 +13,7 @@ Before in OBS, in the Stream settings page, there was a combobox with two choice - Streaming Services - Custom Streaming Server -Each one had his own property view because those two are the two actual registered official services. +Each one had his own property view because those two are the two actual registered first-party services. This behavior could enable third-party service plugin to exist. Nowadays in OBS, this page show the list of services with many new elements showed of hidden depending of the selection (like recommended settings). With also Twitch and Restream OAuth integrations. And no use of the property views provided by `rtmp-services`. @@ -24,7 +22,7 @@ We need to restore the usage of property views and the possibility to create and It will also provide the ability for some stream services to be able to made their own plugin. -*Since using the service API was not possible with the actual OBS, any breaking change in it (if there are) will not impact any plugin for OBS.* +*Since using the Service API was not possible with the actual OBS, any breaking change in it (if there are) should not impact any plugin for OBS.* # Design @@ -523,6 +521,5 @@ Add to the service object an url that lead to an updated service object hosted b Some services could support a protocol without supporting all the compatible codecs, so adding a new field like `supported_codecs` for audio and video may be needed. # Drawbacks -Dockstate from integration are not recoverable. # Additional Information From d7b8aec8f75dd1d199ffbebc64752f85f41b62ef Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 2 Nov 2022 09:18:07 +0100 Subject: [PATCH 10/36] Start of the rewrite --- text/0039-service-overhaul.md | 324 +++++++++++----------------------- 1 file changed, 105 insertions(+), 219 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index ceee9b8..868a8f6 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -3,50 +3,26 @@ - Make OBS able to accept third-party service plugins - Register services with a unique id rather than a common one - A service can be provided with multiple protocols +- Stricter application of maximums and format compatibility (rate control, color format/space/range) - Separate Twitch, Restream and YouTube integration and make them plugins # Motivation -Actually even if OBS has the service API, developer can't create third-party service plugin because there is no mechanism to list those and show their own property view. +Actually even if OBS has the Service API, developer can't create third-party service plugin because there is no mechanism to use them at all. -Before in OBS, in the Stream settings page, there was a combobox with two choice: -- Streaming Services -- Custom Streaming Server - -Each one had his own property view because those two are the two actual registered first-party services. -This behavior could enable third-party service plugin to exist. +Before OBS in the Stream settings page, property views were used for services but with only two registered serices `rtmp-common` which containe all services and `rtmp-custom` for custom servers. Nowadays in OBS, this page show the list of services with many new elements showed of hidden depending of the selection (like recommended settings). With also Twitch and Restream OAuth integrations. And no use of the property views provided by `rtmp-services`. -We need to restore the usage of property views and the possibility to create and use service plugin. - -It will also provide the ability for some stream services to be able to made their own plugin. +This need to be refactored to re-introduce property for the service and for the protocol output. -*Since using the Service API was not possible with the actual OBS, any breaking change in it (if there are) should not impact any plugin for OBS.* +This will also provide the ability for some stream services to be able to made their own plugin. # Design -## UI -The Stream settings page and the auto-wizard will only contain a combo box listing registered services with also the "Show All" option. And the property view of the service will be shown under it. - -A "common" service is a service that is shown in the default service list. To keep this attributes with the UI, a flag will be added to Service API to allow services to not be in this list, so by default third-party plugins will be shown without the need to click on the "Show all" option. - -Note: every service that are not common will have the flag added in first-party plugins so they will not be shown by default. - -- Maximums are limits and one of those 3 choices: - 1. No option at all to bypass it - 2. Add a secret option that shall be added in `basic.ini` to bypass it - 3. Add a checkbox in the Advanced tab to bypass it -- Recommended settings will not provide bitrates and will be ignore-able through a checkbox in the service property. - -Supported resolutions should be enforced by default and can not be disabled. - -Service with an VOD/archive track feature will also have a flag. So this option will only be shown if the combo service-protocol is compatible with this feature. -This feature should be considered different from a multi-track feature. +## Settings UI -*Personal note: Some thought about also adding a flag for bandwidth test mode are also on my mind.* - -Many elements will be moved inside properties views like: +Many elements of the settings UI related to services will be moved inside services properties views like: - Stream key field - Username and password fields - OAuth connect disconnect button @@ -56,94 +32,137 @@ Many elements will be moved inside properties views like: - "Get Stream Key" button - "More Info" button -## Service plugins -### Issue -#### `rtmp-services` -This plugin provide services with only one protocol, so it needs to "register" service like YouTube multiple times (HLS & RTMPS). +Advanced network settings will also be replace by protocol output properties view below the service properties view. -And also OBS is too heavily dependent of it. +### Common, uncommon -#### Service integrations -Those integrations are added and use `rtmp-services` in a hacky way and not as plugins. +Spoiler: Streaming services will be individually registered, so no more `rtmp-common` that represent various services. -### Idea for new services plugins -#### `rtmp-services` -This plugin will be put in a state of deprecation. And be replaced and finally removed after one major release cycle. +So to hide services behind the "Show All" option, a flag (`OBS_SERVICE_UNCOMMON`) will be added to the Service API to indicate that the service is "uncommon". -Since OBS is heavily dependent of this plugin, many changes will be needed to remove this dependency. +So third-party services are shown in the list by default. -##### Conversion `rtmp_common` and `rtmp_custom` to new services -A way to convert user service config to a new one will be added. More detail below. +### Maximums and recommended -#### Service integrations +Maximums and supported resolutions will be strict (e.g. Twitch allows 6000 kbps, more will not be accepted), the UI will not allow to save incompatible settings. -Twitch, YouTube and Restream have their own integration in OBS with OAuth. But those need to be isolated as plugins (frontend if needed). +TODO: Think about recommendation -Those will plugins will provide the basic and OAuth version of the services as one services. +### Audio track(s) -If OBS is built without client ids and hashes, those plugins will be built without their integration. +The service needs to be able to report how it support audio tracks: +- Only one track +- Two with a archve track (VOD Track) +- Multi-track + +TODO IDEA: Enum with one track, archive track (VOD track) and multi-track (only custom service) since protocol makes usage of flags complicated. + +### Rate control -##### Conversion to new plugins -Everything related to auth in `basic.ini` will moved elsewhere. More detail below. +Services by default will ask for only CBR, some service may want something else or allow various. -##### About dock additions (idea/draft) -A new function in the Service API to load UI additions when starting OBS or applying setting. An unload may be needed or added to the destroy function. +Both service and encoder will need to be able to expose this to allow the UI to check for compatibility. -##### About "Manage Broadcast" in YouTube integration About dock additions (idea/draft) -YouTube adds a "broadcast manager", some services could also have the same need (e.g. PeerTube) so the button will be kept and a new function and a flag to the service API allowing this behavior will be added. +The UI will not allow to save incompatible settings. + +### Color format/space/range + +Aside from RTMP(S) (and FTL), newer protocol allow codecs that support 10-bit format and HDR. + +The UI will need to not allow service that do not work with selected settings. + +## Service plugins +### Service API + +Add missing get_properties2 and get_default2 functions for service + +### `custom-service` -#### `custom-service` This plugin is meant to provide a replacement for `rtmp_custom` type. If OBS need to be heavily dependent to one plugin, it shall be this one. -The protocol will be detected (or maybe forced set by the user). -Maybe properties will show depending of the protocol. +The protocol will be detected (or maybe forced set by the user, e.g. HLS). +Properties will change depending of the protocol. + +### `obs-services` -#### `obs-services` This plugin is meant to provide a replacements for `rtmp_common` type for services who doesn't have custom behavior or integration. This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `rtmp-common` id. Those services will be able to provide multiple protocols so no more "Service - HLS" and "Service - FTL". -If a certain protocol is not available, the plugin will not register the service if the service doesn't use another protocol. -If it does, the missing protocol will not be shown. [Thanks to RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md). +If a certain protocol is not available, the UI will not show it if the service doesn't support another protocol. +If it does, the missing protocol will not be shown. Those services should have no specific behavior like ingest management. -But can list with which codec they are compatible if needed. [Thanks to RFC 45](https://github.com/tytan652/rfcs/blob/protocol_api/text/0045-protocols-in-outputs-api.md) - In the end, adding streaming service will only be a JSON addition for this plugin. Only improvements will be accepted in the code of this plugin. -#### A plugin per special case +#### Service ID naming scheme +- Only lower case letter +- All prefixed by `obs-` in code, to avoid potential id conflict with streaming service third-party plugins. +- Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). +- Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new first-party plugin and keep the same id. The change will be seamless for the user. + +### Special case plugins + This/Those plugin(s) is/are meant to provide replacements for `rtmp_common` type for services which need a custom behavior. This/Those plugin(s) is/are meant to have implemented and register services which need a specific behavior like custom ingest with a unique id for each one. -#### Note about the plugins -- Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new plugin and keep the same id. The change will be seamless for the user. +### Conversion (WIP Needs a re-work) -### Conversion of services **Downgrade will break service configuration** A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the `service.json` to a new one. Auth integration config inside `basic.ini` will be also transfered to the new file. -## Other changes +### Integrations + +Twitch, YouTube and Restream have their own integration in OBS with OAuth. But those need to be isolated as plugins. -### Service API changes -- Add missing get_properties2 and get_default2 functions for service +Those will plugins will provide the basic and OAuth version of the services as one services. -### Property API addition -- Add a property to be able to show information with text label +If OBS is built without client ids and hashes, those plugins will be built without their integration. -Since the service API is in a way unusable by third-party, any breakage will only impact OBS built-in service plugins ( so only `rtmp-services`). +#### Dock state -### Service integrations new flow +Actually the dock state is global in the config, but with docks that appear depending on the service which is per profile which is still "also" the case with "old" integrations. -#### How docks and CEF widget for OAuth will be created +This which can lead to dock state losses between profile switching and exiting. The "old" integration actually store a dock state in the profile config and restore it after being the integration loaded is loaded. + +But making restoring a dock state from a plugin should be the last resort. +Making it per profile could avoid this. + +Integrations docks will be added after specific frontend event. +So after each of them the dock state needs to be restored. + +`OBS_FRONTEND_EVENT_FINISHING_LOADING` (finishing not finished) needs to be created +to allow adding docks and restore dock state before `OBS_FRONTEND_EVENT_FINISHED_LOADING` is emitted. + +Like this `OBS_FRONTEND_EVENT_FINISHED_LOADING` keep his meaning and does not get a restore dock state after it. + +#### Dock addition + +Integration plugins will need events to be able to add and remove service at the right moment. + +`OBS_FRONTEND_EVENT_FINISHING_LOADING` can be used when OBS startup to add docks. +`OBS_FRONTEND_EVENT_EXIT` to unload docks that need to be removed before exit. +`OBS_FRONTEND_EVENT_PROFILE_CHANGING` to unload dock before profile got changed. +`OBS_FRONTEND_EVENT_PROFILE_CHANGED` to load integration from the new loaded profile. + +Three new front-end event will be added (**Needs re-work for future multi-stream RFC**): +- `OBS_FRONTEND_EVENT_SERVICE_CHANGING` emitted before the service got changed (new id) like when a user switches between services. +- `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id) like when a user switches between services. +- `OBS_FRONTEND_EVENT_SERVICE_UPDATING` emitted before the service got a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. +- `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. + +Each service integration plugin will react to at least the two first to add or remove his related docks. + +#### Browser features The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks and generating widgets. Note: Free functions for each structure that requires it because of a "dynamic" will be also added. @@ -178,50 +197,19 @@ struct obs_frontend_browser_params { `void *obs_frontend_create_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). -##### Other functions `void obs_frontend_delete_browser_cookie(const char *url)` will remove cookies related to the given URL. -#### How docks will be added - -`OBS_FRONTEND_EVENT_FINISHED_LOADING` can be used when OBS startup to add docks. -`OBS_FRONTEND_EVENT_EXIT` to unload docks that need to be removed before exit. -`OBS_FRONTEND_EVENT_PROFILE_CHANGING` to unload dock before profile got changed. -`OBS_FRONTEND_EVENT_PROFILE_CHANGED` to load integration from the new loaded profile. - -Three new front-end event will be added: -- `OBS_FRONTEND_EVENT_SERVICE_CHANGING` emitted before the service got changed (new id) like when a user switches between services. -- `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id) like when a user switches between services. -- `OBS_FRONTEND_EVENT_SERVICE_UPDATING` emitted before the service got a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. -- `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. - -Each service integration plugin will react to at least the two first to add or remove his related docks. - -#### How docks will keep their state between session and profile -Actually the dock state is global in the config, but with docks that appear depending on the service which is per profile which is still the case with "old" integrations. - -This which can lead to dock state losses between profile switching and exiting. The "old" integration actually store a dock state in the profile config and restore it after being the integration loaded is loaded. - -But making restoring a dock state from a plugin should be the last resort. -Making it per profile could avoid this. - -Integrations docks will be added after specific frontend event. -So after each of them the dock state needs to be restored. - -`OBS_FRONTEND_EVENT_FINISHING_LOADING` (finishing not finished) needs to be created -to allow adding docks and restore dock state before `OBS_FRONTEND_EVENT_FINISHED_LOADING` is emitted. - -Like this `OBS_FRONTEND_EVENT_FINISHED_LOADING` keep his meaning and does not get a restore dock state after it. - -#### Manage Broadcast +#### Broadcast flow (WIP) YouTube is not the only service that could have or need a "Manage Broadcast" button. So adding a way to make other service plugin able to use it. - Add a unique callback meant to be called when the "Manage Broadcast" button is clicked. - Add a callback setter in the frontend-api which will make the button show up. This setter will always override the previous callback. - Add a callback unsetter in the frontend-api which will make the button hide. This unsetter will have the callback as a parameter to check if the set callback should really be unset. -### Service JSON format -#### Old version +## Service JSON + +### Old version The old actually looks like this: ```json @@ -298,17 +286,16 @@ The old actually looks like this: - `"fps"`: frame per seconds. - `"max bitrate"`: maximum video bitrate. -##### Issues with this format +#### Issues with this format - About `"output"`, OBS consider every service as RTMP if not added and it's not a recommended settings at all. It makes OBS use the right protocol for the service. Also this prevent a service of being multi-protocol. - About `"recommended"`, most of the options seems to H264 related - `"common"`, the name makes it not understandable at the first sight maybe adding some documention would be good thing. -#### New format (conversion in JSON Schema with changes is in WIP) -The new format will be parsable with a new interface library named `service-json-parser` to allow first-party plugins to read this format rather than recreating the wheel. +### New format (WIP) -The new format can be considered as the version 4. +The new format will rely on a more strict JSON schemas. -This format will be defined by JSON Schemas (Draft 2020-12): +Those JSON Schemas (Draft 2020-12) will be: - `commonPattern.schema.json`: regex pattern use multiple times - `protocolDefs.schema.json`: regex pattern and enum about protocols to ease protocol additions or removals in schemas - `service.schema.json`: define the service object itself (*still in WIP*) @@ -318,99 +305,11 @@ Those are all present in `0039-json-schemas` folder. *Documention in schemas are in progress, and a schema for integration plugin should also be made.* -JSON Schema allows to validate `services.json` (in `obs-services` case) when a PR is made against it. *Draft python script already made.* +JSON Schema allows to validate `services.json` (in `obs-services` case) when a PR is made against it. The use of JSON Schema allows to create specific additions for a specific plugin by creating a unique schema for it. - - - - -##### Example +#### Example Here is a example with `obs-services` in mind: ```json { @@ -500,26 +399,13 @@ Here is a example with `obs-services` in mind: } ``` -##### Advantages of this format +#### Advantages of this format - Recommended settings are really recommended settings. - Recommendation and maximums are two separated thing. - Some settings are now per protocol or per codec, this allow multi-protocol service to be registered under only one id. This will also need to a way to know which codec is used when applying settings. - Name can be changed without consequences. -##### Possible evolution -Add to the service object an url that lead to an updated service object hosted by the stream service itself. - -### Service ID naming scheme -- Only lower case letter -- Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). - -### Things to be reworked -- Verification with video and output settings to see (if not ignored) if the settings for the service are respected. - -### About codecs -Some services could support a protocol without supporting all the compatible codecs, so adding a new field like `supported_codecs` for audio and video may be needed. - # Drawbacks -# Additional Information +# Additional Information \ No newline at end of file From cf4c7a587e3da62e76f193432d00e8284938ca4a Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 15 Dec 2022 09:20:48 +0100 Subject: [PATCH 11/36] More WIP --- text/0039-service-overhaul.md | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 868a8f6..874f6b6 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -48,29 +48,6 @@ Maximums and supported resolutions will be strict (e.g. Twitch allows 6000 kbps, TODO: Think about recommendation -### Audio track(s) - -The service needs to be able to report how it support audio tracks: -- Only one track -- Two with a archve track (VOD Track) -- Multi-track - -TODO IDEA: Enum with one track, archive track (VOD track) and multi-track (only custom service) since protocol makes usage of flags complicated. - -### Rate control - -Services by default will ask for only CBR, some service may want something else or allow various. - -Both service and encoder will need to be able to expose this to allow the UI to check for compatibility. - -The UI will not allow to save incompatible settings. - -### Color format/space/range - -Aside from RTMP(S) (and FTL), newer protocol allow codecs that support 10-bit format and HDR. - -The UI will need to not allow service that do not work with selected settings. - ## Service plugins ### Service API @@ -207,6 +184,9 @@ YouTube is not the only service that could have or need a "Manage Broadcast" but - Add a callback unsetter in the frontend-api which will make the button hide. This unsetter will have the callback as a parameter to check if the set callback should really be unset. +#### Twitch VOD track +This will be the **only one** custom feature that will be allowed in OBS Studio UI code. + ## Service JSON ### Old version From 7cba267a6180acccca6ec2abb1d7e0890f685931 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 19 Jan 2023 12:35:57 +0100 Subject: [PATCH 12/36] Fixup --- text/0039-service-overhaul.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 874f6b6..b82e1b8 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -38,7 +38,7 @@ Advanced network settings will also be replace by protocol output properties vie Spoiler: Streaming services will be individually registered, so no more `rtmp-common` that represent various services. -So to hide services behind the "Show All" option, a flag (`OBS_SERVICE_UNCOMMON`) will be added to the Service API to indicate that the service is "uncommon". +So to hide services behind the "Show All" option, a flag meant for first-party services (`OBS_SERVICE_UNCOMMON`) will be added to the Service API to indicate that the service is "uncommon". So third-party services are shown in the list by default. From 92a73af03473fa577c9e914199b8f65c939ca828 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Tue, 24 Jan 2023 14:58:40 +0100 Subject: [PATCH 13/36] Update - More about dock state - Dock addition workflow rewrite - Browser API nitpicks - Broadcast flow fixup - Add some TODO - Fix typo --- text/0039-service-overhaul.md | 90 +++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index b82e1b8..05951ee 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -3,18 +3,17 @@ - Make OBS able to accept third-party service plugins - Register services with a unique id rather than a common one - A service can be provided with multiple protocols -- Stricter application of maximums and format compatibility (rate control, color format/space/range) - Separate Twitch, Restream and YouTube integration and make them plugins # Motivation Actually even if OBS has the Service API, developer can't create third-party service plugin because there is no mechanism to use them at all. -Before OBS in the Stream settings page, property views were used for services but with only two registered serices `rtmp-common` which containe all services and `rtmp-custom` for custom servers. +Before OBS in the Stream settings page, property views were used for services but with only two registered services `rtmp_common` which contain all services and `rtmp_custom` for custom servers. Nowadays in OBS, this page show the list of services with many new elements showed of hidden depending of the selection (like recommended settings). With also Twitch and Restream OAuth integrations. And no use of the property views provided by `rtmp-services`. -This need to be refactored to re-introduce property for the service and for the protocol output. +This need to be refactored to re-introduce property views for the service and for the protocol output. This will also provide the ability for some stream services to be able to made their own plugin. @@ -36,9 +35,9 @@ Advanced network settings will also be replace by protocol output properties vie ### Common, uncommon -Spoiler: Streaming services will be individually registered, so no more `rtmp-common` that represent various services. +Spoiler: Streaming services will be individually registered, so no more `rtmp_common` that represent various services. -So to hide services behind the "Show All" option, a flag meant for first-party services (`OBS_SERVICE_UNCOMMON`) will be added to the Service API to indicate that the service is "uncommon". +So to hide services behind the "Show All" option, a flag (`OBS_SERVICE_UNCOMMON`) meant for "first-party" services marked as "uncommon" will be added to the Service API to indicate that the service is "uncommon". So third-party services are shown in the list by default. @@ -46,31 +45,35 @@ So third-party services are shown in the list by default. Maximums and supported resolutions will be strict (e.g. Twitch allows 6000 kbps, more will not be accepted), the UI will not allow to save incompatible settings. +This will require to introduce in the Property API a way to indicate that the settings are not valid. + TODO: Think about recommendation ## Service plugins ### Service API -Add missing get_properties2 and get_default2 functions for service +Adding missing `get_properties2()` and `get_default2()` functions for service might be required. + +**For now all services shall be compatible with H264. Removing this limitation requires to rework of the Output settings UI which is plan for another RFC.** ### `custom-service` This plugin is meant to provide a replacement for `rtmp_custom` type. -If OBS need to be heavily dependent to one plugin, it shall be this one. +If OBS need to be heavily dependent to one service plugin, it shall be this one. The protocol will be detected (or maybe forced set by the user, e.g. HLS). -Properties will change depending of the protocol. +Property view will change depending of the protocol. ### `obs-services` This plugin is meant to provide a replacements for `rtmp_common` type for services who doesn't have custom behavior or integration. -This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `rtmp-common` id. +This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `rtmp_common` id. Those services will be able to provide multiple protocols so no more "Service - HLS" and "Service - FTL". -If a certain protocol is not available, the UI will not show it if the service doesn't support another protocol. +If a certain protocol is not available, the UI will not show it if the service doesn't support another protocol. Same goes for codecs. If it does, the missing protocol will not be shown. Those services should have no specific behavior like ingest management. @@ -82,7 +85,7 @@ Only improvements will be accepted in the code of this plugin. - Only lower case letter - All prefixed by `obs-` in code, to avoid potential id conflict with streaming service third-party plugins. - Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). -- Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new first-party plugin and keep the same id. The change will be seamless for the user. +- Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new first-party plugin and keep the same id. The change will be seamless for the user if done properly. ### Special case plugins @@ -90,12 +93,14 @@ This/Those plugin(s) is/are meant to provide replacements for `rtmp_common` type This/Those plugin(s) is/are meant to have implemented and register services which need a specific behavior like custom ingest with a unique id for each one. +**TODO: Write about maintenance** + ### Conversion (WIP Needs a re-work) **Downgrade will break service configuration** A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the `service.json` to a new one. -Auth integration config inside `basic.ini` will be also transfered to the new file. +Auth integration config inside `basic.ini` will be also transfered under a new section if in service settings. ### Integrations @@ -109,43 +114,54 @@ If OBS is built without client ids and hashes, those plugins will be built witho Actually the dock state is global in the config, but with docks that appear depending on the service which is per profile which is still "also" the case with "old" integrations. -This which can lead to dock state losses between profile switching and exiting. The "old" integration actually store a dock state in the profile config and restore it after being the integration loaded is loaded. +This can lead to dock state losses between profile switching and exiting. The "old" integration actually store a dock state in the profile config and restore it after the integration is is loaded. -But making restoring a dock state from a plugin should be the last resort. +But making restoring a dock state from a plugin should should not be considered at all. Making it per profile could avoid this. Integrations docks will be added after specific frontend event. So after each of them the dock state needs to be restored. -`OBS_FRONTEND_EVENT_FINISHING_LOADING` (finishing not finished) needs to be created -to allow adding docks and restore dock state before `OBS_FRONTEND_EVENT_FINISHED_LOADING` is emitted. +- `OBS_FRONTEND_EVENT_FINISHING_LOADING` (finish**ing** not finished) needs to be created to allow adding docks. And restore dock state before if docks are indeed added before `OBS_FRONTEND_EVENT_FINISHED_LOADING` is emitted. + +- `OBS_FRONTEND_EVENT_PROFILE_CHANGED`, profile dock state will be loaded after a profile is changes. + +Also they will be removed after specific frontend event. +So before each of them the dock state needs to be saved. + +- `OBS_FRONTEND_EVENT_PROFILE_CHANGING`, profile dock state will be saved before a profile is changes. -Like this `OBS_FRONTEND_EVENT_FINISHED_LOADING` keep his meaning and does not get a restore dock state after it. +- `OBS_FRONTEND_EVENT_EXIT`, profile dock state will be saved before while OBS is exiting. -#### Dock addition +#### Dock addition (**The concept needs to be tested**) -Integration plugins will need events to be able to add and remove service at the right moment. +Integration plugins will need events/signals to be able to add and remove their docks at the right moment. -`OBS_FRONTEND_EVENT_FINISHING_LOADING` can be used when OBS startup to add docks. -`OBS_FRONTEND_EVENT_EXIT` to unload docks that need to be removed before exit. -`OBS_FRONTEND_EVENT_PROFILE_CHANGING` to unload dock before profile got changed. -`OBS_FRONTEND_EVENT_PROFILE_CHANGED` to load integration from the new loaded profile. -Three new front-end event will be added (**Needs re-work for future multi-stream RFC**): -- `OBS_FRONTEND_EVENT_SERVICE_CHANGING` emitted before the service got changed (new id) like when a user switches between services. -- `OBS_FRONTEND_EVENT_SERVICE_CHANGED` emitted when the service was changed (new id) like when a user switches between services. -- `OBS_FRONTEND_EVENT_SERVICE_UPDATING` emitted before the service got a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. -- `OBS_FRONTEND_EVENT_SERVICE_UPDATED` emitted when the service had a parameter updated (no id change) like when a user has changed one of the available properties/settings of the actual service. +3 signals will be added to Core OBS signaling: -Each service integration plugin will react to at least the two first to add or remove his related docks. +- "service_create (ptr service)" +- "service_update (ptr service)" +- "service_destroy (ptr service)" + +A variant of `obs_service_create()` to spawn signal-less (and maybe even private) service will be needed to allow protocol checking in settings. + +The plugin will have to store if `OBS_FRONTEND_EVENT_FINISHED_LOADING` was passed or not. + +If created before `OBS_FRONTEND_EVENT_FINISHED_LOADING`, a front-event callback will be added to react to `OBS_FRONTEND_EVENT_FINISHING_LOADING` to add docks (if integration connected) and then removed itself. + +When created/updated (after `OBS_FRONTEND_EVENT_FINISHED_LOADING`) the service will add the docks (if integration connected). + +When `OBS_FRONTEND_EVENT_PROFILE_CHANGING` `OBS_FRONTEND_EVENT_EXIT` or the service is destroyed, docks will be removed (if integration connected). #### Browser features The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks and generating widgets. -Note: Free functions for each structure that requires it because of a "dynamic" will be also added. +Note: Free functions for each structure that requires it because of a "dynamic" type will be also added. `bool obs_frontend_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. -`bool obs_frontend_browser_initialised()` will indicate if the CEF was initialised when the function is called required for OAuth through CEF. + +CEF should be initialised after `OBS_FRONTEND_EVENT_FINISHED_LOADING`. ```C++ struct obs_frontend_browser_connect { @@ -158,8 +174,8 @@ struct obs_frontend_browser_params { bool enable_cookie; struct dstr startup_script; DARRAY(char *) force_popup_url; - DARRAY(struct obs_frontend_browser_connect) title_changed; - DARRAY(struct obs_frontend_browser_connect) url_changed; + DARRAY(struct obs_frontend_browser_connect) title_changed; + DARRAY(struct obs_frontend_browser_connect) url_changed; }; ``` @@ -170,7 +186,7 @@ struct obs_frontend_browser_params { - `DARRAY(struct obs_frontend_browser_connect) title_changed` allow to connect QCefWidget `titleChanged()` signal to a slot - `DARRAY(struct obs_frontend_browser_connect) url_changed` allow to connect QCefWidget `urlChanged()` signal to a slot -`bool obs_frontend_add_browser_dock(const char *id, struct obs_frontend_browser_dock *params)` is the function that will add those browser docks to the UI. +`bool obs_frontend_add_browser_dock(const char *id, const char *title, struct obs_frontend_browser_dock *params)` is the function that will add those browser docks to the UI. `void *obs_frontend_create_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). @@ -179,9 +195,9 @@ struct obs_frontend_browser_params { #### Broadcast flow (WIP) YouTube is not the only service that could have or need a "Manage Broadcast" button. So adding a way to make other service plugin able to use it. -- Add a unique callback meant to be called when the "Manage Broadcast" button is clicked. -- Add a callback setter in the frontend-api which will make the button show up. This setter will always override the previous callback. -- Add a callback unsetter in the frontend-api which will make the button hide. This unsetter will have the callback as a parameter to check if the set callback should really be unset. +- Add a callback bond to a service pointer meant to be called when the "Manage Broadcast" button is clicked. +- Add a callback setter in the frontend-api which will make the button show up. +- Add a callback unsetter in the frontend-api which disable the button. #### Twitch VOD track From 62ae2c8755389c80292756a166e19c99932f1334 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sat, 11 Feb 2023 13:43:54 +0100 Subject: [PATCH 14/36] JSON Schema update --- text/0039-json-schemas/codecDefs.json | 54 + .../commonPattern.schema.json | 23 - text/0039-json-schemas/examples/services.json | 2650 +++++++++++++++++ text/0039-json-schemas/obs-services.json | 64 + .../obs-services.schema.json | 45 - .../protocolCodecsMap.schema.json | 48 - text/0039-json-schemas/protocolDefs.json | 63 + .../protocolDefs.schema.json | 24 - text/0039-json-schemas/service.json | 309 ++ text/0039-json-schemas/service.schema.json | 128 - text/0039-service-overhaul.md | 102 +- 11 files changed, 3146 insertions(+), 364 deletions(-) create mode 100644 text/0039-json-schemas/codecDefs.json delete mode 100644 text/0039-json-schemas/commonPattern.schema.json create mode 100644 text/0039-json-schemas/examples/services.json create mode 100644 text/0039-json-schemas/obs-services.json delete mode 100644 text/0039-json-schemas/obs-services.schema.json delete mode 100644 text/0039-json-schemas/protocolCodecsMap.schema.json create mode 100644 text/0039-json-schemas/protocolDefs.json delete mode 100644 text/0039-json-schemas/protocolDefs.schema.json create mode 100644 text/0039-json-schemas/service.json delete mode 100644 text/0039-json-schemas/service.schema.json diff --git a/text/0039-json-schemas/codecDefs.json b/text/0039-json-schemas/codecDefs.json new file mode 100644 index 0000000..c1fcc9f --- /dev/null +++ b/text/0039-json-schemas/codecDefs.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://obsproject.com/schemas/codecDefs.json", + "title": "Codec Enums, Patterns and Properties", + "description": "Codec-related enums, patterns and properties used in OBS JSON Schemas", + "$comment": "Made to allow an easy way to add codec to schemas", + "$defs": { + "videoCodecEnum": { + "$comment": "Enumeration of video codecs", + "enum": ["h264","hevc","av1"] + }, + "audioCodecEnum": { + "$comment": "Enumeration of audio codecs", + "enum": ["aac","opus"] + }, + "codecProperties": { + "$comment": "Per-codec properties meant for obs-services schema", + "type": "object", + "properties": { + "h264": + { + "type": "object", + "title": "H264 Settings", + "description": "Properties related to the H264 codec", + "properties": { + "profile": { + "type": "string", + "title": "Profile", + "enum": [ "baseline", "main", "high" ] + }, + "keyint": { + "type": "integer", + "title": "Keyframe Interval (seconds)", + "minimum": 0 + }, + "bframes": + { + "type": "integer", + "title": "B-Frames", + "minimum": 0 + } + }, + "minProperties": 1 + }, + "obs_x264": { + "type": "string", + "title": "x264 Encoder Options", + "description": "Options meant for the x264 encoder implementation with the id 'obs_x264'", + "minLength": 1 + } + } + } + } +} diff --git a/text/0039-json-schemas/commonPattern.schema.json b/text/0039-json-schemas/commonPattern.schema.json deleted file mode 100644 index fd34bf7..0000000 --- a/text/0039-json-schemas/commonPattern.schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "Common Pattern", - "description": "Pattern used multiple times in OBS JSON Schemas", - "$defs": { - "linkPattern": { - "description": "Pattern to enforce HTTP(S) links", - "pattern": "^https?://" - }, - "codecPattern": { - "description": "Pattern to enforce lowercase and no whitecase on codec naming", - "pattern": "^[a-z0-9]+$" - }, - "resolutionPattern": { - "description": "Pattern for resolution without framerate", - "pattern": "^[0-9]+x[0-9]+$" - }, - "resolutionFrameratePattern": { - "description": "Pattern for resolution with framerate", - "pattern": "^[0-9]+x[0-9]+@[0-9]+$" - } - } -} diff --git a/text/0039-json-schemas/examples/services.json b/text/0039-json-schemas/examples/services.json new file mode 100644 index 0000000..5d395f6 --- /dev/null +++ b/text/0039-json-schemas/examples/services.json @@ -0,0 +1,2650 @@ +{ + "$schema": "../obs-services.json", + "format_version": 1, + "services": [ + { + "id": "loola", + "name": "Loola.tv", + "servers": [ + { + "name": "US East: Virginia", + "url": "rtmp://rtmp.loola.tv/push" + }, + { + "name": "EU Central: Germany", + "url": "rtmp://rtmp-eu.loola.tv/push" + }, + { + "name": "South America: Brazil", + "url": "rtmp://rtmp-sa.loola.tv/push" + }, + { + "name": "Asia/Pacific: Singapore", + "url": "rtmp://rtmp-sg.loola.tv/push" + }, + { + "name": "Middle East: Bahrain", + "url": "rtmp://rtmp-me.loola.tv/push" + } + ], + "maximums": { + "video_bitrate": { + "h264": 2500 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "lovecast", + "name": "Lovecast", + "servers": [ + { + "name": "Default", + "url": "rtmp://live-a.lovecastapp.com:5222/app" + } + ], + "supported_resolutions": [ + "1920x1080", + "1280x720" + ], + "maximums": { + "video_bitrate": { + "h264": 8000 + }, + "framerate": 30, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "luzento", + "name": "Luzento.com - RTMP", + "stream_key_link": "https://cms.luzento.com/dashboard/stream-key?from=OBS", + "servers": [ + { + "name": "Primary", + "url": "rtmp://ingest.luzento.com/live" + }, + { + "name": "Primary (Test)", + "url": "rtmp://ingest.luzento.com/test" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 256 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "vimm", + "name": "VIMM", + "servers": [ + { + "name": "Europe: Frankfurt", + "url": "rtmp://eu.vimm.tv/live" + }, + { + "name": "North America: Montreal", + "url": "rtmp://us.vimm.tv/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 8000 + }, + "audio_bitrate": { + "aac": 320 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "web_tv", + "name": "Web.TV", + "servers": [ + { + "name": "Primary", + "url": "rtmp://live3.origins.web.tv/liveext" + } + ], + "maximums": { + "video_bitrate": { + "h264": 3500 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "goodgame", + "name": "GoodGame.ru", + "servers": [ + { + "name": "Моscow", + "url": "rtmp://msk.goodgame.ru:1940/live" + } + ] + }, + { + "id": "youstreamer", + "name": "YouStreamer", + "stream_key_link": "https://www.app.youstreamer.com/stream/", + "servers": [ + { + "name": "Moscow", + "url": "rtmp://push.youstreamer.com/in/" + } + ] + }, + { + "id": "vaughn_live", + "name": "Vaughn Live / iNSTAGIB", + "servers": [ + { + "name": "US: Chicago, IL", + "url": "rtmp://live-ord.vaughnsoft.net/live" + }, + { + "name": "US: Vint Hill, VA", + "url": "rtmp://live-iad.vaughnsoft.net/live" + }, + { + "name": "US: Denver, CO", + "url": "rtmp://live-den.vaughnsoft.net/live" + }, + { + "name": "US: New York, NY", + "url": "rtmp://live-nyc.vaughnsoft.net/live" + }, + { + "name": "US: Miami, FL", + "url": "rtmp://live-mia.vaughnsoft.net/live" + }, + { + "name": "US: Seattle, WA", + "url": "rtmp://live-sea.vaughnsoft.net/live" + }, + { + "name": "EU: Amsterdam, NL", + "url": "rtmp://live-ams.vaughnsoft.net/live" + }, + { + "name": "EU: London, UK", + "url": "rtmp://live-lhr.vaughnsoft.net/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 15000 + }, + "audio_bitrate": { + "aac": 320 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "breakers_tv", + "name": "Breakers.TV", + "servers": [ + { + "name": "US: Chicago, IL", + "url": "rtmp://live-ord.vaughnsoft.net/live" + }, + { + "name": "US: Vint Hill, VA", + "url": "rtmp://live-iad.vaughnsoft.net/live" + }, + { + "name": "US: Denver, CO", + "url": "rtmp://live-den.vaughnsoft.net/live" + }, + { + "name": "US: New York, NY", + "url": "rtmp://live-nyc.vaughnsoft.net/live" + }, + { + "name": "US: Miami, FL", + "url": "rtmp://live-mia.vaughnsoft.net/live" + }, + { + "name": "US: Seattle, WA", + "url": "rtmp://live-sea.vaughnsoft.net/live" + }, + { + "name": "EU: Amsterdam, NL", + "url": "rtmp://live-ams.vaughnsoft.net/live" + }, + { + "name": "EU: London, UK", + "url": "rtmp://live-lhr.vaughnsoft.net/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 15000 + }, + "audio_bitrate": { + "aac": 320 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "facebook", + "name": "Facebook Live", + "common": true, + "stream_key_link": "https://www.facebook.com/live/producer?ref=OBS", + "servers": [ + { + "name": "Default", + "url": "rtmps://rtmp-api.facebook.com:443/rtmp/" + } + ], + "supported_resolutions": [ + "640x360@30", + "640x360@60", + "852x480@30", + "852x480@60", + "1280x720@30", + "1280x720@60", + "1920x1080@30", + "1920x1080@60" + ], + "maximums": { + "video_bitrate_matrix": { + "640x360@30": { + "h264": 1000 + }, + "640x360@60": { + "h264": 1500 + }, + "852x480@30": { + "h264": 2000 + }, + "852x480@60": { + "h264": 3000 + }, + "1280x720@30": { + "h264": 4000 + }, + "1280x720@60": { + "h264": 6000 + }, + "1920x1080@30": { + "h264": 6000 + }, + "1920x1080@60": { + "h264": 9000 + } + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "castr", + "name": "Castr.io", + "servers": [ + { + "name": "US-East (Chicago, IL)", + "url": "rtmp://cg.castr.io/static" + }, + { + "name": "US-East (New York, NY)", + "url": "rtmp://ny.castr.io/static" + }, + { + "name": "US-East (Miami, FL)", + "url": "rtmp://mi.castr.io/static" + }, + { + "name": "US-West (Seattle, WA)", + "url": "rtmp://se.castr.io/static" + }, + { + "name": "US-West (Los Angeles, CA)", + "url": "rtmp://la.castr.io/static" + }, + { + "name": "US-Central (Dallas, TX)", + "url": "rtmp://da.castr.io/static" + }, + { + "name": "NA-East (Toronto, CA)", + "url": "rtmp://qc.castr.io/static" + }, + { + "name": "SA (Sao Paulo, BR)", + "url": "rtmp://br.castr.io/static" + }, + { + "name": "EU-West (London, UK)", + "url": "rtmp://uk.castr.io/static" + }, + { + "name": "EU-Central (Frankfurt, DE)", + "url": "rtmp://fr.castr.io/static" + }, + { + "name": "Russia (Moscow)", + "url": "rtmp://ru.castr.io/static" + }, + { + "name": "Asia (Singapore)", + "url": "rtmp://sg.castr.io/static" + }, + { + "name": "Asia (India)", + "url": "rtmp://in.castr.io/static" + }, + { + "name": "Australia (Sydney)", + "url": "rtmp://au.castr.io/static" + }, + { + "name": "US Central", + "url": "rtmp://us-central.castr.io/static" + }, + { + "name": "US West", + "url": "rtmp://us-west.castr.io/static" + }, + { + "name": "US East", + "url": "rtmp://us-east.castr.io/static" + }, + { + "name": "US South", + "url": "rtmp://us-south.castr.io/static" + }, + { + "name": "South America", + "url": "rtmp://south-am.castr.io/static" + }, + { + "name": "EU Central", + "url": "rtmp://eu-central.castr.io/static" + }, + { + "name": "Singapore", + "url": "rtmp://sg-central.castr.io/static" + } + ], + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "boomstream", + "name": "Boomstream", + "servers": [ + { + "name": "Default", + "url": "rtmp://live.boomstream.com/live" + } + ] + }, + { + "id": "meridix", + "name": "Meridix Live Sports Platform", + "servers": [ + { + "name": "Primary", + "url": "rtmp://publish.meridix.com/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 3500 + } + } + }, + { + "id": "afreecatv", + "name": "AfreecaTV", + "servers": [ + { + "name": "Asia : Korea", + "url": "rtmp://rtmpmanager-freecat.afreeca.tv/app" + }, + { + "name": "North America : US East", + "url": "rtmp://rtmp-esu.afreecatv.com/app" + }, + { + "name": "North America : US West", + "url": "rtmp://rtmp-wsu.afreecatv.com/app" + }, + { + "name": "South America : Brazil", + "url": "rtmp://rtmp-brz.afreecatv.com/app" + }, + { + "name": "Europe : UK", + "url": "rtmp://rtmp-uk.afreecatv.com/app" + }, + { + "name": "Asia : Singapore", + "url": "rtmp://rtmp-sgp.afreecatv.com/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 8000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "cam4", + "name": "CAM4", + "servers": [ + { + "name": "CAM4", + "url": "rtmp://origin.cam4.com/cam4-origin-live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 3000 + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "profile": "baseline", + "keyint": 1 + } + } + }, + { + "id": "eplay", + "name": "ePlay", + "servers": [ + { + "name": "ePlay Primary", + "url": "rtmp://live.eplay.link/origin" + } + ], + "maximums": { + "video_bitrate": { + "h264": 7500 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "picarto", + "name": "Picarto", + "servers": [ + { + "name": "Autoselect closest server", + "url": "rtmp://live.us.picarto.tv/golive" + }, + { + "name": "Los Angeles, USA", + "url": "rtmp://live.us-losangeles.picarto.tv/golive" + }, + { + "name": "Dallas, USA", + "url": "rtmp://live.us-dallas.picarto.tv/golive" + }, + { + "name": "Miami, USA", + "url": "rtmp://live.us-miami.picarto.tv/golive" + }, + { + "name": "New York, USA", + "url": "rtmp://live.us-newyork.picarto.tv/golive" + }, + { + "name": "Europe", + "url": "rtmp://live.eu-west1.picarto.tv/golive" + } + ], + "maximums": { + "video_bitrate": { + "h264": 3500 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "livestream", + "name": "Livestream", + "servers": [ + { + "name": "Primary", + "url": "rtmp://rtmpin.livestreamingest.com/rtmpin" + } + ] + }, + { + "id": "uscreen", + "name": "Uscreen", + "servers": [ + { + "name": "Default", + "url": "rtmp://global-live.uscreen.app:5222/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 8000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "stripchat", + "name": "Stripchat", + "servers": [ + { + "name": "Auto", + "url": "rtmp://s-sd.doppiocdn.com/ext" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + }, + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "camsoda", + "name": "CamSoda", + "servers": [ + { + "name": "North America", + "url": "rtmp://obs-ingest-na.livemediahost.com/cam_obs" + }, + { + "name": "South America", + "url": "rtmp://obs-ingest-sa.livemediahost.com/cam_obs" + }, + { + "name": "Asia", + "url": "rtmp://obs-ingest-as.livemediahost.com/cam_obs" + }, + { + "name": "Europe", + "url": "rtmp://obs-ingest-eu.livemediahost.com/cam_obs" + }, + { + "name": "Oceania", + "url": "rtmp://obs-ingest-oc.livemediahost.com/cam_obs" + } + ], + "supported_resolutions": [ + "1920x1080", + "1280x720", + "852x480", + "480x360" + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "framerate": 30, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "chartubate", + "name": "Chaturbate", + "servers": [ + { + "name": "Global Main Fastest - Recommended", + "url": "rtmp://live.stream.highwebmedia.com/live-origin" + }, + { + "name": "Global Backup", + "url": "rtmp://live-backup.stream.highwebmedia.com/live-origin" + }, + { + "name": "US West: Seattle, WA", + "url": "rtmp://live-sea.stream.highwebmedia.com/live-origin" + }, + { + "name": "US West: Phoenix, AZ", + "url": "rtmp://live-phx.stream.highwebmedia.com/live-origin" + }, + { + "name": "US Central: Salt Lake City, UT", + "url": "rtmp://live-slc.stream.highwebmedia.com/live-origin" + }, + { + "name": "US Central: Chicago, IL", + "url": "rtmp://live-chi.stream.highwebmedia.com/live-origin" + }, + { + "name": "US East: Atlanta, GA", + "url": "rtmp://live-atl.stream.highwebmedia.com/live-origin" + }, + { + "name": "US East: Ashburn, VA", + "url": "rtmp://live-ash.stream.highwebmedia.com/live-origin" + }, + { + "name": "South America: Sao Paulo, Brazil", + "url": "rtmp://live-gru.stream.highwebmedia.com/live-origin" + }, + { + "name": "EU: Amsterdam, NL", + "url": "rtmp://live-nld.stream.highwebmedia.com/live-origin" + }, + { + "name": "EU: Alblasserdam, NL", + "url": "rtmp://live-alb.stream.highwebmedia.com/live-origin" + }, + { + "name": "EU: Frankfurt, DE", + "url": "rtmp://live-fra.stream.highwebmedia.com/live-origin" + }, + { + "name": "EU: Belgrade, Serbia", + "url": "rtmp://live-srb.stream.highwebmedia.com/live-origin" + }, + { + "name": "Asia: Singapore", + "url": "rtmp://live-sin.stream.highwebmedia.com/live-origin" + }, + { + "name": "Asia: Tokyo, Japan", + "url": "rtmp://live-nrt.stream.highwebmedia.com/live-origin" + }, + { + "name": "Australia: Sydney", + "url": "rtmp://live-syd.stream.highwebmedia.com/live-origin" + } + ], + "maximums": { + "video_bitrate": { + "h264": 50000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "wpstream", + "name": "WpStream", + "more_info_link": "https://wpstream.net/obs-more-info", + "stream_key_link": "https://wpstream.net/obs-get-stream-key", + "servers": [ + { + "name": "Closest server - Automatic", + "url": "rtmp://ingest.wpstream.net/golive" + }, + { + "name": "North America", + "url": "rtmp://ingest-na.wpstream.net/golive" + }, + { + "name": "Europe", + "url": "rtmp://ingest-eu.wpstream.net/golive" + }, + { + "name": "Asia", + "url": "rtmp://ingest-as.wpstream.net/golive" + }, + { + "name": "South America", + "url": "rtmp://ingest-sa.wpstream.net/golive" + }, + { + "name": "Australia & Oceania", + "url": "rtmp://ingest-au.wpstream.net/golive" + } + ], + "maximums": { + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "twitter", + "name": "Twitter", + "common": true, + "stream_key_link": "https://studio.twitter.com/producer/sources", + "servers": [ + { + "name": "US West: California", + "url": "rtmp://ca.pscp.tv:80/x" + }, + { + "name": "US West: Oregon", + "url": "rtmp://or.pscp.tv:80/x" + }, + { + "name": "US East: Virginia", + "url": "rtmp://va.pscp.tv:80/x" + }, + { + "name": "South America: Brazil", + "url": "rtmp://br.pscp.tv:80/x" + }, + { + "name": "EU West: France", + "url": "rtmp://fr.pscp.tv:80/x" + }, + { + "name": "EU West: Ireland", + "url": "rtmp://ie.pscp.tv:80/x" + }, + { + "name": "EU Central: Germany", + "url": "rtmp://de.pscp.tv:80/x" + }, + { + "name": "Asia/Pacific: Australia", + "url": "rtmp://au.pscp.tv:80/x" + }, + { + "name": "Asia/Pacific: India", + "url": "rtmp://in.pscp.tv:80/x" + }, + { + "name": "Asia/Pacific: Japan", + "url": "rtmp://jp.pscp.tv:80/x" + }, + { + "name": "Asia/Pacific: Korea", + "url": "rtmp://kr.pscp.tv:80/x" + }, + { + "name": "Asia/Pacific: Singapore", + "url": "rtmp://sg.pscp.tv:80/x" + } + ], + "maximums": { + "video_bitrate": { + "h264": 12000 + }, + "framerate": 60, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "keyint": 3 + } + } + }, + { + "id": "switchboard_live", + "name": "Switchboard Live", + "servers": [ + { + "name": "Global Zone (geo based)", + "url": "rtmp://ingest-global.switchboard.zone/live" + }, + { + "name": "US Zone (geo based)", + "url": "rtmp://ingest-us.switchboard.zone/live" + }, + { + "name": "US West", + "url": "rtmp://ingest-us-west.switchboard.zone/live" + }, + { + "name": "US East", + "url": "rtmp://ingest-us-east.switchboard.zone/live" + }, + { + "name": "US Central", + "url": "rtmp://ingest-us-central.switchboard.zone/live" + }, + { + "name": "South America", + "url": "rtmp://ingest-sa.switchboard.zone/live" + }, + { + "name": "EU (auto)", + "url": "rtmp://ingest-eu.switchboard.zone/live" + }, + { + "name": "Australia", + "url": "rtmp://ingest-au.switchboard.zone/live" + }, + { + "name": "APAC (auto)", + "url": "rtmp://ingest-asia.switchboard.zone/live" + }, + { + "name": "UK", + "url": "rtmp://ingest-uk.switchboard.zone/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + } + } + }, + { + "id": "looch", + "name": "Looch", + "servers": [ + { + "name": "Primary Looch ingest server", + "url": "rtmp://ingest.looch.tv/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "eventials", + "name": "Eventials", + "servers": [ + { + "name": "Default", + "url": "rtmp://transmission.eventials.com/eventialsLiveOrigin" + } + ], + "maximums": { + "video_bitrate": { + "h264": 900 + }, + "audio_bitrate": { + "aac": 96 + } + }, + "recommended": { + "h264": { + "profile": "baseline", + "keyint": 1 + } + } + }, + { + "id": "eventlive", + "name": "EventLive.pro", + "servers": [ + { + "name": "Default", + "url": "rtmp://go.eventlive.pro/live" + } + ], + "supported_resolutions": [ + "1920x1080", + "1280x720" + ], + "maximums": { + "video_bitrate": { + "h264": 3000 + }, + "framerate": 30, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "lahzenegar", + "name": "Lahzenegar - StreamG | لحظه‌نگار - استریمجی", + "servers": [ + { + "name": "Primary", + "url": "rtmp://rtmp.lahzecdn.com/pro" + }, + { + "name": "Iran", + "url": "rtmp://rtmp-iran.lahzecdn.com/pro" + } + ], + "maximums": { + "video_bitrate": { + "h264": 4000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "mylive", + "name": "MyLive", + "servers": [ + { + "name": "Default", + "url": "rtmp://stream.mylive.in.th/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 7000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "trovo", + "name": "Trovo", + "stream_key_link": "https://studio.trovo.live/mychannel/stream", + "servers": [ + { + "name": "Default", + "url": "rtmp://livepush.trovo.live/live/" + } + ], + "maximums": { + "video_bitrate": { + "h264": 9000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "mixcloud", + "name": "Mixcloud", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.mixcloud.com/broadcast" + } + ], + "supported_resolutions": [ + "1280x720", + "852x480", + "480x360" + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "framerate": 30, + "audio_bitrate": { + "aac": 320 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "sermonaudio", + "name": "SermonAudio Cloud", + "servers": [ + { + "name": "Primary", + "url": "rtmp://webcast.sermonaudio.com/sa" + } + ], + "maximums": { + "video_bitrate": { + "h264": 2000 + }, + "audio_bitrate": { + "aac": 128 + } + } + }, + { + "id": "vimeo", + "name": "Vimeo", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.cloud.vimeo.com/live" + } + ] + }, + { + "id": "aparat", + "name": "Aparat", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.cdn.asset.aparat.com:443/event" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 320 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "kakaotv", + "name": "KakaoTV", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.play.kakao.com/kakaotv" + } + ], + "maximums": { + "video_bitrate": { + "h264": 8000 + }, + "audio_bitrate": { + "aac": 192 + } + } + }, + { + "id": "piczel_tv", + "name": "Piczel.tv", + "servers": [ + { + "name": "Default", + "url": "rtmp://piczel.tv:1935/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 2500 + }, + "audio_bitrate": { + "aac": 256 + } + }, + "recommended": { + "h264": { + "keyint": 4 + }, + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "stage_ten", + "name": "STAGE TEN", + "servers": [ + { + "name": "STAGE TEN", + "url": "rtmps://app-rtmp.stageten.tv:443/stageten" + } + ], + "maximums": { + "video_bitrate": { + "h264": 4000 + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "profile": "baseline", + "keyint": 2 + } + } + }, + { + "id": "dlive", + "name": "DLive", + "servers": [ + { + "name": "Default", + "url": "rtmp://stream.dlive.tv/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "lightcast_com", + "name": "Lightcast.com", + "servers": [ + { + "name": "North America / East", + "url": "rtmp://us-east.live.lightcast.com/202E1F/default" + }, + { + "name": "North America / West", + "url": "rtmp://us-west.live.lightcast.com/202E1F/default" + }, + { + "name": "Europe / Amsterdam", + "url": "rtmp://europe.live.lightcast.com/202E1F/default" + }, + { + "name": "Europe / Frankfurt", + "url": "rtmp://europe-fra.live.lightcast.com/202E1F/default" + }, + { + "name": "Europe / Stockholm", + "url": "rtmp://europe-sto.live.lightcast.com/202E1F/default" + }, + { + "name": "Asia / Hong Kong", + "url": "rtmp://asia.live.lightcast.com/202E1F/default" + }, + { + "name": "Australia / Sydney", + "url": "rtmp://australia.live.lightcast.com/202E1F/default" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "bongacams", + "name": "Bongacams", + "servers": [ + { + "name": "Automatic / Default", + "url": "rtmp://auto.origin.gnsbc.com:1934/live" + }, + { + "name": "Automatic / Backup", + "url": "rtmp://origin.bcvidorigin.com:1934/live" + }, + { + "name": "Europe", + "url": "rtmp://z-eu.origin.gnsbc.com:1934/live" + }, + { + "name": "North America", + "url": "rtmp://z-us.origin.gnsbc.com:1934/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "chathostess", + "name": "Chathostess", + "servers": [ + { + "name": "Chathostess - Backup", + "url": "rtmp://wowza05.foobarweb.com/cmschatsys_video" + } + ], + "maximums": { + "video_bitrate": { + "h264": 3600 + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "onlyfans", + "name": "OnlyFans.com", + "servers": [ + { + "name": "USA", + "url": "rtmp://route0.onlyfans.com/live" + }, + { + "name": "Europe", + "url": "rtmp://route0-dc2.onlyfans.com/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 2500 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + }, + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "steam", + "name": "Steam", + "servers": [ + { + "name": "Default", + "url": "rtmp://ingest-rtmp.broadcast.steamcontent.com/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 7000 + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + } + } + }, + { + "id": "konduit", + "name": "Konduit.live", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.konduit.live/live" + } + ], + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "loco", + "name": "LOCO", + "servers": [ + { + "name": "Default", + "url": "rtmp://ivory-ingest.getloconow.com:1935/stream" + } + ], + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "niconico-premium", + "name": "niconico, premium member (ニコニコ生放送 プレミアム会員)", + "servers": [ + { + "name": "Default", + "url": "rtmp://aliveorigin.dmc.nico/named_input" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5808 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + }, + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "niconico-free", + "name": "niconico, free member (ニコニコ生放送 一般会員)", + "servers": [ + { + "name": "Default", + "url": "rtmp://aliveorigin.dmc.nico/named_input" + } + ], + "maximums": { + "video_bitrate": { + "h264": 904 + }, + "audio_bitrate": { + "aac": 96 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + }, + "obs_x264": "tune=zerolatency" + } + }, + { + "id": "wasd_tv", + "name": "WASD.TV", + "servers": [ + { + "name": "Automatic", + "url": "rtmp://push.rtmp.wasd.tv/live" + }, + { + "name": "Russia, Moscow", + "url": "rtmp://ru-moscow.rtmp.wasd.tv/live" + }, + { + "name": "Germany, Frankfurt", + "url": "rtmp://de-frankfurt.rtmp.wasd.tv/live" + }, + { + "name": "Finland, Helsinki", + "url": "rtmp://fi-helsinki.rtmp.wasd.tv/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 10000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "xlovecam", + "name": "XLoveCam.com", + "servers": [ + { + "name": "Europe(main)", + "url": "rtmp://nl.eu.stream.xlove.com/performer-origin" + }, + { + "name": "Europe(Romania)", + "url": "rtmp://ro.eu.stream.xlove.com/performer-origin" + }, + { + "name": "Europe(Russia)", + "url": "rtmp://ru.eu.stream.xlove.com/performer-origin" + }, + { + "name": "North America(US East)", + "url": "rtmp://usec.na.stream.xlove.com/performer-origin" + }, + { + "name": "North America(US West)", + "url": "rtmp://uswc.na.stream.xlove.com/performer-origin" + }, + { + "name": "North America(Canada)", + "url": "rtmp://ca.na.stream.xlove.com/performer-origin" + }, + { + "name": "South America", + "url": "rtmp://co.sa.stream.xlove.com/performer-origin" + }, + { + "name": "Asia", + "url": "rtmp://sg.as.stream.xlove.com/performer-origin" + } + ], + "recommended": { + "obs_x264": "scenecut=0" + } + }, + { + "id": "angelthump", + "name": "AngelThump", + "servers": [ + { + "name": "Auto", + "url": "rtmp://ingest.angelthump.com/live" + }, + { + "name": "New York 3", + "url": "rtmp://nyc-ingest.angelthump.com:1935/live" + }, + { + "name": "San Francisco 2", + "url": "rtmp://sfo-ingest.angelthump.com:1935/live" + }, + { + "name": "Singapore 1", + "url": "rtmp://sgp-ingest.angelthump.com:1935/live" + }, + { + "name": "London 1", + "url": "rtmp://lon-ingest.angelthump.com:1935/live" + }, + { + "name": "Frankfurt 1", + "url": "rtmp://fra-ingest.angelthump.com:1935/live" + }, + { + "name": "Toronto 1", + "url": "rtmp://tor-ingest.angelthump.com:1935/live" + }, + { + "name": "Bangalore 1", + "url": "rtmp://blr-ingest.angelthump.com:1935/live" + }, + { + "name": "Amsterdam 3", + "url": "rtmp://ams-ingest.angelthump.com:1935/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 3500 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + } + } + }, + { + "id": "api_video", + "name": "api.video", + "servers": [ + { + "name": "Default", + "url": "rtmp://broadcast.api.video/s" + } + ], + "maximums": { + "video_bitrate": { + "h264": 20000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "mux", + "name": "Mux", + "servers": [ + { + "name": "Global (RTMPS)", + "url": "rtmps://global-live.mux.com:443/app" + }, + { + "name": "Global (RTMP)", + "url": "rtmp://global-live.mux.com:5222/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "viloud", + "name": "Viloud", + "servers": [ + { + "name": "Default", + "url": "rtmp://live.viloud.tv:5222/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "myfreecams", + "name": "MyFreeCams", + "servers": [ + { + "name": "Automatic", + "url": "rtmp://publish.myfreecams.com/NxServer" + }, + { + "name": "Australia", + "url": "rtmp://publish-syd.myfreecams.com/NxServer" + }, + { + "name": "East Asia", + "url": "rtmp://publish-tyo.myfreecams.com/NxServer" + }, + { + "name": "Europe (East)", + "url": "rtmp://publish-buh.myfreecams.com/NxServer" + }, + { + "name": "Europe (West)", + "url": "rtmp://publish-ams.myfreecams.com/NxServer" + }, + { + "name": "North America (East Coast)", + "url": "rtmp://publish-ord.myfreecams.com/NxServer" + }, + { + "name": "North America (West Coast)", + "url": "rtmp://publish-tuk.myfreecams.com/NxServer" + }, + { + "name": "South America", + "url": "rtmp://publish-sao.myfreecams.com/NxServer" + } + ], + "maximums": { + "video_bitrate": { + "h264": 10000 + }, + "framerate": 60, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 1 + }, + "obs_x264": "tune=zerolatency scenecut=0" + } + }, + { + "id": "polystreamer", + "name": "PolyStreamer.com", + "servers": [ + { + "name": "Auto-select closest server", + "url": "rtmp://live.polystreamer.com/live" + }, + { + "name": "United States - West", + "url": "rtmp://us-west.live.polystreamer.com/live" + }, + { + "name": "United States - East", + "url": "rtmp://us-east.live.polystreamer.com/live" + }, + { + "name": "Australia", + "url": "rtmp://aus.live.polystreamer.com/live" + }, + { + "name": "India", + "url": "rtmp://ind.live.polystreamer.com/live" + }, + { + "name": "Germany", + "url": "rtmp://deu.live.polystreamer.com/live" + }, + { + "name": "Japan", + "url": "rtmp://jpn.live.polystreamer.com/live" + }, + { + "name": "Singapore", + "url": "rtmp://sgp.live.polystreamer.com/live" + } + ], + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "glimesh", + "name": "Glimesh", + "stream_key_link": "https://glimesh.tv/users/settings/stream", + "servers": [ + { + "name": "North America - Chicago, United States", + "protocol": "FTL", + "url": "ingest.kord.live.glimesh.tv" + }, + { + "name": "North America - New York, United States", + "protocol": "FTL", + "url": "ingest.kjfk.live.glimesh.tv" + }, + { + "name": "North America - San Francisco, United States", + "protocol": "FTL", + "url": "ingest.ksfo.live.glimesh.tv" + }, + { + "name": "North America - Toronto, Canada", + "protocol": "FTL", + "url": "ingest.cyyz.live.glimesh.tv" + }, + { + "name": "South America - Sao Paulo, Brazil", + "protocol": "FTL", + "url": "ingest.sbgr.live.glimesh.tv" + }, + { + "name": "Europe - Amsterdam, Netherlands", + "protocol": "FTL", + "url": "ingest.eham.live.glimesh.tv" + }, + { + "name": "Europe - Frankfurt, Germany", + "protocol": "FTL", + "url": "ingest.eddf.live.glimesh.tv" + }, + { + "name": "Europe - London, United Kingdom", + "protocol": "FTL", + "url": "ingest.egll.live.glimesh.tv" + }, + { + "name": "Asia - Bangalore, India", + "protocol": "FTL", + "url": "ingest.vobl.live.glimesh.tv" + }, + { + "name": "Asia - Singapore", + "protocol": "FTL", + "url": "ingest.wsss.live.glimesh.tv" + }, + { + "name": "Australia - Sydney, Australia", + "protocol": "FTL", + "url": "ingest.yssy.live.glimesh.tv" + }, + { + "name": "North America - Chicago, United States", + "url": "rtmp://ingest.kord.live.glimesh.tv" + }, + { + "name": "North America - New York, United States", + "url": "rtmp://ingest.kjfk.live.glimesh.tv" + }, + { + "name": "North America - San Francisco, United States", + "url": "rtmp://ingest.ksfo.live.glimesh.tv" + }, + { + "name": "North America - Toronto, Canada", + "url": "rtmp://ingest.cyyz.live.glimesh.tv" + }, + { + "name": "South America - Sao Paulo, Brazil", + "url": "rtmp://ingest.sbgr.live.glimesh.tv" + }, + { + "name": "Europe - Amsterdam, Netherlands", + "url": "rtmp://ingest.eham.live.glimesh.tv" + }, + { + "name": "Europe - Frankfurt, Germany", + "url": "rtmp://ingest.eddf.live.glimesh.tv" + }, + { + "name": "Europe - London, United Kingdom", + "url": "rtmp://ingest.egll.live.glimesh.tv" + }, + { + "name": "Asia - Bangalore, India", + "url": "rtmp://ingest.vobl.live.glimesh.tv" + }, + { + "name": "Asia - Singapore", + "url": "rtmp://ingest.wsss.live.glimesh.tv" + }, + { + "name": "Australia - Sydney, Australia", + "url": "rtmp://ingest.yssy.live.glimesh.tv" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "opus": 160, + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "openrec_tv", + "name": "OPENREC.tv - Premium member (プレミアム会員)", + "stream_key_link": "https://www.openrec.tv/login?keep_login=true&url=https://www.openrec.tv/dashboard/live?from=obs", + "servers": [ + { + "name": "Default", + "url": "rtmp://a.station.openrec.tv:1935/live1" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "nanostream", + "name": "nanoStream Cloud / bintu", + "more_info_link": "https://www.nanocosmos.de/obs", + "stream_key_link": "https://bintu-cloud-frontend.nanocosmos.de/organisation", + "servers": [ + { + "name": "bintu-stream global ingest (rtmp)", + "url": "rtmp://bintu-stream.nanocosmos.de/live" + }, + { + "name": "bintu-stream global ingest (rtmps)", + "url": "rtmps://bintu-stream.nanocosmos.de:1937/live" + }, + { + "name": "bintu-vtrans global ingest with transcoding/ABR (rtmp)", + "url": "rtmp://bintu-vtrans.nanocosmos.de/live" + }, + { + "name": "bintu-vtrans global ingest with transcoding/ABR (rtmps)", + "url": "rtmps://bintu-vtrans.nanocosmos.de:1937/live" + }, + { + "name": "bintu-stream Europe (EU)", + "url": "rtmp://bintu-stream-eu.nanocosmos.de/live" + }, + { + "name": "bintu-stream USA West (USW)", + "url": "rtmp://bintu-stream-usw.nanocosmos.de/live" + }, + { + "name": "bintu-stream US East (USE)", + "url": "rtmp://bintu-stream-use.nanocosmos.de/live" + }, + { + "name": "bintu-stream Asia South (ASS)", + "url": "rtmp://bintu-stream-ass.nanocosmos.de/live" + }, + { + "name": "bintu-stream Australia (AU)", + "url": "rtmp://bintu-stream-au.nanocosmos.de/live" + }, + { + "name": "bintu-vtrans Europe (EU)", + "url": "rtmp://bintu-vtrans-eu.nanocosmos.de/live" + }, + { + "name": "bintu-vtrans USA West (USW)", + "url": "rtmp://bintu-vtrans-usw.nanocosmos.de/live" + }, + { + "name": "bintu-vtrans US East (USE)", + "url": "rtmp://bintu-vtrans-use.nanocosmos.de/live" + }, + { + "name": "bintu-vtrans Asia South (ASS)", + "url": "rtmp://bintu-vtrans-ass.nanocosmos.de/live" + }, + { + "name": "bintu-vtrans Australia (AU)", + "url": "rtmp://bintu-vtrans-au.nanocosmos.de/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "baseline", + "keyint": 2 + }, + "obs_x264": "tune=zerolatency b-pyramid=0 scenecut=0" + } + }, + { + "id": "bilibili", + "name": "Bilibili Live - RTMP | 哔哩哔哩直播 - RTMP", + "more_info_link": "https://link.bilibili.com/p/help/index#/tools-tutorial?id=9", + "stream_key_link": "https://link.bilibili.com/p/center/index#/my-room/start-live", + "servers": [ + { + "name": "Default | 默认", + "url": "rtmp://live-push.bilivideo.com/live-bvc/" + } + ] + }, + { + "id": "volume_com", + "name": "Volume.com", + "stream_key_link": "https://volume.com/b?show_key=1&webrtc=0", + "servers": [ + { + "name": "Default - Recommended", + "url": "rtmp://live.volume.com/live-origin" + }, + { + "name": "US - West", + "url": "rtmp://live-pdx.volume.com/live-origin" + }, + { + "name": "US - East", + "url": "rtmp://live-ash.volume.com/live-origin" + } + ], + "maximums": { + "video_bitrate": { + "h264": 20000 + }, + "framerate": 60 + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "boxcast", + "name": "BoxCast", + "stream_key_link": "https://dashboard.boxcast.com/#/sources", + "servers": [ + { + "name": "BoxCast", + "url": "rtmp://rtmp.boxcast.com/live" + } + ] + }, + { + "id": "disciple", + "name": "Disciple Media", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.disciplemedia.com/b-fme" + } + ] + }, + { + "id": "jio_games", + "name": "Jio Games", + "servers": [ + { + "name": "Primary", + "url": "rtmp://livepub1.api.engageapps.jio/live" + }, + { + "name": "Secondary", + "url": "rtmp://livepub2.api.engageapps.jio/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 32000 + }, + "audio_bitrate": { + "aac": 256 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "kuaishou", + "name": "Kuaishou Live", + "stream_key_link": "https://studio.kuaishou.com/live/list", + "servers": [ + { + "name": "Default", + "url": "rtmp://open-push.voip.yximgs.com/gifshow/" + }, + { + "name": "North America", + "url": "rtmp://tx.push.yximgs.com/live/" + } + ] + }, + { + "id": "ultreon", + "name": "Utreon", + "servers": [ + { + "name": "Default", + "url": "rtmp://live.utreon.com:5222/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "autistici_org", + "name": "Autistici.org Live", + "servers": [ + { + "name": "Default", + "url": "rtmp://live.autistici.org/ingest" + } + ], + "maximums": { + "video_bitrate": { + "h264": 2500 + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "phonelivestreaming", + "name": "PhoneLiveStreaming", + "stream_key_link": "https://app.phonelivestreaming.com/media/rtmp", + "servers": [ + { + "name": "PhoneLiveStreaming", + "url": "rtmp://live.phonelivestreaming.com/live/" + } + ], + "maximums": { + "video_bitrate": { + "h264": 128 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "manyvids", + "name": "ManyVids", + "servers": [ + { + "name": "Default", + "url": "rtmp://rtmp.str.manyvids.com:1935/live_stream/" + } + ], + "supported_resolutions": [ + "960x540@30", + "1280x720@30" + ], + "maximums": { + "video_bitrate_matrix": { + "960x540@30": { + "h264": 3000 + }, + "1280x720@30": { + "h264": 4000 + } + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "fantasy_club", + "name": "Fantasy.Club", + "more_info_link": "https://help.fantasy.club/", + "stream_key_link": "https://fantasy.club/app/create-content/stream-now", + "servers": [ + { + "name": "US: East", + "url": "rtmp://live-east.fantasy.club/live" + }, + { + "name": "US: West", + "url": "rtmp://live-west.fantasy.club/live" + }, + { + "name": "Europe", + "url": "rtmp://live-eu.fantasy.club/live" + }, + { + "name": "South America", + "url": "rtmp://live-sa.fantasy.club/live" + } + ], + "supported_resolutions": [ + "852x480@30", + "1280x720@30", + "1280x720@60", + "1920x1080@30", + "1920x1080@60" + ], + "maximums": { + "video_bitrate_matrix": { + "852x480@30": { + "h264": 1200 + }, + "1280x720@30": { + "h264": 3600 + }, + "1280x720@60": { + "h264": 4200 + }, + "1920x1080@30": { + "h264": 5000 + }, + "1920x1080@60": { + "h264": 7200 + } + }, + "audio_bitrate": { + "aac": 196 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 2 + }, + "obs_x264": "scenecut=0" + } + }, + { + "id": "shareplay", + "name": "Shareplay", + "more_info_link": "https://shareplay.tv", + "servers": [ + { + "name": "Default", + "url": "rtmp://shareplay.tv:833/live" + } + ], + "supported_resolutions": [ + "640x360@30", + "640x360@60", + "852x480@30", + "852x480@60", + "1280x720@30", + "1280x720@60", + "1920x1080@30", + "1920x1080@60" + ], + "maximums": { + "video_bitrate_matrix": { + "640x360@30": { + "h264": 1000 + }, + "640x360@60": { + "h264": 1500 + }, + "852x480@30": { + "h264": 2000 + }, + "852x480@60": { + "h264": 3000 + }, + "1280x720@30": { + "h264": 4000 + }, + "1280x720@60": { + "h264": 6000 + }, + "1920x1080@30": { + "h264": 6000 + }, + "1920x1080@60": { + "h264": 9000 + } + }, + "audio_bitrate": { + "aac": 128 + } + }, + "recommended": { + "h264": { + "profile": "main", + "keyint": 2 + } + } + }, + { + "id": "sympla", + "name": "Sympla", + "servers": [ + { + "name": "Sympla RTMP", + "url": "rtmp://rtmp.sympla.com.br:5222/app" + } + ], + "maximums": { + "video_bitrate": { + "h264": 5000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "mildom", + "name": "Mildom", + "more_info_link": "https://www.mildom.com/course/pc", + "stream_key_link": "https://www.mildom.com/creator/live", + "servers": [ + { + "name": "Global", + "url": "rtmp://txlvb-push.mildom.tv/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "nonolive", + "name": "Nonolive", + "more_info_link": "https://wia.nonolive.com/views/obs_assistant_tutorial.html", + "stream_key_link": "https://www.nonolive.com/room_setting", + "servers": [ + { + "name": "Asia: Hong Kong, China", + "url": "rtmp://live-hk-zl.nonolive.tv/live" + }, + { + "name": "Asia: Jakarta, Indonesia", + "url": "rtmp://live-jkt-zl.nonolive.tv/live" + }, + { + "name": "EU: Frankfurt, DE", + "url": "rtmp://live-fra-zl.nonolive.tv/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 6000 + }, + "audio_bitrate": { + "aac": 160 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "streamvi", + "name": "StreamVi", + "stream_key_link": "https://streamvi.ru/settings", + "servers": [ + { + "name": "Default", + "url": "rtmp://live-default.streamvi.ru/live" + }, + { + "name": "Russia (Moscow)", + "url": "rtmp://live-msk.streamvi.ru/live" + }, + { + "name": "EU Central: Germany", + "url": "rtmp://live1.streamvi.ru/live" + } + ] + }, + { + "id": "livepush", + "name": "Livepush", + "more_info_link": "https://docs.livepush.io/en/articles/5065323-how-to-stream-live-from-obs-to-livepush", + "servers": [ + { + "name": "Livepush Global (Default)", + "url": "rtmp://dc-global.livepush.io/live" + }, + { + "name": "Chicago, US", + "url": "rtmp://us-central-ch.livepush.io/live" + }, + { + "name": "New York, US", + "url": "rtmp://us-east-ny.livepush.io/live" + }, + { + "name": "Los Angeles, US", + "url": "rtmp://us-west-la.livepush.io/live" + }, + { + "name": "Miami, US", + "url": "rtmp://us-south-mia.livepush.io/live" + }, + { + "name": "Dallas, US", + "url": "rtmp://us-central-dal.livepush.io/live" + }, + { + "name": "Montreal, CA", + "url": "rtmp://ca-central-mon.livepush.io/live" + }, + { + "name": "Toronto, CA", + "url": "rtmp://ca-south-tor.livepush.io/live" + }, + { + "name": "Sydney, AU", + "url": "rtmp://au-east-syd.livepush.io/live" + }, + { + "name": "London, UK", + "url": "rtmp://uk-central-ldn.livepush.io/live" + }, + { + "name": "Milan, Italy", + "url": "rtmp://it-north-mln.livepush.io/live" + }, + { + "name": "Paris, FR", + "url": "rtmp://fr-central-par.livepush.io/live" + }, + { + "name": "Singapore", + "url": "rtmp://as-southeast-sg.livepush.io/live" + }, + { + "name": "Bangalore, IN", + "url": "rtmp://in-south-blr.livepush.io/live" + }, + { + "name": "Turkiye", + "url": "rtmp://tr-north-ist.livepush.io/live" + } + ], + "maximums": { + "video_bitrate": { + "h264": 16000 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "vindral", + "name": "Vindral", + "more_info_link": "https://docs.vindral.com/docs/vindral-cdn/", + "servers": [ + { + "name": "eu-north", + "url": "rtmps://rtmp.eu-north.cdn.vindral.com/publish" + }, + { + "name": "eu-west", + "url": "rtmps://rtmp.eu-west.cdn.vindral.com/publish" + } + ], + "maximums": { + "video_bitrate": { + "h264": 20000 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "profile": "high", + "keyint": 1 + } + } + }, + { + "id": "whowhatch", + "name": "Whowatch (ふわっち)", + "more_info_link": "https://whowatch.tv/help/encoder", + "stream_key_link": "https://whowatch.tv/publish", + "servers": [ + { + "name": "default", + "url": "rtmp://live.whowatch.tv/live/" + } + ], + "maximums": { + "video_bitrate": { + "h264": 1800 + }, + "audio_bitrate": { + "aac": 192 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "irltoolkit", + "name": "IRLToolkit", + "stream_key_link": "https://irl.run/settings/ingest/", + "servers": [ + { + "name": "Global (Recommended)", + "url": "rtmp://stream.global.irl.run/ingest" + }, + { + "name": "Los Angeles, US", + "url": "rtmp://stream.lax.irl.run/ingest" + }, + { + "name": "New York, US", + "url": "rtmp://stream.ewr.irl.run/ingest" + }, + { + "name": "Rotterdam, NL", + "url": "rtmp://stream.rtm.irl.run/ingest" + }, + { + "name": "Singapore", + "url": "rtmp://stream.sin.irl.run/ingest" + }, + { + "name": "Tokyo, JP", + "url": "rtmp://stream.tyo.irl.run/ingest" + } + ], + "maximums": { + "video_bitrate": { + "h264": 20000 + } + }, + "recommended": { + "h264": { + "keyint": 2 + } + } + }, + { + "id": "bitmovin", + "name": "Bitmovin", + "more_info_link": "https://developer.bitmovin.com/docs/overview", + "stream_key_link": "https://bitmovin.com/dashboard/streams?streamsTab=LIVE", + "servers": [ + { + "name": "Streams Live", + "url": "rtmp://live-input.bitmovin.com/streams" + } + ], + "recommended": { + "h264": { + "keyint": 2 + } + } + } + ] +} \ No newline at end of file diff --git a/text/0039-json-schemas/obs-services.json b/text/0039-json-schemas/obs-services.json new file mode 100644 index 0000000..ccff171 --- /dev/null +++ b/text/0039-json-schemas/obs-services.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://obsproject.com/schemas/obs-service.json", + "title": "OBS Services Plugin JSON Schema", + "type": "object", + "properties": { + "format_version": { + "type": "integer", + "const": 1 + }, + "services": { + "type": "array", + "items": { + "allOf": [ + { + "title": "Service", + "properties": { + "id": { + "type": "string", + "title": "Service ID", + "description": "Human readable identifier used to register the service in OBS\nMaking it human readable is meant to allow users to use it through scripts and plugins", + "pattern": "^[a-z0-9_\\-]+$", + "minLength": 1 + }, + "name": { + "type": "string", + "title": "Service Name", + "description": "Name of the streaming service. Will be displayed in the Service dropdown.", + "minLength": 1 + }, + "common": { + "type": "boolean", + "title": "Property reserved to OBS Project developers", + "description": "Whether or not the service is shown in the list before it is expanded to all services by the user.", + "default": false + } + }, + "$commit": "Forbid 'common' being set if false", + "if": { "properties": { "common": { "const": false } } }, + "then": { "properties": { "common": { "description": "This property is unneeded if set to false" , "const": true } } }, + "required": ["id","name"] + }, + { + "$comment": "Add base service JSON schema", + "$ref": "service.json" + }, + { + "$comment": "Add protocol properties", + "$ref": "protocolDefs.json#/$defs/protocolProperties" + } + ], + "unevaluatedProperties": false + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + } + }, + "$comment": "Support '$schema' without making it a proper property", + "if": { "not": { "maxProperties": 2 } }, + "then": { "properties": { "$schema": { "type": "string" } } }, + "required": ["format_version", "services"], + "unevaluatedProperties": false +} diff --git a/text/0039-json-schemas/obs-services.schema.json b/text/0039-json-schemas/obs-services.schema.json deleted file mode 100644 index ad4445e..0000000 --- a/text/0039-json-schemas/obs-services.schema.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "OBS Services Plugin JSON Schema", - "type": "object", - "required": ["format_version", "services"], - "properties": { - "format_version": { - "type": "integer", - "const": 4 - }, - "services": { - "type": "array", - "minItems": 1, - "items": { - "$comment": "Import common service object as a base, and then add new properties", - "$ref": "service.schema.json", - "required": ["id","name"], - "properties": { - "id": { - "title": "Service identifier", - "description": "Human readable identifier used to register the service in OBS", - "$comment": "Making it human readable is meant to allow users to use it through scripts and plugins, like service detection", - "type": "string", - "pattern": "^[a-z0-9_\\-]+$" - }, - "name": { - "title": "Name of the service", - "description": "Name showed in the OBS when choosing a service", - "type": "string" - }, - "common": { - "title": "Property reserved to OBS Project developers", - "description": "If not set, this value is considered as false", - "type": "boolean", - "default": false, - "$comment": "Set as a constant to true to avoid adding uselessly this property set to false", - "const": true - } - }, - "unevaluatedProperties": false - }, - "additionalItems": false - } - } -} diff --git a/text/0039-json-schemas/protocolCodecsMap.schema.json b/text/0039-json-schemas/protocolCodecsMap.schema.json deleted file mode 100644 index c8ab776..0000000 --- a/text/0039-json-schemas/protocolCodecsMap.schema.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "Protocol Codecs Map", - "description": "Hashmap of supported codecs per protocol supported by the service", - "type": "object", - "propertyNames": { - "$comment": "This hashmap can only contain properties where the name match the following pattern", - "$ref": "protocolDefs.schema.json#/$defs/protocolPattern" - }, - "properties": { - "*": { - "title": "Any protocol supported codecs", - "description": "List of supported codecs for any protocol supported by the service", - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "$comment": "Codec name shall match the following pattern", - "$ref": "commonPattern.schema.json#/$defs/codecPattern", - "examples": ["aac"] - }, - "examples": [ - { "*": ["h264"] } - ] - } - }, - "additionalProperties": { - "description": "Additional list of supported codecs for a specific protocol supported by the service", - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "$comment": "Codec name shall match the following pattern", - "$ref": "commonPattern.schema.json#/$defs/codecPattern", - "examples": ["opus"] - }, - "examples": [ - { "HLS": ["av1", "vp9"] } - ] - }, - "examples": [ - { - "*": ["aac"], - "SRT": ["opus"] - } - ], - "unevaluatedProperties": false -} diff --git a/text/0039-json-schemas/protocolDefs.json b/text/0039-json-schemas/protocolDefs.json new file mode 100644 index 0000000..6abee37 --- /dev/null +++ b/text/0039-json-schemas/protocolDefs.json @@ -0,0 +1,63 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://obsproject.com/schemas/protocolDefs.json", + "title": "Protocol Enums, Patterns and Properties", + "description": "Protocol-related enums, patterns and properties used in OBS JSON Schemas", + "$comment": "Made to allow an easy way to add protocol to schemas", + "$defs": { + "protocolEnum": { + "$comment": "Enumeration of protocols", + "enum": ["RTMP","RTMPS","FTL","HLS","SRT","RIST"] + }, + "protocolMapEnum": { + "$comment": "Enumeration of protocols (with '*' as any) that have various compatible codecs", + "enum": ["*","HLS","SRT","RIST"] + }, + "serverPattern": { + "$comment": "Pattern to enforce a supported server URL", + "pattern": "^(rtmps?|https?|srt|rist)://" + }, + "notRequireProtocolPattern": { + "$comment": "Pattern meant to match with protocol that have a unique URL prefix", + "pattern": "^(rtmps?|srt|rist)://" + }, + "protocolProperties": { + "$comment": "Per-protocol properties meant for obs-services schema", + "type": "object", + "properties": { + "SRT": { + "type": "object", + "title": "SRT Properties", + "description": "Properties related to the SRT protocol", + "properties": { + "stream_id": { + "type": "boolean", + "default": true + }, + "encrypt_passphrase": { + "type": "boolean", + "default": false + } + }, + "required": ["stream_id", "encrypt_passphrase"] + }, + "RIST": { + "type": "object", + "title": "RIST Properties", + "description": "Properties related to the RIST protocol", + "properties": { + "encrypt_passphrase": { + "type": "boolean", + "default": true + }, + "srp_username_password": { + "type": "boolean", + "default": false + } + }, + "required": ["encrypt_passphrase", "srp_username_password"] + } + } + } + } +} diff --git a/text/0039-json-schemas/protocolDefs.schema.json b/text/0039-json-schemas/protocolDefs.schema.json deleted file mode 100644 index 7d7fbb4..0000000 --- a/text/0039-json-schemas/protocolDefs.schema.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "Protocol Enum and Pattern", - "description": "Protocol-related enum and pattern used in OBS JSON Schemas", - "$comment": "Made to allow an easy way to add protocol to schemas", - "$defs": { - "protocolEnum": { - "description": "Enumeration of protocols", - "enum": ["RTMP","RTMPS","HLS","SRT","RIST","SRT","FTL"] - }, - "protocolPattern": { - "description": "Pattern to enforce properties to named with a protocol or '*'", - "pattern": "^(\\*|RTMPS?|HLS|SRT|RIST|FTL)$" - }, - "serverPattern": { - "description": "Pattern to enforce a supported server URL", - "pattern": "^(rtmps?|https?|srt|rist|ftl)://" - }, - "requireProtocolPattern": { - "description": "Pattern meant to match with protocol that have a unique link prefix", - "pattern": "^(rtmps?|srt|rist|ftl)://" - } - } -} diff --git a/text/0039-json-schemas/service.json b/text/0039-json-schemas/service.json new file mode 100644 index 0000000..9602d98 --- /dev/null +++ b/text/0039-json-schemas/service.json @@ -0,0 +1,309 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://obsproject.com/schemas/service.json", + "title": "OBS Service Object Schema", + "type": "object", + "properties": { + "more_info_link": { + "type": "string", + "description": "Link that provides additional info about the service, presented in the UI as a button next to the services dropdown.", + "format": "uri", + "$ref": "#/$defs/httpPattern", + "minLength": 1 + }, + "stream_key_link": { + "type": "string", + "description": "Link where a logged-in user can find the 'stream key', presented as a button alongside the stream key field.", + "format": "uri", + "$ref": "#/$defs/httpPattern", + "minLength": 1 + }, + "servers": { + "type": "array", + "description": "Array of server objects", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the server (e.g. location, primary/backup), displayed in the Server dropdown.", + "minLength": 1 + }, + "protocol": { + "type": "string", + "title": "Server Protocol", + "description": "Protocol used by the server. Required if the URI scheme can't help identify the streaming protocol (e.g. HLS).", + "$ref": "protocolDefs.json#/$defs/protocolEnum" + }, + "url": { + "type": "string", + "title": "Server URL", + "description": "URL of the ingest server.", + "minLength": 1 + } + }, + "allOf": [ + { + "$comment": "Add format and pattern through 'if' until FTL is dropped", + "if": { "properties": { "url": { "format": "uri" } } }, + "then": { "properties": { "url": { "format": "uri", "$ref": "protocolDefs.json#/$defs/serverPattern" } } }, + "else": { "properties": { "url": { "format": "hostname" } } } + }, + { + "$comment": "Making 'protocol' required if no unique prefix is found (e.g. HLS will require 'protocol')", + "if": { "not": { "properties": { "url": { "$ref": "protocolDefs.json#/$defs/notRequireProtocolPattern" } } } }, + "then": { "required": ["protocol"] }, + "else": { "properties": { "protocol": { "description": "This property is unneeded if the URL scheme is unique to a streaming protocol", "const": "Remove this property" } } } + } + ], + "required": ["name","url"], + "unevaluatedProperties": false + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + }, + "supported_codecs": { + "type": "object", + "title": "Supported Codecs", + "description": "Codecs that are supported by the service.", + "properties": { + "video": { + "type": "object", + "title": "Supported Video Codecs", + "description": "Video codecs that are supported by the service.", + "propertyNames": { "$ref": "protocolDefs.json#/$defs/protocolMapEnum" }, + "properties": { + "*": { + "type": "array", + "title": "Any Protocol Supported Video Codec", + "description": "Video codecs that are supported by the service and any supported protocol.", + "items": { + "type": "string", + "$ref": "codecDefs.json#/$defs/videoCodecEnum" + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + } + }, + "additionalProperties": { + "type": "array", + "title": "Protocol Supported Video Codec", + "description": "Video codecs that are supported by the service on this protocol.", + "items": { + "type": "string", + "$ref": "codecDefs.json#/$defs/videoCodecEnum" + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + }, + "minProperties": 1, + "unevaluatedProperties": false + }, + "audio": { + "type": "object", + "title": "Supported Audio Codecs", + "description": "Audio codecs that are supported by the service.", + "propertyNames": { "$ref": "protocolDefs.json#/$defs/protocolMapEnum" }, + "properties": { + "*": { + "type": "array", + "title": "Any Protocol Supported Audio Codec", + "description": "Audio codecs that are supported by the service and any supported protocol.", + "items": { + "type": "string", + "$ref": "codecDefs.json#/$defs/audioCodecEnum" + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + } + }, + "additionalProperties": { + "type": "array", + "title": "Protocol Supported Audio Codec", + "description": "Audio codecs that are supported by the service on this protocol.", + "items": { + "type": "string", + "$ref": "codecDefs.json#/$defs/audioCodecEnum" + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + }, + "minProperties": 1, + "unevaluatedProperties": false + } + }, + "minProperties": 1, + "unevaluatedProperties": false + }, + "supported_resolutions": { + "type": "array", + "title": "Supported Resolutions", + "description": "Resolution supported by the service. All with or all withtout the framerate.", + "items": { + "type": "string", + "pattern": "^[0-9]+x[0-9]+(|@[0-9]+)$" + }, + "allOf": [ + { + "if": { "items": { "$ref": "#/$defs/resolutionFrameratePattern" } }, + "then": { "items": { "$ref": "#/$defs/resolutionFrameratePattern" } } + }, + { + "if": { "items": { "$ref": "#/$defs/resolutionPattern" } }, + "then": { "items": { "$ref": "#/$defs/resolutionPattern" } } + } + ], + "minItems": 1, + "uniqueItems": true, + "additionalItems": false + }, + "maximums": { + "type": "object", + "title": "Maximums", + "description": "Maximum values allowed by the service", + "properties": { + "framerate": { + "type": "integer", + "title": "Maximum Framerate", + "exclusiveMinimum": 0 + }, + "video_bitrate": { + "type": "object", + "title": "Maximum Video Bitrate", + "description": "Maximum video bitrate per codec", + "propertyNames": { "$ref": "codecDefs.json#/$defs/videoCodecEnum" }, + "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, + "minProperties": 1, + "unevaluatedProperties":false + }, + "audio_bitrate": { + "type": "object", + "title": "Maximum Audio Bitrate", + "description": "Maximum audio bitrate per codec", + "propertyNames": { "$ref": "codecDefs.json#/$defs/audioCodecEnum" }, + "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, + "minProperties": 1, + "unevaluatedProperties":false + }, + "video_bitrate_matrix": { + "type": "object", + "title": "Maximum Video Bitrate Matrix", + "description": "Maximum video bitrate per supported resolution with framerate and per codec", + "propertyNames": { "$ref": "#/$defs/resolutionFrameratePattern" }, + "additionalProperties": { + "type": "object", + "propertyNames": { "$ref": "codecDefs.json#/$defs/videoCodecEnum" }, + "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, + "minProperties": 1, + "unevaluatedProperties":false + }, + "minProperties": 1, + "unevaluatedProperties": false + } + }, + "minProperties": 1, + "unevaluatedProperties": false + }, + "recommended": { + "type": "object", + "title": "Recommended settings", + "description": "Settings that are applied only if the user wants to do so.", + "allOf": [ + { + "properties": { + "framerate": { + "type": "integer", + "title": "Recommended Framerate", + "exclusiveMinimum": 0 + }, + "video_bitrate": { + "type": "object", + "title": "Recommended Video Bitrate", + "description": "Recommended video bitrate per codec", + "propertyNames": { "$ref": "#codecDefs.json/$defs/videoCodecEnum" }, + "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, + "minProperties": 1, + "unevaluatedProperties":false + }, + "audio_bitrate": { + "type": "object", + "title": "Recommended Audio Bitrate", + "description": "Recommended audio bitrate per codec", + "propertyNames": { "$ref": "#codecDefs.json/$defs/audioCodecEnum" }, + "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, + "minProperties": 1, + "unevaluatedProperties":false + }, + "video_bitrate_matrix": { + "type": "object", + "title": "Recommended Video Bitrate Matrix", + "description": "Recommended video bitrate per supported resolution with framerate and per codec", + "propertyNames": { "$ref": "#/$defs/resolutionFrameratePattern" }, + "additionalProperties": { + "type": "object", + "propertyNames": { "$ref": "#codecDefs.json/$defs/videoCodecEnum" }, + "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, + "minProperties": 1, + "unevaluatedProperties":false + }, + "minProperties": 1, + "unevaluatedProperties": false + } + } + }, + { + "$comment": "Add codec properties", + "$ref": "codecDefs.json#/$defs/codecProperties" + } + ], + "minProperties": 1, + "unevaluatedProperties": true + } + }, + "allOf": [ + { + "$comment": "Make 'video_bitrate_matrix' unusable if 'supported_resolutions' is empty", + "if": { "properties": { "supported_resolutions": { "maxItems": 0 } } }, + "then": { "properties": { + "maximums": { "properties": { "video_bitrate_matrix": { "description": "This matrix is only available if supported resolutions with framerates are set", "maxProperties": 0 } } }, + "recommended": { "properties": { "video_bitrate_matrix": { "description": "This matrix is only available if supported resolutions with framerates are set", "maxProperties": 0 } } } + } } + }, + { + "$comment": "Make 'video_bitrate_matrix' unusable if supported resolutions are without framerate", + "if": { "not": { "properties": { "supported_resolutions": { "items": { "$ref": "#/$defs/resolutionFrameratePattern" } } } } }, + "then": { "properties": { + "maximums": { "properties": { "video_bitrate_matrix": { "description": "This matrix is only available if 'supported_resolutions' is with framerates", "maxProperties": 0 } } }, + "recommended": { "properties": { "video_bitrate_matrix": { "description": "This matrix is only available if 'supported_resolutions' is with framerates", "maxProperties": 0 } } } + } } + }, + { + "$comment": "Make 'framerate' unusable if supported resolutions are with framerate", + "if": { "not": {"properties": { "supported_resolutions": { "items": { "$ref": "#/$defs/resolutionPattern" } } } } }, + "then": { "properties": { + "maximums": { "properties": { "framerate": { "description": "This property is only available if 'supported_resolutions' is without framerates or not set", "const": 0 } } }, + "recommended": { "properties": { "framerate": { "description": "This property is only available if 'supported_resolutions' is without framerates or not set", "const": 0 } } } + } } + } + ], + "required": ["servers"], + "$defs": { + "httpPattern": { + "$comment": "Pattern to enforce HTTP(S) links", + "pattern": "^https?://" + }, + "resolutionPattern": { + "$comment": "Pattern for resolution without framerate", + "pattern": "^[0-9]+x[0-9]+$" + }, + "resolutionFrameratePattern": { + "$comment": "Pattern for resolution with framerate", + "pattern": "^[0-9]+x[0-9]+@[0-9]+$" + } + } +} diff --git a/text/0039-json-schemas/service.schema.json b/text/0039-json-schemas/service.schema.json deleted file mode 100644 index 300aa67..0000000 --- a/text/0039-json-schemas/service.schema.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "title": "OBS Common Service Object Schema", - "description": "Common structure shared among OBS first-party service plugins", - "type": "object", - "required": ["servers"], - "properties": { - "more_info_link": { - "description": "Link to a web page that show more info about the streaming service", - "type": "string", - "format": "uri", - "$comment": "Add a restriction to the URI format", - "$ref": "commonPattern.schema.json#/$defs/linkPattern" - }, - "stream_key_link": { - "description": "Link to a web page that allow the user to obtain streaming service stream key", - "type": "string", - "format": "uri", - "$comment": "Add a restriction to the URI format", - "$ref": "commonPattern.schema.json#/$defs/linkPattern" - }, - "servers": { - "description": "Array of server objects", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": ["name","url"], - "properties": { - "name": { - "title": "Server given name", - "type": "string" - }, - "protocol": { - "description": "Protocol used by the server. Required if the prefix can't help identify the streaming protocol (e.g. HLS).", - "type": "string", - "$ref": "protocolDefs.schema.json#/$defs/protocolEnum" - }, - "url": { - "title": "Server URL", - "type": "string", - "format": "uri", - "$comment": "Add a restriction to the URI format based on protocols supported by OBS", - "$ref": "protocolDefs.schema.json#/$defs/serverPattern" - } - }, - "additionalProperties": false, - "$comment": "Making 'protocol' required if no unique prefix is found (e.g. HLS will require 'protocol')", - "if": { "not": { "properties": { "url": { "$ref": "protocolDefs.schema.json#/$defs/requireProtocolPattern" } } } }, - "then": { "required": ["protocol"] } - }, - "additionalItems": false - }, - "supported_codecs": { - "description": "Supported video and audio codecs by the service per protocol", - "type": "object", - "properties": { - "video": { "$ref": "protocolCodecsMap.schema.json" }, - "audio": { "$ref": "protocolCodecsMap.schema.json" } - }, - "additionalProperties": false - }, - "supported_resolutions": { - "title": "Resolutions supported by the service", - "description": "All resolutions shall follow the same pattern between two possibility, with or without framerate. Check examples below.", - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "pattern": "^[0-9]+x[0-9]+", - "examples": [ - "1920x1080", - "1280x720@60" - ] - }, - "additionalItems": false, - "$comment": "Detect if resolutions contain a framerate, if true force every resolutions to have it and vice-versa", - "if": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionFrameratePattern" } }, - "then": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionFrameratePattern" } }, - "else": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionPattern" } } - }, - "maximums": { - "type": "object", - "properties": { - "video_bitrate_matrix": { - "description": "Video bitrate per resolution with framerate", - "type": "object", - "propertyNames": { - "$comment": "This object can only contain properties where the name that match the following pattern", - "$ref": "commonPattern.schema.json#/$defs/resolutionFrameratePattern" - }, - "additionalProperties": { - "type": "object", - "propertyNames": { "$ref": "commonPattern.schema.json#/$defs/codecPattern" }, - "additionalProperties": { "type": "integer" }, - "unevaluatedProperties": false - }, - "examples": [ - { - "1280x720@60": { - "h264": 6000, - "av1": 5000 - } - } - ], - "unevaluatedProperties": false - } - } - }, - "recommended": { "type": "object" } - }, - "allOf": [ - { - "if": { - "$comment": "Forbid 'video_bitrate_matrix' objects from being set if 'supported_resolutions' is not set with framerate", - "properties": { "supported_resolutions": { "items": { "$ref": "commonPattern.schema.json#/$defs/resolutionPattern" } } } - }, - "then": { "properties": { - "maximums": { "not": { "required": ["video_bitrate_matrix"] } }, - "recommended": { "not": { "required": ["video_bitrate_matrix"] } } - } }, - "else": { - "$comment": "Otherwise forbid 'maximums/fps' from being set if 'supported_resolutions' is set with framerate", - "properties": { "maximums": { "not": { "required": ["fps"] } } } - } - } - ] -} \ No newline at end of file diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 05951ee..a0eba03 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -289,15 +289,15 @@ The old actually looks like this: ### New format (WIP) -The new format will rely on a more strict JSON schemas. +The new format will rely on more strict JSON schemas. Those JSON Schemas (Draft 2020-12) will be: -- `commonPattern.schema.json`: regex pattern use multiple times -- `protocolDefs.schema.json`: regex pattern and enum about protocols to ease protocol additions or removals in schemas -- `service.schema.json`: define the service object itself (*still in WIP*) -- `obs-services.schema.json`: `obs-services` JSON Schema +- `protocolDefs.json`: enums, regex patterns and properties related to protocols to ease protocol additions or removals in schemas +- `codecDefs.json`: enums, regex patterns and properties related to codecs to ease codec additions or removals in schemas +- `service.json`: define the service object itself, will be used for every service plugin htat needs a JSON +- `obs-services.json`: `obs-services` JSON Schema -Those are all present in `0039-json-schemas` folder. +Those are all present in `0039-json-schemas` folder with an example of `obs-services` JSON. *Documention in schemas are in progress, and a schema for integration plugin should also be made.* @@ -305,96 +305,6 @@ JSON Schema allows to validate `services.json` (in `obs-services` case) when a P The use of JSON Schema allows to create specific additions for a specific plugin by creating a unique schema for it. -#### Example -Here is a example with `obs-services` in mind: -```json -{ - "format_version": 4, - "services": [ - { - "id": "example", - "name": "Example of stream services", - "more_info_link": "https://example.com/more_info", - "stream_key_link": "https://example.com/stream_key", - "servers": [ - { - "name": "SRT Server", - "url": "srt://example.com" - }, - { - "name": "RTMPS Server", - "url": "rtmps://example.com/server" - }, - { - "name": "FTL Server", - "url": "ftl://example.com/" - }, - { - "name": "HLS Server", - "protocol": "HLS", - "url": "https://example.com/http_upload_hls?cid={stream_key}©=0&file=out.m3u8" - } - ], - "supported_codecs": { - "video": { - "*": [ - "h264" - ], - "SRT": [ - "av1" - ] - }, - "audio": { - "*": [ - "aac" - ], - "SRT": [ - "opus" - ] - } - }, - "supported_resolutions": [ - "1920x1080@60", - "1920x1080@30", - "1280x720@60", - "1280x720@30" - ], - "maximums": { - "fps": 60, - "video_bitrate": { - "any_codec": 9000, - "av1": 8000, - }, - "audio_bitrate": { - "any_codec": 320, - "opus": 640, - }, - "video_bitrate_matrix": { - "1920x1080@60": { - "h264": 9000, - "av1": 8000 - }, - "1920x1080@30": { - "h264": 6000, - "av1": 5000 - }, - "1280x720@60": { - "h264": 6000, - "av1": 5000 - }, - "1280x720@30": { - "h264": 4000, - "av1": 3000 - } - }, - }, - "recommended": { - } - } - ] -} -``` - #### Advantages of this format - Recommended settings are really recommended settings. From ba8c124080c6e205b1ccccbad41f4f5c077e2a84 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 22 Mar 2023 15:35:37 +0100 Subject: [PATCH 15/36] Frontend API deprecations and output in settings --- text/0039-service-overhaul.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index a0eba03..64c4bf5 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -31,7 +31,9 @@ Many elements of the settings UI related to services will be moved inside servic - "Get Stream Key" button - "More Info" button -Advanced network settings will also be replace by protocol output properties view below the service properties view. +This streaming output will be selected through the settings windows and no longer auto-selected while starting the stream and its property view will be placed below the service properties view. + +Advanced network settings will also be replace by the output properties view below the service properties view, since those are meant for `"rtmp_output"` (RTMP(S) output). ### Common, uncommon @@ -49,6 +51,14 @@ This will require to introduce in the Property API a way to indicate that the se TODO: Think about recommendation +## Deprecations in the Frontend API + +Those functions will be deprecated without replacement: +- `obs_frontend_set_streaming_service()` must be deprecated because the output selection is done in the settings windows and is no longer done while the stream is starting. +- `obs_frontend_save_streaming_service()` must be deprecated because plugin should not be able to override what is saved by the settings window. + +Those needs to deprecated before the rest of the RFC implementation is merged or those functions will have to be turned into stub functions while being deprecated. + ## Service plugins ### Service API From c9e0889c0dceb525915952da4d89c97b23447357 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Fri, 24 Mar 2023 08:20:31 +0100 Subject: [PATCH 16/36] Try to avoid Frontend API deprecations --- text/0039-service-overhaul.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 64c4bf5..36d29ae 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -33,6 +33,8 @@ Many elements of the settings UI related to services will be moved inside servic This streaming output will be selected through the settings windows and no longer auto-selected while starting the stream and its property view will be placed below the service properties view. +The service output settings (if any) will be saved in the `service.json` file. + Advanced network settings will also be replace by the output properties view below the service properties view, since those are meant for `"rtmp_output"` (RTMP(S) output). ### Common, uncommon @@ -51,13 +53,11 @@ This will require to introduce in the Property API a way to indicate that the se TODO: Think about recommendation -## Deprecations in the Frontend API - -Those functions will be deprecated without replacement: -- `obs_frontend_set_streaming_service()` must be deprecated because the output selection is done in the settings windows and is no longer done while the stream is starting. -- `obs_frontend_save_streaming_service()` must be deprecated because plugin should not be able to override what is saved by the settings window. +## Frontend API -Those needs to deprecated before the rest of the RFC implementation is merged or those functions will have to be turned into stub functions while being deprecated. +Those functions will be modified: +- `obs_frontend_set_streaming_service()` because the output selection is done in the settings windows and is no longer done while the stream is starting will now swap the output if the service protocol and the actual output does not match. +- `obs_frontend_save_streaming_service()` will save service output settings. ## Service plugins ### Service API From fa569f2d4c8983ceb114198cfa47f2c208180356 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Fri, 24 Mar 2023 08:37:18 +0100 Subject: [PATCH 17/36] rtmp-services and nitpiks --- text/0039-service-overhaul.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 36d29ae..7dd30fe 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -64,11 +64,22 @@ Those functions will be modified: Adding missing `get_properties2()` and `get_default2()` functions for service might be required. -**For now all services shall be compatible with H264. Removing this limitation requires to rework of the Output settings UI which is plan for another RFC.** +TODO: Add details about the new flag attribute + +**All services must at least be compatible with H264 because of how simple output mode is designed.** + +### `rtmp-services` + +Services provided by this plugin (`"rtmp_custom"`, `"rtmp_common"`) will be deprecated and completely unused in OBS Studio. + +Those are deprecated rather than completely removed to allow scripting and plugins to migrate if they happen to use them. + +Its service JSON will no longer be updated. + ### `custom-service` -This plugin is meant to provide a replacement for `rtmp_custom` type. +This plugin is meant to provide a replacement for `"rtmp_custom"` type, `"custom_service"`. If OBS need to be heavily dependent to one service plugin, it shall be this one. @@ -77,9 +88,9 @@ Property view will change depending of the protocol. ### `obs-services` -This plugin is meant to provide a replacements for `rtmp_common` type for services who doesn't have custom behavior or integration. +This plugin is meant to provide a replacements for `"rtmp_common"` type for services who doesn't have custom behavior or integration. -This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `rtmp_common` id. +This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `"rtmp_common"` id. Those services will be able to provide multiple protocols so no more "Service - HLS" and "Service - FTL". @@ -93,13 +104,13 @@ Only improvements will be accepted in the code of this plugin. #### Service ID naming scheme - Only lower case letter -- All prefixed by `obs-` in code, to avoid potential id conflict with streaming service third-party plugins. +- (**Might be removed**) All prefixed by `obs-` in code, to avoid potential id conflict with streaming service third-party plugins. - Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). - Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new first-party plugin and keep the same id. The change will be seamless for the user if done properly. ### Special case plugins -This/Those plugin(s) is/are meant to provide replacements for `rtmp_common` type for services which need a custom behavior. +This/Those plugin(s) is/are meant to provide replacements for `"rtmp_common"` type for services which need a custom behavior. This/Those plugin(s) is/are meant to have implemented and register services which need a specific behavior like custom ingest with a unique id for each one. From fa753a27b9bd2af41afe75b085aa14cf4102a169 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Tue, 4 Apr 2023 18:39:53 +0200 Subject: [PATCH 18/36] Update RFC, more service API and more service types --- text/0039-service-overhaul.md | 63 ++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 7dd30fe..14c6d8c 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -37,6 +37,8 @@ The service output settings (if any) will be saved in the `service.json` file. Advanced network settings will also be replace by the output properties view below the service properties view, since those are meant for `"rtmp_output"` (RTMP(S) output). +**TODO/REDO: All services must at least be compatible with H264 because of how simple output mode is designed.** + ### Common, uncommon Spoiler: Streaming services will be individually registered, so no more `rtmp_common` that represent various services. @@ -59,14 +61,25 @@ Those functions will be modified: - `obs_frontend_set_streaming_service()` because the output selection is done in the settings windows and is no longer done while the stream is starting will now swap the output if the service protocol and the actual output does not match. - `obs_frontend_save_streaming_service()` will save service output settings. +## About the FTL protocol + +The FTL protocol is actually planned to be deprecated once a new protocol is added after this RFC is implemented. + +Any services that only support FTL will follow the deprecation cycle and be dropped at the same time as FTL if those services did not added support for another protocol. + ## Service plugins ### Service API -Adding missing `get_properties2()` and `get_default2()` functions for service might be required. +Adding to `obs_service_info`: + - `uint32_t flags` with the following flags: + - `OBS_SERVICE_DEPRECATED`: (**TODO: Re-think about it because of internal**) The service is deprecated and will not be shown in the UI combobox list. + - `OBS_SERVICE_INTERNAL`: The service is meant to be used internally in some plugin (e.g., WebSocket, Scripting) and usually not directly exposed in the UI. + - `OBS_SERVICE_UNCOMMON`: The service can be hidden behind a "Show All/More" option UI/UX-wise. + - `OBS_SERVICE_ANY_PROTOCOL`: The service supports any protocol, mainly meant for `"custom_service"` + - `const char *supported_protocols`: Protocol supported by the service, required if `OBS_SERVICE_ANY_PROTOCOL` is not set as a flag. + - `obs_properties_t *(*get_properties2)(void *data, void *type_data)`: Same as its non-2 variant but give access to the `type_data` pointer. -TODO: Add details about the new flag attribute - -**All services must at least be compatible with H264 because of how simple output mode is designed.** +**TODO: Adding `get_default2()` functions for service might be required.** ### `rtmp-services` @@ -77,14 +90,26 @@ Those are deprecated rather than completely removed to allow scripting and plugi Its service JSON will no longer be updated. -### `custom-service` +### `custom-services` + +If OBS Studio need to be heavily dependent to one service plugin, it must be this one. + +This plugin is meant to provide replacements for the `"rtmp_custom"` type. -This plugin is meant to provide a replacement for `"rtmp_custom"` type, `"custom_service"`. +#### `"custom_service"` -If OBS need to be heavily dependent to one service plugin, it shall be this one. +This the only service of this plugin thar will be exposed to the user through the UI. -The protocol will be detected (or maybe forced set by the user, e.g. HLS). -Property view will change depending of the protocol. +The protocol will be selected by the user and the properties view will change depending of the protocol. + +**TODO: Add about third-party support in `"custom_service"` type** + +#### Custom type per protocol + +Service types that support only the protocol inside their id (`"custom_`*insert lowercase protocol acronym*`"`) for any first-party protocol except FTL (deprecation). + +Services that will only support the first-party protocol related to their id/type. +The flag `OBS_SERVICE_INTERNAL` will be applied to not show them in the UI list. Those are meant for being used in WebSocket and scripting. ### `obs-services` @@ -110,11 +135,19 @@ Only improvements will be accepted in the code of this plugin. ### Special case plugins -This/Those plugin(s) is/are meant to provide replacements for `"rtmp_common"` type for services which need a custom behavior. +Those plugins are meant to provide replacements for `"rtmp_common"` type for services that were working around the JSON usually by adding ingest management code and is not a service with an integration. + +So those services that match those will have their own plugin. + +4 services are concerned: +- Dacast +- Nimo TV +- SHOWROOM +- YouNow (FTL only, also falls under the FTL deprecation cycle) -This/Those plugin(s) is/are meant to have implemented and register services which need a specific behavior like custom ingest with a unique id for each one. +Beside the `"rtmp_common"` part being replace by a unique service type, most of the ingest code will stay identical. -**TODO: Write about maintenance** +The maintenance of the code of those services after implementation will be on the organisation that originaly added them to `rtmp-services`. ### Conversion (WIP Needs a re-work) @@ -224,9 +257,9 @@ YouTube is not the only service that could have or need a "Manage Broadcast" but #### Twitch VOD track This will be the **only one** custom feature that will be allowed in OBS Studio UI code. -## Service JSON +## Service JSON for `obs-services` -### Old version +### Old version from `rtmp-services` The old actually looks like this: ```json @@ -320,7 +353,7 @@ Those JSON Schemas (Draft 2020-12) will be: Those are all present in `0039-json-schemas` folder with an example of `obs-services` JSON. -*Documention in schemas are in progress, and a schema for integration plugin should also be made.* +*Documentation in schemas are in progress, and a schema for integration plugin should also be made.* JSON Schema allows to validate `services.json` (in `obs-services` case) when a PR is made against it. From 4e13bff23ce8b952563482895b8df845c68b3d36 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 5 Apr 2023 17:23:44 +0200 Subject: [PATCH 19/36] Move custom_service to post load for less complexity --- text/0039-service-overhaul.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 14c6d8c..8539b94 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -75,8 +75,7 @@ Adding to `obs_service_info`: - `OBS_SERVICE_DEPRECATED`: (**TODO: Re-think about it because of internal**) The service is deprecated and will not be shown in the UI combobox list. - `OBS_SERVICE_INTERNAL`: The service is meant to be used internally in some plugin (e.g., WebSocket, Scripting) and usually not directly exposed in the UI. - `OBS_SERVICE_UNCOMMON`: The service can be hidden behind a "Show All/More" option UI/UX-wise. - - `OBS_SERVICE_ANY_PROTOCOL`: The service supports any protocol, mainly meant for `"custom_service"` - - `const char *supported_protocols`: Protocol supported by the service, required if `OBS_SERVICE_ANY_PROTOCOL` is not set as a flag. + - `const char *supported_protocols`: Protocol supported by the service. - `obs_properties_t *(*get_properties2)(void *data, void *type_data)`: Same as its non-2 variant but give access to the `type_data` pointer. **TODO: Adding `get_default2()` functions for service might be required.** @@ -102,7 +101,11 @@ This the only service of this plugin thar will be exposed to the user through th The protocol will be selected by the user and the properties view will change depending of the protocol. -**TODO: Add about third-party support in `"custom_service"` type** +This service will all first-party protocol, the properties view will change visible fields depending on the protocol. + +And also support any third-party protocol by allowing to choose which fields (e.g., username + password, stream key, custom field…) to add in the view. + +This service will be registered in the "post load module" step (`obs_post_load_modules()`) to make the service aware of all registered protocol in the "load module" step. #### Custom type per protocol From cdae65855bbad3b95022f20995f1cf7052a57c87 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 5 Apr 2023 21:17:43 +0200 Subject: [PATCH 20/36] OBS_SERVICE_DEPRECATED only mark as deprecated --- text/0039-service-overhaul.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 8539b94..b5a1a05 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -72,7 +72,7 @@ Any services that only support FTL will follow the deprecation cycle and be drop Adding to `obs_service_info`: - `uint32_t flags` with the following flags: - - `OBS_SERVICE_DEPRECATED`: (**TODO: Re-think about it because of internal**) The service is deprecated and will not be shown in the UI combobox list. + - `OBS_SERVICE_DEPRECATED`: The service is marked as deprecated. - `OBS_SERVICE_INTERNAL`: The service is meant to be used internally in some plugin (e.g., WebSocket, Scripting) and usually not directly exposed in the UI. - `OBS_SERVICE_UNCOMMON`: The service can be hidden behind a "Show All/More" option UI/UX-wise. - `const char *supported_protocols`: Protocol supported by the service. @@ -82,7 +82,7 @@ Adding to `obs_service_info`: ### `rtmp-services` -Services provided by this plugin (`"rtmp_custom"`, `"rtmp_common"`) will be deprecated and completely unused in OBS Studio. +Services provided by this plugin (`"rtmp_custom"`, `"rtmp_common"`) will be deprecated (`OBS_SERVICE_DEPRECATED` and `OBS_SERVICE_INTERNAL` applied) and completely unused in OBS Studio. Those are deprecated rather than completely removed to allow scripting and plugins to migrate if they happen to use them. From e6c961138ebb3b5befbbf7b3b91418fe1745f806 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 6 Apr 2023 10:50:06 +0200 Subject: [PATCH 21/36] New service JSON file. --- text/0039-service-overhaul.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index b5a1a05..78edac8 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -152,7 +152,13 @@ Beside the `"rtmp_common"` part being replace by a unique service type, most of The maintenance of the code of those services after implementation will be on the organisation that originaly added them to `rtmp-services`. -### Conversion (WIP Needs a re-work) +### Conversion from old services + +`streamService.json` will replace `service.json`, a new file approach is taken to avoid sudden breakage if the user happen to downgrade. + +`streamService.json` will contain the type/id of the service and its settings but also the type/id of of the used output and its settings. + +If `streamService.json` is not found, it will be generated from `service.json` if available. **Downgrade will break service configuration** A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the `service.json` to a new one. From 16ea079893613be4ab4edb1a09325371047fa915 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 4 May 2023 20:41:54 +0200 Subject: [PATCH 22/36] Some updates --- text/0039-json-schemas/protocolDefs.json | 2 +- text/0039-json-schemas/service.json | 14 ++++---------- text/0039-service-overhaul.md | 12 +++++------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/text/0039-json-schemas/protocolDefs.json b/text/0039-json-schemas/protocolDefs.json index 6abee37..e527c8a 100644 --- a/text/0039-json-schemas/protocolDefs.json +++ b/text/0039-json-schemas/protocolDefs.json @@ -11,7 +11,7 @@ }, "protocolMapEnum": { "$comment": "Enumeration of protocols (with '*' as any) that have various compatible codecs", - "enum": ["*","HLS","SRT","RIST"] + "enum": ["*","RTMP","RTMPS","HLS","SRT","RIST"] }, "serverPattern": { "$comment": "Pattern to enforce a supported server URL", diff --git a/text/0039-json-schemas/service.json b/text/0039-json-schemas/service.json index 9602d98..6ee5995 100644 --- a/text/0039-json-schemas/service.json +++ b/text/0039-json-schemas/service.json @@ -48,15 +48,9 @@ "if": { "properties": { "url": { "format": "uri" } } }, "then": { "properties": { "url": { "format": "uri", "$ref": "protocolDefs.json#/$defs/serverPattern" } } }, "else": { "properties": { "url": { "format": "hostname" } } } - }, - { - "$comment": "Making 'protocol' required if no unique prefix is found (e.g. HLS will require 'protocol')", - "if": { "not": { "properties": { "url": { "$ref": "protocolDefs.json#/$defs/notRequireProtocolPattern" } } } }, - "then": { "required": ["protocol"] }, - "else": { "properties": { "protocol": { "description": "This property is unneeded if the URL scheme is unique to a streaming protocol", "const": "Remove this property" } } } } ], - "required": ["name","url"], + "required": ["name","url","protocol"], "unevaluatedProperties": false }, "minItems": 1, @@ -225,7 +219,7 @@ "type": "object", "title": "Recommended Video Bitrate", "description": "Recommended video bitrate per codec", - "propertyNames": { "$ref": "#codecDefs.json/$defs/videoCodecEnum" }, + "propertyNames": { "$ref": "codecDefs.json#/$defs/videoCodecEnum" }, "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, "minProperties": 1, "unevaluatedProperties":false @@ -234,7 +228,7 @@ "type": "object", "title": "Recommended Audio Bitrate", "description": "Recommended audio bitrate per codec", - "propertyNames": { "$ref": "#codecDefs.json/$defs/audioCodecEnum" }, + "propertyNames": { "$ref": "codecDefs.json#/$defs/audioCodecEnum" }, "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, "minProperties": 1, "unevaluatedProperties":false @@ -246,7 +240,7 @@ "propertyNames": { "$ref": "#/$defs/resolutionFrameratePattern" }, "additionalProperties": { "type": "object", - "propertyNames": { "$ref": "#codecDefs.json/$defs/videoCodecEnum" }, + "propertyNames": { "$ref": "codecDefs.json#/$defs/videoCodecEnum" }, "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, "minProperties": 1, "unevaluatedProperties":false diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 78edac8..6a782a6 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -25,9 +25,8 @@ Many elements of the settings UI related to services will be moved inside servic - Stream key field - Username and password fields - OAuth connect disconnect button -- Text with clickable link +- Text with clickable link (e.g., YouTube integration links) - Maximum and recommended settings information -- Ignore "recommended setting" checkbox - "Get Stream Key" button - "More Info" button @@ -76,10 +75,9 @@ Adding to `obs_service_info`: - `OBS_SERVICE_INTERNAL`: The service is meant to be used internally in some plugin (e.g., WebSocket, Scripting) and usually not directly exposed in the UI. - `OBS_SERVICE_UNCOMMON`: The service can be hidden behind a "Show All/More" option UI/UX-wise. - `const char *supported_protocols`: Protocol supported by the service. + - `void (*get_defaults2)(void *type_data, obs_data_t *settings)`: Same as its non-2 variant but give access to the `type_data` pointer. - `obs_properties_t *(*get_properties2)(void *data, void *type_data)`: Same as its non-2 variant but give access to the `type_data` pointer. -**TODO: Adding `get_default2()` functions for service might be required.** - ### `rtmp-services` Services provided by this plugin (`"rtmp_custom"`, `"rtmp_common"`) will be deprecated (`OBS_SERVICE_DEPRECATED` and `OBS_SERVICE_INTERNAL` applied) and completely unused in OBS Studio. @@ -160,9 +158,9 @@ The maintenance of the code of those services after implementation will be on th If `streamService.json` is not found, it will be generated from `service.json` if available. -**Downgrade will break service configuration** -A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the `service.json` to a new one. +A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the service to a new one. +**Downgrade might break service integration** Auth integration config inside `basic.ini` will be also transfered under a new section if in service settings. ### Integrations @@ -347,7 +345,7 @@ The old actually looks like this: #### Issues with this format - About `"output"`, OBS consider every service as RTMP if not added and it's not a recommended settings at all. It makes OBS use the right protocol for the service. Also this prevent a service of being multi-protocol. -- About `"recommended"`, most of the options seems to H264 related +- About `"recommended"`, most of the options seems to H264 related and are mostly only maximums. - `"common"`, the name makes it not understandable at the first sight maybe adding some documention would be good thing. ### New format (WIP) From 222a2873eb8bac4c076f0499b0604765fd75df82 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sat, 13 May 2023 16:31:14 +0200 Subject: [PATCH 23/36] Add audio track capability --- text/0039-service-overhaul.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 6a782a6..fbe8c56 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -75,9 +75,15 @@ Adding to `obs_service_info`: - `OBS_SERVICE_INTERNAL`: The service is meant to be used internally in some plugin (e.g., WebSocket, Scripting) and usually not directly exposed in the UI. - `OBS_SERVICE_UNCOMMON`: The service can be hidden behind a "Show All/More" option UI/UX-wise. - `const char *supported_protocols`: Protocol supported by the service. + - `enum obs_service_audio_track_cap (*get_audio_track_cap)(void *data)`: Returns the service audio track capability with the following possible values: + - `OBS_SERVICE_AUDIO_SINGLE_TRACK` - Only a single audio track is used by the service + - `OBS_SERVICE_AUDIO_ARCHIVE_TRACK` - A second audio track is accepted and is meant to become the archive/VOD audio + - `OBS_SERVICE_AUDIO_MULTI_TRACK` - Supports multiple audio tracks - `void (*get_defaults2)(void *type_data, obs_data_t *settings)`: Same as its non-2 variant but give access to the `type_data` pointer. - `obs_properties_t *(*get_properties2)(void *data, void *type_data)`: Same as its non-2 variant but give access to the `type_data` pointer. +TODO: List functions added to the Services API + ### `rtmp-services` Services provided by this plugin (`"rtmp_custom"`, `"rtmp_common"`) will be deprecated (`OBS_SERVICE_DEPRECATED` and `OBS_SERVICE_INTERNAL` applied) and completely unused in OBS Studio. From 8acfc4a8affe5db63ae9fa6ca0521c65782bcfc3 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sat, 20 May 2023 16:38:43 +0200 Subject: [PATCH 24/36] Update special case services --- text/0039-service-overhaul.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index fbe8c56..d0ea6e2 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -140,21 +140,19 @@ Only improvements will be accepted in the code of this plugin. - Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). - Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new first-party plugin and keep the same id. The change will be seamless for the user if done properly. -### Special case plugins +### Plugin for special case services -Those plugins are meant to provide replacements for `"rtmp_common"` type for services that were working around the JSON usually by adding ingest management code and is not a service with an integration. - -So those services that match those will have their own plugin. +This plugins is meant to provide replacements for `"rtmp_common"` type for services that were working around the JSON usually by adding ingest management code (except Twitch). 4 services are concerned: - Dacast - Nimo TV - SHOWROOM -- YouNow (FTL only, also falls under the FTL deprecation cycle) +- YouNow (FTL only, so falls under the FTL deprecation cycle) Beside the `"rtmp_common"` part being replace by a unique service type, most of the ingest code will stay identical. -The maintenance of the code of those services after implementation will be on the organisation that originaly added them to `rtmp-services`. +This plugin is not meant to be maintained by OBS Project, but as a temporary measure until those services create their own third-party plugins. So all of those services will be put in deprecation. ### Conversion from old services From c5845e2d142b6d25088dc38b872b52b2d1143ca1 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 21 May 2023 20:13:49 +0200 Subject: [PATCH 25/36] Add behavior is plugin is removed --- text/0039-service-overhaul.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index d0ea6e2..b514a05 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -268,6 +268,9 @@ YouTube is not the only service that could have or need a "Manage Broadcast" but #### Twitch VOD track This will be the **only one** custom feature that will be allowed in OBS Studio UI code. +### If the saved service id is not registered becuase the plugin is longer there +OBS Studio will fallback to an empty `"custom_service"` with a message for the user explaining that maybe a plugin is missing. + ## Service JSON for `obs-services` ### Old version from `rtmp-services` From 43a1220323493e68f3c647391edad5f73df6dbb0 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Mon, 22 May 2023 16:26:30 +0200 Subject: [PATCH 26/36] Little changes --- text/0039-service-overhaul.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index b514a05..6c163c4 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -164,6 +164,8 @@ If `streamService.json` is not found, it will be generated from `service.json` i A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the service to a new one. +**TODO: Some user might have a removed service (e.g., Mixer)** + **Downgrade might break service integration** Auth integration config inside `basic.ini` will be also transfered under a new section if in service settings. @@ -187,16 +189,16 @@ Making it per profile could avoid this. Integrations docks will be added after specific frontend event. So after each of them the dock state needs to be restored. -- `OBS_FRONTEND_EVENT_FINISHING_LOADING` (finish**ing** not finished) needs to be created to allow adding docks. And restore dock state before if docks are indeed added before `OBS_FRONTEND_EVENT_FINISHED_LOADING` is emitted. +- The initial restoration of the profile dock state will be moved just after `OBS_FRONTEND_EVENT_FINISHED_LOADING`. - `OBS_FRONTEND_EVENT_PROFILE_CHANGED`, profile dock state will be loaded after a profile is changes. Also they will be removed after specific frontend event. So before each of them the dock state needs to be saved. -- `OBS_FRONTEND_EVENT_PROFILE_CHANGING`, profile dock state will be saved before a profile is changes. +- `OBS_FRONTEND_EVENT_PROFILE_CHANGING`, profile dock state will be saved before a profile is changed. -- `OBS_FRONTEND_EVENT_EXIT`, profile dock state will be saved before while OBS is exiting. +- `OBS_FRONTEND_EVENT_EXIT`, profile dock state must be saved before this event while OBS is exiting. #### Dock addition (**The concept needs to be tested**) @@ -213,7 +215,7 @@ A variant of `obs_service_create()` to spawn signal-less (and maybe even private The plugin will have to store if `OBS_FRONTEND_EVENT_FINISHED_LOADING` was passed or not. -If created before `OBS_FRONTEND_EVENT_FINISHED_LOADING`, a front-event callback will be added to react to `OBS_FRONTEND_EVENT_FINISHING_LOADING` to add docks (if integration connected) and then removed itself. +If created before `OBS_FRONTEND_EVENT_FINISHED_LOADING`, a front-event callback will be added to react to to later event to add docks (if integration connected). When created/updated (after `OBS_FRONTEND_EVENT_FINISHED_LOADING`) the service will add the docks (if integration connected). From c1dee72b220f7910bc4a269141a23ad0b3d84fd0 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 25 May 2023 14:26:51 +0200 Subject: [PATCH 27/36] Various changes --- text/0039-service-overhaul.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 6c163c4..e366fb0 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -9,13 +9,13 @@ Actually even if OBS has the Service API, developer can't create third-party service plugin because there is no mechanism to use them at all. -Before OBS in the Stream settings page, property views were used for services but with only two registered services `rtmp_common` which contain all services and `rtmp_custom` for custom servers. +Before in OBS in the Stream settings page, property views were used for services but with only two registered services `rtmp_common` which contain all services and `rtmp_custom` for custom servers. -Nowadays in OBS, this page show the list of services with many new elements showed of hidden depending of the selection (like recommended settings). With also Twitch and Restream OAuth integrations. And no use of the property views provided by `rtmp-services`. +Currently in OBS, this page shows the list of services with many new elements shown or hidden depending on the selection (like recommended settings). With also Twitch and Restream OAuth integrations. And no use of the property views provided by `rtmp-services`. This need to be refactored to re-introduce property views for the service and for the protocol output. -This will also provide the ability for some stream services to be able to made their own plugin. +This will also provide the ability for some stream services to be able to make their own plugin. # Design @@ -34,7 +34,7 @@ This streaming output will be selected through the settings windows and no longe The service output settings (if any) will be saved in the `service.json` file. -Advanced network settings will also be replace by the output properties view below the service properties view, since those are meant for `"rtmp_output"` (RTMP(S) output). +Advanced network settings will also be replaced by the output properties view below the service properties view, since those are meant for `"rtmp_output"` (RTMP(S) output). **TODO/REDO: All services must at least be compatible with H264 because of how simple output mode is designed.** @@ -57,7 +57,7 @@ TODO: Think about recommendation ## Frontend API Those functions will be modified: -- `obs_frontend_set_streaming_service()` because the output selection is done in the settings windows and is no longer done while the stream is starting will now swap the output if the service protocol and the actual output does not match. +- `obs_frontend_set_streaming_service()` because while the output selection is done in the settings windows and is no longer done while the stream is starting will now swap the output if the service protocol and the actual output does not match. - `obs_frontend_save_streaming_service()` will save service output settings. ## About the FTL protocol @@ -95,21 +95,21 @@ Its service JSON will no longer be updated. ### `custom-services` -If OBS Studio need to be heavily dependent to one service plugin, it must be this one. +If OBS Studio needs to be heavily dependent on one service plugin, it must be this one. This plugin is meant to provide replacements for the `"rtmp_custom"` type. #### `"custom_service"` -This the only service of this plugin thar will be exposed to the user through the UI. +This the only service of this plugin that will be exposed to the user through the UI. The protocol will be selected by the user and the properties view will change depending of the protocol. -This service will all first-party protocol, the properties view will change visible fields depending on the protocol. +This service will support all first-party protocols, the properties view will change visible fields according to the protocol. -And also support any third-party protocol by allowing to choose which fields (e.g., username + password, stream key, custom field…) to add in the view. +And also support any third-party protocols by allowing to choose which fields (e.g., username + password, stream key, custom field…) to add in the view. -This service will be registered in the "post load module" step (`obs_post_load_modules()`) to make the service aware of all registered protocol in the "load module" step. +This service will be registered in the "post load module" step (`obs_post_load_modules()`) to make the service aware of all registered protocols in the "load module" step. #### Custom type per protocol @@ -120,7 +120,7 @@ The flag `OBS_SERVICE_INTERNAL` will be applied to not show them in the UI list. ### `obs-services` -This plugin is meant to provide a replacements for `"rtmp_common"` type for services who doesn't have custom behavior or integration. +This plugin is meant to provide a replacement for `"rtmp_common"` type for services who don't rely on custom behavior nor integration. This plugin will need a brand new services.json with new format, to register each streaming service with their own id. No more things like `"rtmp_common"` id. @@ -173,17 +173,17 @@ Auth integration config inside `basic.ini` will be also transfered under a new s Twitch, YouTube and Restream have their own integration in OBS with OAuth. But those need to be isolated as plugins. -Those will plugins will provide the basic and OAuth version of the services as one services. +Those plugins will provide the basic and OAuth version of the services as one services. If OBS is built without client ids and hashes, those plugins will be built without their integration. #### Dock state -Actually the dock state is global in the config, but with docks that appear depending on the service which is per profile which is still "also" the case with "old" integrations. +Actually the dock state is global (same on any profile). But with docks that appear depending on the service integration which is per profile. -This can lead to dock state losses between profile switching and exiting. The "old" integration actually store a dock state in the profile config and restore it after the integration is is loaded. +This can lead to dock state losses between profile switching and exiting. Currents integrations actually store a dock state in the profile config and restore it after the integration is loaded. -But making restoring a dock state from a plugin should should not be considered at all. +But restoring a dock state from a plugin must not be considered at all. Making it per profile could avoid this. Integrations docks will be added after specific frontend event. From 51254e9f041c2ebbf16a9c880880fc49a816811d Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 25 May 2023 14:28:52 +0200 Subject: [PATCH 28/36] Forgot to fix this one --- text/0039-service-overhaul.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index e366fb0..ca8caac 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -57,7 +57,7 @@ TODO: Think about recommendation ## Frontend API Those functions will be modified: -- `obs_frontend_set_streaming_service()` because while the output selection is done in the settings windows and is no longer done while the stream is starting will now swap the output if the service protocol and the actual output does not match. +- `obs_frontend_set_streaming_service()` because while the output selection is done in the settings windows and is no longer done while the stream is starting will now swap the output if the service protocol and the actual output do not match. - `obs_frontend_save_streaming_service()` will save service output settings. ## About the FTL protocol From a20784dde223ff512fa440f8ae650bf57acb4f12 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 22 Jun 2023 11:13:29 +0200 Subject: [PATCH 29/36] Docks; browser (WIP), broadcast flow --- text/0039-service-overhaul.md | 93 +++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 21 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index ca8caac..9c04580 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -204,24 +204,15 @@ So before each of them the dock state needs to be saved. Integration plugins will need events/signals to be able to add and remove their docks at the right moment. +The plugin will have to store if `OBS_FRONTEND_EVENT_FINISHED_LOADING` or `OBS_FRONTEND_EVENT_PROFILE_CHANGED` was passed or not. -3 signals will be added to Core OBS signaling: +If created before these events, the plugin will wait their emission to add docks (if integration connected). -- "service_create (ptr service)" -- "service_update (ptr service)" -- "service_destroy (ptr service)" - -A variant of `obs_service_create()` to spawn signal-less (and maybe even private) service will be needed to allow protocol checking in settings. - -The plugin will have to store if `OBS_FRONTEND_EVENT_FINISHED_LOADING` was passed or not. - -If created before `OBS_FRONTEND_EVENT_FINISHED_LOADING`, a front-event callback will be added to react to to later event to add docks (if integration connected). - -When created/updated (after `OBS_FRONTEND_EVENT_FINISHED_LOADING`) the service will add the docks (if integration connected). +When created/updated (after these events) the service will add the docks (if integration connected). When `OBS_FRONTEND_EVENT_PROFILE_CHANGING` `OBS_FRONTEND_EVENT_EXIT` or the service is destroyed, docks will be removed (if integration connected). -#### Browser features +#### Browser features (MORE CHANGES INCOMMING) The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks and generating widgets. Note: Free functions for each structure that requires it because of a "dynamic" type will be also added. @@ -253,19 +244,79 @@ struct obs_frontend_browser_params { - `DARRAY(struct obs_frontend_browser_connect) title_changed` allow to connect QCefWidget `titleChanged()` signal to a slot - `DARRAY(struct obs_frontend_browser_connect) url_changed` allow to connect QCefWidget `urlChanged()` signal to a slot -`bool obs_frontend_add_browser_dock(const char *id, const char *title, struct obs_frontend_browser_dock *params)` is the function that will add those browser docks to the UI. - -`void *obs_frontend_create_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). +`void *obs_frontend_get_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). `void obs_frontend_delete_browser_cookie(const char *url)` will remove cookies related to the given URL. -#### Broadcast flow (WIP) -YouTube is not the only service that could have or need a "Manage Broadcast" button. So adding a way to make other service plugin able to use it. +#### Broadcast flow +YouTube is not the only service that could have or need a "Manage Broadcast" button but the feature/flow is actually made only for how YouTube works. + +So refactoring it to make service plugin able to use it without enforcing YouTube flow on them is required. + +Inside the Frontend API: + + - `void obs_frontend_add_broadcast_flow(const obs_service_t *service, const struct obs_frontend_broadcast_flow *flow)` adds a broacast flow bound the given service. If the given service is actually the same service as OBS Studio use, the broadcast flow will be enabled. + + - `void obs_frontend_remove_broadcast_flow(const obs_service_t *service)` removes the broadcast flow. If the given service is actually the same service as OBS Studio use, the broadcast flow will be dsiabled. + +```c +struct obs_frontend_broadcast_flow { + void *priv; + + uint32_t flags; + + enum obs_broadcast_state (*get_broadcast_state)(void *priv); + enum obs_broadcast_start (*get_broadcast_start_type)(void *priv); + enum obs_broadcast_stop (*get_broadcast_stop_type)(void *priv); + + void (*manage_broadcast)(void *priv); + void (*manage_broadcast2)(void *priv, bool streaming_active); + + void (*stopped_streaming)(void *priv); + + void (*differed_start_broadcast)(void *priv); + enum obs_broadcast_stream_state (*is_broadcast_stream_active)(void *priv); + + bool (*differed_stop_broadcast)(void *priv); + + const char *(*get_last_error)(void *priv); +}; +``` + +- `uint32_t flags` with the following flags: + - `OBS_BROADCAST_FLOW_ALLOW_MANAGE_WHILE_STREAMING`, the flow allow managing broadcast while streaming + - `OBS_BROADCAST_FLOW_ALLOW_DIFFERED_BROADCAST_START`, the flow can set broadcast that require to be started after the streaming is started. + - `OBS_BROADCAST_FLOW_ALLOW_DIFFERED_BROADCAST_STOP`, the flow can set broadcast that require to be stopped after the streaming is stopped. + +- `enum obs_broadcast_state (*get_broadcast_state)(void *priv)` return the state of the broadcast: + - `OBS_BROADCAST_NONE`, no broadcast is setup + - `OBS_BROADCAST_ACTIVE`, the broacast is active + - `OBS_BROADCAST_INACTIVE`, the broadcast will need a differed start + +- `enum obs_broadcast_start (*get_broadcast_start_type)(void *priv)` return the start type of the broadcast: + - `OBS_BROADCAST_START_WITH_STREAM`, the broadcast start with the stream + - `OBS_BROADCAST_START_WITH_STREAM_NOW`, same as the previous but streaming is also started + - `OBS_BROADCAST_START_DIFFER_FROM_STREAM`, the broadcast will need a differed start + +- `enum obs_broadcast_stop (*get_broadcast_stop_type)(void *priv)` return the stop type of the broadcast: + - `OBS_BROADCAST_STOP_NEVER`, the broadcast is not meant to be ended + - `OBS_BROADCAST_STOP_WITH_STREAM`, the broadcast is ended with the stream + - `OBS_BROADCAST_STOP_DIFFER_FROM_STREAM`,the broadcast will need a differed stop + +- `void (*manage_broadcast)(void *priv)` and `void (*manage_broadcast2)(void *priv, bool streaming_active)`, callcack to create and show the service broadcast manager. The `2` variant allows to open it while streaming. + +- `void (*stopped_streaming)(void *priv)`, signal to the flow that the broadcast has stopped allowing to change state if needed + +- `void (*differed_start_broadcast)(void *priv)`, start the broadcast if differed. If the broadcast is not updated to active, the broadcast failed to start. If success OBS Studio will run a thread with the next callback to wait for the stream to be active. + +- `enum obs_broadcast_stream_state (*is_broadcast_stream_active)(void *priv)` return the state of the broadcast stream: + - `OBS_BROADCAST_STREAM_FAILURE`, stream has failed to be started + - `OBS_BROADCAST_STREAM_INACTIVE`, stream is not started + - `OBS_BROADCAST_STREAM_ACTIVE`, stream is started -- Add a callback bond to a service pointer meant to be called when the "Manage Broadcast" button is clicked. -- Add a callback setter in the frontend-api which will make the button show up. -- Add a callback unsetter in the frontend-api which disable the button. +- `bool (*differed_stop_broadcast)(void *priv)`, stop the broadcast if differred. Returns `true` if it succeeded +- `const char *(*get_last_error)(void *priv)`, return the last error if differed callbacks failed. #### Twitch VOD track This will be the **only one** custom feature that will be allowed in OBS Studio UI code. From 28abb35f5c12afde5002fdfefda1b258c0ad2259 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 22 Jun 2023 16:45:16 +0200 Subject: [PATCH 30/36] VOD track and bandwidth test --- text/0039-service-overhaul.md | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 9c04580..70d01b6 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -81,6 +81,9 @@ Adding to `obs_service_info`: - `OBS_SERVICE_AUDIO_MULTI_TRACK` - Supports multiple audio tracks - `void (*get_defaults2)(void *type_data, obs_data_t *settings)`: Same as its non-2 variant but give access to the `type_data` pointer. - `obs_properties_t *(*get_properties2)(void *data, void *type_data)`: Same as its non-2 variant but give access to the `type_data` pointer. + - `bool (*can_bandwidth_test)(void *data)`: Return if the service is able to do bandwith test + - `void (*enable_bandwidth_test)(void *data, bool enabled)`: Enable bandwidth test on the service + - `bool (*bandwidth_test_enabled)(void *data)`: Return if the service has the bandwidth test enabled TODO: List functions added to the Services API @@ -200,7 +203,7 @@ So before each of them the dock state needs to be saved. - `OBS_FRONTEND_EVENT_EXIT`, profile dock state must be saved before this event while OBS is exiting. -#### Dock addition (**The concept needs to be tested**) +#### Dock addition Integration plugins will need events/signals to be able to add and remove their docks at the right moment. @@ -219,30 +222,19 @@ Note: Free functions for each structure that requires it because of a "dynamic" `bool obs_frontend_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. -CEF should be initialised after `OBS_FRONTEND_EVENT_FINISHED_LOADING`. - ```C++ -struct obs_frontend_browser_connect { - void *qobject; // QObject - const char *slot; // SLOT() -}; - struct obs_frontend_browser_params { const char *url; - bool enable_cookie; - struct dstr startup_script; - DARRAY(char *) force_popup_url; - DARRAY(struct obs_frontend_browser_connect) title_changed; - DARRAY(struct obs_frontend_browser_connect) url_changed; + const char *startup_script; + const char **force_popup_url; + bool enable_cookie; }; ``` - `const char *url`, URL of the dock. +- `const char *startup_script` allow to set a startup script for the dock. +- `const char **force_popup_url` allow to set a list of URL to force those to popup. - `bool enable_cookie`, if true `panel_cookie` will be set on the dock rather than a `nullptr`. This will allow to keep cookie which is required. -- `struct dstr startup_script` allow to set a startup script for the dock. -- `DARRAY(char *) force_popup_url` allow to set a list of URL to force those to popup. -- `DARRAY(struct obs_frontend_browser_connect) title_changed` allow to connect QCefWidget `titleChanged()` signal to a slot -- `DARRAY(struct obs_frontend_browser_connect) url_changed` allow to connect QCefWidget `urlChanged()` signal to a slot `void *obs_frontend_get_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). @@ -318,8 +310,11 @@ struct obs_frontend_broadcast_flow { - `const char *(*get_last_error)(void *priv)`, return the last error if differed callbacks failed. +#### Twitch and YouTube bandwidth test +Those services have code in the UI to have such feature, it will now be moved to their respective services with the new Services API related to bandwidth test. + #### Twitch VOD track -This will be the **only one** custom feature that will be allowed in OBS Studio UI code. +This Twitch-only feature will be modified to rely on `obs_service_audio_track_cap` rather than the service name. ### If the saved service id is not registered becuase the plugin is longer there OBS Studio will fallback to an empty `"custom_service"` with a message for the user explaining that maybe a plugin is missing. From 5ee582a29caf0d78075c4b29f806b91958506237 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 6 Jul 2023 17:56:07 +0200 Subject: [PATCH 31/36] Some stuff --- text/0039-service-overhaul.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 70d01b6..28228d5 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -30,14 +30,12 @@ Many elements of the settings UI related to services will be moved inside servic - "Get Stream Key" button - "More Info" button -This streaming output will be selected through the settings windows and no longer auto-selected while starting the stream and its property view will be placed below the service properties view. +The streaming output will be selected through the settings windows and its property view will be placed below the service properties view. -The service output settings (if any) will be saved in the `service.json` file. +The service output settings (if any) will be saved as a JSON string in the profile config file. Advanced network settings will also be replaced by the output properties view below the service properties view, since those are meant for `"rtmp_output"` (RTMP(S) output). -**TODO/REDO: All services must at least be compatible with H264 because of how simple output mode is designed.** - ### Common, uncommon Spoiler: Streaming services will be individually registered, so no more `rtmp_common` that represent various services. @@ -84,6 +82,9 @@ Adding to `obs_service_info`: - `bool (*can_bandwidth_test)(void *data)`: Return if the service is able to do bandwith test - `void (*enable_bandwidth_test)(void *data, bool enabled)`: Enable bandwidth test on the service - `bool (*bandwidth_test_enabled)(void *data)`: Return if the service has the bandwidth test enabled + - `void (*get_supported_resolutions2)(void *data, struct obs_service_resolution **resolutions,size_t *count, bool *with_fps)`: Replace its non-two variant to enable framerate value + - `int (*get_max_video_bitrate)(void *data, const char *codec struct obs_service_resolution resolution)`: Return a maximum bitrate based on a video codec and a resolution + - `int (*get_max_codec_bitrate)(void *data, const char *codec)`: Return a maximum bitrate for a specific codec TODO: List functions added to the Services API @@ -139,7 +140,6 @@ Only improvements will be accepted in the code of this plugin. #### Service ID naming scheme - Only lower case letter -- (**Might be removed**) All prefixed by `obs-` in code, to avoid potential id conflict with streaming service third-party plugins. - Hyphen `-` are only used to distinguish two service providing the same stream service but with noteworthy differences like NicoNico (free & premium). - Like this if the service needs a specific behavior, you can 'transfer' it from `obs-services` to a new first-party plugin and keep the same id. The change will be seamless for the user if done properly. @@ -167,10 +167,9 @@ If `streamService.json` is not found, it will be generated from `service.json` i A JSON or a harcoded list with old service name linked to their new id, to make OBS able to convert the service to a new one. -**TODO: Some user might have a removed service (e.g., Mixer)** +If the user had an no longer available service, the user will be switch to `custom_service`. -**Downgrade might break service integration** -Auth integration config inside `basic.ini` will be also transfered under a new section if in service settings. +Integration settings will be migrated to their respective config file. ### Integrations @@ -227,6 +226,7 @@ struct obs_frontend_browser_params { const char *url; const char *startup_script; const char **force_popup_url; + const char **popup_whitelist_urls; bool enable_cookie; }; ``` @@ -234,6 +234,7 @@ struct obs_frontend_browser_params { - `const char *url`, URL of the dock. - `const char *startup_script` allow to set a startup script for the dock. - `const char **force_popup_url` allow to set a list of URL to force those to popup. +- `const char **popup_whitelist_urls` allow to set a list of URL to popup whitelist. - `bool enable_cookie`, if true `panel_cookie` will be set on the dock rather than a `nullptr`. This will allow to keep cookie which is required. `void *obs_frontend_get_browser_widget(struct obs_frontend_browser_params *params)` is the function that will return a browser widget (QCefWidget) that we can cast to a QWidget for OAuth or a custom chat dock (e.g. Youtube). @@ -410,7 +411,7 @@ The new format will rely on more strict JSON schemas. Those JSON Schemas (Draft 2020-12) will be: - `protocolDefs.json`: enums, regex patterns and properties related to protocols to ease protocol additions or removals in schemas - `codecDefs.json`: enums, regex patterns and properties related to codecs to ease codec additions or removals in schemas -- `service.json`: define the service object itself, will be used for every service plugin htat needs a JSON +- `service.json`: define the service object itself, will be used for every service plugin that needs a JSON - `obs-services.json`: `obs-services` JSON Schema Those are all present in `0039-json-schemas` folder with an example of `obs-services` JSON. From 0f9c0ff719f7620facc9ae83a71b76214bf1c86e Mon Sep 17 00:00:00 2001 From: tytan652 Date: Fri, 7 Jul 2023 17:54:52 +0200 Subject: [PATCH 32/36] Some stuff --- text/0039-service-overhaul.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 28228d5..cfb5ba6 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -85,6 +85,7 @@ Adding to `obs_service_info`: - `void (*get_supported_resolutions2)(void *data, struct obs_service_resolution **resolutions,size_t *count, bool *with_fps)`: Replace its non-two variant to enable framerate value - `int (*get_max_video_bitrate)(void *data, const char *codec struct obs_service_resolution resolution)`: Return a maximum bitrate based on a video codec and a resolution - `int (*get_max_codec_bitrate)(void *data, const char *codec)`: Return a maximum bitrate for a specific codec + - `void (*apply_encoder_settings2)(void *data, const char *encoder_id, obs_data_t *encoder_settings)`: Replace its non-two variant to enable settings per encoder id and codec TODO: List functions added to the Services API @@ -426,7 +427,7 @@ The use of JSON Schema allows to create specific additions for a specific plugin - Recommended settings are really recommended settings. - Recommendation and maximums are two separated thing. -- Some settings are now per protocol or per codec, this allow multi-protocol service to be registered under only one id. This will also need to a way to know which codec is used when applying settings. +- Some settings are now per protocol or per codec, this allow multi-protocol service to be registered under only one id. This will also need a way to know which codec is used when applying settings. - Name can be changed without consequences. # Drawbacks From f4c31421151f662d09a363f4ffd0c9a95fcae050 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sat, 8 Jul 2023 18:31:15 +0200 Subject: [PATCH 33/36] Cleanup --- text/0039-json-schemas/codecDefs.json | 2 +- text/0039-json-schemas/obs-services.json | 13 +++++- text/0039-json-schemas/protocolDefs.json | 8 +--- text/0039-json-schemas/service.json | 52 +----------------------- text/0039-service-overhaul.md | 22 ++-------- 5 files changed, 20 insertions(+), 77 deletions(-) diff --git a/text/0039-json-schemas/codecDefs.json b/text/0039-json-schemas/codecDefs.json index c1fcc9f..894b1de 100644 --- a/text/0039-json-schemas/codecDefs.json +++ b/text/0039-json-schemas/codecDefs.json @@ -25,7 +25,7 @@ "properties": { "profile": { "type": "string", - "title": "Profile", + "title": "H264 Profile", "enum": [ "baseline", "main", "high" ] }, "keyint": { diff --git a/text/0039-json-schemas/obs-services.json b/text/0039-json-schemas/obs-services.json index ccff171..8701e11 100644 --- a/text/0039-json-schemas/obs-services.json +++ b/text/0039-json-schemas/obs-services.json @@ -33,12 +33,23 @@ "title": "Property reserved to OBS Project developers", "description": "Whether or not the service is shown in the list before it is expanded to all services by the user.", "default": false + }, + "github_logins": { + "type": "array", + "title": "Github logins", + "description": "Login to ping on Github when the services check is failing.\n 'obsproject' is used as a placeholder.", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true, + "additionalItems": false } }, "$commit": "Forbid 'common' being set if false", "if": { "properties": { "common": { "const": false } } }, "then": { "properties": { "common": { "description": "This property is unneeded if set to false" , "const": true } } }, - "required": ["id","name"] + "required": ["id","name", "github_logins"] }, { "$comment": "Add base service JSON schema", diff --git a/text/0039-json-schemas/protocolDefs.json b/text/0039-json-schemas/protocolDefs.json index e527c8a..a7a19e6 100644 --- a/text/0039-json-schemas/protocolDefs.json +++ b/text/0039-json-schemas/protocolDefs.json @@ -7,20 +7,16 @@ "$defs": { "protocolEnum": { "$comment": "Enumeration of protocols", - "enum": ["RTMP","RTMPS","FTL","HLS","SRT","RIST"] + "enum": ["RTMP","RTMPS","HLS","SRT","RIST","WHIP"] }, "protocolMapEnum": { "$comment": "Enumeration of protocols (with '*' as any) that have various compatible codecs", - "enum": ["*","RTMP","RTMPS","HLS","SRT","RIST"] + "enum": ["*","RTMP","RTMPS","HLS","SRT","RIST","WHIP"] }, "serverPattern": { "$comment": "Pattern to enforce a supported server URL", "pattern": "^(rtmps?|https?|srt|rist)://" }, - "notRequireProtocolPattern": { - "$comment": "Pattern meant to match with protocol that have a unique URL prefix", - "pattern": "^(rtmps?|srt|rist)://" - }, "protocolProperties": { "$comment": "Per-protocol properties meant for obs-services schema", "type": "object", diff --git a/text/0039-json-schemas/service.json b/text/0039-json-schemas/service.json index 6ee5995..d05d564 100644 --- a/text/0039-json-schemas/service.json +++ b/text/0039-json-schemas/service.json @@ -39,17 +39,11 @@ "type": "string", "title": "Server URL", "description": "URL of the ingest server.", + "format": "uri", + "$ref": "protocolDefs.json#/$defs/serverPattern", "minLength": 1 } }, - "allOf": [ - { - "$comment": "Add format and pattern through 'if' until FTL is dropped", - "if": { "properties": { "url": { "format": "uri" } } }, - "then": { "properties": { "url": { "format": "uri", "$ref": "protocolDefs.json#/$defs/serverPattern" } } }, - "else": { "properties": { "url": { "format": "hostname" } } } - } - ], "required": ["name","url","protocol"], "unevaluatedProperties": false }, @@ -208,48 +202,6 @@ "title": "Recommended settings", "description": "Settings that are applied only if the user wants to do so.", "allOf": [ - { - "properties": { - "framerate": { - "type": "integer", - "title": "Recommended Framerate", - "exclusiveMinimum": 0 - }, - "video_bitrate": { - "type": "object", - "title": "Recommended Video Bitrate", - "description": "Recommended video bitrate per codec", - "propertyNames": { "$ref": "codecDefs.json#/$defs/videoCodecEnum" }, - "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, - "minProperties": 1, - "unevaluatedProperties":false - }, - "audio_bitrate": { - "type": "object", - "title": "Recommended Audio Bitrate", - "description": "Recommended audio bitrate per codec", - "propertyNames": { "$ref": "codecDefs.json#/$defs/audioCodecEnum" }, - "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, - "minProperties": 1, - "unevaluatedProperties":false - }, - "video_bitrate_matrix": { - "type": "object", - "title": "Recommended Video Bitrate Matrix", - "description": "Recommended video bitrate per supported resolution with framerate and per codec", - "propertyNames": { "$ref": "#/$defs/resolutionFrameratePattern" }, - "additionalProperties": { - "type": "object", - "propertyNames": { "$ref": "codecDefs.json#/$defs/videoCodecEnum" }, - "additionalProperties": { "type": "integer", "exclusiveMinimum": 0 }, - "minProperties": 1, - "unevaluatedProperties":false - }, - "minProperties": 1, - "unevaluatedProperties": false - } - } - }, { "$comment": "Add codec properties", "$ref": "codecDefs.json#/$defs/codecProperties" diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index cfb5ba6..bb63526 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -44,14 +44,6 @@ So to hide services behind the "Show All" option, a flag (`OBS_SERVICE_UNCOMMON` So third-party services are shown in the list by default. -### Maximums and recommended - -Maximums and supported resolutions will be strict (e.g. Twitch allows 6000 kbps, more will not be accepted), the UI will not allow to save incompatible settings. - -This will require to introduce in the Property API a way to indicate that the settings are not valid. - -TODO: Think about recommendation - ## Frontend API Those functions will be modified: @@ -112,10 +104,6 @@ The protocol will be selected by the user and the properties view will change de This service will support all first-party protocols, the properties view will change visible fields according to the protocol. -And also support any third-party protocols by allowing to choose which fields (e.g., username + password, stream key, custom field…) to add in the view. - -This service will be registered in the "post load module" step (`obs_post_load_modules()`) to make the service aware of all registered protocols in the "load module" step. - #### Custom type per protocol Service types that support only the protocol inside their id (`"custom_`*insert lowercase protocol acronym*`"`) for any first-party protocol except FTL (deprecation). @@ -215,7 +203,7 @@ When created/updated (after these events) the service will add the docks (if int When `OBS_FRONTEND_EVENT_PROFILE_CHANGING` `OBS_FRONTEND_EVENT_EXIT` or the service is destroyed, docks will be removed (if integration connected). -#### Browser features (MORE CHANGES INCOMMING) +#### Browser features The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks and generating widgets. Note: Free functions for each structure that requires it because of a "dynamic" type will be also added. @@ -318,7 +306,7 @@ Those services have code in the UI to have such feature, it will now be moved to #### Twitch VOD track This Twitch-only feature will be modified to rely on `obs_service_audio_track_cap` rather than the service name. -### If the saved service id is not registered becuase the plugin is longer there +### If the saved service id is not registered because the plugin is longer there OBS Studio will fallback to an empty `"custom_service"` with a message for the user explaining that maybe a plugin is missing. ## Service JSON for `obs-services` @@ -405,7 +393,7 @@ The old actually looks like this: - About `"recommended"`, most of the options seems to H264 related and are mostly only maximums. - `"common"`, the name makes it not understandable at the first sight maybe adding some documention would be good thing. -### New format (WIP) +### New format The new format will rely on more strict JSON schemas. @@ -417,12 +405,8 @@ Those JSON Schemas (Draft 2020-12) will be: Those are all present in `0039-json-schemas` folder with an example of `obs-services` JSON. -*Documentation in schemas are in progress, and a schema for integration plugin should also be made.* - JSON Schema allows to validate `services.json` (in `obs-services` case) when a PR is made against it. -The use of JSON Schema allows to create specific additions for a specific plugin by creating a unique schema for it. - #### Advantages of this format - Recommended settings are really recommended settings. From 50f0f3c6255795cfcb1a26908dcdb42e983fe5e8 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sat, 8 Jul 2023 18:46:23 +0200 Subject: [PATCH 34/36] Add Services API functions --- text/0039-service-overhaul.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index bb63526..36fbb8f 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -79,7 +79,23 @@ Adding to `obs_service_info`: - `int (*get_max_codec_bitrate)(void *data, const char *codec)`: Return a maximum bitrate for a specific codec - `void (*apply_encoder_settings2)(void *data, const char *encoder_id, obs_data_t *encoder_settings)`: Replace its non-two variant to enable settings per encoder id and codec -TODO: List functions added to the Services API +Adding to the Services API: + - `enum obs_service_audio_track_cap obs_service_get_audio_track_cap(const obs_service_t *service)`: Return the service audio track capability + - `uint32_t obs_get_service_flags(const char *id)` and `uint32_t obs_service_get_flags(const obs_service_t *service)`: Return services flags + - `const char *obs_get_service_supported_protocols(const char *id)`: Return all protocols that the service can support + - `bool obs_service_can_bandwidth_test(const obs_service_t *service)`: Return if the service has bandwidth test capability + - `void obs_service_enable_bandwidth_test(const obs_service_t *service, bool enabled)`: Enable/disable the service bandwidth test + - `bool obs_service_bandwidth_test_enabled(const obs_service_t *service)`; Return if the service bandwidth test is enabled + - `int obs_service_get_max_codec_bitrate(const obs_service_t *service, const char *codec)`: Return the maximum bitrate supported by the service depending on the codec + - `void obs_service_get_supported_resolutions2( const obs_service_t *service, struct obs_service_resolution **resolutions, size_t *count, bool *with_fps)`: Return resolutions supported by the service with optional framerate + - `int obs_service_get_max_video_bitrate(const obs_service_t *service, const char *codec, struct obs_service_resolution resolution)`: Return the maximum bitrate supported by the service depending on the codec and a resolution + - `void obs_service_apply_encoder_settings2(obs_service_t *service, const char *encoder_id, obs_data_t *encoder_settings)`: Apply encoder settings for a specific encoder id + + +Deprecating in the Services API: + - `obs_service_apply_encoder_settings`: replaced by `obs_service_apply_encoder_settings2` to allow per encoder id/codec settings + - `obs_service_get_supported_resolutions`: replaced by `obs_service_get_supported_resolutions2` to enable returning framerate + - `obs_service_get_max_bitrate`: replaced by `obs_service_get_max_codec_bitrate` and `obs_service_get_max_video_bitrate` for per codec (and resolution for the second) bitrate ### `rtmp-services` From e75f4c5cfcb656b5d76bb767eedc8937acaea1ce Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 19 Jul 2023 08:18:14 +0200 Subject: [PATCH 35/36] Review fixups --- text/0039-service-overhaul.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 36fbb8f..6571bb0 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -80,7 +80,10 @@ Adding to `obs_service_info`: - `void (*apply_encoder_settings2)(void *data, const char *encoder_id, obs_data_t *encoder_settings)`: Replace its non-two variant to enable settings per encoder id and codec Adding to the Services API: - - `enum obs_service_audio_track_cap obs_service_get_audio_track_cap(const obs_service_t *service)`: Return the service audio track capability + - `enum obs_service_audio_track_cap obs_service_get_audio_track_cap(const obs_service_t *service)`: Returns the service audio track capability with the following possible values: + - `OBS_SERVICE_AUDIO_SINGLE_TRACK` - Only a single audio track is used by the service + - `OBS_SERVICE_AUDIO_ARCHIVE_TRACK` - A second audio track is accepted and is meant to become the archive/VOD audio + - `OBS_SERVICE_AUDIO_MULTI_TRACK` - Supports multiple audio tracks - `uint32_t obs_get_service_flags(const char *id)` and `uint32_t obs_service_get_flags(const obs_service_t *service)`: Return services flags - `const char *obs_get_service_supported_protocols(const char *id)`: Return all protocols that the service can support - `bool obs_service_can_bandwidth_test(const obs_service_t *service)`: Return if the service has bandwidth test capability @@ -220,11 +223,9 @@ When created/updated (after these events) the service will add the docks (if int When `OBS_FRONTEND_EVENT_PROFILE_CHANGING` `OBS_FRONTEND_EVENT_EXIT` or the service is destroyed, docks will be removed (if integration connected). #### Browser features -The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks and generating widgets. - -Note: Free functions for each structure that requires it because of a "dynamic" type will be also added. +The Front-end API needs to enable the possibility to access some `obs-browser` related feature like adding browser docks (e.g. Chat, Stream Settings) and generating widgets (e.g. login through CEF). -`bool obs_frontend_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. +`bool obs_frontend_is_browser_available()` will indicate if OBS Studio have the `obs-browser` included and available with a Wayland check on Linux/FreeBSD. This will allow plugins to know if they can use browser features. ```C++ struct obs_frontend_browser_params { From a87498f72948565e46cd2dfb8bd25f81a9c4abe7 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 19 Jul 2023 08:23:21 +0200 Subject: [PATCH 36/36] Review fixup --- text/0039-service-overhaul.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0039-service-overhaul.md b/text/0039-service-overhaul.md index 6571bb0..a638444 100644 --- a/text/0039-service-overhaul.md +++ b/text/0039-service-overhaul.md @@ -141,7 +141,7 @@ Those services will be able to provide multiple protocols so no more "Service - If a certain protocol is not available, the UI will not show it if the service doesn't support another protocol. Same goes for codecs. If it does, the missing protocol will not be shown. -Those services should have no specific behavior like ingest management. +Those services should have no custom behavior like ingest management like it was done it `rtmp-services` plugin. In the end, adding streaming service will only be a JSON addition for this plugin. Only improvements will be accepted in the code of this plugin.