Documentation / Tutorials

Tutorial: build a stream deck for OBS Studio

Fifteen keys, an ON AIR lamp and two timers on a 3.5-inch touchscreen, built from an empty project one step at a time.

The finished deck in Preview, with SCREEN chosen, a recording under way and the stream live.
The finished deck in Preview, with SCREEN chosen, a recording under way and the stream live.

This is the gallery's OBS Stream Deck, rebuilt from nothing. To the PC it is a Bluetooth keyboard, so there is no driver, no companion program and no cable: you pair it, tell OBS Studio which key does what, and it works. Along the way it uses most of what makes a design do something - events, variables, bindings, automations and a ready-made Timer - so it is also a tour of the designer.

Every step below was carried out in the designer to take its picture, and the design that came out of them was generated and compiled for the board: 1.32 MB of firmware. The example it rebuilds has been run against OBS Studio on this board.

What is free and what is Pro. Building this design and trying it in Preview are free and need no account. Generating its code is part of Pro, because it uses two Pro parts: the Bluetooth keyboard and the Timer widget. The export dialog says so before anything is charged (step 46).

What you need

Allow about an hour for the design and ten minutes for the build. If you would rather start from the finished thing, open the example and press Open a copy: everything below is then there to read, key by key.

Part 1: a new project

1 Start a project for Arduino

Open the designer. On a first visit the setup wizard is already there; otherwise choose File > New project. For What are you building for? choose Arduino (C++) and press Next. A Bluetooth keyboard is in the Arduino export only.

The wizard's first question: what the project is for.
The wizard's first question: what the project is for.

2 Choose the board

Under All-in-one boards choose LCDWIKI 3.5" ESP32-S3 (ES3C35P). Choosing a board fills in every pin, the panel's controller and the touch chip, so there is no wiring to enter. Press Next.

The board list, with the ES3C35P chosen.
The board list, with the ES3C35P chosen.

3 Turn the panel on its side

Set Rotation to 90 degrees. The panel is 320 x 480 upright, and the deck is drawn 480 x 320. Press Next.

The panel step, with Rotation set to 90 degrees.
The panel step, with Rotation set to 90 degrees.

4 Keep LVGL 9

LVGL 9 is already chosen. Press Next.

LVGL 9, the current release.
LVGL 9, the current release.

5 Name it and start empty

Type OBS Deck for the project name, choose Start from an empty screen, and press Create the project.

The last step: a name, an empty screen, and Create the project.
The last step: a name, an empty screen, and Create the project.

6 Look round the designer

The screen is in the middle. Widgets are on the left, with the Hierarchy of what is on the screen beside them. On the right are the tabs this tutorial uses most: Inspector (the selected widget), Hardware, Data and Theme. Along the bottom are Assets, the Console and Problems. Your work is saved in the browser as you go.

The designer with the new, empty project: a 480 x 320 screen.
The designer with the new, empty project: a 480 x 320 screen.

Part 2: make the board a Bluetooth keyboard

7 Switch Bluetooth on, as a keyboard

Open the Hardware tab and, in its second row of tabs, Bluetooth.

  1. Tick This board uses Bluetooth.
  2. Under This board is, choose A keyboard (HID).
  3. Set Name to OBS Deck. That is what the PC will list it as.

A board has one Bluetooth role. As a keyboard, anything that fires an event can send a key, which is all a stream deck is.

Hardware, then Bluetooth.
Hardware, then Bluetooth.
Bluetooth switched on, as a keyboard called OBS Deck.
Bluetooth switched on, as a keyboard called OBS Deck.

Part 3: the ground the keys sit on

8 Set the theme to dark

Open the Theme tab and the LVGL theme section. Set Mode to Dark, Primary to #22C8F5 and Secondary to #FF2D55.

The theme is what a widget looks like before you style it. Every widget in this design is styled, so this mostly decides what LVGL draws for a moment while the board starts.

Theme: dark, with the deck's two colours.
Theme: dark, with the deck's two colours.

9 Make the screen itself dark

