diff --git a/doc/mediaunit_logo_black.png b/.github/images/mediaunit_logo_black.png similarity index 100% rename from doc/mediaunit_logo_black.png rename to .github/images/mediaunit_logo_black.png diff --git a/doc/supportclass_logo_blacktext.png b/.github/images/supportclass_logo_blacktext.png similarity index 100% rename from doc/supportclass_logo_blacktext.png rename to .github/images/supportclass_logo_blacktext.png diff --git a/.gitignore b/.gitignore index bb3e027a..599feb88 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ /build64/ /release/ /installer/Output/ + +.vscode \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 1e9905aa..aa7df423 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,4 @@ language: cpp -branches: - except: - - gh-pages env: global: @@ -10,8 +7,15 @@ env: # AWS key secret - secure: bGwljoP3E1OVBXLXox0O6p8kwQXLcNQ8YDKVa4H8u9Y+Ic7uqE4iV3rYS3ynNWSBMVRWY3ZbyClnhrCNwRhBAlcd8qWSJdpjVzs6HdQyzhuKa1P3V4FJPb7upGP/5R/DECGwex8Mun9dmXpYDak75LxfKIJUidPis5VDCYqul7k/xVVCou6Ctjpj7vQhWXDj2G/py+mdB8DERhymnQCtyK1Ziu8c4QlFKByZmnD72GFm/h3JPI1Pq1V2mz3x6x6GaYjb9Rdbd0UNwqjGQX4q2M/c3GEJa6B2JBCoTncawNZBNnPUF9qtv+zh0TNaNHMRWX13AJ/qYB+nVDub0C9b/6Mc48mt0Tv4ze15MproVrylZdV6qHYEG8yGPBqpTVbRP6gv6Y2TXIHWoTzqA+F/Gv2IDChyHXsld/MQQS2MSo5iaYktIrZKtX8Z0qAmTzPwIVBromaSI3vrE7UH0fRSQ6fAM8+Tn+MRthOBdqu23kS1dnG+X2CPbUhBfsJp0OSwVQD5jQtA51/sREVeGFiJvzQIkvwQDjb5MYilsRnwmoBXemkLmqaviXVY4rz1o5AIvz2pgZS2YggK1xHZCuI5tSjcNEkb77VwZTfsqrdDo9EJh6VgfdnGlHQhR2/A5hUJ4ANpJ/LgZlgfVp71Xg2GWQW6M4Znc5uj6A6xLBkO6FA= +cache: + directories: + - node_modules + matrix: include: + - os: linux + script: "./CI/generate-docs.sh" + - os: linux dist: trusty sudo: required @@ -30,7 +34,8 @@ matrix: osx_image: xcode8.3 before_install: "./CI/install-dependencies-osx.sh" script: "./CI/build-osx.sh" - after_success: "./CI/package-osx.sh" + after_success: + - ./CI/package-osx.sh deploy: - provider: s3 @@ -43,7 +48,9 @@ deploy: acl: public_read on: repo: Palakis/obs-websocket - condition: "$TRAVIS_OS_NAME = linux" + condition: + - "$TRAVIS_OS_NAME = linux" + - "-d /home/travis/package" all_branches: true - provider: s3 region: eu-central-1 diff --git a/CI/generate-docs.sh b/CI/generate-docs.sh new file mode 100755 index 00000000..54b07dd9 --- /dev/null +++ b/CI/generate-docs.sh @@ -0,0 +1,32 @@ +#!/bin/bash +echo "-- Generating documentation." +echo "-- Node version: $(node -v)" +echo "-- NPM version: $(npm -v)" + +cd docs +npm install +npm run build + +echo "-- Documentation successfully generated." + +if git diff --quiet; then + echo "-- No documentation changes to commit." + exit 0 +fi + +if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "master" ]; then + echo "-- Skipping documentation deployment because this is either a pull request or a non-master branch." + exit 0 +fi + +REMOTE_URL="$(git config remote.origin.url)" +TARGET_REPO=${REMOTE_URL/https:\/\/github.com\//github.com/} +GITHUB_REPO=https://${GH_TOKEN:-git}@${TARGET_REPO} + +git config user.name "Travis CI" +git config user.email "$COMMIT_AUTHOR_EMAIL" + +git add ./generated +git pull +git commit -m "docs(travis): Update protocol.md - $(git rev-parse --short HEAD) [skip ci]" +git push -q $GITHUB_REPO HEAD:$TRAVIS_BRANCH diff --git a/PROTOCOL.md b/PROTOCOL.md deleted file mode 100644 index 41dea2fd..00000000 --- a/PROTOCOL.md +++ /dev/null @@ -1,1004 +0,0 @@ -obs-websocket 4.1 protocol reference -================================ -**This is the reference for the latest 4.1 developement build. [See here for obs-websocket 4.0.0!](https://github.com/Palakis/obs-websocket/blob/4.0.0/PROTOCOL.md)** - -## General Introduction -Messages exchanged between the client and the server are JSON objects. -The protocol in general is based on the OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio. - -### Table of contents -* [Authentication](#authentication) -* [Events](#events) - - [Description](#description) - - [Event Types](#event-types) - - **Scenes** - - ["SwitchScenes"](#switchscenes) - - ["ScenesChanged"](#sceneschanged) - - **Scene Items** - - ["SourceOrderChanged"](#sourceorderchanged) - - ["SceneItemAdded"](#sceneitemadded) - - ["SceneItemRemoved"](#sceneitemremoved) - - ["SceneItemVisibilityChanged"](#sceneitemvisibilitychanged) - - **Scene Collections** - - ["SceneCollectionChanged"](#scenecollectionchanged) - - ["SceneCollectionListChanged"](#scenecollectionlistchanged) - - **Transitions** - - ["SwitchTransition"](#switchtransition) - - ["TransitionDurationChanged"](#transitiondurationchanged) - - ["TransitionListChanged"](#transitionlistchanged) - - ["TransitionBegin"](#transitionbegin) - - **Studio Mode** - - ["PreviewSceneChanged"](#previewscenechanged) - - ["StudioModeSwitched"](#studiomodeswitched) - - **Profiles** - - ["ProfileChanged"](#profilechanged) - - ["ProfileListChanged"](#profilelistchanged) - - **Streaming** - - ["StreamStarting"](#streamstarting) - - ["StreamStarted"](#streamstarted) - - ["StreamStopping"](#streamstopping) - - ["StreamStopped"](#streamstopped) - - ["StreamStatus"](#streamstatus) - - **Recording** - - ["RecordingStarting"](#recordingstarting) - - ["RecordingStarted"](#recordingstarted) - - ["RecordingStopping"](#recordingstopping) - - ["RecordingStopped"](#recordingstopped) - - **Other** - - ["Exiting"](#exiting) -* [Requests](#requests) - - [Description](#description-1) - - [Request Types](#request-types) - - **General** - - ["GetVersion"](#getversion) - - ["GetAuthRequired"](#getauthrequired) - - ["Authenticate"](#authenticate) - - **Scenes** - - ["GetCurrentScene"](#getcurrentscene) - - ["SetCurrentScene"](#setcurrentscene) - - ["GetSceneList"](#getscenelist) - - **Studio Mode** - - ["GetStudioModeStatus"](#getstudiomodestatus) - - ["SetPreviewScene"](#setpreviewscene) - - ["TransitionToProgram"](#transitiontoprogram) - - ["EnableStudioMode"](#enablestudiomode) - - ["DisableStudioMode"](#disablestudiomode) - - ["ToggleStudioMode"](#togglestudiomode) - - **Streaming** - - ["StartStopStreaming"](#startstopstreaming) - - ["StartStreaming"](#startstreaming) - - ["StopStreaming"](#stopstreaming) - - ["GetStreamingStatus"](#getstreamingstatus) - - **Recording** - - ["StartStopRecording"](#startstoprecording) - - ["StartRecording"](#startrecording) - - ["StopRecording"](#stoprecording) - - ["GetStreamingStatus"](#getstreamingstatus) - - ["SetRecordingFolder"](#setrecordingfolder) - - ["GetRecordingFolder"](#getrecordingfolder) - - **Transitions** - - ["GetTransitionList"](#gettransitionlist) - - ["GetCurrentTransition"](#getcurrenttransition) - - ["SetCurrentTransition"](#setcurrenttransition) - - ["GetTransitionDuration"](#gettransitionduration) - - ["SetTransitionDuration"](#settransitionduration) - - **Sources** - - ["GetCurrentScene"](#getcurrentscene) - - ["GetSceneList"](#getscenelist) - - ["GetSpecialSources"](#getspecialsources) - - ["GetTextGDIPlusProperties"](#gettextgdiplusproperties) - - ["SetTextGDIPlusProperties"](#settextgdiplusproperties) - - ["GetBrowserSourceProperties"](#getbrowsersourceproperties) - - ["SetBrowserSourceProperties"](#setbrowsersourceproperties) - - ["SetVolume"](#setvolume) - - ["GetVolume"](#getvolume) - - ["SetMute"](#setmute) - - ["GetMute"](#getmute) - - ["ToggleMute"](#togglemute) - - ["SetSyncOffset"](#setsyncoffset) - - ["GetSyncOffset"](#getsyncoffset) - - **Scene Items** - - ["SetSceneItemRender"](#setsourcerender) (a.k.a `SetSourceRender`) - - ["SetSceneItemPosition"](#setsceneitemposition) - - ["SetSceneItemTransform"](#setsceneitemtransform) - - ["SetSceneItemCrop"](#setsceneitemcrop) - - ["ResetSceneItem"](#resetsceneitem) - - **Scene Collections** - - ["ListSceneCollections"](#listscenecollections) - - ["SetCurrentSceneCollection"](#setcurrentscenecollection) - - ["GetCurrentSceneCollection"](#getcurrentscenecollection) - - **Streaming Server Settings** - - ["GetStreamSettings"](#getstreamsettings) - - ["SetStreamSettings"](#setstreamsettings) - - ["SaveStreamSettings"](#savestreamsettings) - - **Profiles** - - ["ListProfiles"](#listprofiles) - - ["SetCurrentProfile"](#setcurrentprofile) - - ["GetCurrentProfile"](#getcurrentprofile) - -## Authentication -A call to [`GetAuthRequired`](#getauthrequired) gives the client two elements : -- A challenge : a random string that will be used to generate the auth response -- A salt : applied to the password when generating the auth response - -The client knows a password and must it to authenticate itself to the server. -However, it must keep this password secret, and it is the purpose of the authentication mecanism used by obs-websocket. - -After a call to [`GetAuthRequired`](#getauthrequired), the client knows a password (kept secret), a challenge and a salt (sent by the server). -To generate the answer to the auth challenge, follow this procedure : -- Concatenate the password with the salt sent by the server (in this order : password + server salt), then generate a binary SHA256 hash of the result and encode the resulting SHA256 binary hash to base64. -- Concatenate the base64 secret with the challenge sent by the server (in this order : base64 secret + server challenge), then generate a binary SHA256 hash of the result and encode it to base64. -- Voilà, this last base64 string is the auth response. You may now use it to authenticate to the server with the `Authenticate` request. - -Here's how it looks in pseudocode : -``` -password = "supersecretpassword" -challenge = "ztTBnnuqrqaKDzRM3xcVdbYm" -salt = "PZVbYpvAnZut2SS6JNJytDm9" - -secret_string = password + salt -secret_hash = binary_sha256(secret_string) -secret = base64_encode(secret_hash) - -auth_response_string = secret + challenge -auth_response_hash = binary_sha256(auth_response_string) -auth_response = base64_encode(auth_response_hash) -``` - -A client can then authenticate to the server by calling [`Authenticate`](#authenticate) with the computed challenge response. - -## Events -### Description -Events are sent exclusively by the server and broadcast to each connected client. -An event message will contain at least one field : -- **update-type** (string) : the type of event -- **stream-timecode** (string, optional) : time elapsed between now and stream start (only present if OBS Studio is streaming) -- **rec-timecode** (string, optional) : time elapsed between now and recording start (only present if OBS Studio is recording) - -Timecodes are in the following format : HH:MM:SS.mmm - -Additional fields will be present in the event message depending on the event type. - -### Event Types -#### "SwitchScenes" -OBS is switching to another scene (called at the end of the transition). -- **scene-name** (string) : The name of the scene being switched to. -- **sources** (array of objects) : List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). - ---- - -#### "ScenesChanged" -The scene list has been modified (Scenes have been added, removed, or renamed). - ---- - -#### "SourceOrderChanged" -Scene items have been reordered. -- **"scene-name"** (string) : name of the scene where items have been reordered - ---- - -#### "SceneItemAdded" -An item has been added to the current scene. -- **"scene-name"** (string) : name of the scene -- **"item-name"** (string) : name of the item added to **scene-name** - ---- - -#### "SceneItemRemoved" -An item has been removed from the current scene. -- **"scene-name"** (string) : name of the scene -- **"item-name"** (string) : name of the item removed from **scene-name** - ---- - -#### "SceneItemVisibilityChanged" -An item's visibility has been toggled. -- **"scene-name"** (string) : name of the scene -- **"item-name"** (string) : name of the item in **scene-name** -- **"item-visible"** (bool) : new visibility of item **item-name** - ---- - -#### "SceneCollectionChanged" -Triggered when switching to another scene collection or when renaming the current scene collection. - ---- - -#### "SceneCollectionListChanged" -Triggered when a scene collection is created, added, renamed or removed. - ---- - -#### "SwitchTransition" -The active transition has been changed. -- **transition-name** (string) : The name of the active transition. - ---- - -#### "TransitionDurationChanged" -Triggered when the transition duration has changed. -- **"new-duration"** (integer) : new transition duration - ---- - -#### "TransitionListChanged" -The list of available transitions has been modified (Transitions have been added, removed, or renamed). - ---- - -#### "TransitionBegin" -A transition other than "Cut" has begun. -- **"name"** (string) : transition name -- **"duration"** (integer) : transition duration (in milliseconds) - ---- - -#### "PreviewSceneChanged" -The selected Preview scene changed (only in Studio Mode). -- **scene-name** (string) : Name of the scene being previewed. -- **sources** (array of objects) : List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). - ---- - -#### "StudioModeSwitched" -Studio Mode has been switched on or off. -- **"new-state"** (bool) : new state of Studio Mode: true if enabled, false if disabled. - ---- - -#### "ProfileChanged" -Triggered when switching to another profile or when renaming the current profile. - ---- - -#### "ProfileListChanged" -Triggered when a profile is created, added, renamed or removed. - ---- - -#### "StreamStarting" -A request to start streaming has been issued. -- **preview-only** (bool) : Always false. - ---- - -#### "StreamStarted" -Streaming started successfully. - ---- - -#### "StreamStopping" -A request to stop streaming has been issued. -- **preview-only** (bool) : Always false. - ---- - -#### "StreamStopped" -Streaming stopped successfully. - ---- - -#### "RecordingStarting" -A request to start recording has been issued. - ---- - -#### "RecordingStarted" -Recording started successfully. - ---- - -#### "RecordingStopping" -A request to stop streaming has been issued. - ---- - -#### "RecordingStopped" -Recording stopped successfully. - ---- - -#### "StreamStatus" -Sent every 2 seconds with the following information : -- **streaming** (bool) : Current Streaming state. -- **recording** (bool) : Current Recording state. -- **preview-only** (bool) : Always false. -- **bytes-per-sec** (integer) : Amount of data per second (in bytes) transmitted by the stream encoder. -- **kbits-per-sec** (integer) : "bytes-per-sec" converted to kilobits per second -- **strain** (double) : Percentage of dropped frames -- **total-stream-time** (integer) : Total time (in seconds) since the stream started. -- **num-total-frames** (integer) : Total number of frames transmitted since the stream started. -- **num-dropped-frames** (integer) : Number of frames dropped by the encoder since the stream started. -- **fps** (double) : Current framerate. - ---- - -#### "Exiting" -OBS is exiting. - ---- - -## Requests - -### Description -Requests are sent by the client and must have at least the following two fields : -- **"request-type"** (string) : One of the request types listed in the sub-section "[Requests Types](#request-types)". -- **"message-id"** (string) : An identifier defined by the client which will be embedded in the server response. - -Depending on the request type additional fields may be required (see the "[Request Types](#request-types)" section below for more information). - -Once a request is sent, the server will return a JSON response with the following fields : -- **"message-id"** (string) : The identifier specified in the request. -- **"status"** (string) : Response status, will be one of the following : "ok", "error" -- **"error"** (string) : The error message associated with an "error" status. - -Depending on the request type additional fields may be present (see the "[Request Types](#request-types)" section below for more information). - -### Request Types -#### "GetVersion" -Returns the latest version of the plugin and the API. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"obs-websocket-version"** (string) : obs-websocket version string -- **"obs-studio-version"** (string) : OBS Studio version string -- **"available-requests"** (string) : comma-separated list of available request types - ---- - -#### "GetAuthRequired" -Tells the client if authentication is required. If it is, authentication parameters "challenge" and "salt" are passed in the response fields (see "Authentication"). - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"authRequired"** (bool) -- **"challenge"** (string) -- **"salt"** (string) - ---- - -#### "Authenticate" -Try to authenticate the client on the server. - -__Request fields__ : -- **"auth"** (string) : response to the auth challenge (see "Authentication"). - -__Response__ : OK if auth succeeded, error if invalid credentials. No additional fields. - ---- - -#### "GetCurrentScene" -Get the current scene's name and items. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"name"** (string) : name of the current scene -- **"sources"** (array of objects) : ordered list of the current scene's items descriptions - -Objects in the "sources" array have the following fields : -- **"name"** (string) : name of the source associated with the scene item -- **"type"** (string) : internal source type name -- **"volume"** (double) : audio volume of the source, ranging from 0.0 to 1.0 -- **"x"** (double) : X coordinate of the top-left corner of the item in the scene -- **"y"** (double) : Y coordinate of the top-left corner of the item in the scene -- **"source_cx"** (integer) : width of the item (without scale applied) -- **"source_cy"** (integer) : height of the item (without scale applied) -- **"cx"** (double) : width of the item (with scale applied) -- **"cy"** (double) : height of the item (with scale applied) -- **"render"** (bool) : visibility of the source in the scene - ---- - -#### "SetCurrentScene" -Switch to the scene specified in "scene-name". - -__Request fields__ : -- **"scene-name"** (string) : name of the scene to switch to. - -__Response__ : always OK if scene exists, error if it doesn't. No additional fields - ---- - -#### "GetSceneList" -List OBS' scenes. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"current-scene"** (string) : name of the currently active scene -- **"scenes"** (array of objects) : ordered list of scene descriptions (see `GetCurrentScene` for reference) - ---- - -#### "SetSourceRender" -Show or hide a specific source in the current scene. - -__Request fields__ : -- **"source"** (string) : name of the source in the currently active scene. -- **"render"** (bool) : desired visibility -- **"scene-name"** (string; optional) : name of the scene the source belongs to. defaults to current scene. - -__Response__ : OK if source exists in the current scene, error otherwise. - ---- - -#### "GetStudioModeStatus" -Tells if Studio Mode is currently enabled or disabled. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"studio-mode"** (bool) : true if OBS is in Studio Mode, false otherwise. - ---- - -#### "GetPreviewScene" -Studio Mode only. Gets the name of the currently Previewed scene, along with a list of its sources. - -__Request fields__ : none -__Response__ : OK if Studio Mode is enabled, with the same fields as [`GetCurrentScene`](#getcurrentscene), error otherwise. - ---- - -#### "SetPreviewScene" -Studio Mode only. Sets the specified scene as the Previewed scene in Studio Mode. - -__Request fields__ : -- **"scene-name"** (string) : name of the scene to selected as the preview of Studio Mode - -__Response__ : OK if Studio Mode is enabled and specified scene exists, error otherwise. - ---- - -#### "TransitionToProgram" -Studio Mode only. Transitions the currently previewed scene to Program (main output). - -__Request fields__ : -- **"with-transition"** (object, optional) : if specified, use this transition when switching from preview to program. This will change the current transition in the frontend to this one. - -__Response__ : OK if studio mode is enabled and optional transition exists, error otherwise. - -An object passed as `"with-transition"` in a request must have the following fields : -- **"name"** (string, optional) : transition name -- **"duration"** (integer, optional) : transition duration in milliseconds - ---- - -#### "EnableStudioMode" -Enables Studio Mode. - -__Request fields__ : none -__Response__ : always OK. No additional fields. - ---- - -#### "DisableStudioMode" -Disables Studio Mode. - -__Request fields__ : none -__Response__ : always OK. No additional fields. - ---- - -#### "ToggleStudioMode" -Toggles Studio Mode on or off. - -__Request fields__ : none -__Response__ : always OK. No additional fields. - ---- - -#### "StartStopStreaming" -Toggles streaming on or off. - -__Request fields__ : none -__Response__ : always OK. No additional fields. - ---- - -#### "StartStopRecording" -Toggles recording on or off. - -__Request fields__ : -- **"stream"** (object; optional) : See 'stream' parameter in 'StartStreaming'. Ignored if stream is already started. - -__Response__ : always OK. No additional fields. - ---- - -#### "StartStreaming" -Start streaming. - -__Request fields__ : -- **"stream"** (object; optional) : If specified allows for special configuration of the stream - -The 'stream' object has the following fields: -- **"settings"** (object; optional) : The settings for the stream -- **"type"** (string; optional) : If specified ensures the type of the stream matches the given type (usually 'rtmp\_custom' or 'rtmp\_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the 'settings' object or an error will occur starting the stream. -- **"metadata"** (object; optional) : Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the stream. - -The 'settings' object has the following fields: -- **"server"** (string; optional) : The publish URL -- **"key"** (string; optional) : The publish key of the stream -- **"use-auth"** (bool; optional) : should authentication be used when connecting to the streaming server -- **"username"** (string; optional) : if authentication is enabled, the username for access to the streaming server. Ignored if 'use-auth' is not specified as 'true'. -- **"password"** (string; optional) : if authentication is enabled, the password for access to the streaming server. Ignored if 'use-auth' is not specified as 'true'. - -The 'metadata' object supports passing any string, numeric or boolean field. - -__Response__ : Error if streaming is already active, OK otherwise. No additional fields. - ---- - -#### "StopStreaming" -Stop streaming. - -__Request fields__ : none -__Response__ : Error if streaming is already inactive, OK otherwise. No additional fields. - ---- - -#### "StartRecording" -Start recording. - -__Request fields__ : none -__Response__ : Error if recording is already active, OK otherwise. No additional fields. - ---- - -#### "StopRecording" -Stop recording. - -__Request fields__ : none -__Response__ : Error if recording is already inactive, OK otherwise. No additional fields. - ---- - -#### "SetRecordingFolder" -Change the current recording folder. - -__Request fields__ : -- **"rec-folder"** (string) : path of the desired recording folder - -__Response__ : OK if path is valid, error otherwise. - ---- - -#### "GetRecordingFolder" -Get the path of the current recording folder. - -__Request fields__ : none - -__Response__ : OK with these additional fields : -- **"rec-folder"** (string) : path of the current recording folder - ---- - -#### "GetStreamingStatus" -Get current streaming and recording status. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"streaming"** (bool) : streaming status (active or not) -- **"recording"** (bool) : recording status (active or not) -- **stream-timecode** (string, optional) : time elapsed between now and stream start (only present if OBS Studio is streaming) -- **rec-timecode** (string, optional) : time elapsed between now and recording start (only present if OBS Studio is recording) -- **"preview-only"** (bool) : always false. Retrocompat with OBSRemote. - ---- - -#### "GetTransitionList" -List all transitions available in the frontend's dropdown menu. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"current-transition"** (string) : name of the current transition -- **"transitions"** (array of objects) : list of transition descriptions - -Objects in the "transitions" array have only one field : -- **"name"** (string) : name of the transition - ---- - -#### "GetCurrentTransition" -Get the name of the currently selected transition in the frontend's dropdown menu. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"name"** (string) : name of the selected transition -- **"duration"** (integer, only if transition supports this) : transition duration - ---- - -#### "SetCurrentTransition" -__Request fields__ : -- **"transition-name"** (string) : The name of the transition. - -__Response__ : OK if specified transition exists, error otherwise. - ---- - -#### "SetTransitionDuration" -Set the duration of the currently selected transition. - -__Request fields__ : -- **"duration"** (integer) : desired transition duration in milliseconds - -__Response__ : always OK. - ---- - -#### "GetTransitionDuration" -Set the duration of the currently selected transition. - -__Request fields__ : none -__Response__ : always OK, with these additional fields : -- **"transition-duration"** (integer) : current transition duration, in milliseconds - ---- - -#### "SetVolume" -Set the volume of a specific source. - -__Request fields__ : -- **"source"** (string) : the name of the source -- **"volume"** (double) : the desired volume - -__Response__ : OK if specified source exists, error otherwise. - ---- - -#### "GetVolume" -Get the volume of a specific source. - -__Request fields__ : -- **"source"** (string) : name of the source - -__Response__ : OK if source exists, with these additional fields : -- **"name"** (string) : source name -- **"volume"** (double) : source volume, on a linear scale (0.0 to 1.0) -- **"muted"** (bool) : source mute status - ---- - -#### "SetMute" -Mutes or unmutes a specific source. - -__Request fields__ : -- **"source"** (string) : the name of the source -- **"mute"** (bool) : the desired mute status - -__Response__ : OK if specified source exists, error otherwise. - ---- - -#### "GetMute" -Get mute status of a specific source. - -__Request fields__ : -- **"source"** (string) : the name of the source - -__Response__ : OK if source exists, with these additional fields : -- **"name"** (string) : source name -- **"muted"** (bool) : source mute status - ---- - -#### "ToggleMute" -Inverts the mute status of a specific source. - -__Request fields__ : -- **"source"** (string) : the name of the source - -__Response__ : OK if specified source exists, error otherwise. - ---- - -#### "SetSyncOffset" -Set the sync offset of a specific source. - -__Request fields__ : -- **"source"** (string) : the name of the source -- **"offset"** (integer) : the desired sync offset in nanoseconds - -__Response__ : OK if specified source exists, error otherwise. - ---- - -#### "GetSyncOffset" -Get the sync offset of a specific source. - -__Request fields__ : -- **"source"** (string) : the name of the source - -__Response__ : OK if source exists, with these additional fields : -- **"name"** (string) : source name -- **"offset"** (integer) : source sync offset, in nanoseconds - ---- - -#### "GetSpecialSources" -Get configured special sources like Desktop Audio and Mic/Aux sources. - -__Request fields__ : none - -__Response__ : always OK, with these additional fields : -- **"desktop-1"** (string, optional) : Name of the first Desktop Audio capture source -- **"desktop-1"** (string, optional) : Name of the second Desktop Audio capture source -- **"mic-1"** (string, optional) : Name of the first Mic/Aux input source -- **"mic-2"** (string, optional) : Name of the second Mic/Aux input source -- **"mic-3"** (string, optional) : Name of the third Mic/Aux input source - ---- - -#### "SetSceneItemPosition" -__Request fields__ : -- **"item"** (string) : The name of the scene item. -- **"x"** (float) : x coordinate -- **"y"** (float) : y coordinate -- **"scene-name"** (string) : scene the item belongs to. defaults to current scene. - -__Response__ : OK if specified item exists, error otherwise. - ---- - -#### "SetSceneItemTransform" -__Request fields__ : -- **"item"** (string) : The name of the scene item. -- **"x-scale"** (float) : width scale factor -- **"y-scale"** (float) : height scale factor -- **"rotation"** (float) : item rotation (in degrees) -- **"scene-name"** (string) : scene the item belongs to. defaults to current scene. - -__Response__ : OK if specified item exists, error otherwise. - ---- - -#### "SetSceneItemCrop" -__Request fields__ : -- **"item"** (string) : Name of the scene item -- **"scene-name"** (string, optional) : Scene the item belongs to. Default : current scene. -- **"top"** (integer) -- **"bottom"** (integer) -- **"left"** (integer) -- **"right"** (integer) - -__Response__ : OK if specified item exists, error otherwise. - ---- - -#### "ResetSceneItem" -__Request fields__ : -- **"item"** (string) : Name of the scene item -- **"scene-name"** (string, optional) : Scene the item belongs to. Default : current scene. - -__Response__ : OK if specified item exists, error otherwise. - ---- - -#### "SetCurrentSceneCollection" -Change the current scene collection. - -__Request fields__ : -- **"sc-name"** (string) : name of the desired scene collection - -__Response__ : OK if scene collection exists, error otherwise. - ---- - -#### "GetCurrentSceneCollection" -Get the name of the current scene collection. - -__Request fields__ : none - -__Response__ : OK with these additional fields : -- **"sc-name"** (string) : name of the current scene collection - ---- - -#### "ListSceneCollections" -Get a list of available scene collections. - -__Request fields__ : none - -__Response__ : OK with these additional fields : -- **"scene-collections"** (array of objects) : names of available scene collections - ---- - -#### "GetStreamSettings" -Gets the current streaming server settings - -__Request fields__ : none - -__Response__ : OK with these additional fields : -- **"type"** (string) : The type of streaming service configuration usually 'rtmp\_custom' or 'rtmp\_common' -- **"settings"** (object) : The actual settings of the stream (i.e. server, key, use-auth, username, password) - -The 'settings' object has the following fields however they may vary by 'type': -- **"server"** (string) : The publish URL -- **"key"** (string) : The publish key of the stream -- **"use-auth"** (bool) : should authentication be used when connecting to the streaming server -- **"username"** (string) : if authentication is enabled, the username for access to the streaming server -- **"password"** (string) : if authentication is enabled, the password for access to the streaming server - --- - -#### "SetStreamSettings" -Sets one or more attributes of the current streaming server settings. Any options not passed will remain unchanged. Returns the updated settings in response. -If 'type' is different than the current streaming service type, all settings are required. -Returns the full settings of the stream (i.e. the same as GetStreamSettings) - -__Request fields__ : -- **"type"** (string) : The type of streaming service configuration usually 'rtmp\_custom' or 'rtmp\_common' -- **"settings"** (object) : The actual settings of the stream (i.e. server, key, use-auth, username, password) -- **"save"** (bool) : If specified as true, saves the settings to disk - -The 'settings' object has the following fields however they may vary by 'type': -- **"server"** (string; optional) : The publish URL -- **"key"** (string; optional) : The publish key of the stream -- **"use-auth"** (bool; optional) : should authentication be used when connecting to the streaming server -- **"username"** (string; optional) : if authentication is enabled, the username for access to the streaming server -- **"password"** (string; optional) : if authentication is enabled, the password for access to the streaming server - -__Response__ : OK with the same fields as the request (except 'save') - ---- - -#### "SaveStreamSettings" -Saves the current streaming server settings to disk - -__Request fields__ : none - -__Response__ : OK - - -#### "SetCurrentProfile" -Change the current profile. - -__Request fields__ : -- **"profile-name"** (string) : name of the desired profile - -__Response__ : OK if profile exists, error otherwise. - ---- - -#### "GetCurrentProfile" -Get the name of the current profile. - -__Request fields__ : none - -__Response__ : OK with these additional fields : -- **"profile-name"** (string) : name of the current profile - ---- - -#### "ListProfiles" -Get a list of available profiles. - -__Request fields__ : none - -__Response__ : OK with the additional fields : -- **"profiles"** (array of objects) : names of available profiles - ---- - -#### "GetTextGDIPlusProperties" -Gets current properties for Text GDI Plus source. - -__Request fields__ : -- **"source"** (string) : name of the source in the currently active scene. -- **"scene-name"** (string; optional) : name of the scene the source belongs to. defaults to current scene. - -__Response__ : OK if source exists in the current scene with these additional fields when fields are set, error otherwise. -- **"align"** (string) : "left","center","right" : text alignment -- **"bk_color"** (integer) : background color -- **"bk_opacity"** (integer) : background opacity range 0 to 100 -- **"chatlog"** (bool) : chat log -- **"chatlog_lines"** (integer) : chat log lines -- **"color"** (integer) : text color -- **"extents"** (bool) : extents -- **"extents_wrap"** (bool) : extents wrap -- **"extents_cx"** (integer) : extents cx -- **"extents_cy"** (integer) : extents cy -- **"file"** (string) : file path name -- **"read_from_file"** (bool) : read text from file specified -- **"font"** (object) : holds font data for face, flags, size and style --- Example: "font": {"face": "Arial","flags": 0,"size": 150,"style": ""} -- **"face"** (string) : font face i.e. Arial -- **"flags"** (integer) : font text style flag i.e. Bold 1, Italic 2, Bold Italic 3, Underline 5, Strikeout 8 -- **"size"** (integer) : font text size -- **"style"** (string) : font style (unknown function) -- **"gradient"** (bool) : gradient -- **"gradient_color"** (integer) : gradient color -- **"gradient_dir"** (float) : gradient direction -- **"gradient_opacity"** (integer) : gradient opacity range 0 to 100 -- **"outline"** (bool) : outline -- **"outline_color"** (integer) : outline color -- **"outline_size"** (integer) : outline size -- **"outline_opacity"** (integer) : outline opacity range 0 to 100 -- **"text"** (string) : text to be displayed -- **"valign"** (string) : "top","center","bottom" : text vertical alignment -- **"vertical"** (bool) : vertical text -- **"render"** (bool) : visibility of the scene item - ---- - -#### "SetTextGDIPlusProperties" -Sets current properties for Text GDI Plus source. - -__Request fields__ : -- **"source"** (string) : name of the source in the currently active scene. -- **"scene-name"** (string; optional) : name of the scene the source belongs to. defaults to current scene. -- **"align"** (string; optional) : "left","center","right" : text alignment -- **"bk_color"** (integer; optional) : background color -- **"bk_opacity"** (integer; optional) : background opacity range 0 to 100 -- **"chatlog"** (bool; optional) : chat log -- **"chatlog_lines"** (integer; optional) : chat log lines -- **"color"** (integer; optional) : text color -- **"extents"** (bool; optional) : extents -- **"extents_wrap"** (bool; optional) : extents wrap -- **"extents_cx"** (integer; optional) : extents cx -- **"extents_cy"** (integer; optional) : extents cy -- **"file"** (string; optional) : file path name -- **"read_from_file"** (bool; optional) : read text from file specified -- **"font"** (object; optional) : holds font data for face, flags, size and style --- Example: "font":{"face": "Arial","flags": 0,"size": 150,"style": ""} -- **"face"** (string; optional) : font face i.e. Arial --- Example: "font":{"face": "Arial"} -- **"flags"** (integer; optional) : font text style flag i.e. Bold 1, Italic 2, Bold Italic 3, Underline 5, Strikeout 8 -- **"size"** (integer; optional) : font text size --- Example: "font": {"size":125} -- **"style"** (string; optional) : font style (unknown function) -- **"gradient"** (bool; optional) : gradient -- **"gradient_color"** (integer; optional) : gradient color -- **"gradient_dir"** (float; optional) : gradient direction -- **"gradient_opacity"** (integer; optional) : gradient opacity range 0 to 100 -- **"outline"** (bool; optional) : outline -- **"outline_color"** (integer; optional) : outline color -- **"outline_size"** (integer; optional) : outline size -- **"outline_opacity"** (integer; optional) : outline opacity range 0 to 100 -- **"text"** (string; optional) : text to be displayed -- **"valign"** (string; optional) : "top","center","bottom" : text vertical alignment -- **"vertical"** (bool; optional) : vertical text -- **"render"** (bool; optional) : visibility of the scene item - -__Response__ : OK if source exists in the current scene, error otherwise. - ---- - -#### "GetBrowserSourceProperties" -Gets current properties for Browser Source. - -__Request fields__ : -- **"source"** (string) : name of the source in the currently active scene. -- **"scene-name"** (string; optional) : name of the scene the source belongs to. defaults to current scene. - -__Response__ : OK if source exists in the current scene with these additional fields when fields are set, error otherwise. - -- **"is_local_file"** (bool) : use local file -- **"url"** (string) : url or file path -- **"css"** (string) : cascading style sheet code -- **"width"** (integer) : width -- **"height"** (integer) : height -- **"fps"** (integer) : frames per second -- **"shutdown"** (bool) : shutdown when sorce is not visible -- **"render"** (bool; optional) : visibility of the scene item - ---- - -#### "SetBrowserSourceProperties" -Sets current properties for Browser Source. - -__Request fields__ : -- **"source"** (string) : name of the source in the currently active scene. -- **"scene-name"** (string; optional) : name of the scene the source belongs to. defaults to current scene. -- **"is_local_file"** (bool; optional) : use local file -- **"url"** (string; optional) : url or file path -- **"css"** (string; optional) : cascading style sheet code -- **"width"** (integer; optional) : width -- **"height"** (integer; optional) : height -- **"fps"** (integer; optional) : frames per second -- **"shutdown"** (bool; optional) : shutdown when sorce is not visible -- **"render"** (bool; optional) : visibility of the scene item - ---- diff --git a/README.md b/README.md index 819999fa..4f1e7e2c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ It is **highly recommended** to protect obs-websocket with a password against un ### For developers The server is a typical Websockets server running by default on port 4444 (the port number can be changed in the Settings dialog). -The protocol understood by the server is documented in [PROTOCOL.md](PROTOCOL.md). +The protocol understood by the server is documented in [PROTOCOL.md](docs/generated/protocol.md). Here's a list of available language APIs for obs-websocket : - Javascript (browser & nodejs): [obs-websocket-js](https://github.com/haganbmj/obs-websocket-js) by Brendan Hagan @@ -39,7 +39,7 @@ See the [build instructions](BUILDING.md). ## Special thanks In order of appearance: -- [Brendan H.](https://github.com/haganbmj) : Code contributions and better English in the Protocol specification +- [Brendan H.](https://github.com/haganbmj) : Code contributions and gooder English in the Protocol specification - [Mikhail Swift](https://github.com/mikhailswift) : Code contributions - [Tobias Frahmer](https://github.com/Frahmer) : German translation - [Genture](https://github.com/Genteure) : Simplified Chinese and Traditional Chinese translations @@ -61,10 +61,10 @@ They have contributed financially to the project and made possible the addition [Support Class](http://supportclass.net) designs and develops professional livestreams, with services ranging from broadcast graphics design and integration to event organization, along many other skills. -[![Support Class](doc/supportclass_logo_blacktext.png)](http://supportclass.net) +[![Support Class](.github/images/supportclass_logo_blacktext.png)](http://supportclass.net) --- [MediaUnit](http://www.mediaunit.no) is a Norwegian media company developing products and services for the media industry, primarly focused on web and events. -[![MediaUnit](doc/mediaunit_logo_black.png)](http://www.mediaunit.no/) +[![MediaUnit](.github/images/mediaunit_logo_black.png)](http://www.mediaunit.no/) diff --git a/WSEvents.cpp b/WSEvents.cpp index 75fbdd38..c1381da8 100644 --- a/WSEvents.cpp +++ b/WSEvents.cpp @@ -1,21 +1,21 @@ -/* -obs-websocket -Copyright (C) 2016-2017 Stéphane Lepin -Copyright (C) 2017 Brendan Hagan - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see -*/ +/** + * obs-websocket + * Copyright (C) 2016-2017 Stéphane Lepin + * Copyright (C) 2017 Brendan Hagan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see + */ #include @@ -259,6 +259,16 @@ const char* WSEvents::GetRecordingTimecode() { return ns_to_timestamp(GetRecordingTime()); } + /** + * Indicates a scene change. + * + * @return {String} `scene-name` The new scene. + * @return {Array} `sources` List of sources in the new scene. + * + * @api events + * @name OnSceneChange + * @category scenes + */ void WSEvents::OnSceneChange() { obs_data_t* data = obs_data_create(); @@ -283,10 +293,25 @@ void WSEvents::OnSceneChange() { } } +/** + * The scene list has been modified. + * Scenes have been added, removed, or renamed. + * + * @api events + * @name ScenesChanged + * @category scenes + */ void WSEvents::OnSceneListChange() { broadcastUpdate("ScenesChanged"); } +/** + * Triggered when switching to another scene collection or when renaming the current scene collection. + * + * @api events + * @name SceneCollectionChanged + * @category scenes + */ void WSEvents::OnSceneCollectionChange() { broadcastUpdate("SceneCollectionChanged"); @@ -300,10 +325,26 @@ void WSEvents::OnSceneCollectionChange() { OnSceneChange(); } +/** + * Triggered when a scene collection is created, added, renamed, or removed. + * + * @api events + * @name SceneCollectionListChanged + * @category scenes + */ void WSEvents::OnSceneCollectionListChange() { broadcastUpdate("SceneCollectionListChanged"); } +/** + * The active transition has been changed. + * + * @return {String} `transition-name` The name of the new active transition. + * + * @api events + * @name SwitchTransition + * @category transitions + */ void WSEvents::OnTransitionChange() { obs_source_t* current_transition = obs_frontend_get_current_transition(); connectTransitionSignals(current_transition); @@ -318,18 +359,49 @@ void WSEvents::OnTransitionChange() { obs_source_release(current_transition); } +/** + * The list of available transitions has been modified. + * Transitions have been added, removed, or renamed. + * + * @api events + * @name TransitionListChanged + * @category transitions + */ void WSEvents::OnTransitionListChange() { broadcastUpdate("TransitionListChanged"); } +/** + * Triggered when switching to another profile or when renaming the current profile. + * + * @api events + * @name ProfileChanged + * @category profiles + */ void WSEvents::OnProfileChange() { broadcastUpdate("ProfileChanged"); } +/** + * Triggered when a profile is created, added, renamed, or removed. + * + * @api events + * @name ProfileListChanged + * @category profiles + */ void WSEvents::OnProfileListChange() { broadcastUpdate("ProfileListChanged"); } +/** + * A request to start streaming has been issued. + * + * @return {boolean} `preview-only` Always false (retrocompatibility). + * + * @api events + * @name StreamStarting + * @category streaming + */ void WSEvents::OnStreamStarting() { obs_data_t* data = obs_data_create(); obs_data_set_bool(data, "preview-only", false); @@ -339,12 +411,28 @@ void WSEvents::OnStreamStarting() { obs_data_release(data); } +/** + * Streaming started successfully. + * + * @api events + * @name StreamStarted + * @category streaming + */ void WSEvents::OnStreamStarted() { _stream_starttime = os_gettime_ns(); _lastBytesSent = 0; broadcastUpdate("StreamStarted"); } +/** + * A request to stop streaming has been issued. + * + * @return {boolean} `preview-only` Always false (retrocompatibility). + * + * @api events + * @name StreamStopping + * @category streaming + */ void WSEvents::OnStreamStopping() { obs_data_t* data = obs_data_create(); obs_data_set_bool(data, "preview-only", false); @@ -354,33 +442,93 @@ void WSEvents::OnStreamStopping() { obs_data_release(data); } +/** + * Streaming stopped successfully. + * + * @api events + * @name StreamStopped + * @category streaming + */ void WSEvents::OnStreamStopped() { _stream_starttime = 0; broadcastUpdate("StreamStopped"); } +/** + * A request to start recording has been issued. + * + * @api events + * @name RecordingStarting + * @category recording + */ void WSEvents::OnRecordingStarting() { broadcastUpdate("RecordingStarting"); } +/** + * Recording started successfully. + * + * @api events + * @name RecordingStarted + * @category recording + */ void WSEvents::OnRecordingStarted() { _rec_starttime = os_gettime_ns(); broadcastUpdate("RecordingStarted"); } +/** + * A request to stop recording has been issued. + * + * @api events + * @name RecordingStopping + * @category recording + */ void WSEvents::OnRecordingStopping() { broadcastUpdate("RecordingStopping"); } +/** + * Recording stopped successfully. + * + * @api events + * @name RecordingStopped + * @category recording + */ void WSEvents::OnRecordingStopped() { _rec_starttime = 0; broadcastUpdate("RecordingStopped"); } +/** + * OBS is exiting. + * + * @api events + * @name Exiting + * @category other + */ void WSEvents::OnExit() { broadcastUpdate("Exiting"); } +/** + * Emit every 2 seconds. + * + * @return {boolean} `streaming` Current streaming state. + * @return {boolean} `recording` Current recording state. + * @return {boolean} `preview-only` Always false (retrocompatibility). + * @return {int} `bytes-per-sec` Amount of data per second (in bytes) transmitted by the stream encoder. + * @return {int} `kbits-per-sec` Amount of data per second (in kilobits) transmitted by the stream encoder. + * @return {double} `strain` Percentage of dropped frames. + * @return {int} `total-stream-time` Total time (in seconds) since the stream started. + * @return {int} `num-total-frames` Total number of frames transmitted since the stream started. + * @return {int} `num-dropped-frames` Number of frames dropped by the encoder since the stream started. + * @return {double} `fps` Current framerate. + * + * @api events + * @name StreamStatus + * @category streaming + */ void WSEvents::StreamStatus() { bool streaming_active = obs_frontend_streaming_active(); bool recording_active = obs_frontend_recording_active(); @@ -438,6 +586,15 @@ void WSEvents::StreamStatus() { obs_output_release(stream_output); } +/** + * The active transition duration has been changed. + * + * @return {int} `new-duration` New transition duration. + * + * @api events + * @name TransitionDurationChanged + * @category transitions + */ void WSEvents::TransitionDurationChanged(int ms) { obs_data_t* fields = obs_data_create(); obs_data_set_int(fields, "new-duration", ms); @@ -446,6 +603,16 @@ void WSEvents::TransitionDurationChanged(int ms) { obs_data_release(fields); } +/** + * A transition (other than "cut") has begun. + * + * @return {String} `name` Transition name. + * @return {int} `duration` Transition duration (in milliseconds). + * + * @api events + * @name TransitionBegin + * @category transitions + */ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) { UNUSED_PARAMETER(data); WSEvents* instance = static_cast(param); @@ -463,6 +630,15 @@ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) { obs_source_release(current_transition); } +/** + * Scene items have been reordered. + * + * @return {String} `scene-name` Name of the scene where items have been reordered. + * + * @api events + * @name SourceOrderChanged + * @category sources + */ void WSEvents::OnSceneReordered(void* param, calldata_t* data) { WSEvents* instance = static_cast(param); @@ -477,6 +653,16 @@ void WSEvents::OnSceneReordered(void* param, calldata_t* data) { obs_data_release(fields); } +/** + * An item has been added to the current scene. + * + * @return {String} `scene-name` Name of the scene. + * @return {String} `item-name` Name of the item added to the scene. + * + * @api events + * @name SceneItemAdded + * @category sources + */ void WSEvents::OnSceneItemAdd(void* param, calldata_t* data) { WSEvents* instance = static_cast(param); @@ -499,6 +685,16 @@ void WSEvents::OnSceneItemAdd(void* param, calldata_t* data) { obs_data_release(fields); } +/** + * An item has been removed from the current scene. + * + * @return {String} `scene-name` Name of the scene. + * @return {String} `item-name` Name of the item removed from the scene. + * + * @api events + * @name SceneItemRemoved + * @category sources + */ void WSEvents::OnSceneItemDelete(void* param, calldata_t* data) { WSEvents* instance = static_cast(param); @@ -521,6 +717,17 @@ void WSEvents::OnSceneItemDelete(void* param, calldata_t* data) { obs_data_release(fields); } +/** + * An item's visibility has been toggled. + * + * @return {String} `scene-name` Name of the scene. + * @return {String} `item-name` Name of the item in the scene. + * @return {boolean} `item-visible` New visibility state of the item. + * + * @api events + * @name SceneItemVisibilityChanged + * @category sources + */ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { WSEvents* instance = static_cast(param); @@ -547,6 +754,16 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { obs_data_release(fields); } +/** + * The selected preview scene has changed (only available in Studio Mode). + * + * @return {String} `scene-name` Name of the scene being previewed. + * @return {Source|Array} `sources` List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). + * + * @api events + * @name PreviewSceneChanged + * @category studio mode + */ void WSEvents::SelectedSceneChanged(QListWidgetItem* current, QListWidgetItem* prev) { if (Utils::IsPreviewModeActive()) { obs_scene_t* scene = Utils::SceneListItemToScene(current); @@ -566,6 +783,15 @@ void WSEvents::SelectedSceneChanged(QListWidgetItem* current, QListWidgetItem* p } } +/** + * Studio Mode has been enabled or disabled. + * + * @return {boolean} `new-state` The new enabled state of Studio Mode. + * + * @api events + * @name StudioModeSwitched + * @category studio mode + */ void WSEvents::ModeSwitchClicked(bool checked) { obs_data_t* data = obs_data_create(); obs_data_set_bool(data, "new-state", checked); diff --git a/WSRequestHandler.cpp b/WSRequestHandler.cpp index 48df3a45..b367d816 100644 --- a/WSRequestHandler.cpp +++ b/WSRequestHandler.cpp @@ -1,21 +1,21 @@ -/* -obs-websocket -Copyright (C) 2016-2017 Stéphane Lepin -Copyright (C) 2017 Mikhail Swift - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program. If not, see -*/ +/** + * obs-websocket + * Copyright (C) 2016-2017 Stéphane Lepin + * Copyright (C) 2017 Mikhail Swift + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see + */ #include @@ -195,6 +195,18 @@ bool WSRequestHandler::hasField(const char* name) { return obs_data_has_user_value(data, name); } +/** + * Returns the latest version of the plugin and the API. + * + * @return {double} `version` OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility. + * @return {String} `obs-websocket-version` obs-websocket plugin version. + * @return {String} `obs-studio-version` OBS Studio program version. + * @return {String|Array} `available-requests` List of available request types. + * + * @api requests + * @name GetVersion + * @category general + */ void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) { const char* obs_version = Utils::OBSVersionString(); @@ -217,6 +229,18 @@ void WSRequestHandler::HandleGetVersion(WSRequestHandler* req) { bfree((void*)obs_version); } +/** + * Tells the client if authentication is required. If so, returns authentication parameters `challenge` + * and `salt` (see "Authentication" for more information). + * + * @return {boolean} `authRequired` Indicates whether authentication is required. + * @return {String (optional)} `challenge` + * @return {String (optional)} `salt` + * + * @api requests + * @name GetAuthRequired + * @category general + */ void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) { bool authRequired = Config::Current()->AuthRequired; @@ -235,6 +259,15 @@ void WSRequestHandler::HandleGetAuthRequired(WSRequestHandler* req) { obs_data_release(data); } +/** + * Attempt to authenticate the client to the server. + * + * @param {String} `auth` Response to the auth challenge (see "Authentication" for more information). + * + * @api requests + * @name Authenticate + * @category general + */ void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) { if (!req->hasField("auth")) { req->SendErrorResponse("missing request parameters"); @@ -256,6 +289,15 @@ void WSRequestHandler::HandleAuthenticate(WSRequestHandler* req) { } } + /** + * Switch to the specified scene. + * + * @param {String} `scene-name` Name of the scene to switch to. + * + * @api requests + * @name SetCurrentScene + * @category scenes + */ void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) { if (!req->hasField("scene-name")) { req->SendErrorResponse("missing request parameters"); @@ -275,6 +317,16 @@ void WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) { obs_source_release(source); } +/** + * Get the current scene's name and source items. + * + * @return {String} `name` Name of the currently active scene. + * @return {Source|Array} `sources` Ordered list of the current scene's source items. + * + * @api requests + * @name GetCurrentScene + * @category scenes + */ void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) { obs_source_t* current_scene = obs_frontend_get_current_scene(); const char* name = obs_source_get_name(current_scene); @@ -292,6 +344,16 @@ void WSRequestHandler::HandleGetCurrentScene(WSRequestHandler* req) { obs_source_release(current_scene); } +/** + * Get a list of scenes in the currently active profile. + * + * @return {String} `current-scene` Name of the currently active scene. + * @return {Scene|Array} `scenes` Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information). + * + * @api requests + * @name GetSceneList + * @category scenes + */ void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { obs_source_t* current_scene = obs_frontend_get_current_scene(); obs_data_array_t* scenes = Utils::GetScenes(); @@ -308,6 +370,17 @@ void WSRequestHandler::HandleGetSceneList(WSRequestHandler* req) { obs_source_release(current_scene); } + /** + * Show or hide a specified source item in a specified scene. + * + * @param {String} `source` Name of the source in the specified scene. + * @param {boolean} `render` Desired visibility. + * @param {String (optional)} `scene-name` Name of the scene where the source resides. Defaults to the currently active scene. + * + * @api requests + * @name SetSourceRender + * @category sources + */ void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) { if (!req->hasField("source") || !req->hasField("render")) { @@ -342,6 +415,19 @@ void WSRequestHandler::HandleSetSceneItemRender(WSRequestHandler* req) { obs_source_release(scene); } + /** + * Get current streaming and recording status. + * + * @return {boolean} `streaming` Current streaming status. + * @return {boolean} `recording` Current recording status. + * @return {String (optional)} `stream-timecode` Time elapsed since streaming started (only present if currently streaming). + * @return {String (optional)} `rec-timecode` Time elapsed since recording started (only present if currently recording). + * @return {boolean} `preview-only` Always false. Retrocompatibility with OBSRemote. + * + * @api requests + * @name GetStreamingStatus + * @category streaming + */ void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) { obs_data_t* data = obs_data_create(); obs_data_set_bool(data, "streaming", obs_frontend_streaming_active()); @@ -365,6 +451,13 @@ void WSRequestHandler::HandleGetStreamingStatus(WSRequestHandler* req) { obs_data_release(data); } +/** + * Toggle streaming on or off. + * + * @api requests + * @name StartStopStreaming + * @category streaming + */ void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) { if (obs_frontend_streaming_active()) HandleStopStreaming(req); @@ -372,6 +465,13 @@ void WSRequestHandler::HandleStartStopStreaming(WSRequestHandler* req) { HandleStartStreaming(req); } +/** + * Toggle recording on or off. + * + * @api requests + * @name StartStopRecording + * @category recording + */ void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) { if (obs_frontend_recording_active()) @@ -382,6 +482,24 @@ void WSRequestHandler::HandleStartStopRecording(WSRequestHandler* req) req->SendOKResponse(); } +/** + * Start streaming. + * Will return an `error` if streaming is already active. + * + * @param {Object (optional)} `stream` Special stream configuration. + * @param {String (optional)} `type` If specified ensures the type of stream matches the given type (usually 'rtmp_custom' or 'rtmp_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the `settings` object or an error will occur when starting the stream. + * @param {Object (optional)} `metadata` Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the streaming. May be any String, Numeric, or Boolean field. + * @param {Object (optional)} `settings` Settings for the stream. + * @param {String (optional)} `settings.server` The publish URL. + * @param {String (optional)} `settings.key` The publish key of the stream. + * @param {boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server. + * @param {String (optional)} `settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`. + * @param {String (optional)} `settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`. + * + * @api requests + * @name StartStreaming + * @category streaming + */ void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) { if (obs_frontend_streaming_active() == false) { @@ -475,6 +593,14 @@ void WSRequestHandler::HandleStartStreaming(WSRequestHandler* req) } } +/** + * Stop streaming. + * Will return an `error` if streaming is not active. + * + * @api requests + * @name StopStreaming + * @category streaming + */ void WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) { if (obs_frontend_streaming_active() == true) { obs_frontend_streaming_stop(); @@ -484,6 +610,14 @@ void WSRequestHandler::HandleStopStreaming(WSRequestHandler* req) { } } +/** + * Start recording. + * Will return an `error` if recording is already active. + * + * @api requests + * @name StartRecording + * @category recording + */ void WSRequestHandler::HandleStartRecording(WSRequestHandler* req) { if (obs_frontend_recording_active() == false) { obs_frontend_recording_start(); @@ -493,6 +627,14 @@ void WSRequestHandler::HandleStartRecording(WSRequestHandler* req) { } } +/** + * Stop recording. + * Will return an `error` if recording is not active. + * + * @api requests + * @name StopRecording + * @category recording + */ void WSRequestHandler::HandleStopRecording(WSRequestHandler* req) { if (obs_frontend_recording_active() == true) { obs_frontend_recording_stop(); @@ -502,6 +644,17 @@ void WSRequestHandler::HandleStopRecording(WSRequestHandler* req) { } } +/** + * List of all transitions available in the frontend's dropdown menu. + * + * @return {String} `current-transition` Name of the currently active transition. + * @return {Object|Array} `transitions` List of transitions. + * @return {String} `transitions[].name` Name of the transition. + * + * @api requests + * @name GetTransitionList + * @category transitions + */ void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) { obs_source_t* current_transition = obs_frontend_get_current_transition(); obs_frontend_source_list transitionList = {}; @@ -531,6 +684,16 @@ void WSRequestHandler::HandleGetTransitionList(WSRequestHandler* req) { obs_source_release(current_transition); } +/** + * Get the name of the currently selected transition in the frontend's dropdown menu. + * + * @return {String} `name` Name of the selected transition. + * @return {int (optional)} `duration` Transition duration (in milliseconds) if supported by the transition. + * + * @api requests + * @name GetCurrentTransition + * @category transitions + */ void WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) { obs_source_t* current_transition = obs_frontend_get_current_transition(); @@ -547,6 +710,15 @@ void WSRequestHandler::HandleGetCurrentTransition(WSRequestHandler* req) { obs_source_release(current_transition); } +/** + * Set the active transition. + * + * @param {String} `transition-name` The name of the transition. + * + * @api requests + * @name SetCurrentTransition + * @category transitions + */ void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) { if (!req->hasField("transition-name")) { req->SendErrorResponse("missing request parameters"); @@ -561,6 +733,15 @@ void WSRequestHandler::HandleSetCurrentTransition(WSRequestHandler* req) { req->SendErrorResponse("requested transition does not exist"); } +/** + * Set the duration of the currently selected transition if supported. + * + * @param {int} `duration` Desired duration of the transition (in milliseconds). + * + * @api requests + * @name SetTransitionDuration + * @category transitions + */ void WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) { if (!req->hasField("duration")) { req->SendErrorResponse("missing request parameters"); @@ -572,6 +753,15 @@ void WSRequestHandler::HandleSetTransitionDuration(WSRequestHandler* req) { req->SendOKResponse(); } +/** + * Get the duration of the currently selected transition if supported. + * + * @return {int} `transition-duration` Duration of the current transition (in milliseconds). + * + * @api requests + * @name GetTransitionDuration + * @category transitions + */ void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) { obs_data_t* response = obs_data_create(); obs_data_set_int(response, "transition-duration", @@ -581,6 +771,16 @@ void WSRequestHandler::HandleGetTransitionDuration(WSRequestHandler* req) { obs_data_release(response); } +/** + * Set the volume of the specified source. + * + * @param {String} `source` Name of the source. + * @param {double} `volume` Desired volume. Must be between `0.0` and `1.0`. + * + * @api requests + * @name SetVolume + * @category sources + */ void WSRequestHandler::HandleSetVolume(WSRequestHandler* req) { if (!req->hasField("source") || !req->hasField("volume")) { @@ -609,6 +809,19 @@ void WSRequestHandler::HandleSetVolume(WSRequestHandler* req) { obs_source_release(source); } +/** + * Get the volume of the specified source. + * + * @param {String} `source` Name of the source. + * + * @return {String} `name` Name of the source. + * @return {double} `volume` Volume of the source. Between `0.0` and `1.0`. + * @return {boolean} `mute` Indicates whether the source is muted. + * + * @api requests + * @name GetVolume + * @category sources + */ void WSRequestHandler::HandleGetVolume(WSRequestHandler* req) { if (!req->hasField("source")) { req->SendErrorResponse("missing request parameters"); @@ -633,6 +846,15 @@ void WSRequestHandler::HandleGetVolume(WSRequestHandler* req) { } } +/** + * Inverts the mute status of a specified source. + * + * @param {String} `source` The name of the source. + * + * @api requests + * @name ToggleMute + * @category sources + */ void WSRequestHandler::HandleToggleMute(WSRequestHandler* req) { if (!req->hasField("source")) { req->SendErrorResponse("missing request parameters"); @@ -657,6 +879,16 @@ void WSRequestHandler::HandleToggleMute(WSRequestHandler* req) { obs_source_release(source); } +/** + * Sets the mute status of a specified source. + * + * @param {String} `source` The name of the source. + * @param {boolean} `mute` Desired mute status. + * + * @api requests + * @name SetMute + * @category sources + */ void WSRequestHandler::HandleSetMute(WSRequestHandler* req) { if (!req->hasField("source") || !req->hasField("mute")) { @@ -684,6 +916,18 @@ void WSRequestHandler::HandleSetMute(WSRequestHandler* req) { obs_source_release(source); } +/** + * Get the mute status of a specified source. + * + * @param {String} `source` The name of the source. + * + * @return {String} `name` The name of the source. + * @return {boolean} `muted` Mute status of the source. + * + * @api requests + * @name GetMute + * @category sources + */ void WSRequestHandler::HandleGetMute(WSRequestHandler* req) { if (!req->hasField("source")) { req->SendErrorResponse("mssing request parameters"); @@ -712,26 +956,34 @@ void WSRequestHandler::HandleGetMute(WSRequestHandler* req) { obs_data_release(response); } +/** + * Set the audio sync offset of a specified source. + * + * @param {String} `source` The name of the source. + * @param {int} `offset` The desired audio sync offset (in nanoseconds). + * + * @api requests + * @name SetSyncOffset + * @category sources + */ void WSRequestHandler::HandleSetSyncOffset(WSRequestHandler* req) { - if (!req->hasField("source") || - !req->hasField("offset")) { - req->SendErrorResponse("missing request parameters"); - return; + if (!req->hasField("source") || !req->hasField("offset")) { + req->SendErrorResponse("missing request parameters"); + return; } const char* source_name = obs_data_get_string(req->data, "source"); int64_t source_sync_offset = (int64_t)obs_data_get_int(req->data, "offset"); - if (!source_name || strlen(source_name) < 1 || - source_sync_offset < 0) { - req->SendErrorResponse("invalid request parameters"); - return; + if (!source_name || strlen(source_name) < 1 || source_sync_offset < 0) { + req->SendErrorResponse("invalid request parameters"); + return; } obs_source_t* source = obs_get_source_by_name(source_name); if (!source) { req->SendErrorResponse("specified source doesn't exist"); - return; + return; } obs_source_set_sync_offset(source, source_sync_offset); @@ -740,30 +992,54 @@ void WSRequestHandler::HandleSetSyncOffset(WSRequestHandler* req) { obs_source_release(source); } +/** + * Get the audio sync offset of a specified source. + * + * @param {String} `source` The name of the source. + * + * @return {String} `name` The name of the source. + * @return {int} `offset` The audio sync offset (in nanoseconds). + * + * @api requests + * @name GetSyncOffset + * @category sources + */ void WSRequestHandler::HandleGetSyncOffset(WSRequestHandler* req) { if (!req->hasField("source")) { - req->SendErrorResponse("missing request parameters"); - return; + req->SendErrorResponse("missing request parameters"); + return; } const char* source_name = obs_data_get_string(req->data, "source"); if (str_valid(source_name)) { - obs_source_t* source = obs_get_source_by_name(source_name); + obs_source_t* source = obs_get_source_by_name(source_name); - obs_data_t* response = obs_data_create(); - obs_data_set_string(response, "name", source_name); - obs_data_set_int(response, "offset", obs_source_get_sync_offset(source)); + obs_data_t* response = obs_data_create(); + obs_data_set_string(response, "name", source_name); + obs_data_set_int(response, "offset", obs_source_get_sync_offset(source)); - req->SendOKResponse(response); + req->SendOKResponse(response); - obs_data_release(response); - obs_source_release(source); - } - else { - req->SendErrorResponse("invalid request parameters"); + obs_data_release(response); + obs_source_release(source); + } else { + req->SendErrorResponse("invalid request parameters"); } } +/** + * Sets the coordinates of a specified source item. + * + * @param {String (optional)} `scene-name` The name of the scene that the source item belongs to. Defaults to the current scene. + * @param {String} `item` The name of the source item. + * @param {double} `x` X coordinate. + * @param {double} `y` Y coordinate. + + * + * @api requests + * @name SetSceneItemPosition + * @category sources + */ void WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) { if (!req->hasField("item") || !req->hasField("x") || !req->hasField("y")) { @@ -801,6 +1077,19 @@ void WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Set the transform of the specified source item. + * + * @param {String (optional)} `scene-name` The name of the scene that the source item belongs to. Defaults to the current scene. + * @param {String} `item` The name of the source item. + * @param {double} `x-scale` Width scale factor. + * @param {double} `y-scale` Height scale factor. + * @param {double} `rotation` Source item rotation (in degrees). + * + * @api requests + * @name SetSceneItemTransform + * @category sources + */ void WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) { if (!req->hasField("item") || !req->hasField("x-scale") || @@ -842,6 +1131,20 @@ void WSRequestHandler::HandleSetSceneItemTransform(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Sets the crop coordinates of the specified source item. + * + * @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene. + * @param {String} `item` The name of the source. + * @param {int} `top` Pixel position of the top of the source item. + * @param {int} `bottom` Pixel position of the bottom of the source item. + * @param {int} `left` Pixel position of the left of the source item. + * @param {int} `right` Pixel position of the right of the source item. + * + * @api requests + * @name SetSceneItemCrop + * @category sources + */ void WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) { if (!req->hasField("item")) { req->SendErrorResponse("missing request parameters"); @@ -880,6 +1183,15 @@ void WSRequestHandler::HandleSetSceneItemCrop(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Change the active scene collection. + * + * @param {String} `sc-name` Name of the desired scene collection. + * + * @api requests + * @name SetCurrentSceneCollection + * @category scene collections + */ void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) { if (!req->hasField("sc-name")) { req->SendErrorResponse("missing request parameters"); @@ -896,6 +1208,15 @@ void WSRequestHandler::HandleSetCurrentSceneCollection(WSRequestHandler* req) { } } +/** + * Get the name of the current scene collection. + * + * @return {String} `sc-name` Name of the currently active scene collection. + * + * @api requests + * @name GetCurrentSceneCollection + * @category scene collections + */ void WSRequestHandler::HandleGetCurrentSceneCollection(WSRequestHandler* req) { obs_data_t* response = obs_data_create(); obs_data_set_string(response, "sc-name", @@ -916,6 +1237,15 @@ void WSRequestHandler::HandleListSceneCollections(WSRequestHandler* req) { obs_data_array_release(scene_collections); } +/** + * Set the currently active profile. + * + * @param {String} `profile-name` Name of the desired profile. + * + * @api requests + * @name SetCurrentProfile + * @category profiles + */ void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) { if (!req->hasField("profile-name")) { req->SendErrorResponse("missing request parameters"); @@ -932,6 +1262,15 @@ void WSRequestHandler::HandleSetCurrentProfile(WSRequestHandler* req) { } } + /** + * Get the name of the current profile. + * + * @return {String} `profile-name` Name of the currently active profile. + * + * @api requests + * @name GetCurrentProfile + * @category profiles + */ void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) { obs_data_t* response = obs_data_create(); obs_data_set_string(response, "profile-name", @@ -941,6 +1280,22 @@ void WSRequestHandler::HandleGetCurrentProfile(WSRequestHandler* req) { obs_data_release(response); } +/** + * Sets one or more attributes of the current streaming server settings. Any options not passed will remain unchanged. Returns the updated settings in response. If 'type' is different than the current streaming service type, all settings are required. Returns the full settings of the stream (the same as GetStreamSettings). + * + * @param {String} `type` The type of streaming service configuration, usually `rtmp_custom` or `rtmp_common`. + * @param {Object} `settings` The actual settings of the stream. + * @param {String (optional)} `settings.server` The publish URL. + * @param {String (optional)} `settings.key` The publish key. + * @param {boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server. + * @param {String (optional)} `settings.username` The username for the streaming service. + * @param {String (optional)} `settings.password` The password for the streaming service. + * @param {boolean} `save` Persist the settings to disk. + * + * @api requests + * @name SetStreamingSettings + * @category settings + */ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { obs_service_t* service = obs_frontend_get_streaming_service(); @@ -987,6 +1342,21 @@ void WSRequestHandler::HandleSetStreamSettings(WSRequestHandler* req) { obs_data_release(response); } +/** + * Get the current streaming server settings. + * + * @return {String} `type` The type of streaming service configuration. Usually 'rtmp_custom' or 'rtmp_common'. + * @return {Object} `settings` Setings of the stream. + * @return {String} `settings.server` The publish URL. + * @return {String} `settings.key` The publish key of the stream. + * @return {boolean} `settings.use-auth` Indicates whether audentication should be used when connecting to the streaming server. + * @return {String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`. + * @return {String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`. + * + * @api requests + * @name GetStreamSettings + * @category settings + */ void WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) { obs_service_t* service = obs_frontend_get_streaming_service(); const char* serviceType = obs_service_get_type(service); @@ -1001,11 +1371,27 @@ void WSRequestHandler::HandleGetStreamSettings(WSRequestHandler* req) { obs_data_release(response); } +/** + * Save the current streaming server settings to disk. + * + * @api requests + * @name SaveStreamSettings + * @category settings + */ void WSRequestHandler::HandleSaveStreamSettings(WSRequestHandler* req) { obs_frontend_save_streaming_service(); req->SendOKResponse(); } +/** + * Get a list of available profiles. + * + * @return {Object|Array} `profiles` List of available profiles. + * + * @api requests + * @name ListProfiles + * @category profiles + */ void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) { obs_data_array_t* profiles = Utils::GetProfiles(); @@ -1017,6 +1403,15 @@ void WSRequestHandler::HandleListProfiles(WSRequestHandler* req) { obs_data_array_release(profiles); } +/** + * Indicates if Studio Mode is currently enabled. + * + * @return {boolean} `studio-mode` Indicates if Studio Mode is enabled. + * + * @api requests + * @name GetStudioModeStatus + * @category studio mode + */ void WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) { bool previewActive = Utils::IsPreviewModeActive(); @@ -1027,6 +1422,17 @@ void WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* req) { obs_data_release(response); } +/** + * Get the name of the currently previewed scene and its list of sources. + * Will return an `error` if Studio Mode is not enabled. + * + * @return {String} `name` The name of the active preview scene. + * @return {Source|Array} `sources` + * + * @api requests + * @name GetPreviewScene + * @category studio mode + */ void WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) { if (!Utils::IsPreviewModeActive()) { req->SendErrorResponse("studio mode not enabled"); @@ -1049,6 +1455,16 @@ void WSRequestHandler::HandleGetPreviewScene(WSRequestHandler* req) { obs_scene_release(preview_scene); } +/** + * Set the active preview scene. + * Will return an `error` if Studio Mode is not enabled. + * + * @param {String} `scene-name` The name of the scene to preview. + * + * @api requests + * @name SetPreviewScene + * @category studio mode + */ void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) { if (!Utils::IsPreviewModeActive()) { req->SendErrorResponse("studio mode not enabled"); @@ -1068,6 +1484,18 @@ void WSRequestHandler::HandleSetPreviewScene(WSRequestHandler* req) { req->SendErrorResponse("specified scene doesn't exist"); } +/** + * Transitions the currently previewed scene to the main output. + * Will return an `error` if Studio Mode is not enabled. + * + * @param {Object (optional)} `with-transition` Change the active transition before switching scenes. Defaults to the active transition. + * @param {String} `with-transition.name` Name of the transition. + * @param {int (optional)} `with-transition.duration` Transition duration (in milliseconds). + * + * @api requests + * @name TransitionToProgram + * @category studio mode + */ void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) { if (!Utils::IsPreviewModeActive()) { req->SendErrorResponse("studio mode not enabled"); @@ -1107,21 +1535,55 @@ void WSRequestHandler::HandleTransitionToProgram(WSRequestHandler* req) { req->SendOKResponse(); } +/** + * Enables Studio Mode. + * + * @api requests + * @name EnableStudioMode + * @category studio mode + */ void WSRequestHandler::HandleEnableStudioMode(WSRequestHandler* req) { Utils::EnablePreviewMode(); req->SendOKResponse(); } +/** + * Disables Studio Mode. + * + * @api requests + * @name DisableStudioMode + * @category studio mode + */ void WSRequestHandler::HandleDisableStudioMode(WSRequestHandler* req) { Utils::DisablePreviewMode(); req->SendOKResponse(); } +/** + * Toggles Studio Mode. + * + * @api requests + * @name ToggleStudioMode + * @category studio mode + */ void WSRequestHandler::HandleToggleStudioMode(WSRequestHandler* req) { Utils::TogglePreviewMode(); req->SendOKResponse(); } +/** + * Get configured special sources like Desktop Audio and Mic/Aux sources. + * + * @return {String (optional)} `desktop-1` Name of the first Desktop Audio capture source. + * @return {String (optional)} `desktop-2` Name of the second Desktop Audio capture source. + * @return {String (optional)} `mic-1` Name of the first Mic/Aux input source. + * @return {String (optional)} `mic-2` Name of the second Mic/Aux input source. + * @return {String (optional)} `mic-3` NAme of the third Mic/Aux input source. + * + * @api requests + * @name GetSpecialSources + * @category studio mode + */ void WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req) { obs_data_t* response = obs_data_create(); @@ -1150,6 +1612,15 @@ void WSRequestHandler::HandleGetSpecialSources(WSRequestHandler* req) { obs_data_release(response); } +/** + * Change the current recording folder. + * + * @param {Stsring} `rec-folder` Path of the recording folder. + * + * @api requests + * @name SetRecordingFolder + * @category recording + */ void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) { if (!req->hasField("rec-folder")) { req->SendErrorResponse("missing request parameters"); @@ -1164,6 +1635,15 @@ void WSRequestHandler::HandleSetRecordingFolder(WSRequestHandler* req) { req->SendErrorResponse("invalid request parameters"); } +/** + * Get the path of the current recording folder. + * + * @return {Stsring} `rec-folder` Path of the recording folder. + * + * @api requests + * @name GetRecordingFolder + * @category recording + */ void WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) { const char* recFolder = Utils::GetRecordingFolder(); @@ -1174,6 +1654,45 @@ void WSRequestHandler::HandleGetRecordingFolder(WSRequestHandler* req) { obs_data_release(response); } +/** + * Get the current properties of a Text GDI Plus source. + * + * @param {String (optional)} `scene-name` Name of the scene to retrieve. Defaults to the current scene. + * @param {String} `source` Name of the source. + * + * @return {String} `align` Text Alignment ("left", "center", "right"). + * @return {int} `bk-color` Background color. + * @return {int} `bk-opacity` Background opacity (0-100). + * @return {boolean} `chatlog` Chat log. + * @return {int} `chatlog_lines` Chat log lines. + * @return {int} `color` Text color. + * @return {boolean} `extents` Extents wrap. + * @return {int} `extents_cx` Extents cx. + * @return {int} `extents_cy` Extents cy. + * @return {String} `file` File path name. + * @return {boolean} `read_from_file` Read text from the specified file. + * @return {Object} `font` Holds data for the font. Ex: `"font": { "face": "Arial", "flags": 0, "size": 150, "style": "" }` + * @return {String} `font.face` Font face. + * @return {int} `font.flags` Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8` + * @return {int} `font.size` Font text size. + * @return {String} `font.style` Font Style (unknown function). + * @return {boolean} `gradient` Gradient enabled. + * @return {int} `gradient_color` Gradient color. + * @return {float} `gradient_dir` Gradient direction. + * @return {int} `gradient_opacity` Gradient opacity (0-100). + * @return {boolean} `outline` Outline. + * @return {int} `outline_color` Outline color. + * @return {int} `outline_size` Outline size. + * @return {int} `outline_opacity` Outline opacity (0-100). + * @return {String} `text` Text content to be displayed. + * @return {String} `valign` Text vertical alignment ("top", "center", "bottom"). + * @return {boolean} `vertical` Vertical text enabled. + * @return {boolean} `render` Visibility of the scene item. + * + * @api requests + * @name GetTextGDIPlusProperties + * @category sources + */ void WSRequestHandler::HandleGetTextGDIPlusProperties(WSRequestHandler* req) { const char* itemName = obs_data_get_string(req->data, "source"); if (!itemName) { @@ -1214,6 +1733,44 @@ void WSRequestHandler::HandleGetTextGDIPlusProperties(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Get the current properties of a Text GDI Plus source. + * + * @param {String (optional)} `scene-name` Name of the scene to retrieve. Defaults to the current scene. + * @param {String} `source` Name of the source. + * @param {String (optional)} `align` Text Alignment ("left", "center", "right"). + * @param {int (optional)} `bk-color` Background color. + * @param {int (optional)} `bk-opacity` Background opacity (0-100). + * @param {boolean (optional)} `chatlog` Chat log. + * @param {int (optional)} `chatlog_lines` Chat log lines. + * @param {int (optional)} `color` Text color. + * @param {boolean (optional)} `extents` Extents wrap. + * @param {int (optional)} `extents_cx` Extents cx. + * @param {int (optional)} `extents_cy` Extents cy. + * @param {String (optional)} `file` File path name. + * @param {boolean (optional)} `read_from_file` Read text from the specified file. + * @param {Object (optional)} `font` Holds data for the font. Ex: `"font": { "face": "Arial", "flags": 0, "size": 150, "style": "" }` + * @param {String (optional)} `font.face` Font face. + * @param {int (optional)} `font.flags` Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8` + * @param {int (optional)} `font.size` Font text size. + * @param {String (optional)} `font.style` Font Style (unknown function). + * @param {boolean (optional)} `gradient` Gradient enabled. + * @param {int (optional)} `gradient_color` Gradient color. + * @param {float (optional)} `gradient_dir` Gradient direction. + * @param {int (optional)} `gradient_opacity` Gradient opacity (0-100). + * @param {boolean (optional)} `outline` Outline. + * @param {int (optional)} `outline_color` Outline color. + * @param {int (optional)} `outline_size` Outline size. + * @param {int (optional)} `outline_opacity` Outline opacity (0-100). + * @param {String (optional)} `text` Text content to be displayed. + * @param {String (optional)} `valign` Text vertical alignment ("top", "center", "bottom"). + * @param {boolean (optional)} `vertical` Vertical text enabled. + * @param {boolean (optional)} `render` Visibility of the scene item. + * + * @api requests + * @name SetTextGDIPlusProperties + * @category sources + */ void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { if (!req->hasField("source")) { req->SendErrorResponse("missing request parameters"); @@ -1406,6 +1963,25 @@ void WSRequestHandler::HandleSetTextGDIPlusProperties(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Get current properties for a Browser Source. + * + * @param {String (optional)} `scene-name` Name of the scene that the source belongs to. Defaults to the current scene. + * @param {String} `source` Name of the source. + * + * @return {boolean} `is_local_file` Indicates that a local file is in use. + * @return {String} `url` Url or file path. + * @return {String} `css` CSS to inject. + * @return {int} `width` Width. + * @return {int} `height` Height. + * @return {int} `fps` Framerate. + * @return {boolean} `shutdown` Indicates whether the source should be shutdown when not visible. + * @return {boolean (optional)} `render` Visibility of the scene item. + * + * @api requests + * @name GetBrowserSourceProperties + * @category sources + */ void WSRequestHandler::HandleGetBrowserSourceProperties(WSRequestHandler* req) { const char* itemName = obs_data_get_string(req->data, "source"); if (!itemName) { @@ -1445,6 +2021,24 @@ void WSRequestHandler::HandleGetBrowserSourceProperties(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Set current properties for a Browser Source. + * + * @param {String (optional)} `scene-name` Name of the scene that the source belongs to. Defaults to the current scene. + * @param {String} `source` Name of the source. + * @param {boolean (optional)} `is_local_file` Indicates that a local file is in use. + * @param {String (optional)} `url` Url or file path. + * @param {String (optional)} `css` CSS to inject. + * @param {int (optional)} `width` Width. + * @param {int (optional)} `height` Height. + * @param {int (optional)} `fps` Framerate. + * @param {boolean (optional)} `shutdown` Indicates whether the source should be shutdown when not visible. + * @param {boolean (optional)} `render` Visibility of the scene item. + * + * @api requests + * @name SetBrowserSourceProperties + * @category sources + */ void WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHandler* req) { if (!req->hasField("source")) { req->SendErrorResponse("missing request parameters"); @@ -1532,6 +2126,16 @@ void WSRequestHandler::HandleSetBrowserSourceProperties(WSRequestHandler* req) { obs_source_release(scene); } +/** + * Reset a source item. + * + * @param {String (optional)} `scene-name` Name of the scene the source belogns to. Defaults to the current scene. + * @param {String} `item` Name of the source item. + * + * @api requests + * @name ResetSceneItem + * @category sources + */ void WSRequestHandler::HandleResetSceneItem(WSRequestHandler* req) { if (!req->hasField("item")) { req->SendErrorResponse("missing request parameters"); diff --git a/docs/.editorconfig b/docs/.editorconfig new file mode 100644 index 00000000..2e0a7808 --- /dev/null +++ b/docs/.editorconfig @@ -0,0 +1,11 @@ +[*] +end_of_line = lf +charset = utf-8 +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md, *.mustache] +trim_trailing_whitespace = false +insert_final_newline = false diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..8c549731 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,4 @@ +node_modules +logs +*.log +npm-debug.log* diff --git a/docs/.npmrc b/docs/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/docs/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..265cbd22 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,21 @@ +## Installation + +Install node and update npm if necessary. + +```sh +cd obs-websocket/docs +npm install +``` + +## Build + +```sh +# Just extract the comments. +npm run comments + +# Just render the markdown. +npm run docs + +# Do both comments and markdown. +npm run build +``` diff --git a/docs/comments.js b/docs/comments.js new file mode 100644 index 00000000..2361daa7 --- /dev/null +++ b/docs/comments.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const glob = require('glob'); +const parseComments = require('parse-comments'); + +/** + * Read each file and call `parse-comments` on it. + * + * @param {String|Array} `files` List of file paths to read from. + * @return {Object|Array} Array of `parse-comments` objects. + */ +const parseFiles = files => { + let response = []; + files.forEach(file => { + const f = fs.readFileSync(file, 'utf8').toString(); + response = response.concat(parseComments(f)); + }); + + return response; +}; + +/** + * Filters/sorts the results from `parse-comments`. + * @param {Object|Array} `comments` Array of `parse-comments` objects. + * @return {Object} Filtered comments sorted by `@api` and `@category`. + */ +const processComments = comments => { + let sorted = {}; + + comments.forEach(comment => { + if (typeof comment.api === 'undefined') return; + + // Store the object based on its api (ie. requests, events) and category (ie. general, scenes, etc). + comment.category = comment.category || 'miscellaneous'; + + // Remove some unnecessary properties to avoid result differences in travis. + comment.comment = undefined; + comment.context = undefined; + + // Create an entry in sorted for the api/category if one does not exist. + sorted[comment.api] = sorted[comment.api] || {}; + sorted[comment.api][comment.category] = sorted[comment.api][comment.category] || []; + + // Store the comment in the appropriate api/category. + sorted[comment.api][comment.category].push(comment); + }); + + return sorted; +}; + +const files = glob.sync("./../*.@(cpp|h)"); +const comments = processComments(parseFiles(files)); +fs.writeFileSync('./generated/comments.json', JSON.stringify(comments, null, 2)); diff --git a/docs/docs.js b/docs/docs.js new file mode 100644 index 00000000..8300aaa5 --- /dev/null +++ b/docs/docs.js @@ -0,0 +1,31 @@ +const fs = require('fs'); +const toc = require('markdown-toc'); +const handlebars = require('handlebars'); + +const helpers = require('handlebars-helpers')({ + handlebars: handlebars +}); + +// Allows pipe characters to be used within markdown tables. +handlebars.registerHelper('depipe', (text) => { + return text.replace('|', `\\|`); +}); + +const insertHeader = (text) => { + return '\n\n' + text; +}; + +/** + * Writes `protocol.md` using `protocol.mustache`. + * + * @param {Object} `data` Data to assign to the mustache template. + */ +const generateProtocol = (templatePath, data) => { + const template = fs.readFileSync(templatePath).toString(); + const generated = handlebars.compile(template)(data); + return insertHeader(toc.insert(generated)); +}; + +const comments = fs.readFileSync('./generated/comments.json', 'utf8'); +const markdown = generateProtocol('./protocol.hbs', JSON.parse(comments)); +fs.writeFileSync('./generated/protocol.md', markdown); diff --git a/docs/generated/comments.json b/docs/generated/comments.json new file mode 100644 index 00000000..69cdfec0 --- /dev/null +++ b/docs/generated/comments.json @@ -0,0 +1,3464 @@ +{ + "events": { + "scenes": [ + { + "subheads": [], + "description": "Indicates a scene change.", + "return": [ + "{String} `scene-name` The new scene.", + "{Array} `sources` List of sources in the new scene." + ], + "api": "events", + "name": "OnSceneChange", + "category": "scenes", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "The new scene." + }, + { + "type": "Array", + "name": "sources", + "description": "List of sources in the new scene." + } + ], + "names": [ + { + "name": "", + "description": "OnSceneChange" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "OnSceneChange" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "The scene list has been modified.\nScenes have been added, removed, or renamed.", + "api": "events", + "name": "ScenesChanged", + "category": "scenes", + "names": [ + { + "name": "", + "description": "ScenesChanged" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "ScenesChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Triggered when switching to another scene collection or when renaming the current scene collection.", + "api": "events", + "name": "SceneCollectionChanged", + "category": "scenes", + "names": [ + { + "name": "", + "description": "SceneCollectionChanged" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "SceneCollectionChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Triggered when a scene collection is created, added, renamed, or removed.", + "api": "events", + "name": "SceneCollectionListChanged", + "category": "scenes", + "names": [ + { + "name": "", + "description": "SceneCollectionListChanged" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "SceneCollectionListChanged" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "transitions": [ + { + "subheads": [], + "description": "The active transition has been changed.", + "return": "{String} `transition-name` The name of the new active transition.", + "api": "events", + "name": "SwitchTransition", + "category": "transitions", + "returns": [ + { + "type": "String", + "name": "transition-name", + "description": "The name of the new active transition." + } + ], + "names": [ + { + "name": "", + "description": "SwitchTransition" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "SwitchTransition" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "The list of available transitions has been modified.\nTransitions have been added, removed, or renamed.", + "api": "events", + "name": "TransitionListChanged", + "category": "transitions", + "names": [ + { + "name": "", + "description": "TransitionListChanged" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "TransitionListChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "The active transition duration has been changed.", + "return": "{int} `new-duration` New transition duration.", + "api": "events", + "name": "TransitionDurationChanged", + "category": "transitions", + "returns": [ + { + "type": "int", + "name": "new-duration", + "description": "New transition duration." + } + ], + "names": [ + { + "name": "", + "description": "TransitionDurationChanged" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "TransitionDurationChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "A transition (other than \"cut\") has begun.", + "return": [ + "{String} `name` Transition name.", + "{int} `duration` Transition duration (in milliseconds)." + ], + "api": "events", + "name": "TransitionBegin", + "category": "transitions", + "returns": [ + { + "type": "String", + "name": "name", + "description": "Transition name." + }, + { + "type": "int", + "name": "duration", + "description": "Transition duration (in milliseconds)." + } + ], + "names": [ + { + "name": "", + "description": "TransitionBegin" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "TransitionBegin" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "profiles": [ + { + "subheads": [], + "description": "Triggered when switching to another profile or when renaming the current profile.", + "api": "events", + "name": "ProfileChanged", + "category": "profiles", + "names": [ + { + "name": "", + "description": "ProfileChanged" + } + ], + "categories": [ + { + "name": "", + "description": "profiles" + } + ], + "heading": { + "level": 2, + "text": "ProfileChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Triggered when a profile is created, added, renamed, or removed.", + "api": "events", + "name": "ProfileListChanged", + "category": "profiles", + "names": [ + { + "name": "", + "description": "ProfileListChanged" + } + ], + "categories": [ + { + "name": "", + "description": "profiles" + } + ], + "heading": { + "level": 2, + "text": "ProfileListChanged" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "streaming": [ + { + "subheads": [], + "description": "A request to start streaming has been issued.", + "return": "{boolean} `preview-only` Always false (retrocompatibility).", + "api": "events", + "name": "StreamStarting", + "category": "streaming", + "returns": [ + { + "type": "boolean", + "name": "preview-only", + "description": "Always false (retrocompatibility)." + } + ], + "names": [ + { + "name": "", + "description": "StreamStarting" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StreamStarting" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Streaming started successfully.", + "api": "events", + "name": "StreamStarted", + "category": "streaming", + "names": [ + { + "name": "", + "description": "StreamStarted" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StreamStarted" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "A request to stop streaming has been issued.", + "return": "{boolean} `preview-only` Always false (retrocompatibility).", + "api": "events", + "name": "StreamStopping", + "category": "streaming", + "returns": [ + { + "type": "boolean", + "name": "preview-only", + "description": "Always false (retrocompatibility)." + } + ], + "names": [ + { + "name": "", + "description": "StreamStopping" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StreamStopping" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Streaming stopped successfully.", + "api": "events", + "name": "StreamStopped", + "category": "streaming", + "names": [ + { + "name": "", + "description": "StreamStopped" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StreamStopped" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Emit every 2 seconds.", + "return": [ + "{boolean} `streaming` Current streaming state.", + "{boolean} `recording` Current recording state.", + "{boolean} `preview-only` Always false (retrocompatibility).", + "{int} `bytes-per-sec` Amount of data per second (in bytes) transmitted by the stream encoder.", + "{int} `kbits-per-sec` Amount of data per second (in kilobits) transmitted by the stream encoder.", + "{double} `strain` Percentage of dropped frames.", + "{int} `total-stream-time` Total time (in seconds) since the stream started.", + "{int} `num-total-frames` Total number of frames transmitted since the stream started.", + "{int} `num-dropped-frames` Number of frames dropped by the encoder since the stream started.", + "{double} `fps` Current framerate." + ], + "api": "events", + "name": "StreamStatus", + "category": "streaming", + "returns": [ + { + "type": "boolean", + "name": "streaming", + "description": "Current streaming state." + }, + { + "type": "boolean", + "name": "recording", + "description": "Current recording state." + }, + { + "type": "boolean", + "name": "preview-only", + "description": "Always false (retrocompatibility)." + }, + { + "type": "int", + "name": "bytes-per-sec", + "description": "Amount of data per second (in bytes) transmitted by the stream encoder." + }, + { + "type": "int", + "name": "kbits-per-sec", + "description": "Amount of data per second (in kilobits) transmitted by the stream encoder." + }, + { + "type": "double", + "name": "strain", + "description": "Percentage of dropped frames." + }, + { + "type": "int", + "name": "total-stream-time", + "description": "Total time (in seconds) since the stream started." + }, + { + "type": "int", + "name": "num-total-frames", + "description": "Total number of frames transmitted since the stream started." + }, + { + "type": "int", + "name": "num-dropped-frames", + "description": "Number of frames dropped by the encoder since the stream started." + }, + { + "type": "double", + "name": "fps", + "description": "Current framerate." + } + ], + "names": [ + { + "name": "", + "description": "StreamStatus" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StreamStatus" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "recording": [ + { + "subheads": [], + "description": "A request to start recording has been issued.", + "api": "events", + "name": "RecordingStarting", + "category": "recording", + "names": [ + { + "name": "", + "description": "RecordingStarting" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "RecordingStarting" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Recording started successfully.", + "api": "events", + "name": "RecordingStarted", + "category": "recording", + "names": [ + { + "name": "", + "description": "RecordingStarted" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "RecordingStarted" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "A request to stop recording has been issued.", + "api": "events", + "name": "RecordingStopping", + "category": "recording", + "names": [ + { + "name": "", + "description": "RecordingStopping" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "RecordingStopping" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Recording stopped successfully.", + "api": "events", + "name": "RecordingStopped", + "category": "recording", + "names": [ + { + "name": "", + "description": "RecordingStopped" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "RecordingStopped" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "other": [ + { + "subheads": [], + "description": "OBS is exiting.", + "api": "events", + "name": "Exiting", + "category": "other", + "names": [ + { + "name": "", + "description": "Exiting" + } + ], + "categories": [ + { + "name": "", + "description": "other" + } + ], + "heading": { + "level": 2, + "text": "Exiting" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "sources": [ + { + "subheads": [], + "description": "Scene items have been reordered.", + "return": "{String} `scene-name` Name of the scene where items have been reordered.", + "api": "events", + "name": "SourceOrderChanged", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene where items have been reordered." + } + ], + "names": [ + { + "name": "", + "description": "SourceOrderChanged" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SourceOrderChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "An item has been added to the current scene.", + "return": [ + "{String} `scene-name` Name of the scene.", + "{String} `item-name` Name of the item added to the scene." + ], + "api": "events", + "name": "SceneItemAdded", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene." + }, + { + "type": "String", + "name": "item-name", + "description": "Name of the item added to the scene." + } + ], + "names": [ + { + "name": "", + "description": "SceneItemAdded" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SceneItemAdded" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "An item has been removed from the current scene.", + "return": [ + "{String} `scene-name` Name of the scene.", + "{String} `item-name` Name of the item removed from the scene." + ], + "api": "events", + "name": "SceneItemRemoved", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene." + }, + { + "type": "String", + "name": "item-name", + "description": "Name of the item removed from the scene." + } + ], + "names": [ + { + "name": "", + "description": "SceneItemRemoved" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SceneItemRemoved" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "An item's visibility has been toggled.", + "return": [ + "{String} `scene-name` Name of the scene.", + "{String} `item-name` Name of the item in the scene.", + "{boolean} `item-visible` New visibility state of the item." + ], + "api": "events", + "name": "SceneItemVisibilityChanged", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene." + }, + { + "type": "String", + "name": "item-name", + "description": "Name of the item in the scene." + }, + { + "type": "boolean", + "name": "item-visible", + "description": "New visibility state of the item." + } + ], + "names": [ + { + "name": "", + "description": "SceneItemVisibilityChanged" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SceneItemVisibilityChanged" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "studio mode": [ + { + "subheads": [], + "description": "The selected preview scene has changed (only available in Studio Mode).", + "return": [ + "{String} `scene-name` Name of the scene being previewed.", + "{Source|Array} `sources` List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene)." + ], + "api": "events", + "name": "PreviewSceneChanged", + "category": "studio mode", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene being previewed." + }, + { + "type": "Source|Array", + "name": "sources", + "description": "List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene)." + } + ], + "names": [ + { + "name": "", + "description": "PreviewSceneChanged" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "PreviewSceneChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Studio Mode has been enabled or disabled.", + "return": "{boolean} `new-state` The new enabled state of Studio Mode.", + "api": "events", + "name": "StudioModeSwitched", + "category": "studio mode", + "returns": [ + { + "type": "boolean", + "name": "new-state", + "description": "The new enabled state of Studio Mode." + } + ], + "names": [ + { + "name": "", + "description": "StudioModeSwitched" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "StudioModeSwitched" + }, + "lead": "", + "type": "class", + "examples": [] + } + ] + }, + "requests": { + "general": [ + { + "subheads": [], + "description": "Returns the latest version of the plugin and the API.", + "return": [ + "{double} `version` OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility.", + "{String} `obs-websocket-version` obs-websocket plugin version.", + "{String} `obs-studio-version` OBS Studio program version.", + "{String|Array} `available-requests` List of available request types." + ], + "api": "requests", + "name": "GetVersion", + "category": "general", + "returns": [ + { + "type": "double", + "name": "version", + "description": "OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility." + }, + { + "type": "String", + "name": "obs-websocket-version", + "description": "obs-websocket plugin version." + }, + { + "type": "String", + "name": "obs-studio-version", + "description": "OBS Studio program version." + }, + { + "type": "String|Array", + "name": "available-requests", + "description": "List of available request types." + } + ], + "names": [ + { + "name": "", + "description": "GetVersion" + } + ], + "categories": [ + { + "name": "", + "description": "general" + } + ], + "heading": { + "level": 2, + "text": "GetVersion" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Tells the client if authentication is required. If so, returns authentication parameters `challenge`\nand `salt` (see \"Authentication\" for more information).", + "return": [ + "{boolean} `authRequired` Indicates whether authentication is required.", + "{String (optional)} `challenge`", + "{String (optional)} `salt`" + ], + "api": "requests", + "name": "GetAuthRequired", + "category": "general", + "returns": [ + { + "type": "boolean", + "name": "authRequired", + "description": "Indicates whether authentication is required." + }, + { + "type": "String (optional)", + "name": "challenge", + "description": "" + }, + { + "type": "String (optional)", + "name": "salt", + "description": "" + } + ], + "names": [ + { + "name": "", + "description": "GetAuthRequired" + } + ], + "categories": [ + { + "name": "", + "description": "general" + } + ], + "heading": { + "level": 2, + "text": "GetAuthRequired" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Attempt to authenticate the client to the server.", + "param": "{String} `auth` Response to the auth challenge (see \"Authentication\" for more information).", + "api": "requests", + "name": "Authenticate", + "category": "general", + "params": [ + { + "type": "String", + "name": "auth", + "description": "Response to the auth challenge (see \"Authentication\" for more information)." + } + ], + "names": [ + { + "name": "", + "description": "Authenticate" + } + ], + "categories": [ + { + "name": "", + "description": "general" + } + ], + "heading": { + "level": 2, + "text": "Authenticate" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "scenes": [ + { + "subheads": [], + "description": "Switch to the specified scene.", + "param": "{String} `scene-name` Name of the scene to switch to.", + "api": "requests", + "name": "SetCurrentScene", + "category": "scenes", + "params": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene to switch to." + } + ], + "names": [ + { + "name": "", + "description": "SetCurrentScene" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "SetCurrentScene" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the current scene's name and source items.", + "return": [ + "{String} `name` Name of the currently active scene.", + "{Source|Array} `sources` Ordered list of the current scene's source items." + ], + "api": "requests", + "name": "GetCurrentScene", + "category": "scenes", + "returns": [ + { + "type": "String", + "name": "name", + "description": "Name of the currently active scene." + }, + { + "type": "Source|Array", + "name": "sources", + "description": "Ordered list of the current scene's source items." + } + ], + "names": [ + { + "name": "", + "description": "GetCurrentScene" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "GetCurrentScene" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get a list of scenes in the currently active profile.", + "return": [ + "{String} `current-scene` Name of the currently active scene.", + "{Scene|Array} `scenes` Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information)." + ], + "api": "requests", + "name": "GetSceneList", + "category": "scenes", + "returns": [ + { + "type": "String", + "name": "current-scene", + "description": "Name of the currently active scene." + }, + { + "type": "Scene|Array", + "name": "scenes", + "description": "Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information)." + } + ], + "names": [ + { + "name": "", + "description": "GetSceneList" + } + ], + "categories": [ + { + "name": "", + "description": "scenes" + } + ], + "heading": { + "level": 2, + "text": "GetSceneList" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "sources": [ + { + "subheads": [], + "description": "Show or hide a specified source item in a specified scene.", + "param": [ + "{String} `source` Name of the source in the specified scene.", + "{boolean} `render` Desired visibility.", + "{String (optional)} `scene-name` Name of the scene where the source resides. Defaults to the currently active scene." + ], + "api": "requests", + "name": "SetSourceRender", + "category": "sources", + "params": [ + { + "type": "String", + "name": "source", + "description": "Name of the source in the specified scene." + }, + { + "type": "boolean", + "name": "render", + "description": "Desired visibility." + }, + { + "type": "String (optional)", + "name": "scene-name", + "description": "Name of the scene where the source resides. Defaults to the currently active scene." + } + ], + "names": [ + { + "name": "", + "description": "SetSourceRender" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetSourceRender" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Set the volume of the specified source.", + "param": [ + "{String} `source` Name of the source.", + "{double} `volume` Desired volume. Must be between `0.0` and `1.0`." + ], + "api": "requests", + "name": "SetVolume", + "category": "sources", + "params": [ + { + "type": "String", + "name": "source", + "description": "Name of the source." + }, + { + "type": "double", + "name": "volume", + "description": "Desired volume. Must be between `0.0` and `1.0`." + } + ], + "names": [ + { + "name": "", + "description": "SetVolume" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetVolume" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the volume of the specified source.", + "param": "{String} `source` Name of the source.", + "return": [ + "{String} `name` Name of the source.", + "{double} `volume` Volume of the source. Between `0.0` and `1.0`.", + "{boolean} `mute` Indicates whether the source is muted." + ], + "api": "requests", + "name": "GetVolume", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "name", + "description": "Name of the source." + }, + { + "type": "double", + "name": "volume", + "description": "Volume of the source. Between `0.0` and `1.0`." + }, + { + "type": "boolean", + "name": "mute", + "description": "Indicates whether the source is muted." + } + ], + "params": [ + { + "type": "String", + "name": "source", + "description": "Name of the source." + } + ], + "names": [ + { + "name": "", + "description": "GetVolume" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "GetVolume" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Inverts the mute status of a specified source.", + "param": "{String} `source` The name of the source.", + "api": "requests", + "name": "ToggleMute", + "category": "sources", + "params": [ + { + "type": "String", + "name": "source", + "description": "The name of the source." + } + ], + "names": [ + { + "name": "", + "description": "ToggleMute" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "ToggleMute" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Sets the mute status of a specified source.", + "param": [ + "{String} `source` The name of the source.", + "{boolean} `mute` Desired mute status." + ], + "api": "requests", + "name": "SetMute", + "category": "sources", + "params": [ + { + "type": "String", + "name": "source", + "description": "The name of the source." + }, + { + "type": "boolean", + "name": "mute", + "description": "Desired mute status." + } + ], + "names": [ + { + "name": "", + "description": "SetMute" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetMute" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the mute status of a specified source.", + "param": "{String} `source` The name of the source.", + "return": [ + "{String} `name` The name of the source.", + "{boolean} `muted` Mute status of the source." + ], + "api": "requests", + "name": "GetMute", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "name", + "description": "The name of the source." + }, + { + "type": "boolean", + "name": "muted", + "description": "Mute status of the source." + } + ], + "params": [ + { + "type": "String", + "name": "source", + "description": "The name of the source." + } + ], + "names": [ + { + "name": "", + "description": "GetMute" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "GetMute" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Sets the coordinates of a specified source item.", + "param": [ + "{String (optional)} `scene-name` The name of the scene that the source item belongs to. Defaults to the current scene.", + "{String} `item` The name of the source item.", + "{double} `x` X coordinate.", + "{double} `y` Y coordinate." + ], + "api": "requests", + "name": "SetSceneItemPosition", + "category": "sources", + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "The name of the scene that the source item belongs to. Defaults to the current scene." + }, + { + "type": "String", + "name": "item", + "description": "The name of the source item." + }, + { + "type": "double", + "name": "x", + "description": "X coordinate." + }, + { + "type": "double", + "name": "y", + "description": "Y coordinate." + } + ], + "names": [ + { + "name": "", + "description": "SetSceneItemPosition" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetSceneItemPosition" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Set the transform of the specified source item.", + "param": [ + "{String (optional)} `scene-name` The name of the scene that the source item belongs to. Defaults to the current scene.", + "{String} `item` The name of the source item.", + "{double} `x-scale` Width scale factor.", + "{double} `y-scale` Height scale factor.", + "{double} `rotation` Source item rotation (in degrees)." + ], + "api": "requests", + "name": "SetSceneItemTransform", + "category": "sources", + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "The name of the scene that the source item belongs to. Defaults to the current scene." + }, + { + "type": "String", + "name": "item", + "description": "The name of the source item." + }, + { + "type": "double", + "name": "x-scale", + "description": "Width scale factor." + }, + { + "type": "double", + "name": "y-scale", + "description": "Height scale factor." + }, + { + "type": "double", + "name": "rotation", + "description": "Source item rotation (in degrees)." + } + ], + "names": [ + { + "name": "", + "description": "SetSceneItemTransform" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetSceneItemTransform" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Sets the crop coordinates of the specified source item.", + "param": [ + "{String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.", + "{String} `item` The name of the source.", + "{int} `top` Pixel position of the top of the source item.", + "{int} `bottom` Pixel position of the bottom of the source item.", + "{int} `left` Pixel position of the left of the source item.", + "{int} `right` Pixel position of the right of the source item." + ], + "api": "requests", + "name": "SetSceneItemCrop", + "category": "sources", + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "the name of the scene that the source item belongs to. Defaults to the current scene." + }, + { + "type": "String", + "name": "item", + "description": "The name of the source." + }, + { + "type": "int", + "name": "top", + "description": "Pixel position of the top of the source item." + }, + { + "type": "int", + "name": "bottom", + "description": "Pixel position of the bottom of the source item." + }, + { + "type": "int", + "name": "left", + "description": "Pixel position of the left of the source item." + }, + { + "type": "int", + "name": "right", + "description": "Pixel position of the right of the source item." + } + ], + "names": [ + { + "name": "", + "description": "SetSceneItemCrop" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetSceneItemCrop" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the current properties of a Text GDI Plus source.", + "param": [ + "{String (optional)} `scene-name` Name of the scene to retrieve. Defaults to the current scene.", + "{String} `source` Name of the source." + ], + "return": [ + "{String} `align` Text Alignment (\"left\", \"center\", \"right\").", + "{int} `bk-color` Background color.", + "{int} `bk-opacity` Background opacity (0-100).", + "{boolean} `chatlog` Chat log.", + "{int} `chatlog_lines` Chat log lines.", + "{int} `color` Text color.", + "{boolean} `extents` Extents wrap.", + "{int} `extents_cx` Extents cx.", + "{int} `extents_cy` Extents cy.", + "{String} `file` File path name.", + "{boolean} `read_from_file` Read text from the specified file.", + "{Object} `font` Holds data for the font. Ex: `\"font\": { \"face\": \"Arial\", \"flags\": 0, \"size\": 150, \"style\": \"\" }`", + "{String} `font.face` Font face.", + "{int} `font.flags` Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8`", + "{int} `font.size` Font text size.", + "{String} `font.style` Font Style (unknown function).", + "{boolean} `gradient` Gradient enabled.", + "{int} `gradient_color` Gradient color.", + "{float} `gradient_dir` Gradient direction.", + "{int} `gradient_opacity` Gradient opacity (0-100).", + "{boolean} `outline` Outline.", + "{int} `outline_color` Outline color.", + "{int} `outline_size` Outline size.", + "{int} `outline_opacity` Outline opacity (0-100).", + "{String} `text` Text content to be displayed.", + "{String} `valign` Text vertical alignment (\"top\", \"center\", \"bottom\").", + "{boolean} `vertical` Vertical text enabled.", + "{boolean} `render` Visibility of the scene item." + ], + "api": "requests", + "name": "GetTextGDIPlusProperties", + "category": "sources", + "returns": [ + { + "type": "String", + "name": "align", + "description": "Text Alignment (\"left\", \"center\", \"right\")." + }, + { + "type": "int", + "name": "bk-color", + "description": "Background color." + }, + { + "type": "int", + "name": "bk-opacity", + "description": "Background opacity (0-100)." + }, + { + "type": "boolean", + "name": "chatlog", + "description": "Chat log." + }, + { + "type": "int", + "name": "chatlog_lines", + "description": "Chat log lines." + }, + { + "type": "int", + "name": "color", + "description": "Text color." + }, + { + "type": "boolean", + "name": "extents", + "description": "Extents wrap." + }, + { + "type": "int", + "name": "extents_cx", + "description": "Extents cx." + }, + { + "type": "int", + "name": "extents_cy", + "description": "Extents cy." + }, + { + "type": "String", + "name": "file", + "description": "File path name." + }, + { + "type": "boolean", + "name": "read_from_file", + "description": "Read text from the specified file." + }, + { + "type": "Object", + "name": "font", + "description": "Holds data for the font. Ex: `\"font\": { \"face\": \"Arial\", \"flags\": 0, \"size\": 150, \"style\": \"\" }`" + }, + { + "type": "String", + "name": "font.face", + "description": "Font face." + }, + { + "type": "int", + "name": "font.flags", + "description": "Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8`" + }, + { + "type": "int", + "name": "font.size", + "description": "Font text size." + }, + { + "type": "String", + "name": "font.style", + "description": "Font Style (unknown function)." + }, + { + "type": "boolean", + "name": "gradient", + "description": "Gradient enabled." + }, + { + "type": "int", + "name": "gradient_color", + "description": "Gradient color." + }, + { + "type": "float", + "name": "gradient_dir", + "description": "Gradient direction." + }, + { + "type": "int", + "name": "gradient_opacity", + "description": "Gradient opacity (0-100)." + }, + { + "type": "boolean", + "name": "outline", + "description": "Outline." + }, + { + "type": "int", + "name": "outline_color", + "description": "Outline color." + }, + { + "type": "int", + "name": "outline_size", + "description": "Outline size." + }, + { + "type": "int", + "name": "outline_opacity", + "description": "Outline opacity (0-100)." + }, + { + "type": "String", + "name": "text", + "description": "Text content to be displayed." + }, + { + "type": "String", + "name": "valign", + "description": "Text vertical alignment (\"top\", \"center\", \"bottom\")." + }, + { + "type": "boolean", + "name": "vertical", + "description": "Vertical text enabled." + }, + { + "type": "boolean", + "name": "render", + "description": "Visibility of the scene item." + } + ], + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "Name of the scene to retrieve. Defaults to the current scene." + }, + { + "type": "String", + "name": "source", + "description": "Name of the source." + } + ], + "names": [ + { + "name": "", + "description": "GetTextGDIPlusProperties" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "GetTextGDIPlusProperties" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the current properties of a Text GDI Plus source.", + "param": [ + "{String (optional)} `scene-name` Name of the scene to retrieve. Defaults to the current scene.", + "{String} `source` Name of the source.", + "{String (optional)} `align` Text Alignment (\"left\", \"center\", \"right\").", + "{int (optional)} `bk-color` Background color.", + "{int (optional)} `bk-opacity` Background opacity (0-100).", + "{boolean (optional)} `chatlog` Chat log.", + "{int (optional)} `chatlog_lines` Chat log lines.", + "{int (optional)} `color` Text color.", + "{boolean (optional)} `extents` Extents wrap.", + "{int (optional)} `extents_cx` Extents cx.", + "{int (optional)} `extents_cy` Extents cy.", + "{String (optional)} `file` File path name.", + "{boolean (optional)} `read_from_file` Read text from the specified file.", + "{Object (optional)} `font` Holds data for the font. Ex: `\"font\": { \"face\": \"Arial\", \"flags\": 0, \"size\": 150, \"style\": \"\" }`", + "{String (optional)} `font.face` Font face.", + "{int (optional)} `font.flags` Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8`", + "{int (optional)} `font.size` Font text size.", + "{String (optional)} `font.style` Font Style (unknown function).", + "{boolean (optional)} `gradient` Gradient enabled.", + "{int (optional)} `gradient_color` Gradient color.", + "{float (optional)} `gradient_dir` Gradient direction.", + "{int (optional)} `gradient_opacity` Gradient opacity (0-100).", + "{boolean (optional)} `outline` Outline.", + "{int (optional)} `outline_color` Outline color.", + "{int (optional)} `outline_size` Outline size.", + "{int (optional)} `outline_opacity` Outline opacity (0-100).", + "{String (optional)} `text` Text content to be displayed.", + "{String (optional)} `valign` Text vertical alignment (\"top\", \"center\", \"bottom\").", + "{boolean (optional)} `vertical` Vertical text enabled.", + "{boolean (optional)} `render` Visibility of the scene item." + ], + "api": "requests", + "name": "SetTextGDIPlusProperties", + "category": "sources", + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "Name of the scene to retrieve. Defaults to the current scene." + }, + { + "type": "String", + "name": "source", + "description": "Name of the source." + }, + { + "type": "String (optional)", + "name": "align", + "description": "Text Alignment (\"left\", \"center\", \"right\")." + }, + { + "type": "int (optional)", + "name": "bk-color", + "description": "Background color." + }, + { + "type": "int (optional)", + "name": "bk-opacity", + "description": "Background opacity (0-100)." + }, + { + "type": "boolean (optional)", + "name": "chatlog", + "description": "Chat log." + }, + { + "type": "int (optional)", + "name": "chatlog_lines", + "description": "Chat log lines." + }, + { + "type": "int (optional)", + "name": "color", + "description": "Text color." + }, + { + "type": "boolean (optional)", + "name": "extents", + "description": "Extents wrap." + }, + { + "type": "int (optional)", + "name": "extents_cx", + "description": "Extents cx." + }, + { + "type": "int (optional)", + "name": "extents_cy", + "description": "Extents cy." + }, + { + "type": "String (optional)", + "name": "file", + "description": "File path name." + }, + { + "type": "boolean (optional)", + "name": "read_from_file", + "description": "Read text from the specified file." + }, + { + "type": "Object (optional)", + "name": "font", + "description": "Holds data for the font. Ex: `\"font\": { \"face\": \"Arial\", \"flags\": 0, \"size\": 150, \"style\": \"\" }`" + }, + { + "type": "String (optional)", + "name": "font.face", + "description": "Font face." + }, + { + "type": "int (optional)", + "name": "font.flags", + "description": "Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8`" + }, + { + "type": "int (optional)", + "name": "font.size", + "description": "Font text size." + }, + { + "type": "String (optional)", + "name": "font.style", + "description": "Font Style (unknown function)." + }, + { + "type": "boolean (optional)", + "name": "gradient", + "description": "Gradient enabled." + }, + { + "type": "int (optional)", + "name": "gradient_color", + "description": "Gradient color." + }, + { + "type": "float (optional)", + "name": "gradient_dir", + "description": "Gradient direction." + }, + { + "type": "int (optional)", + "name": "gradient_opacity", + "description": "Gradient opacity (0-100)." + }, + { + "type": "boolean (optional)", + "name": "outline", + "description": "Outline." + }, + { + "type": "int (optional)", + "name": "outline_color", + "description": "Outline color." + }, + { + "type": "int (optional)", + "name": "outline_size", + "description": "Outline size." + }, + { + "type": "int (optional)", + "name": "outline_opacity", + "description": "Outline opacity (0-100)." + }, + { + "type": "String (optional)", + "name": "text", + "description": "Text content to be displayed." + }, + { + "type": "String (optional)", + "name": "valign", + "description": "Text vertical alignment (\"top\", \"center\", \"bottom\")." + }, + { + "type": "boolean (optional)", + "name": "vertical", + "description": "Vertical text enabled." + }, + { + "type": "boolean (optional)", + "name": "render", + "description": "Visibility of the scene item." + } + ], + "names": [ + { + "name": "", + "description": "SetTextGDIPlusProperties" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetTextGDIPlusProperties" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get current properties for a Browser Source.", + "param": [ + "{String (optional)} `scene-name` Name of the scene that the source belongs to. Defaults to the current scene.", + "{String} `source` Name of the source." + ], + "return": [ + "{boolean} `is_local_file` Indicates that a local file is in use.", + "{String} `url` Url or file path.", + "{String} `css` CSS to inject.", + "{int} `width` Width.", + "{int} `height` Height.", + "{int} `fps` Framerate.", + "{boolean} `shutdown` Indicates whether the source should be shutdown when not visible.", + "{boolean (optional)} `render` Visibility of the scene item." + ], + "api": "requests", + "name": "GetBrowserSourceProperties", + "category": "sources", + "returns": [ + { + "type": "boolean", + "name": "is_local_file", + "description": "Indicates that a local file is in use." + }, + { + "type": "String", + "name": "url", + "description": "Url or file path." + }, + { + "type": "String", + "name": "css", + "description": "CSS to inject." + }, + { + "type": "int", + "name": "width", + "description": "Width." + }, + { + "type": "int", + "name": "height", + "description": "Height." + }, + { + "type": "int", + "name": "fps", + "description": "Framerate." + }, + { + "type": "boolean", + "name": "shutdown", + "description": "Indicates whether the source should be shutdown when not visible." + }, + { + "type": "boolean (optional)", + "name": "render", + "description": "Visibility of the scene item." + } + ], + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "Name of the scene that the source belongs to. Defaults to the current scene." + }, + { + "type": "String", + "name": "source", + "description": "Name of the source." + } + ], + "names": [ + { + "name": "", + "description": "GetBrowserSourceProperties" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "GetBrowserSourceProperties" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Set current properties for a Browser Source.", + "param": [ + "{String (optional)} `scene-name` Name of the scene that the source belongs to. Defaults to the current scene.", + "{String} `source` Name of the source.", + "{boolean (optional)} `is_local_file` Indicates that a local file is in use.", + "{String (optional)} `url` Url or file path.", + "{String (optional)} `css` CSS to inject.", + "{int (optional)} `width` Width.", + "{int (optional)} `height` Height.", + "{int (optional)} `fps` Framerate.", + "{boolean (optional)} `shutdown` Indicates whether the source should be shutdown when not visible.", + "{boolean (optional)} `render` Visibility of the scene item." + ], + "api": "requests", + "name": "SetBrowserSourceProperties", + "category": "sources", + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "Name of the scene that the source belongs to. Defaults to the current scene." + }, + { + "type": "String", + "name": "source", + "description": "Name of the source." + }, + { + "type": "boolean (optional)", + "name": "is_local_file", + "description": "Indicates that a local file is in use." + }, + { + "type": "String (optional)", + "name": "url", + "description": "Url or file path." + }, + { + "type": "String (optional)", + "name": "css", + "description": "CSS to inject." + }, + { + "type": "int (optional)", + "name": "width", + "description": "Width." + }, + { + "type": "int (optional)", + "name": "height", + "description": "Height." + }, + { + "type": "int (optional)", + "name": "fps", + "description": "Framerate." + }, + { + "type": "boolean (optional)", + "name": "shutdown", + "description": "Indicates whether the source should be shutdown when not visible." + }, + { + "type": "boolean (optional)", + "name": "render", + "description": "Visibility of the scene item." + } + ], + "names": [ + { + "name": "", + "description": "SetBrowserSourceProperties" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "SetBrowserSourceProperties" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Reset a source item.", + "param": [ + "{String (optional)} `scene-name` Name of the scene the source belogns to. Defaults to the current scene.", + "{String} `item` Name of the source item." + ], + "api": "requests", + "name": "ResetSceneItem", + "category": "sources", + "params": [ + { + "type": "String (optional)", + "name": "scene-name", + "description": "Name of the scene the source belogns to. Defaults to the current scene." + }, + { + "type": "String", + "name": "item", + "description": "Name of the source item." + } + ], + "names": [ + { + "name": "", + "description": "ResetSceneItem" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "heading": { + "level": 2, + "text": "ResetSceneItem" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "streaming": [ + { + "subheads": [], + "description": "Get current streaming and recording status.", + "return": [ + "{boolean} `streaming` Current streaming status.", + "{boolean} `recording` Current recording status.", + "{String (optional)} `stream-timecode` Time elapsed since streaming started (only present if currently streaming).", + "{String (optional)} `rec-timecode` Time elapsed since recording started (only present if currently recording).", + "{boolean} `preview-only` Always false. Retrocompatibility with OBSRemote." + ], + "api": "requests", + "name": "GetStreamingStatus", + "category": "streaming", + "returns": [ + { + "type": "boolean", + "name": "streaming", + "description": "Current streaming status." + }, + { + "type": "boolean", + "name": "recording", + "description": "Current recording status." + }, + { + "type": "String (optional)", + "name": "stream-timecode", + "description": "Time elapsed since streaming started (only present if currently streaming)." + }, + { + "type": "String (optional)", + "name": "rec-timecode", + "description": "Time elapsed since recording started (only present if currently recording)." + }, + { + "type": "boolean", + "name": "preview-only", + "description": "Always false. Retrocompatibility with OBSRemote." + } + ], + "names": [ + { + "name": "", + "description": "GetStreamingStatus" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "GetStreamingStatus" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Toggle streaming on or off.", + "api": "requests", + "name": "StartStopStreaming", + "category": "streaming", + "names": [ + { + "name": "", + "description": "StartStopStreaming" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StartStopStreaming" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Start streaming.\nWill return an `error` if streaming is already active.", + "param": [ + "{Object (optional)} `stream` Special stream configuration.", + "{String (optional)} `type` If specified ensures the type of stream matches the given type (usually 'rtmp_custom' or 'rtmp_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the `settings` object or an error will occur when starting the stream.", + "{Object (optional)} `metadata` Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the streaming. May be any String, Numeric, or Boolean field.", + "{Object (optional)} `settings` Settings for the stream.", + "{String (optional)} `settings.server` The publish URL.", + "{String (optional)} `settings.key` The publish key of the stream.", + "{boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.", + "{String (optional)} `settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`.", + "{String (optional)} `settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`." + ], + "api": "requests", + "name": "StartStreaming", + "category": "streaming", + "params": [ + { + "type": "Object (optional)", + "name": "stream", + "description": "Special stream configuration." + }, + { + "type": "String (optional)", + "name": "type", + "description": "If specified ensures the type of stream matches the given type (usually 'rtmp_custom' or 'rtmp_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the `settings` object or an error will occur when starting the stream." + }, + { + "type": "Object (optional)", + "name": "metadata", + "description": "Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the streaming. May be any String, Numeric, or Boolean field." + }, + { + "type": "Object (optional)", + "name": "settings", + "description": "Settings for the stream." + }, + { + "type": "String (optional)", + "name": "settings.server", + "description": "The publish URL." + }, + { + "type": "String (optional)", + "name": "settings.key", + "description": "The publish key of the stream." + }, + { + "type": "boolean (optional)", + "name": "settings.use-auth", + "description": "Indicates whether authentication should be used when connecting to the streaming server." + }, + { + "type": "String (optional)", + "name": "settings.username", + "description": "If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`." + }, + { + "type": "String (optional)", + "name": "settings.password", + "description": "If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`." + } + ], + "names": [ + { + "name": "", + "description": "StartStreaming" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StartStreaming" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Stop streaming.\nWill return an `error` if streaming is not active.", + "api": "requests", + "name": "StopStreaming", + "category": "streaming", + "names": [ + { + "name": "", + "description": "StopStreaming" + } + ], + "categories": [ + { + "name": "", + "description": "streaming" + } + ], + "heading": { + "level": 2, + "text": "StopStreaming" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "recording": [ + { + "subheads": [], + "description": "Toggle recording on or off.", + "api": "requests", + "name": "StartStopRecording", + "category": "recording", + "names": [ + { + "name": "", + "description": "StartStopRecording" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "StartStopRecording" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Start recording.\nWill return an `error` if recording is already active.", + "api": "requests", + "name": "StartRecording", + "category": "recording", + "names": [ + { + "name": "", + "description": "StartRecording" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "StartRecording" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Stop recording.\nWill return an `error` if recording is not active.", + "api": "requests", + "name": "StopRecording", + "category": "recording", + "names": [ + { + "name": "", + "description": "StopRecording" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "StopRecording" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Change the current recording folder.", + "param": "{Stsring} `rec-folder` Path of the recording folder.", + "api": "requests", + "name": "SetRecordingFolder", + "category": "recording", + "params": [ + { + "type": "Stsring", + "name": "rec-folder", + "description": "Path of the recording folder." + } + ], + "names": [ + { + "name": "", + "description": "SetRecordingFolder" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "SetRecordingFolder" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the path of the current recording folder.", + "return": "{Stsring} `rec-folder` Path of the recording folder.", + "api": "requests", + "name": "GetRecordingFolder", + "category": "recording", + "returns": [ + { + "type": "Stsring", + "name": "rec-folder", + "description": "Path of the recording folder." + } + ], + "names": [ + { + "name": "", + "description": "GetRecordingFolder" + } + ], + "categories": [ + { + "name": "", + "description": "recording" + } + ], + "heading": { + "level": 2, + "text": "GetRecordingFolder" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "transitions": [ + { + "subheads": [], + "description": "List of all transitions available in the frontend's dropdown menu.", + "return": [ + "{String} `current-transition` Name of the currently active transition.", + "{Object|Array} `transitions` List of transitions.", + "{String} `transitions[].name` Name of the transition." + ], + "api": "requests", + "name": "GetTransitionList", + "category": "transitions", + "returns": [ + { + "type": "String", + "name": "current-transition", + "description": "Name of the currently active transition." + }, + { + "type": "Object|Array", + "name": "transitions", + "description": "List of transitions." + }, + { + "type": "String", + "name": "transitions[].name", + "description": "Name of the transition." + } + ], + "names": [ + { + "name": "", + "description": "GetTransitionList" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "GetTransitionList" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the name of the currently selected transition in the frontend's dropdown menu.", + "return": [ + "{String} `name` Name of the selected transition.", + "{int (optional)} `duration` Transition duration (in milliseconds) if supported by the transition." + ], + "api": "requests", + "name": "GetCurrentTransition", + "category": "transitions", + "returns": [ + { + "type": "String", + "name": "name", + "description": "Name of the selected transition." + }, + { + "type": "int (optional)", + "name": "duration", + "description": "Transition duration (in milliseconds) if supported by the transition." + } + ], + "names": [ + { + "name": "", + "description": "GetCurrentTransition" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "GetCurrentTransition" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Set the active transition.", + "param": "{String} `transition-name` The name of the transition.", + "api": "requests", + "name": "SetCurrentTransition", + "category": "transitions", + "params": [ + { + "type": "String", + "name": "transition-name", + "description": "The name of the transition." + } + ], + "names": [ + { + "name": "", + "description": "SetCurrentTransition" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "SetCurrentTransition" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Set the duration of the currently selected transition if supported.", + "param": "{int} `duration` Desired duration of the transition (in milliseconds).", + "api": "requests", + "name": "SetTransitionDuration", + "category": "transitions", + "params": [ + { + "type": "int", + "name": "duration", + "description": "Desired duration of the transition (in milliseconds)." + } + ], + "names": [ + { + "name": "", + "description": "SetTransitionDuration" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "SetTransitionDuration" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the duration of the currently selected transition if supported.", + "return": "{int} `transition-duration` Duration of the current transition (in milliseconds).", + "api": "requests", + "name": "GetTransitionDuration", + "category": "transitions", + "returns": [ + { + "type": "int", + "name": "transition-duration", + "description": "Duration of the current transition (in milliseconds)." + } + ], + "names": [ + { + "name": "", + "description": "GetTransitionDuration" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "heading": { + "level": 2, + "text": "GetTransitionDuration" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "scene collections": [ + { + "subheads": [], + "description": "Change the active scene collection.", + "param": "{String} `sc-name` Name of the desired scene collection.", + "api": "requests", + "name": "SetCurrentSceneCollection", + "category": "scene collections", + "params": [ + { + "type": "String", + "name": "sc-name", + "description": "Name of the desired scene collection." + } + ], + "names": [ + { + "name": "", + "description": "SetCurrentSceneCollection" + } + ], + "categories": [ + { + "name": "", + "description": "scene collections" + } + ], + "heading": { + "level": 2, + "text": "SetCurrentSceneCollection" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the name of the current scene collection.", + "return": "{String} `sc-name` Name of the currently active scene collection.", + "api": "requests", + "name": "GetCurrentSceneCollection", + "category": "scene collections", + "returns": [ + { + "type": "String", + "name": "sc-name", + "description": "Name of the currently active scene collection." + } + ], + "names": [ + { + "name": "", + "description": "GetCurrentSceneCollection" + } + ], + "categories": [ + { + "name": "", + "description": "scene collections" + } + ], + "heading": { + "level": 2, + "text": "GetCurrentSceneCollection" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "profiles": [ + { + "subheads": [], + "description": "Set the currently active profile.", + "param": "{String} `profile-name` Name of the desired profile.", + "api": "requests", + "name": "SetCurrentProfile", + "category": "profiles", + "params": [ + { + "type": "String", + "name": "profile-name", + "description": "Name of the desired profile." + } + ], + "names": [ + { + "name": "", + "description": "SetCurrentProfile" + } + ], + "categories": [ + { + "name": "", + "description": "profiles" + } + ], + "heading": { + "level": 2, + "text": "SetCurrentProfile" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the name of the current profile.", + "return": "{String} `profile-name` Name of the currently active profile.", + "api": "requests", + "name": "GetCurrentProfile", + "category": "profiles", + "returns": [ + { + "type": "String", + "name": "profile-name", + "description": "Name of the currently active profile." + } + ], + "names": [ + { + "name": "", + "description": "GetCurrentProfile" + } + ], + "categories": [ + { + "name": "", + "description": "profiles" + } + ], + "heading": { + "level": 2, + "text": "GetCurrentProfile" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get a list of available profiles.", + "return": "{Object|Array} `profiles` List of available profiles.", + "api": "requests", + "name": "ListProfiles", + "category": "profiles", + "returns": [ + { + "type": "Object|Array", + "name": "profiles", + "description": "List of available profiles." + } + ], + "names": [ + { + "name": "", + "description": "ListProfiles" + } + ], + "categories": [ + { + "name": "", + "description": "profiles" + } + ], + "heading": { + "level": 2, + "text": "ListProfiles" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "settings": [ + { + "subheads": [], + "description": "Sets one or more attributes of the current streaming server settings. Any options not passed will remain unchanged. Returns the updated settings in response. If 'type' is different than the current streaming service type, all settings are required. Returns the full settings of the stream (the same as GetStreamSettings).", + "param": [ + "{String} `type` The type of streaming service configuration, usually `rtmp_custom` or `rtmp_common`.", + "{Object} `settings` The actual settings of the stream.", + "{String (optional)} `settings.server` The publish URL.", + "{String (optional)} `settings.key` The publish key.", + "{boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.", + "{String (optional)} `settings.username` The username for the streaming service.", + "{String (optional)} `settings.password` The password for the streaming service.", + "{boolean} `save` Persist the settings to disk." + ], + "api": "requests", + "name": "SetStreamingSettings", + "category": "settings", + "params": [ + { + "type": "String", + "name": "type", + "description": "The type of streaming service configuration, usually `rtmp_custom` or `rtmp_common`." + }, + { + "type": "Object", + "name": "settings", + "description": "The actual settings of the stream." + }, + { + "type": "String (optional)", + "name": "settings.server", + "description": "The publish URL." + }, + { + "type": "String (optional)", + "name": "settings.key", + "description": "The publish key." + }, + { + "type": "boolean (optional)", + "name": "settings.use-auth", + "description": "Indicates whether authentication should be used when connecting to the streaming server." + }, + { + "type": "String (optional)", + "name": "settings.username", + "description": "The username for the streaming service." + }, + { + "type": "String (optional)", + "name": "settings.password", + "description": "The password for the streaming service." + }, + { + "type": "boolean", + "name": "save", + "description": "Persist the settings to disk." + } + ], + "names": [ + { + "name": "", + "description": "SetStreamingSettings" + } + ], + "categories": [ + { + "name": "", + "description": "settings" + } + ], + "heading": { + "level": 2, + "text": "SetStreamingSettings" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the current streaming server settings.", + "return": [ + "{String} `type` The type of streaming service configuration. Usually 'rtmp_custom' or 'rtmp_common'.", + "{Object} `settings` Setings of the stream.", + "{String} `settings.server` The publish URL.", + "{String} `settings.key` The publish key of the stream.", + "{boolean} `settings.use-auth` Indicates whether audentication should be used when connecting to the streaming server.", + "{String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`.", + "{String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`." + ], + "api": "requests", + "name": "GetStreamSettings", + "category": "settings", + "returns": [ + { + "type": "String", + "name": "type", + "description": "The type of streaming service configuration. Usually 'rtmp_custom' or 'rtmp_common'." + }, + { + "type": "Object", + "name": "settings", + "description": "Setings of the stream." + }, + { + "type": "String", + "name": "settings.server", + "description": "The publish URL." + }, + { + "type": "String", + "name": "settings.key", + "description": "The publish key of the stream." + }, + { + "type": "boolean", + "name": "settings.use-auth", + "description": "Indicates whether audentication should be used when connecting to the streaming server." + }, + { + "type": "String", + "name": "settings.username", + "description": "The username to use when accessing the streaming server. Only present if `use-auth` is `true`." + }, + { + "type": "String", + "name": "settings.password", + "description": "The password to use when accessing the streaming server. Only present if `use-auth` is `true`." + } + ], + "names": [ + { + "name": "", + "description": "GetStreamSettings" + } + ], + "categories": [ + { + "name": "", + "description": "settings" + } + ], + "heading": { + "level": 2, + "text": "GetStreamSettings" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Save the current streaming server settings to disk.", + "api": "requests", + "name": "SaveStreamSettings", + "category": "settings", + "names": [ + { + "name": "", + "description": "SaveStreamSettings" + } + ], + "categories": [ + { + "name": "", + "description": "settings" + } + ], + "heading": { + "level": 2, + "text": "SaveStreamSettings" + }, + "lead": "", + "type": "class", + "examples": [] + } + ], + "studio mode": [ + { + "subheads": [], + "description": "Indicates if Studio Mode is currently enabled.", + "return": "{boolean} `studio-mode` Indicates if Studio Mode is enabled.", + "api": "requests", + "name": "GetStudioModeStatus", + "category": "studio mode", + "returns": [ + { + "type": "boolean", + "name": "studio-mode", + "description": "Indicates if Studio Mode is enabled." + } + ], + "names": [ + { + "name": "", + "description": "GetStudioModeStatus" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "GetStudioModeStatus" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get the name of the currently previewed scene and its list of sources.\nWill return an `error` if Studio Mode is not enabled.", + "return": [ + "{String} `name` The name of the active preview scene.", + "{Source|Array} `sources`" + ], + "api": "requests", + "name": "GetPreviewScene", + "category": "studio mode", + "returns": [ + { + "type": "String", + "name": "name", + "description": "The name of the active preview scene." + }, + { + "type": "Source|Array", + "name": "sources", + "description": "" + } + ], + "names": [ + { + "name": "", + "description": "GetPreviewScene" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "GetPreviewScene" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Set the active preview scene.\nWill return an `error` if Studio Mode is not enabled.", + "param": "{String} `scene-name` The name of the scene to preview.", + "api": "requests", + "name": "SetPreviewScene", + "category": "studio mode", + "params": [ + { + "type": "String", + "name": "scene-name", + "description": "The name of the scene to preview." + } + ], + "names": [ + { + "name": "", + "description": "SetPreviewScene" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "SetPreviewScene" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Transitions the currently previewed scene to the main output.\nWill return an `error` if Studio Mode is not enabled.", + "param": [ + "{Object (optional)} `with-transition` Change the active transition before switching scenes. Defaults to the active transition.", + "{String} `with-transition.name` Name of the transition.", + "{int (optional)} `with-transition.duration` Transition duration (in milliseconds)." + ], + "api": "requests", + "name": "TransitionToProgram", + "category": "studio mode", + "params": [ + { + "type": "Object (optional)", + "name": "with-transition", + "description": "Change the active transition before switching scenes. Defaults to the active transition." + }, + { + "type": "String", + "name": "with-transition.name", + "description": "Name of the transition." + }, + { + "type": "int (optional)", + "name": "with-transition.duration", + "description": "Transition duration (in milliseconds)." + } + ], + "names": [ + { + "name": "", + "description": "TransitionToProgram" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "TransitionToProgram" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Enables Studio Mode.", + "api": "requests", + "name": "EnableStudioMode", + "category": "studio mode", + "names": [ + { + "name": "", + "description": "EnableStudioMode" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "EnableStudioMode" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Disables Studio Mode.", + "api": "requests", + "name": "DisableStudioMode", + "category": "studio mode", + "names": [ + { + "name": "", + "description": "DisableStudioMode" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "DisableStudioMode" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Toggles Studio Mode.", + "api": "requests", + "name": "ToggleStudioMode", + "category": "studio mode", + "names": [ + { + "name": "", + "description": "ToggleStudioMode" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "ToggleStudioMode" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "Get configured special sources like Desktop Audio and Mic/Aux sources.", + "return": [ + "{String (optional)} `desktop-1` Name of the first Desktop Audio capture source.", + "{String (optional)} `desktop-2` Name of the second Desktop Audio capture source.", + "{String (optional)} `mic-1` Name of the first Mic/Aux input source.", + "{String (optional)} `mic-2` Name of the second Mic/Aux input source.", + "{String (optional)} `mic-3` NAme of the third Mic/Aux input source." + ], + "api": "requests", + "name": "GetSpecialSources", + "category": "studio mode", + "returns": [ + { + "type": "String (optional)", + "name": "desktop-1", + "description": "Name of the first Desktop Audio capture source." + }, + { + "type": "String (optional)", + "name": "desktop-2", + "description": "Name of the second Desktop Audio capture source." + }, + { + "type": "String (optional)", + "name": "mic-1", + "description": "Name of the first Mic/Aux input source." + }, + { + "type": "String (optional)", + "name": "mic-2", + "description": "Name of the second Mic/Aux input source." + }, + { + "type": "String (optional)", + "name": "mic-3", + "description": "NAme of the third Mic/Aux input source." + } + ], + "names": [ + { + "name": "", + "description": "GetSpecialSources" + } + ], + "categories": [ + { + "name": "", + "description": "studio mode" + } + ], + "heading": { + "level": 2, + "text": "GetSpecialSources" + }, + "lead": "", + "type": "class", + "examples": [] + } + ] + } +} \ No newline at end of file diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md new file mode 100644 index 00000000..78685415 --- /dev/null +++ b/docs/generated/protocol.md @@ -0,0 +1,1508 @@ + + +# obs-websocket 4.1 protocol reference + +**This is the reference for the latest 4.1 development build. [See here for obs-websocket 4.0.0!](https://github.com/Palakis/obs-websocket/blob/4.0.0/PROTOCOL.md)** + +# General Introduction +Messages are exchanged between the client and the server as JSON objects. +This protocol is based on the original OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio. + + +# Authentication +OBSWebSocket uses SHA256 to transmit credentials. + +A request for [`GetAuthRequired`](#getauthrequired) returns two elements: +- A `challenge`: a random string that will be used to generate the auth response. +- A `salt`: applied to the password when generating the auth response. + +To generate the answer to the auth challenge, follow this procedure: +- Concatenate the user declared password with the `salt` sent by the server (in this order: `password + server salt`). +- Generate a binary SHA256 hash of the result and encode the resulting SHA256 binary hash to base64, known as a `base64 secret`. +- Concatenate the base64 secret with the `challenge` sent by the server (in this order: `base64 secret + server challenge`). +- Generate a binary SHA256 hash of the result and encode it to base64. +- Voilà, this last base64 string is the `auth response`. You may now use it to authenticate to the server with the [`Authenticate`](#authenticate) request. + +Pseudo Code Example: +``` +password = "supersecretpassword" +challenge = "ztTBnnuqrqaKDzRM3xcVdbYm" +salt = "PZVbYpvAnZut2SS6JNJytDm9" + +secret_string = password + salt +secret_hash = binary_sha256(secret_string) +secret = base64_encode(secret_hash) + +auth_response_string = secret + challenge +auth_response_hash = binary_sha256(auth_response_string) +auth_response = base64_encode(auth_response_hash) +``` + + + + +# Table of Contents + + + +- [Events](#events) + * [Scenes](#scenes) + + [OnSceneChange](#onscenechange) + + [ScenesChanged](#sceneschanged) + + [SceneCollectionChanged](#scenecollectionchanged) + + [SceneCollectionListChanged](#scenecollectionlistchanged) + * [Transitions](#transitions) + + [SwitchTransition](#switchtransition) + + [TransitionListChanged](#transitionlistchanged) + + [TransitionDurationChanged](#transitiondurationchanged) + + [TransitionBegin](#transitionbegin) + * [Profiles](#profiles) + + [ProfileChanged](#profilechanged) + + [ProfileListChanged](#profilelistchanged) + * [Streaming](#streaming) + + [StreamStarting](#streamstarting) + + [StreamStarted](#streamstarted) + + [StreamStopping](#streamstopping) + + [StreamStopped](#streamstopped) + + [StreamStatus](#streamstatus) + * [Recording](#recording) + + [RecordingStarting](#recordingstarting) + + [RecordingStarted](#recordingstarted) + + [RecordingStopping](#recordingstopping) + + [RecordingStopped](#recordingstopped) + * [Other](#other) + + [Exiting](#exiting) + * [Sources](#sources) + + [SourceOrderChanged](#sourceorderchanged) + + [SceneItemAdded](#sceneitemadded) + + [SceneItemRemoved](#sceneitemremoved) + + [SceneItemVisibilityChanged](#sceneitemvisibilitychanged) + * [Studio Mode](#studio-mode) + + [PreviewSceneChanged](#previewscenechanged) + + [StudioModeSwitched](#studiomodeswitched) +- [Requests](#requests) + * [General](#general) + + [GetVersion](#getversion) + + [GetAuthRequired](#getauthrequired) + + [Authenticate](#authenticate) + * [Scenes](#scenes-1) + + [SetCurrentScene](#setcurrentscene) + + [GetCurrentScene](#getcurrentscene) + + [GetSceneList](#getscenelist) + * [Sources](#sources-1) + + [SetSourceRender](#setsourcerender) + + [SetVolume](#setvolume) + + [GetVolume](#getvolume) + + [ToggleMute](#togglemute) + + [SetMute](#setmute) + + [GetMute](#getmute) + + [SetSceneItemPosition](#setsceneitemposition) + + [SetSceneItemTransform](#setsceneitemtransform) + + [SetSceneItemCrop](#setsceneitemcrop) + + [GetTextGDIPlusProperties](#gettextgdiplusproperties) + + [SetTextGDIPlusProperties](#settextgdiplusproperties) + + [GetBrowserSourceProperties](#getbrowsersourceproperties) + + [SetBrowserSourceProperties](#setbrowsersourceproperties) + + [ResetSceneItem](#resetsceneitem) + * [Streaming](#streaming-1) + + [GetStreamingStatus](#getstreamingstatus) + + [StartStopStreaming](#startstopstreaming) + + [StartStreaming](#startstreaming) + + [StopStreaming](#stopstreaming) + * [Recording](#recording-1) + + [StartStopRecording](#startstoprecording) + + [StartRecording](#startrecording) + + [StopRecording](#stoprecording) + + [SetRecordingFolder](#setrecordingfolder) + + [GetRecordingFolder](#getrecordingfolder) + * [Transitions](#transitions-1) + + [GetTransitionList](#gettransitionlist) + + [GetCurrentTransition](#getcurrenttransition) + + [SetCurrentTransition](#setcurrenttransition) + + [SetTransitionDuration](#settransitionduration) + + [GetTransitionDuration](#gettransitionduration) + * [Scene Collections](#scene-collections) + + [SetCurrentSceneCollection](#setcurrentscenecollection) + + [GetCurrentSceneCollection](#getcurrentscenecollection) + * [Profiles](#profiles-1) + + [SetCurrentProfile](#setcurrentprofile) + + [GetCurrentProfile](#getcurrentprofile) + + [ListProfiles](#listprofiles) + * [Settings](#settings) + + [SetStreamingSettings](#setstreamingsettings) + + [GetStreamSettings](#getstreamsettings) + + [SaveStreamSettings](#savestreamsettings) + * [Studio Mode](#studio-mode-1) + + [GetStudioModeStatus](#getstudiomodestatus) + + [GetPreviewScene](#getpreviewscene) + + [SetPreviewScene](#setpreviewscene) + + [TransitionToProgram](#transitiontoprogram) + + [EnableStudioMode](#enablestudiomode) + + [DisableStudioMode](#disablestudiomode) + + [ToggleStudioMode](#togglestudiomode) + + [GetSpecialSources](#getspecialsources) + + + +# Events +Events are broadcast by the server to each connected client when a recognized action occurs within OBS. + +An event message will contain at least the following base fields: +- `update-type` _String_: the type of event. +- `stream-timecode` _String (optional)_: time elapsed between now and stream start (only present if OBS Studio is streaming). +- `rec-timecode` _String (optional)_: time elapsed between now and recording start (only present if OBS Studio is recording). + +Timecodes are sent using the format: `HH:MM:SS.mmm` + +Additional fields may be present in the event message depending on the event type. + + +## Scenes + +### OnSceneChange + +Indicates a scene change. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | The new scene. | +| `sources` | _Array_ | List of sources in the new scene. | + + +--- + +### ScenesChanged + +The scene list has been modified. +Scenes have been added, removed, or renamed. + +**Response Items:** + +_No additional response items._ + +--- + +### SceneCollectionChanged + +Triggered when switching to another scene collection or when renaming the current scene collection. + +**Response Items:** + +_No additional response items._ + +--- + +### SceneCollectionListChanged + +Triggered when a scene collection is created, added, renamed, or removed. + +**Response Items:** + +_No additional response items._ + +--- + +## Transitions + +### SwitchTransition + +The active transition has been changed. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `transition-name` | _String_ | The name of the new active transition. | + + +--- + +### TransitionListChanged + +The list of available transitions has been modified. +Transitions have been added, removed, or renamed. + +**Response Items:** + +_No additional response items._ + +--- + +### TransitionDurationChanged + +The active transition duration has been changed. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `new-duration` | _int_ | New transition duration. | + + +--- + +### TransitionBegin + +A transition (other than "cut") has begun. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | Transition name. | +| `duration` | _int_ | Transition duration (in milliseconds). | + + +--- + +## Profiles + +### ProfileChanged + +Triggered when switching to another profile or when renaming the current profile. + +**Response Items:** + +_No additional response items._ + +--- + +### ProfileListChanged + +Triggered when a profile is created, added, renamed, or removed. + +**Response Items:** + +_No additional response items._ + +--- + +## Streaming + +### StreamStarting + +A request to start streaming has been issued. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `preview-only` | _boolean_ | Always false (retrocompatibility). | + + +--- + +### StreamStarted + +Streaming started successfully. + +**Response Items:** + +_No additional response items._ + +--- + +### StreamStopping + +A request to stop streaming has been issued. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `preview-only` | _boolean_ | Always false (retrocompatibility). | + + +--- + +### StreamStopped + +Streaming stopped successfully. + +**Response Items:** + +_No additional response items._ + +--- + +### StreamStatus + +Emit every 2 seconds. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `streaming` | _boolean_ | Current streaming state. | +| `recording` | _boolean_ | Current recording state. | +| `preview-only` | _boolean_ | Always false (retrocompatibility). | +| `bytes-per-sec` | _int_ | Amount of data per second (in bytes) transmitted by the stream encoder. | +| `kbits-per-sec` | _int_ | Amount of data per second (in kilobits) transmitted by the stream encoder. | +| `strain` | _double_ | Percentage of dropped frames. | +| `total-stream-time` | _int_ | Total time (in seconds) since the stream started. | +| `num-total-frames` | _int_ | Total number of frames transmitted since the stream started. | +| `num-dropped-frames` | _int_ | Number of frames dropped by the encoder since the stream started. | +| `fps` | _double_ | Current framerate. | + + +--- + +## Recording + +### RecordingStarting + +A request to start recording has been issued. + +**Response Items:** + +_No additional response items._ + +--- + +### RecordingStarted + +Recording started successfully. + +**Response Items:** + +_No additional response items._ + +--- + +### RecordingStopping + +A request to stop recording has been issued. + +**Response Items:** + +_No additional response items._ + +--- + +### RecordingStopped + +Recording stopped successfully. + +**Response Items:** + +_No additional response items._ + +--- + +## Other + +### Exiting + +OBS is exiting. + +**Response Items:** + +_No additional response items._ + +--- + +## Sources + +### SourceOrderChanged + +Scene items have been reordered. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene where items have been reordered. | + + +--- + +### SceneItemAdded + +An item has been added to the current scene. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene. | +| `item-name` | _String_ | Name of the item added to the scene. | + + +--- + +### SceneItemRemoved + +An item has been removed from the current scene. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene. | +| `item-name` | _String_ | Name of the item removed from the scene. | + + +--- + +### SceneItemVisibilityChanged + +An item's visibility has been toggled. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene. | +| `item-name` | _String_ | Name of the item in the scene. | +| `item-visible` | _boolean_ | New visibility state of the item. | + + +--- + +## Studio Mode + +### PreviewSceneChanged + +The selected preview scene has changed (only available in Studio Mode). + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene being previewed. | +| `sources` | _Source\|Array_ | List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). | + + +--- + +### StudioModeSwitched + +Studio Mode has been enabled or disabled. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `new-state` | _boolean_ | The new enabled state of Studio Mode. | + + +--- + + + + +# Requests +Requests are sent by the client and require at least the following two fields: +- `request-type` _String_: String name of the request type. +- `message-id` _String_: Client defined identifier for the message, will be echoed in the response. + +Once a request is sent, the server will return a JSON response with at least the following fields: +- `message-id` _String_: The client defined identifier specified in the request. +- `status` _String_: Response status, will be one of the following: `ok`, `error` +- `error` _String_: An error message accompanying an `error` status. + +Additional information may be required/returned depending on the request type. See below for more information. + + +## General + +### GetVersion + +Returns the latest version of the plugin and the API. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `version` | _double_ | OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility. | +| `obs-websocket-version` | _String_ | obs-websocket plugin version. | +| `obs-studio-version` | _String_ | OBS Studio program version. | +| `available-requests` | _String\|Array_ | List of available request types. | + + +--- + +### GetAuthRequired + +Tells the client if authentication is required. If so, returns authentication parameters `challenge` +and `salt` (see "Authentication" for more information). + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `authRequired` | _boolean_ | Indicates whether authentication is required. | +| `challenge` | _String (optional)_ | | +| `salt` | _String (optional)_ | | + + +--- + +### Authenticate + +Attempt to authenticate the client to the server. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `auth` | _String_ | Response to the auth challenge (see "Authentication" for more information). | + + +**Response Items:** + +_No additional response items._ + +--- + +## Scenes + +### SetCurrentScene + +Switch to the specified scene. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene to switch to. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetCurrentScene + +Get the current scene's name and source items. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | Name of the currently active scene. | +| `sources` | _Source\|Array_ | Ordered list of the current scene's source items. | + + +--- + +### GetSceneList + +Get a list of scenes in the currently active profile. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `current-scene` | _String_ | Name of the currently active scene. | +| `scenes` | _Scene\|Array_ | Ordered list of the current profile's scenes (See `[GetCurrentScene](#getcurrentscene)` for more information). | + + +--- + +## Sources + +### SetSourceRender + +Show or hide a specified source item in a specified scene. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `source` | _String_ | Name of the source in the specified scene. | +| `render` | _boolean_ | Desired visibility. | +| `scene-name` | _String (optional)_ | Name of the scene where the source resides. Defaults to the currently active scene. | + + +**Response Items:** + +_No additional response items._ + +--- + +### SetVolume + +Set the volume of the specified source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `source` | _String_ | Name of the source. | +| `volume` | _double_ | Desired volume. Must be between `0.0` and `1.0`. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetVolume + +Get the volume of the specified source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `source` | _String_ | Name of the source. | + + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | Name of the source. | +| `volume` | _double_ | Volume of the source. Between `0.0` and `1.0`. | +| `mute` | _boolean_ | Indicates whether the source is muted. | + + +--- + +### ToggleMute + +Inverts the mute status of a specified source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `source` | _String_ | The name of the source. | + + +**Response Items:** + +_No additional response items._ + +--- + +### SetMute + +Sets the mute status of a specified source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `source` | _String_ | The name of the source. | +| `mute` | _boolean_ | Desired mute status. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetMute + +Get the mute status of a specified source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `source` | _String_ | The name of the source. | + + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | The name of the source. | +| `muted` | _boolean_ | Mute status of the source. | + + +--- + +### SetSceneItemPosition + +Sets the coordinates of a specified source item. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | The name of the scene that the source item belongs to. Defaults to the current scene. | +| `item` | _String_ | The name of the source item. | +| `x` | _double_ | X coordinate. | +| `y` | _double_ | Y coordinate. | + + +**Response Items:** + +_No additional response items._ + +--- + +### SetSceneItemTransform + +Set the transform of the specified source item. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | The name of the scene that the source item belongs to. Defaults to the current scene. | +| `item` | _String_ | The name of the source item. | +| `x-scale` | _double_ | Width scale factor. | +| `y-scale` | _double_ | Height scale factor. | +| `rotation` | _double_ | Source item rotation (in degrees). | + + +**Response Items:** + +_No additional response items._ + +--- + +### SetSceneItemCrop + +Sets the crop coordinates of the specified source item. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | the name of the scene that the source item belongs to. Defaults to the current scene. | +| `item` | _String_ | The name of the source. | +| `top` | _int_ | Pixel position of the top of the source item. | +| `bottom` | _int_ | Pixel position of the bottom of the source item. | +| `left` | _int_ | Pixel position of the left of the source item. | +| `right` | _int_ | Pixel position of the right of the source item. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetTextGDIPlusProperties + +Get the current properties of a Text GDI Plus source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | Name of the scene to retrieve. Defaults to the current scene. | +| `source` | _String_ | Name of the source. | + + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `align` | _String_ | Text Alignment ("left", "center", "right"). | +| `bk-color` | _int_ | Background color. | +| `bk-opacity` | _int_ | Background opacity (0-100). | +| `chatlog` | _boolean_ | Chat log. | +| `chatlog_lines` | _int_ | Chat log lines. | +| `color` | _int_ | Text color. | +| `extents` | _boolean_ | Extents wrap. | +| `extents_cx` | _int_ | Extents cx. | +| `extents_cy` | _int_ | Extents cy. | +| `file` | _String_ | File path name. | +| `read_from_file` | _boolean_ | Read text from the specified file. | +| `font` | _Object_ | Holds data for the font. Ex: `"font": { "face": "Arial", "flags": 0, "size": 150, "style": "" }` | +| `font.face` | _String_ | Font face. | +| `font.flags` | _int_ | Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8` | +| `font.size` | _int_ | Font text size. | +| `font.style` | _String_ | Font Style (unknown function). | +| `gradient` | _boolean_ | Gradient enabled. | +| `gradient_color` | _int_ | Gradient color. | +| `gradient_dir` | _float_ | Gradient direction. | +| `gradient_opacity` | _int_ | Gradient opacity (0-100). | +| `outline` | _boolean_ | Outline. | +| `outline_color` | _int_ | Outline color. | +| `outline_size` | _int_ | Outline size. | +| `outline_opacity` | _int_ | Outline opacity (0-100). | +| `text` | _String_ | Text content to be displayed. | +| `valign` | _String_ | Text vertical alignment ("top", "center", "bottom"). | +| `vertical` | _boolean_ | Vertical text enabled. | +| `render` | _boolean_ | Visibility of the scene item. | + + +--- + +### SetTextGDIPlusProperties + +Get the current properties of a Text GDI Plus source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | Name of the scene to retrieve. Defaults to the current scene. | +| `source` | _String_ | Name of the source. | +| `align` | _String (optional)_ | Text Alignment ("left", "center", "right"). | +| `bk-color` | _int (optional)_ | Background color. | +| `bk-opacity` | _int (optional)_ | Background opacity (0-100). | +| `chatlog` | _boolean (optional)_ | Chat log. | +| `chatlog_lines` | _int (optional)_ | Chat log lines. | +| `color` | _int (optional)_ | Text color. | +| `extents` | _boolean (optional)_ | Extents wrap. | +| `extents_cx` | _int (optional)_ | Extents cx. | +| `extents_cy` | _int (optional)_ | Extents cy. | +| `file` | _String (optional)_ | File path name. | +| `read_from_file` | _boolean (optional)_ | Read text from the specified file. | +| `font` | _Object (optional)_ | Holds data for the font. Ex: `"font": { "face": "Arial", "flags": 0, "size": 150, "style": "" }` | +| `font.face` | _String (optional)_ | Font face. | +| `font.flags` | _int (optional)_ | Font text styling flag. `Bold=1, Italic=2, Bold Italic=3, Underline=5, Strikeout=8` | +| `font.size` | _int (optional)_ | Font text size. | +| `font.style` | _String (optional)_ | Font Style (unknown function). | +| `gradient` | _boolean (optional)_ | Gradient enabled. | +| `gradient_color` | _int (optional)_ | Gradient color. | +| `gradient_dir` | _float (optional)_ | Gradient direction. | +| `gradient_opacity` | _int (optional)_ | Gradient opacity (0-100). | +| `outline` | _boolean (optional)_ | Outline. | +| `outline_color` | _int (optional)_ | Outline color. | +| `outline_size` | _int (optional)_ | Outline size. | +| `outline_opacity` | _int (optional)_ | Outline opacity (0-100). | +| `text` | _String (optional)_ | Text content to be displayed. | +| `valign` | _String (optional)_ | Text vertical alignment ("top", "center", "bottom"). | +| `vertical` | _boolean (optional)_ | Vertical text enabled. | +| `render` | _boolean (optional)_ | Visibility of the scene item. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetBrowserSourceProperties + +Get current properties for a Browser Source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | Name of the scene that the source belongs to. Defaults to the current scene. | +| `source` | _String_ | Name of the source. | + + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `is_local_file` | _boolean_ | Indicates that a local file is in use. | +| `url` | _String_ | Url or file path. | +| `css` | _String_ | CSS to inject. | +| `width` | _int_ | Width. | +| `height` | _int_ | Height. | +| `fps` | _int_ | Framerate. | +| `shutdown` | _boolean_ | Indicates whether the source should be shutdown when not visible. | +| `render` | _boolean (optional)_ | Visibility of the scene item. | + + +--- + +### SetBrowserSourceProperties + +Set current properties for a Browser Source. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | Name of the scene that the source belongs to. Defaults to the current scene. | +| `source` | _String_ | Name of the source. | +| `is_local_file` | _boolean (optional)_ | Indicates that a local file is in use. | +| `url` | _String (optional)_ | Url or file path. | +| `css` | _String (optional)_ | CSS to inject. | +| `width` | _int (optional)_ | Width. | +| `height` | _int (optional)_ | Height. | +| `fps` | _int (optional)_ | Framerate. | +| `shutdown` | _boolean (optional)_ | Indicates whether the source should be shutdown when not visible. | +| `render` | _boolean (optional)_ | Visibility of the scene item. | + + +**Response Items:** + +_No additional response items._ + +--- + +### ResetSceneItem + +Reset a source item. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String (optional)_ | Name of the scene the source belogns to. Defaults to the current scene. | +| `item` | _String_ | Name of the source item. | + + +**Response Items:** + +_No additional response items._ + +--- + +## Streaming + +### GetStreamingStatus + +Get current streaming and recording status. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `streaming` | _boolean_ | Current streaming status. | +| `recording` | _boolean_ | Current recording status. | +| `stream-timecode` | _String (optional)_ | Time elapsed since streaming started (only present if currently streaming). | +| `rec-timecode` | _String (optional)_ | Time elapsed since recording started (only present if currently recording). | +| `preview-only` | _boolean_ | Always false. Retrocompatibility with OBSRemote. | + + +--- + +### StartStopStreaming + +Toggle streaming on or off. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### StartStreaming + +Start streaming. +Will return an `error` if streaming is already active. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `stream` | _Object (optional)_ | Special stream configuration. | +| `type` | _String (optional)_ | If specified ensures the type of stream matches the given type (usually 'rtmp_custom' or 'rtmp_common'). If the currently configured stream type does not match the given stream type, all settings must be specified in the `settings` object or an error will occur when starting the stream. | +| `metadata` | _Object (optional)_ | Adds the given object parameters as encoded query string parameters to the 'key' of the RTMP stream. Used to pass data to the RTMP service about the streaming. May be any String, Numeric, or Boolean field. | +| `settings` | _Object (optional)_ | Settings for the stream. | +| `settings.server` | _String (optional)_ | The publish URL. | +| `settings.key` | _String (optional)_ | The publish key of the stream. | +| `settings.use-auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. | +| `settings.username` | _String (optional)_ | If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`. | +| `settings.password` | _String (optional)_ | If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`. | + + +**Response Items:** + +_No additional response items._ + +--- + +### StopStreaming + +Stop streaming. +Will return an `error` if streaming is not active. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +## Recording + +### StartStopRecording + +Toggle recording on or off. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### StartRecording + +Start recording. +Will return an `error` if recording is already active. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### StopRecording + +Stop recording. +Will return an `error` if recording is not active. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### SetRecordingFolder + +Change the current recording folder. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `rec-folder` | _Stsring_ | Path of the recording folder. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetRecordingFolder + +Get the path of the current recording folder. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `rec-folder` | _Stsring_ | Path of the recording folder. | + + +--- + +## Transitions + +### GetTransitionList + +List of all transitions available in the frontend's dropdown menu. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `current-transition` | _String_ | Name of the currently active transition. | +| `transitions` | _Object\|Array_ | List of transitions. | +| `transitions[].name` | _String_ | Name of the transition. | + + +--- + +### GetCurrentTransition + +Get the name of the currently selected transition in the frontend's dropdown menu. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | Name of the selected transition. | +| `duration` | _int (optional)_ | Transition duration (in milliseconds) if supported by the transition. | + + +--- + +### SetCurrentTransition + +Set the active transition. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `transition-name` | _String_ | The name of the transition. | + + +**Response Items:** + +_No additional response items._ + +--- + +### SetTransitionDuration + +Set the duration of the currently selected transition if supported. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `duration` | _int_ | Desired duration of the transition (in milliseconds). | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetTransitionDuration + +Get the duration of the currently selected transition if supported. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `transition-duration` | _int_ | Duration of the current transition (in milliseconds). | + + +--- + +## Scene Collections + +### SetCurrentSceneCollection + +Change the active scene collection. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `sc-name` | _String_ | Name of the desired scene collection. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetCurrentSceneCollection + +Get the name of the current scene collection. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `sc-name` | _String_ | Name of the currently active scene collection. | + + +--- + +## Profiles + +### SetCurrentProfile + +Set the currently active profile. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `profile-name` | _String_ | Name of the desired profile. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetCurrentProfile + +Get the name of the current profile. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `profile-name` | _String_ | Name of the currently active profile. | + + +--- + +### ListProfiles + +Get a list of available profiles. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `profiles` | _Object\|Array_ | List of available profiles. | + + +--- + +## Settings + +### SetStreamingSettings + +Sets one or more attributes of the current streaming server settings. Any options not passed will remain unchanged. Returns the updated settings in response. If 'type' is different than the current streaming service type, all settings are required. Returns the full settings of the stream (the same as GetStreamSettings). + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `type` | _String_ | The type of streaming service configuration, usually `rtmp_custom` or `rtmp_common`. | +| `settings` | _Object_ | The actual settings of the stream. | +| `settings.server` | _String (optional)_ | The publish URL. | +| `settings.key` | _String (optional)_ | The publish key. | +| `settings.use-auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. | +| `settings.username` | _String (optional)_ | The username for the streaming service. | +| `settings.password` | _String (optional)_ | The password for the streaming service. | +| `save` | _boolean_ | Persist the settings to disk. | + + +**Response Items:** + +_No additional response items._ + +--- + +### GetStreamSettings + +Get the current streaming server settings. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `type` | _String_ | The type of streaming service configuration. Usually 'rtmp_custom' or 'rtmp_common'. | +| `settings` | _Object_ | Setings of the stream. | +| `settings.server` | _String_ | The publish URL. | +| `settings.key` | _String_ | The publish key of the stream. | +| `settings.use-auth` | _boolean_ | Indicates whether audentication should be used when connecting to the streaming server. | +| `settings.username` | _String_ | The username to use when accessing the streaming server. Only present if `use-auth` is `true`. | +| `settings.password` | _String_ | The password to use when accessing the streaming server. Only present if `use-auth` is `true`. | + + +--- + +### SaveStreamSettings + +Save the current streaming server settings to disk. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +## Studio Mode + +### GetStudioModeStatus + +Indicates if Studio Mode is currently enabled. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `studio-mode` | _boolean_ | Indicates if Studio Mode is enabled. | + + +--- + +### GetPreviewScene + +Get the name of the currently previewed scene and its list of sources. +Will return an `error` if Studio Mode is not enabled. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | The name of the active preview scene. | +| `sources` | _Source\|Array_ | | + + +--- + +### SetPreviewScene + +Set the active preview scene. +Will return an `error` if Studio Mode is not enabled. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | The name of the scene to preview. | + + +**Response Items:** + +_No additional response items._ + +--- + +### TransitionToProgram + +Transitions the currently previewed scene to the main output. +Will return an `error` if Studio Mode is not enabled. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `with-transition` | _Object (optional)_ | Change the active transition before switching scenes. Defaults to the active transition. | +| `with-transition.name` | _String_ | Name of the transition. | +| `with-transition.duration` | _int (optional)_ | Transition duration (in milliseconds). | + + +**Response Items:** + +_No additional response items._ + +--- + +### EnableStudioMode + +Enables Studio Mode. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### DisableStudioMode + +Disables Studio Mode. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### ToggleStudioMode + +Toggles Studio Mode. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +_No additional response items._ + +--- + +### GetSpecialSources + +Get configured special sources like Desktop Audio and Mic/Aux sources. + +**Request Fields:** + +_No specified parameters._ + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `desktop-1` | _String (optional)_ | Name of the first Desktop Audio capture source. | +| `desktop-2` | _String (optional)_ | Name of the second Desktop Audio capture source. | +| `mic-1` | _String (optional)_ | Name of the first Mic/Aux input source. | +| `mic-2` | _String (optional)_ | Name of the second Mic/Aux input source. | +| `mic-3` | _String (optional)_ | NAme of the third Mic/Aux input source. | + + +--- + + diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000..487be3db --- /dev/null +++ b/docs/package.json @@ -0,0 +1,21 @@ +{ + "name": "obs-websocket-docs", + "version": "1.0.0", + "description": "", + "main": "docs.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "docs": "node ./docs.js", + "comments": "node ./comments.js", + "build": "npm run comments && npm run docs" + }, + "author": "", + "license": "ISC", + "dependencies": { + "glob": "^7.1.2", + "handlebars": "^4.0.10", + "handlebars-helpers": "^0.9.6", + "markdown-toc": "^1.1.0", + "parse-comments": "^0.4.3" + } +} diff --git a/docs/partials/eventsHeader.md b/docs/partials/eventsHeader.md new file mode 100644 index 00000000..e8ccff21 --- /dev/null +++ b/docs/partials/eventsHeader.md @@ -0,0 +1,11 @@ +# Events +Events are broadcast by the server to each connected client when a recognized action occurs within OBS. + +An event message will contain at least the following base fields: +- `update-type` _String_: the type of event. +- `stream-timecode` _String (optional)_: time elapsed between now and stream start (only present if OBS Studio is streaming). +- `rec-timecode` _String (optional)_: time elapsed between now and recording start (only present if OBS Studio is recording). + +Timecodes are sent using the format: `HH:MM:SS.mmm` + +Additional fields may be present in the event message depending on the event type. diff --git a/docs/partials/introduction.md b/docs/partials/introduction.md new file mode 100644 index 00000000..bbd6ddf9 --- /dev/null +++ b/docs/partials/introduction.md @@ -0,0 +1,37 @@ +# obs-websocket 4.1 protocol reference + +**This is the reference for the latest 4.1 development build. [See here for obs-websocket 4.0.0!](https://github.com/Palakis/obs-websocket/blob/4.0.0/PROTOCOL.md)** + +# General Introduction +Messages are exchanged between the client and the server as JSON objects. +This protocol is based on the original OBS Remote protocol created by Bill Hamilton, with new commands specific to OBS Studio. + + +# Authentication +OBSWebSocket uses SHA256 to transmit credentials. + +A request for [`GetAuthRequired`](#getauthrequired) returns two elements: +- A `challenge`: a random string that will be used to generate the auth response. +- A `salt`: applied to the password when generating the auth response. + +To generate the answer to the auth challenge, follow this procedure: +- Concatenate the user declared password with the `salt` sent by the server (in this order: `password + server salt`). +- Generate a binary SHA256 hash of the result and encode the resulting SHA256 binary hash to base64, known as a `base64 secret`. +- Concatenate the base64 secret with the `challenge` sent by the server (in this order: `base64 secret + server challenge`). +- Generate a binary SHA256 hash of the result and encode it to base64. +- Voilà, this last base64 string is the `auth response`. You may now use it to authenticate to the server with the [`Authenticate`](#authenticate) request. + +Pseudo Code Example: +``` +password = "supersecretpassword" +challenge = "ztTBnnuqrqaKDzRM3xcVdbYm" +salt = "PZVbYpvAnZut2SS6JNJytDm9" + +secret_string = password + salt +secret_hash = binary_sha256(secret_string) +secret = base64_encode(secret_hash) + +auth_response_string = secret + challenge +auth_response_hash = binary_sha256(auth_response_string) +auth_response = base64_encode(auth_response_hash) +``` diff --git a/docs/partials/requestsHeader.md b/docs/partials/requestsHeader.md new file mode 100644 index 00000000..457ad61b --- /dev/null +++ b/docs/partials/requestsHeader.md @@ -0,0 +1,11 @@ +# Requests +Requests are sent by the client and require at least the following two fields: +- `request-type` _String_: String name of the request type. +- `message-id` _String_: Client defined identifier for the message, will be echoed in the response. + +Once a request is sent, the server will return a JSON response with at least the following fields: +- `message-id` _String_: The client defined identifier specified in the request. +- `status` _String_: Response status, will be one of the following: `ok`, `error` +- `error` _String_: An error message accompanying an `error` status. + +Additional information may be required/returned depending on the request type. See below for more information. diff --git a/docs/protocol.hbs b/docs/protocol.hbs new file mode 100644 index 00000000..c85e9ea3 --- /dev/null +++ b/docs/protocol.hbs @@ -0,0 +1,80 @@ +{{#read "partials/introduction.md"}}{{/read}} + + + +# Table of Contents + + + + +{{#read "partials/eventsHeader.md"}}{{/read}} + +{{#each events}} +## {{capitalizeAll @key}} + +{{#each this}} +### {{name}} + +{{{description}}} + +**Response Items:** + +{{#if returns.length}} +| Name | Type | Description | +| ---- | :---: | ------------| +{{#each returns}} +| `{{name}}` | _{{depipe type}}_ | {{{description}}} | +{{/each}} + +{{else}} +_No additional response items._ +{{/if}} + +--- + +{{/each}} +{{/each}} + + + +{{#read "partials/requestsHeader.md"}}{{/read}} + +{{#each requests}} +## {{capitalizeAll @key}} + +{{#each this}} +### {{name}} + +{{{description}}} + +**Request Fields:** + +{{#if params.length}} +| Name | Type | Description | +| ---- | :---: | ------------| +{{#each params}} +| `{{name}}` | _{{depipe type}}_ | {{{description}}} | +{{/each}} + +{{else}} +_No specified parameters._ +{{/if}} + +**Response Items:** + +{{#if returns.length}} +| Name | Type | Description | +| ---- | :---: | ------------| +{{#each returns}} +| `{{name}}` | _{{depipe type}}_ | {{{description}}} | +{{/each}} + +{{else}} +_No additional response items._ +{{/if}} + +--- + +{{/each}} +{{/each}} +