## File: README.md

# Streamlabs Desktop

[](https://dev.azure.com/streamlabs/Streamlabs%20OBS/_build/latest?definitionId=1&branchName=staging)

Simple, powerful, and efficient live streaming software built on Electron and OBS.



This application currently only supports OSX 10.14+ and 64-bit Windows.

## Dependencies

### Node.js

Node is required for installing npm packages and for running
various scripts. We recommend the latest LTS release.

https://nodejs.org

### Yarn

We use Yarn as our package manager. We use yarn modern (berry) with
the yarn version checked in to version control. To get the yarn CLI,
we currently recommend installing it with npm:

```
npm install yarn
```

### Bash

Some of our scripts assume a bash-like environment. On Windows, we recommend
using Git Bash, which is included with Git for Windows. On macOS, the
default shell should work fine.

### Native Modules

Streamlabs Desktop uses several native C++ modules. These are NPM modules
that live in separate repositories, and are automatically installed as prebuilt
binaries by Yarn. If you are not doing any development on these native modules,
no additional action is required to install native modules.

## Installation

Install all node modules via yarn:

```
yarn install
```

Then, compile assets with webpack:

```
yarn compile
```

Alternatively, you can watch for changes to app files:

```
yarn watch
```

## Starting

You can start the app by running:

```
yarn start
```

## Environment Variables

These variables can be used in development to force certain behavior.

`SLOBS_FORCE_AUTO_UPDATE`: Force the auto-updater to run in development. Normally
this would only run in production.

`SLOBS_CACHE_DIR`: Force a different location for the user data cache directory.

`SLOBS_DISABLE_MAIN_LOGGING`: Disable javascript logging in the main process.

`SLOBS_REPORT_TO_SENTRY`: Report errors to sentry in the dev environment

`SLOBS_PRODUCTION_DEBUG`: Forces dev tools to open when the app starts

## Development

You can open dev tools by clicking the `</>` button on the sidebar.
In the development environment, the titlebar of the main window will
light up red when an exception occurs in any window.

Our app is comprised of several windows, which are essential separate
copies of the same Javascript app, which are running different pieces
of the code and communicating via Electron IPC.

`worker` - This is a persistent invisible window that runs our entire
services layer.

`main` - This is the main window of the application. It communicates
with the worker window to perform actions.

`child` - This window is always running in the background, and appears
to show windows like Source Properties. It stays always running because
Electron windows can take several seconds to initialize, so we keep it
ready in the background.

There are potentially many other JS runtime processes that can be running
depending on use, for features like Apps, embedded webviews, one-off windows
like projectors, pop-outs etc.

### Sync / Async

Given the heavy reliance on interprocess communication in our application,
we strongly recommend using asynchronous IPC whenever possible. When
accessing a service, calling it as an action will call it asynchronously.

For example the following (synchronous):

```
StreamingService.toggleStreaming()
```

Can be rewritten as (asynchronous):

```
StreamingService.actions.toggleStreaming()
```

The return type of the latter will automatically be `void` as actions
are unable to return values.  In general, receiving information from
services is best done via `views`.  `views` are executed in-window, and
backed by our `vuex` data store, which is replicated across windows.

### Vue / React

We are in the process of migrating from Vue to React. There are many components
of both frameworks in our codebase currently. All new components should be
written in React, and major non-trivial changes to existing Vue components
should be accompanied with a rewrite to React.

We exclusively use functional components in React, relying on the hooks API
for things like component state and lifecycle.

## Contributing

We accept outside contributions, and do our best to respond to Pull Requests.
We ask that all contributors sign a Contributor License Agreement before merging
code. We do not guarantee that all external Pull Requests will be merged, but
we deeply appreciate any and all changes submitted. Thank you for your interest
and contribution.

### Translations

At this time, we are not able to accept translations submitted to GitHub, as we
use a professional translation team that manages translations elsewhere.

## Packaging/Distribution

For Windows:

```
yarn package
```

For macOS:

```
yarn package:mac
```

Note that both of these commands require code signing certificates to be
present in the environment, and in the case of macOS, a valid Apple developer
account for notarization of the app package.

There are some environment variables that can be passed to skip these steps:

`SLOBS_NO_SIGN` Do not attempt to codesign the app package

`SLOBS_NO_NOTARIZE` Do not attempt to notarize the macOS package

## ❤ OBS Developers

At its core, Streamlabs Desktop is powered by the [OBS](https://obsproject.com/)
project. We want to thank all of the developers over at the OBS project for
their years of tireless hard work, without which Streamlabs Desktop wouldn't exist today.

---

## File: docs/README.md

# API reference

Streamlabs-OBS allows remote management of the application via
an RPC-based API. The API is split into several different services.
You can access services' methods and properties by sending
[JSON-RPC](http://www.jsonrpc.org/specification) messages to the
named pipe `slobs`.

Individual JSON-RPC requests should be separated by a single newline
character `LF` ( ASCII code 10).  You should ensure that your JSON message does not
contain any newline characters. Use `\n` as replacement for new lines in JSON. 

# Examples


## Get a list of scenes


### Request
```
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getScenes",
    "params": {
        "resource": "ScenesService"
    }
}
```



### Response
```
{
    "jsonrpc": "2.0",
    "id": 1,
    "result": [
       {
            "_type": "HELPER",
            "resourceId": "Scene[\"3efd436e5546\"]",
            "id": "3efd436e5546",
            "name": "My super scene",
            "activeItemIds": []
        },
       {
            "_type": "HELPER",
            "resourceId": "Scene[\"6b615869aba3\"]",
            "id": "6b615869aba3",
            "name": "NewScene",
            "activeItemIds": []
        }
    ]
}
```

The property `"_type": "HELPER"` means that you can fetch some
additional information by calling methods on this object. To do
that, just include the `resourceId` from the response to `resource`
in the new request.

## Get items in a scene

### Request
```
{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "getItems",
    "params": {
        "resource": "Scene[\"3efd436e5546\"]",
        "args": []
    }
}
```

### Response
```
{
    "jsonrpc": "2.0",
    "id": 2,
    "result": [
       {
            "_type": "HELPER",
            "resourceId": "SceneItem[\"3efd436e5546\"]",
            "sceneItemId": "68b413a288c8",
            "sourceId": "5687af55058c",
            "obsSceneItemId": 1,
            "transform": {
                "position": { "x": 0, "y": 25 },
                "scale": { "x": 1, "y": 1 },
                "rotation": 0
            },
            "visible": true,
            "locked": false
        }
    ]
}
```

## Event subscriptions

Subscribe to the `sceneSwitched` event:

### Request
```
{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "sceneSwitched",
    "params": {
        "resource": "ScenesService",
        "args": []
    }
}
```

### Response
```
{
    "jsonrpc": "2.0",
    "id": 4,
    "result": {
        "_type": "SUBSCRIPTION",
        "resourceId": "ScenesService.sceneSwitched",
        "emitter": "STREAM"
    }
}
```

After subscribing, you will receive events when the user
switches between scenes:

### Event
```
{
    "jsonrpc": "2.0",
    "result": {
        "_type": "EVENT",
        "emitter": "STREAM",
        "resourceId": "ScenesService.sceneSwitched",
        "data": {
            "id": "5c3cf84f797a",
            "name": "NewScene (1)",
            "activeItemIds": []
        }
    }
}
```

Use `resourceId` to unsubscribe:

### Request
```
{
    "jsonrpc": "2.0",
    "id": 5,
    "method": "unsubscribe",
    "params": {
        "resource": "ScenesService.sceneSwitched",
    }
}
```

## Asynchronous Task Execution

Some service methods are asynchronous and return a Javascript promise.
This is exposed via the API by returning a subscription that will
fire a single event.  You can think of the subscription response as
the acknowledgement of your request, and the event as a notification
of completion with a result.

Although fundamentally all requests sent over the socket are asynchronous,
a function that returns a promise is a good indication that your
application consuming the API should probably not block waiting for a
response.  Functions that return a promise do not guarantee fast
execution.

### Request
```
{
    "jsonrpc": "2.0",
    "id": 5,
    "method": "loadConfig",
    "params": {
        "resource": "AppService",
        "args": ["MyScenes"]
    }
}
```

### Response
```
{
    "jsonrpc": "2.0",
    "id": 5,
    "result": {
        "_type": "SUBSCRIPTION",
        "resourceId": "5c3cf84f797a",
        "emitter": "PROMISE"
    }
}
```

### Event
```
{
    "jsonrpc": "2.0",
    "result": {
        "_type": "EVENT",
        "emitter": "PROMISE",
        "resourceId": "5c3cf84f797a",
        "data": {},
        "isRejected": false
    }
}
```

## Reducing response body
By default if the response returns resources with `"_type": "HELPER"`,
Streamlabs-OBS will attach some data by calling `getModel()` method of resource.
To disable that behavior, use the `compactMode` parameter in JSON-RPC request:


### Request
```
{
    "jsonrpc": "2.0",
    "id": 6,
    "method": "getSources",
    "params": {
        "resource": "SourcesService",
        "args": [],
        "compactMode": true
    }
}
```

### Response
```
{
    "jsonrpc": "2.0",
    "id": 6,
    "result": [
        {
            "_type": "HELPER",
            "resourceId": "Source[\"5c3cf84f797a\"]",
        },
        {
            "_type": "HELPER",
            "resourceId": "Source[\"5c3cf84f797b\"]",
        },
        {
            "_type": "HELPER",
            "resourceId": "Source[\"5c3cf84f797c\"]",
        },
    }
}
```

# Remote connections
Streamlabs Desktop allows remote connection via websockets protocol powered by [Sockjs](https://github.com/sockjs).
To enable remote connections go to `Settings->Remote Control` click on QR Code and click `show details`.
Copy the token and close the settings window.
SLOBS will start listening for new collections.

You should provide your token in your first request to the API.
This step is required for each new connection to websockets.

### Request
```
{
    "jsonrpc": "2.0",
    "id": 8,
    "method": "auth",
    "params": {
        "resource": "TcpServerService",
        "args": ["your_secret_token_here"]
    }
}
```


You can find more settings if you start SLOBS with `--adv-settings` parameter and go to `Settings->Developer`.

# FAQ

## What is the difference between Sources and SceneItems?

One thing to keep in mind in OBS is that sources and scene items are different things.
A source exists outside the context of a scene. Muted is a property of a source. 
A scene item is essentially an instance of a source in a scene. 
The same underlying source can be in multiple scenes as a sceneitem. 
Visibility is an attribute on a scene item. 
So the same source can be visible in one scene and invisible in another for example.

## How to mute a source ?

First get the list of audio sources for the current scene

### Request
```
{
    "jsonrpc": "2.0",
    "id": 7,
    "method": "getSourcesForCurrentScene",
    "params": {
        "resource": "AudioService"
    }
}
```


### Response
```
{
    "jsonrpc": "2.0",
    "id": 7,
    "result": [
       {
            "_type": "HELPER",
            "resourceId": "AudioSource[\"wasapi_output_capture_30c2879c\"]",
            "sourceId": "wasapi_output_capture_30c2879c",
            "muted": false,
            "name": "DesktopAudioDevice1",
            "type": "wasapi_output_capture",
            "id": "wasapi_output_capture_30c2879c-989e-4230-a293-c2e47941197a"
        },
       {
            "_type": "HELPER",
            "resourceId": "AudioSource[\"wasapi_input_capture_d497319b\"]",
            "sourceId": "wasapi_input_capture_d497319b",
            "muted": false,
            "name": "AuxAudioDevice1",
            "type": "wasapi_input_capture",
            "id": "wasapi_input_capture_d497319b"
        }
    ]
}
```

Usually the AudioSource with the name AuxAudioDevice1 is the microphone.
To mute it you have to call `IAudioSourceApi.setMuted(true)`.
Use `resourceId` as the reference to `IAudioSourceApi` instance: 

### Request
```
{
    "jsonrpc": "2.0",
    "id": 7,
    "method": "setMuted",
    "params": {
        "resource": "AudioSource[\"wasapi_input_capture_d497319b\"]",
        "args": [true]
    }
}
```

## How to hide/show a scene item?

First get the active scene
### Request
```
{
    "jsonrpc": "2.0",
    "id": 8,
    "method": "activeScene",
    "params": {
        "resource": "ScenesService"
    }
}
```

### Response
```
{
    "jsonrpc": "2.0",
    "id": 8,
    "result": {
        "_type": "HELPER",
        "resourceId": "Scene[\"scene_02da7db7\"]",
        "id": "scene_02da7db7",
        "name": "Scene",
        "items": [
           {
                "sceneItemId": "b18ee2b0",
                "sourceId": "color_source_61221191",
                "transform": {
                    "position": { "x": 0, "y": 25},
                    "scale": { "x": 1, "y": 1},
                    "rotation": 0
                },
                "visible": true
            },
           {
                "sceneItemId": "fffadcdd",
                "sourceId": "image_source_21071a85",
                "transform": {
                    "position": { "x": 0, "y": 25 },
                    "scale": { "x": 1, "y": 1 },
                    "rotation": 0
                },
                "visible": true
            }
        ]
    }
}
```

Lets hide the first scene item via `ISceneItemApi.setVisibility(false)` method.
To do that you need a `resourceId` for this scene item.
Use `ISceneApi.getSceneItem(sceneItemId)`.

### Request
```
{
    "jsonrpc": "2.0",
    "id": 9,
    "method": "getItem",
    "params": {
        "resource": "Scene[\"scene_02da7db7\"]",
        "args": ["b18ee2b0"]
    }
}
```

### Response
```
{
    "jsonrpc": "2.0",
    "id": 9,
    "result": {
        "_type": "HELPER",
        "resourceId": "SceneItem[\"scene_02da7db7\",\"b18ee2b0-6ff7\",\"color_source_61221191\"]",
        "sceneItemId": "b18ee2b0",
        "sourceId": "color_source_61221191",
        "transform": {
            "position" : { "x": 0, "y": 25 },
            "scale": { "x": 1, "y": 1 },
            "rotation": 0
        },
        "visible": true
    }
}
```

Now you have a `resourceId` for the `ISceneItemApi` instance and can use its methods including setVisibility.
### Request
```
{
    "jsonrpc": "2.0",
    "id": 10,
    "method": "setVisibility",
    "params": {
        "resource": "SceneItem[\"scene_02da7db7\",\"b18ee2b0-6ff7\",\"color_source_61221191\"]",
        "args": [false]
    }
}
```

# How to switch a scene collection?

Use `SceneCollectionsService.collections` to find the id of the collection you want to load

### Request
```
{
    "jsonrpc": "2.0",
    "id": 11,
    "method": "collections",
    "params": {
        "resource": "SceneCollectionsService",
        "args": []
    }
}
```

Use `SceneCollectionsService.load` to load it

### Request
```
{
    "jsonrpc": "2.0",
    "id": 12,
    "method": "load",
    "params": {
        "resource": "SceneCollectionsService",
        "args": ["d3165bf4-2690-426a-80a1-f3421658e04e"]
    }
}
```