Go back to the Inspector tab and click Screen1 in the Hierarchy, so the Inspector shows the screen. Open Style settings, then Background, and set Color to #06080C.

A green dot beside a group, and a star beside a setting, mark what you have changed. Only those are written into the code.

The screen's own background colour.
The screen's own background colour.

10 Add the backdrop picture

In the bottom panel, on the Assets tab, press Add image and choose the deck-bg.png you downloaded. It appears as a tile.

The Assets tab with the backdrop added.
The Assets tab with the backdrop added.

11 Keep the picture in the firmware

Click the picture's tile. On the right, set Stored in to Firmware (C array). The other choice keeps pictures on the board's filesystem, which is a second upload; one picture this size is simpler compiled in.

Stored in: Firmware (C array).
Stored in: Firmware (C array).

12 Put the picture on the screen

Open Basic in the Widgets list and drag Image onto the screen. In the Inspector:

  1. Set Name to Backdrop.
  2. Open Image settings and set Asset to deck-bg.png. The widget takes the picture's size, 480 x 320.
  3. Open Geometry and set X and Y to 0.

Everything else goes on top of it. A widget added later is drawn over the ones before it, so adding the backdrop first is what puts it at the back.

The backdrop on the screen: the bar across the top and fifteen wells.
The backdrop on the screen: the bar across the top and fifteen wells.

Part 4: the first key

One key is made completely - its place, its caption, its look, what it sends, when it lights and when it is greyed out. The other fourteen are copies of it with a few things changed.

13 Drag a Button onto the screen

From Basic, drag Button onto the screen, anywhere. It arrives blue, saying "Button".

A new Button, before anything about it is set.
A new Button, before anything about it is set.

14 Name it and put it in the first well

With the button selected, set Name to IntroKey. Open Geometry and type:

XYWidthHeight
11468682

Every key is 86 x 82. The columns are at X 11, 104, 197, 290 and 383, and the rows at Y 46, 136 and 226.

The key's name and its place.
The key's name and its place.

15 Give it a caption and an icon

Open Button settings.

  1. Set Text to INTRO.
  2. Click Icon and choose Rocket. The search box finds one by name.
  3. Set Icon position to Above the text, Icon size to 30 and Icon gap to 6.

The icon is drawn in the button's text colour, so when the key lights up and its text turns dark, the icon turns with it.

The key in its well, not yet styled.
The key in its well, not yet styled.
Caption, icon and where the icon sits.
Caption, icon and where the icon sits.

16 Style the key as it rests

Open Style settings. Part stays on Main and State on Default: this is how the key looks when nothing is happening to it. Open each group and set:

GroupSettingValue
BackgroundColor#272E3D
Grad. color#151A24
Grad. directionVertical
BorderColor#3C4557
Width1
ShadowWidth0
TextColor#22C8F5
FontMontserrat, Bold, 12 px
Letter space1
PaddingTop, Bottom, Left, Right4 each
MiscRadius12
Default state: background and border.
Default state: background and border.
Shadow and text.
Shadow and text.
Padding and the corner radius.
Padding and the corner radius.

17 Style it while a finger is on it

Change State to Pressed. A state holds only what differs from Default, so there is little to set:

GroupSettingValue
BackgroundColor#0E1118
Grad. color#0E1118
BorderColor#22C8F5

While State is on Pressed, the canvas draws the key pressed, so you can see what you are setting.

Pressed: a darker face and a lit edge.
Pressed: a darker face and a lit edge.

18 Style it lit

Change State to Checked. Checked is the state a key is in while it is "on", and for this key that will mean "this is the scene OBS is showing".

GroupSettingValue
BackgroundColor#4FD8FF
Grad. color#12A6DE
BorderColor#4FD8FF
TextColor#03131C
The key as the canvas draws it with State on Checked.
The key as the canvas draws it with State on Checked.
Checked: a bright face with dark text.
Checked: a bright face with dark text.

19 Style it greyed out

Change State to Disabled, open Misc and set Opacity to 90. Then put State back to Default.

A disabled key takes no touch. Step 26 is what disables it: while no PC is connected.

The first key, styled, in its well.
The first key, styled, in its well.
Disabled: faded to 90 out of 255.
Disabled: faded to 90 out of 255.

Part 5: what the key sends

20 Send Ctrl + F13 when it is clicked

Open Events and press Add event.

  1. Leave the trigger on Clicked.
  2. Set Action to Send a key or shortcut. It is in the Bluetooth group, near the end of the list.
  3. Set Key to F13 and tick Ctrl.
  4. Leave Do on Press and let go.

F13 to F24 are real keys that no keyboard has, so nothing else on the PC will ever send one and no program has claimed them. Each key on the deck takes exactly one modifier: Ctrl is "on", Alt is "off" and Shift is a single press.

Clicked: send Ctrl + F13.
Clicked: send Ctrl + F13.

21 Try it in Preview

Press the Preview button, the triangle at the right of the bar above the screen. The screen is now drawn as the panel draws it and takes clicks as touches. Open the Console tab in the bottom panel and click the key: the Console says what the board would have sent.

You should see preview: Bluetooth keyboard: Ctrl + F13.

Press the square Stop button, where the triangle was, to go back to designing.

Preview: the key was clicked, and the Console shows the shortcut.
Preview: the key was clicked, and the Console shows the shortcut.

Part 6: one scene lit at a time

A scene key should light when it is chosen and go out when another is. So the key does not light itself: a variable remembers which scene was chosen, and each key is lit while the variable holds its number.

22 Make a variable called scene

Open the Data tab and the Variables section, and press +.

  1. Name it scene.
  2. Set Type to Integer.
  3. Leave Source on (set by events only) and Initial value on 0.
  4. Set Max to 5.

0 means no scene has been chosen yet.

The variable that remembers the scene.
The variable that remembers the scene.

23 Have the key set it

Back on the Inspector tab, select the key and open Events. Press Add event again: a widget can have as many as you like, and both of these run on one click.

  1. Trigger: Clicked.
  2. Action: Set variable, in the Hardware group.
  3. Variable: scene. Set to: A fixed value. Value: 1.
The second event: scene becomes 1.
The second event: scene becomes 1.

24 Light the key while scene is 1

Open Data bindings and press Add binding. A binding keeps one thing about a widget in step with a variable.

  1. Leave the source on From a variable, and Variable on scene.
  2. Set Drives to Checked.
  3. Leave Direction on Variable -> widget.
  4. In Formula type scene == 1.

A comparison gives 1 or 0, so the key is Checked - and drawn in the bright colours of step 18 - exactly while scene is 1.

Checked follows the variable.
Checked follows the variable.

Part 7: grey until a PC is connected

A key that lit up with nobody listening would leave the deck saying one thing and OBS doing another. So every key is disabled while no host is connected.

25 Make a variable that reads the connection

On the Data tab, add another variable.

  1. Name it connected.
  2. Set Type to Boolean.
  3. Set Source to A host is connected, in the Bluetooth group.

A variable with a source is read from the board, not set by events: this one is 1 while a PC is connected and 0 while none is.

A variable read from Bluetooth.
A variable read from Bluetooth.

26 Disable the key while it is 0

Select the key again and add a second binding.

  1. Variable: connected.
  2. Drives: Disabled (greyed, takes no touch).
  3. Formula: connected == 0.

That is the first key finished: two events and two bindings. The Problems tab in the bottom panel should show no errors.

Disabled while nothing is connected.
Disabled while nothing is connected.

Part 8: five scenes

27 Duplicate the key

Select IntroKey and choose Edit > Duplicate, or press Ctrl + D. The copy has the original's look, its events and its bindings. Do it four times.

Edit, Duplicate. The Inspector shows the two bindings the copy will carry.
Edit, Duplicate. The Inspector shows the two bindings the copy will carry.

28 Change four things on each copy

For each copy, set its Name and X (Geometry), its Text and Icon (Button settings), the Key and the Value in its two events, and the number in its Checked binding's Formula:

NameXTextIconKey (with Ctrl)Set variable: ValueFormula
CameraKey104CAMERAUserF142scene == 2
ScreenKey197SCREENDisplayF153scene == 3
BrbKey290BRBCoffeeF164scene == 4
OutroKey383OUTROExit rightF175scene == 5

Y stays at 46. The captions are a common set of scenes; use whichever five you have.

Five scene keys. CameraKey is selected, showing its caption and icon.
Five scene keys. CameraKey is selected, showing its caption and icon.

29 Check that one goes out when another lights

Press Preview and click CAMERA, then another key. The one you clicked last is lit and the others are not, and the Console lists each shortcut.

Preview takes a PC to be connected. To see the keys greyed, open Bluetooth in the Preview data drawer beside the screen and set It is to Waiting to be paired.

Preview: CAMERA was clicked, so it is lit and INTRO is not.
Preview: CAMERA was clicked, so it is lit and INTRO is not.

Part 9: the second row - keys that stay on, one that is held, one that is tapped

Not every key is a scene. There are three other kinds, and each is a small change to a copy of a scene key.

30 MUTE MIC: a key that stays on

Duplicate IntroKey. Name the copy MuteMicKey, set X 11 and Y 136, the text MUTE MIC and the icon Microphone muted.

Open Flags and tick Checkable. A checkable button turns itself on with one touch and off with the next, which is what a mute key is.

It lights itself now, so in Data bindings delete the binding to scene (the bin on its card). Keep the one that drives Disabled.

Flags: Checkable.
Flags: Checkable.

31 Send one shortcut for on and another for off

In Events, delete the Set variable event. Then:

  1. On the event that is left, change the trigger from Clicked to Checked and the Key to F18, with Ctrl ticked.
  2. Add an event: trigger Unchecked, Send a key or shortcut, F18, with Alt ticked and Ctrl not.

On and off are two shortcuts, never one that toggles. A keyboard only talks one way, so the deck cannot ask OBS whether the microphone is muted. With one shortcut that toggles, a single click of the mouse in OBS leaves the two disagreeing for the rest of the evening. With two, the lit key means "the last thing I sent was Mute", and the next press always sends Unmute.

Checked sends Ctrl + F18, Unchecked sends Alt + F18.
Checked sends Ctrl + F18, Unchecked sends Alt + F18.

32 Give it its own colours

In Style settings, with State on each of these in turn, change:

StateGroup and settingValue
DefaultText, Color#A78BFF
PressedBorder, Color#A78BFF
CheckedBackground, Color#FF7A52
Background, Grad. color#E0432A
Border, Color#FF7A52
Text, Color#FFFFFF

The colour of a key's text is also the colour of the light under its well in the backdrop.

33 TALK: a key that is held

Duplicate MuteMicKey. Name the copy TalkKey, set X 104, the text TALK and the icon Microphone. Untick Checkable.

Change its two events:

  1. The first: trigger Pressed, F18 with Shift ticked only, and Do set to Hold down.
  2. The second: trigger Released, the same key, and Do set to Let go of everything.

The key is then down on the PC for exactly as long as the finger is on the glass: push-to-talk.

It never stays on, so its lit look belongs to Pressed. Set Default's text colour to #3CE38A, and in Pressed: Background #5BF0A0 with Grad. color #22B868, Border #5BF0A0 and Text #03170C.

Pressed holds the shortcut down; Released lets it go.
Pressed holds the shortcut down; Released lets it go.

34 The rest of the row

Three more, all at Y 136. MUTE PC and HIDE CAM are copies of MuteMicKey with a new name, place, caption, icon and key. SNAP is a copy of a scene key with its Set variable event and its scene binding deleted, and Shift in place of Ctrl: a single press.

NameXTextIconText colourIt sends
MutePcKey197MUTE PCVolume muted#A78BFFChecked: Ctrl + F19. Unchecked: Alt + F19
HideCamKey290HIDE CAMEye closed#A78BFFChecked: Ctrl + F20. Unchecked: Alt + F20
SnapKey383SNAPCapture#5CA8FFClicked: Shift + F21

For SNAP, set the Pressed state's border colour to #5CA8FF as well.

Two rows done.
Two rows done.

Part 10: the third row - record, pause and GO LIVE

These keys depend on each other: PAUSE means nothing unless a recording is running, and stopping the recording should put PAUSE out. Three more variables say what the deck last asked for.

35 Three more variables

On the Data tab add rec, paused and live. Each is a Boolean with Source left on (set by events only) and an initial value of 0.

Five variables in all.
Five variables in all.
rec, and the other two are the same.
rec, and the other two are the same.

36 REC: a key that also sets variables

Duplicate MuteMicKey. Name the copy RecKey, set X 11 and Y 226, the text REC and the icon Record. Change its key to F23 in both events.

Then add three events, each with the action Set variable and A fixed value:

TriggerVariableValue
Checkedrec1
Uncheckedrec0
Uncheckedpaused0

Colours: Default text #FF3B4E, Pressed border #FF3B4E, and Checked #FF5A6A to #D61F38 with a #FF5A6A border and #FFFFFF text.

REC's three Set variable events, under its two shortcuts.
REC's three Set variable events, under its two shortcuts.

37 PAUSE: only while recording, and put out by Stop

Duplicate MuteMicKey again. Name the copy PauseKey, set X 104 and Y 226, the text PAUSE, the icon Pause and the key F22. Two bindings make it behave:

  1. On the binding that drives Disabled, change the Formula to connected == 0 || rec == 0: greyed with no host, or with no recording.
  2. Add a binding: Variable paused, Drives Checked, and Direction Both ways. Touching the key now writes paused, and when REC sets paused back to 0 the key goes out by itself.

Colours: Default text #FFB020, Pressed border #FFB020, and Checked #FFC44D to #E8930C with a #FFC44D border and #221300 text.

PAUSE: disabled unless recording, and Checked both ways with paused.
PAUSE: disabled unless recording, and Checked both ways with paused.

38 REPLAY and V-CAM

Both at Y 226. REPLAY is a copy of SnapKey; V-CAM is a copy of MuteMicKey.

NameXTextIconText colourIt sendsChecked colours
ReplayKey197REPLAYUndo history#3CE38AClicked: Shift + F22-
VcamKey290V-CAMVideo#5CA8FFChecked: Ctrl + F21. Unchecked: Alt + F21#7DBBFF to #2E7FE6, border #7DBBFF, text #04142A

Set each one's Pressed border to its text colour.

39 GO LIVE: a key that wants a hold

Going live is the one key that costs something when a sleeve brushes it, so it takes a long press, both to start and to stop. A checkable button cannot do that - it toggles on any release - so GO LIVE is lit by a variable instead.

Duplicate IntroKey. Name the copy GoLiveKey, set X 383 and Y 226, the text GO LIVE and the icon Cast.

  1. In Events, delete the shortcut event. On the Set variable event change the trigger to Long pressed, the Variable to live and Set to to Toggle (bool).
  2. In Data bindings, on the Checked binding change the Variable to live and clear the Formula.

Colours: Default text #FF2D8A, Pressed border #FF2D8A, and Checked #FF5C9E to #E0105F with a #FF5C9E border and #FFFFFF text.

Checked follows live.
Checked follows live.
Long pressed: live is toggled.
Long pressed: live is toggled.

40 Send GO LIVE's shortcuts from two automations

The key only flips a variable. What sends the shortcut is an automation: something that runs without a touch, here when the variable changes. On the Data tab open Automations, choose Variable changes in the list beside Add, and press Add. Make two:

NameVariableConditionValueThen: Send a key or shortcut
GoLiveliveBecomes equal to1F24 with Ctrl
EndStreamliveBecomes equal to0F24 with Alt

For each, press Add action under Then and choose Send a key or shortcut. Sending is an action, so anything that can fire an event can send a key: a variable here, and on a board with a rotary encoder a click of the knob.

When live becomes 1, send Ctrl + F24.
When live becomes 1, send Ctrl + F24.
When it becomes 0, send Alt + F24.
When it becomes 0, send Alt + F24.
All fifteen keys.
All fifteen keys.

Part 11: the tally bar

The bar across the top says what the deck believes is going on: whether a PC is connected, how long the recording has run, and whether the stream is live.

41 The unlit segments of a display

A real seven-segment display shows its unlit segments faintly, and a label behind each timer does the same. Drag a Label from Basic onto the bar. Name it RecSegments, set its Geometry to X 194, Y 8, Width 97, Height 21, and its text to 888:88. In Style settings set Text Color #3A4252, Font Seven-segment Modern, Bold, 20 px, and Align Right.

It goes on first because a widget added later is drawn on top, and the timer has to be on top of it.

42 A timer, with nothing to wire

Open Ready-made in the Widgets list and drag a Timer onto the bar. Name it RecTimer and give it exactly the label's box: X 194, Y 8, Width 97, Height 21. In Timer settings:

  1. It: Counts up - a stopwatch. Shows: Minutes and seconds - 05:07.
  2. It runs: While a variable is on.
  3. While: rec. Held while: paused.
  4. Leave From the beginning each time ticked.

That is the whole of it: the timer runs while rec is on, stands still while paused is, and starts from nothing with each recording. It keeps time by the board's own clock, so three hours of stream read as three hours.

In Style settings set Text Color #FF5A6A, the same Font and Align as the label under it, and all four Paddings 0.

Then make the pair again for the stream, a label and a timer on top of it, both at X 372: LiveSegments, and LiveTimer with While set to live, Held while left on (none) and the text colour #EEF2F7.

RecTimer runs while rec is on and is held while paused is.
RecTimer runs while rec is on and is held while paused is.

43 Lamps that come and go

The rest of the bar is five labels and a small panel, each shown or hidden by a binding that drives Hidden. All the text is Montserrat, Bold, 12 px with Letter space 1.

NameWidgetX, Y, W, HTextHidden while
NoHostLabel60, 8, 78, 22NO HOSTconnected: connected != 0
LinkedLabel60, 8, 78, 22LINKEDconnected: connected == 0
RecLampPanel148, 14, 10, 10-rec: rec == 0
RecCaptionLabel162, 12, 30, 13RECnever
OffAirLabel298, 8, 68, 22OFF AIRlive: live != 0
OnAirLabel298, 8, 68, 22ON AIRlive: live == 0

The four that are pills (NoHost, Linked, OffAir, OnAir) get a Border of Width 1, Misc Radius 11, Text Align Center, and Padding Top 4 with the other three 0. Their colours:

NameBorderTextBackground
NoHost#FFB020#FFB020none
Linked#3CE38A#3CE38Anone
OffAir#3A4252#8791A4none
OnAir#FF7A93#FFFFFF#FF2D55, Opacity 255

RecCaption's text is #8791A4. RecLamp is a red dot: Background #FF3B4E, Radius 5, Border Width 0, all Paddings 0, and Clickable unticked in Flags.

Tick Hidden in Flags for Linked, RecLamp and OnAir, so that they start out of sight: with nothing connected, nothing recording and nothing live, that is the truth.

ON AIR is hidden while live is 0.
ON AIR is hidden while live is 0.
ON AIR's background and border.
ON AIR's background and border.
The finished design. Hidden widgets are greyed in the Hierarchy.
The finished design. Hidden widgets are greyed in the Hierarchy.

Part 12: try the whole deck

44 Record, pause and go live in Preview

Press Preview. Click a scene. Click REC: the lamp comes on and the red timer starts. Click PAUSE: it holds. Click REC again: PAUSE goes out by itself and the timer stops. Hold GO LIVE for about a second: ON AIR appears and the white timer starts.

You should see each shortcut in the Console as it would be sent, GO LIVE's marked with the name of its automation.

SCREEN chosen, a recording running for four seconds, and live for three.
SCREEN chosen, a recording running for four seconds, and live for three.

Part 13: generate the code

45 Read the Problems tab

Leave Preview and open Problems in the bottom panel. There should be no errors. Two warnings come with this board's own wiring - its SD card slot and its BOOT button are on pins the chip also reads at start-up - and neither is in the way of this design.

No errors; two warnings that belong to the board.
No errors; two warnings that belong to the board.

46 Press Export code

Press Export code at the top right. Generating needs an account, and the dialog first says which parts of the design are Pro: the Timer, on its two widgets, and the Bluetooth keyboard, on the keys that send. With Pro, press Generate code.

The export dialog names the Pro parts this design uses before anything is generated.
The export dialog names the Pro parts this design uses before anything is generated.

47 Download the project

The dialog lists every file it wrote - 31 for this design - and shows any of them when clicked: the screen's own C, the sketch, the Bluetooth module, the fonts and the backdrop as a C array. Press Download project .zip.

The generated project: 31 files, with ui.h open.
The generated project: 31 files, with ui.h open.

Part 14: build it and put it on the board

48 Build and upload

Unzip the project. With PlatformIO, plug the board in, open a terminal in the folder and run:

pio run -t upload

The first build fetches the libraries and takes a few minutes. With the Arduino IDE, open OBS_Deck.ino from the folder, install the libraries that LIBRARIES.md lists, and set the Tools menu as README.md says before pressing Upload. Flashing and configuration has both routes in full.

The backdrop is compiled in, so there is no second upload for pictures.

You should see the deck on the panel with its keys greyed and NO HOST in the bar. If the screen stays dark after uploading, unplug the board and plug it in again once: this panel's reset is the board's own RESET button, not a pin the firmware can pulse.

49 Pair it with the PC

On the PC, add a Bluetooth device and choose OBS Deck. On Windows that is Settings > Bluetooth & devices > Add device > Bluetooth. There is no number to type. The bar changes from NO HOST to LINKED and the keys come to life.

If you ever erase the board and upload again, remove OBS Deck from the PC's Bluetooth devices and pair it afresh: the PC keeps a pairing the board no longer has.

Part 15: tell OBS which key does what

50 Fill in OBS's hotkeys by tapping the deck

In OBS open Settings > Hotkeys. Click the box beside an action and tap its key on the deck: OBS writes the shortcut in for you. A key with two shortcuts sends the second on its second tap - tap REC for Start Recording, click the Stop Recording box, tap REC again. For GO LIVE, hold the key each time. Or type them in from this table:

Key on the deckIt sendsIn OBS, Settings > Hotkeys, give that to
INTROCtrl + F13Switch to scene, on your opening scene
CAMERACtrl + F14Switch to scene, on your camera scene
SCREENCtrl + F15Switch to scene, on your screen or game scene
BRBCtrl + F16Switch to scene, on your "be right back" scene
OUTROCtrl + F17Switch to scene, on your closing scene
MUTE MICCtrl + F18 on, Alt + F18 offMic/Aux > Mute, Mic/Aux > Unmute
TALKShift + F18, held for as long as the key isMic/Aux > Push-to-talk
MUTE PCCtrl + F19 on, Alt + F19 offDesktop Audio > Mute, Desktop Audio > Unmute
HIDE CAMCtrl + F20 on, Alt + F20 offHide (your camera source), Show (your camera source)
SNAPShift + F21Screenshot Output
RECCtrl + F23 on, Alt + F23 offStart Recording, Stop Recording
PAUSECtrl + F22 on, Alt + F22 offPause Recording, Unpause Recording
REPLAYShift + F22Save Replay
V-CAMCtrl + F21 on, Alt + F21 offStart Virtual Camera, Stop Virtual Camera
GO LIVECtrl + F24 to start, Alt + F24 to stop. Hold the key.Start Streaming, Stop Streaming

Push-to-talk also needs Enable Push-to-talk ticked for the microphone under Settings > Audio. Hide and Show are listed under the scene a source is in, once for each source.

The deck and OBS can only disagree if you change something with the mouse. If they do, one press of the key puts it right: the next press always sends the opposite of what the deck last sent.

Making it yours