# Encoders

> How encoders work in Buttons, how a turn reaches a button, and real-world examples for audio levels, pan, camera iris and source selection.

An encoder is a knob that turns endlessly in both directions. Buttons uses encoders for anything that's a level or a position rather than an on/off press: a microphone fader, a pan, a camera's iris, or a choice from a long list such as the source on a monitor output.

An encoder never has actions of its own. It always works through a **button**: the button holds the actions, and an encoder turns that button. This page explains how a turn reaches a button, the two ways a button can react to it, and how to build the setups operators ask for most.

## Before you begin

- A surface with encoders, attached to the position:

  | Surface | Encoders | Where they are | | --- | --- | --- | | Stream Deck Studio | 2, each with a ring of 24 LEDs | One at each end of the key rows | | Stream Deck Plus | 4 | Under the touch strip | | Stream Deck Plus XL | 6 | Under the touch strip | | Galleon K100 SD | 2 | Above the keys |

- A button to control, see [Create your first button](/docs/buttons/v1.8/positions/create-your-first-button).

## Choose how the button reacts to a turn

A button reacts to turns through two kinds of action handler, added from **Add Action Handler** on its **Actions** tab. Choosing between them is the most important decision on this page.

|  | **Encoder** | **Left** and **Right** |
| --- | --- | --- |
| What a turn does | Moves a number that Buttons keeps for the button, between a **Min** and a **Max**, and sends the new number to the actions | Runs the **Left** actions once per click to the left, and the **Right** actions once per click to the right |
| What the action receives | The number, as **Encoder Value** or `$(self.encoderValue)` | Nothing: each action carries its own fixed step |
| Typical actions | "Set" actions: set fader gain, set pan, set iris | "Adjust" or "Increment" actions: adjust fader gain by 1 dB, increment iris |
| Use it when | Buttons is the only place the value is changed | The value can also change somewhere else: on the console, on the camera, or from another panel |

The difference matters because Buttons doesn't read the device's value back into the encoder. An **Encoder** button counts from its own number. It starts at **Initial**, and every turn moves it from wherever the encoder last left it. If an engineer moves the same fader on the console, the encoder doesn't know. The next click sends Buttons' number, and the level jumps back.

**Left** and **Right** don't have that problem. An "Adjust" or "Increment" action works from the device's current value, so the level always moves on from where it actually is.

A button can have both. You can also keep **Press** and **Release** on the same button. With **Click Select**, those run when the operator claims and lets go of the encoders, see [Which encoder turns which button](#which-encoder-turns-which-button).

## Set up an Encoder handler

When you turn on **Encoder**, its settings appear above its actions:

| Setting | What it does |
| --- | --- |
| **Initial** | The value the button starts at. |
| **Min**, **Max** | The range. Turning past either end keeps the value at that end. |
| **Current** | The value used when you run one of the button's actions from the editor. |
| **Assignment** | Which encoder turns this button. See [Which encoder turns which button](#which-encoder-turns-which-button). |
| **Display** | How the LED ring shows the value on a Stream Deck Studio. See [Show the value](#show-the-value). |
| **Active Style** | How the button looks while an encoder is turning it: **Highlight** (an outline in the button's **Encoder Color**, white if none is set; the default), **Ignore** (no change), or **Value on white background** (the value in large text, with the button's text above it). |

![The Encoder handler of a Comm 1 button set to Initial -20, Min -60, Max 10, Assignment Location, Display Start and Active Style Highlight, above its Fairlight Audio: Set fader gain action on the ATEM Mini](https://bitfocus.io/api/docs-media/file/encoder-settings-location.png?prefix=docs-media)

Each click of the encoder moves the value by 1. A quick turn sends several clicks at once, so the value moves faster. The value is always a whole number. If a device expects something else, such as 0–1 or 0–255, scale it in the action, as in the examples below.

To send the value to an action, select the encoder button next to a field that offers it, and the field shows **Encoder Value**. For a value that needs scaling, switch the field to expression mode and use `$(self.encoderValue)` in a calculation.

Each step of a button has its own value. A button with two steps can hold two different levels.

## Which encoder turns which button

**Assignment** decides which encoder turns the button. There are three choices.

### Click Select: claim the encoders with a tap

**Click Select** is the default. It lets a few encoders control many buttons, one at a time.

- **Tap** the button (shorter than 0.3 seconds) to claim the encoders. Its **Press** actions run. From now on, every encoder on the position that isn't assigned to a particular button turns this one.
- Tap the button again, or push the encoder knob, to let go. Its **Release** actions run.
- Tap a different **Click Select** button to move the encoders to it. Only one button on a position holds the encoders this way at a time.
- **Hold** the button (longer than 0.3 seconds) for a quick adjustment: the encoders turn it only while you hold it, and let go when you release.

A button with only **Left** and **Right**, and no **Encoder** handler, always uses **Click Select**. To give it a fixed encoder, turn on **Encoder** as well, set its **Assignment**, and leave its actions empty.

### Location: the encoder under the button

With **Location**, the button is turned by the encoder at its own place on the position: there's no tap, and the encoder always turns that button.

Location only works in the cell that belongs to an encoder:

- On a Stream Deck Plus or Plus XL, that's the touch-strip segment above each encoder. A key in the row above the strip doesn't get an encoder, even though it's next to one.
- On a Stream Deck Studio, the encoders sit at the far left and far right of the top key row, so only a button in either of those two cells gets that encoder.

A **Location** button anywhere else isn't turned by any encoder.

**Location** and **Click Select** work well together. Location buttons in the strip each keep their own encoder. The remaining encoders, such as the last two on a Plus XL with four strip buttons, are free for whichever **Click Select** button is claimed.

![A Stream Deck Studio with Comm 1 at -12 dB in the top-left key, turned by the left encoder through Location, and a Pan button at -4 claimed with Click Select, outlined in blue and turned by the right encoder](https://bitfocus.io/api/docs-media/file/surface-level-and-pan.png?prefix=docs-media)

### Enc 1 to Enc 16: a fixed encoder

Choose a number to tie the button to one encoder, wherever the button is placed. Buttons numbers every encoder on the position by where it sits: top row first, left to right, then the next row. With two Stream Deck Studios stacked on one position, **Enc 1** and **Enc 2** are the top unit's left and right encoders, and **Enc 3** and **Enc 4** are the bottom unit's.

### When nothing claims an encoder

An encoder that no button is using scrolls the sections that have scrolling turned on. Push the knob to move to the next scrolling section. See [Organize controls in a section](/docs/buttons/v1.8/positions/basic-sections).

If more than one setting could apply, a numbered assignment wins, then **Location**, then a **Click Select** button, then scrolling.

## Show the value

**On a Stream Deck Studio ring.** **Display** sets how the 24 LEDs show the value:

| Display | The ring shows | Good for |
| --- | --- | --- |
| **Single** | One lit LED at the value | Choosing from a list |
| **Start** | A bar that grows from the low end | Levels: faders, gain, iris |
| **End** | A bar that grows from the high end | Values that read downward, such as attenuation |
| **Split** | A bar from the middle out to the value | Pan, balance, anything centred on zero |

The ring is clearest with 24 steps or fewer between **Min** and **Max**, where every step has its own LED. With more steps, a single LED goes round the ring and wraps every 24 clicks. To keep the ring readable, use fewer, bigger steps and scale them in the action. The ring takes its color from the button's **Encoder Color** style.

**On the button.** Every surface can show the value on the button itself. Set **Active Style** to **Value on white background**, or put `$(self.encoderValue)` in the button's text, such as `$(self.encoderValue) dB` on the second line. Use the button for surfaces without rings, and whenever the operator needs the number rather than a bar.

## Real-world examples

The examples use an ATEM with Fairlight audio, but the pattern is the same for any connection with "set" and "adjust" actions: audio consoles, vision mixers, cameras and media servers.

### Commentary mic levels on a Stream Deck Plus

Four commentators, four mic faders, one knob each, and no tapping needed.

1. Put four buttons in the touch-strip row, named **Comm 1** to **Comm 4**.
2. On each button, turn on **Encoder** and set **Initial** `-20`, **Min** `-60`, **Max** `10`, and **Assignment** to **Location**.
3. Add **Fairlight Audio: Set fader gain** for that commentator's input, and set **Fader Level** to **Encoder Value**. Match **Source** to the input: the mic inputs on an ATEM Mini are mono, so choose **Mono (Ch1)** rather than **Stereo**.
4. Put `$(self.encoderValue) dB` on the second line of each button's text, so the strip shows the level above each knob.

Each knob now always controls the fader above it, 1 dB per click. Use this when nobody else touches these faders. If the sound engineer also rides them on the console, use the Left and Right version below instead.

The same button works on a Stream Deck Studio in the top-left or top-right key. With 70 steps from -60 to 10, its ring shows a single LED going round rather than a bar, so the level on the button is what the operator reads.

### Ride a level that is also changed on the console

A producer's panel trims the presenter mic, but the audio desk works on the same channel.

1. On the **Presenter** button, turn on **Right** and add **Fairlight Audio: Adjust fader gain** with **Delta** `1`.
2. Turn on **Left** and add the same action with **Delta** `-1`.

![The Left handler of a Presenter button with a Fairlight Audio: Adjust fader gain action on the ATEM Mini, Input Mic 2, Source Mono (Ch1) and Delta -1](https://bitfocus.io/api/docs-media/file/left-adjust-fader.png?prefix=docs-media)

Every click moves the fader 1 dB from wherever it really is, so the producer and the desk never fight each other. To show the level, add the connection's variable for that fader to the button's text, if it has one. The variable comes from the mixer, so it stays right whoever moved the fader.

### Pan with a centred ring

1. Turn on **Encoder** and set **Initial** `0`, **Min** `-10`, **Max** `10`, and **Display** to **Split**.
2. Add **Fairlight Audio: Set input pan** and set **Pan** to the expression `$(self.encoderValue) * 10`.

Twenty-one steps fit on the ring, the centre LED is dead centre, and each click moves the pan by 10 across its -100 to 100 range.

### Iris for a shader on a Stream Deck Studio

A shader runs four cameras from one Stream Deck Studio. There's one button per camera, and either encoder irises whichever camera is selected.

1. Make one button per camera: **Cam 1** to **Cam 4**.
2. On each, turn on **Right** with **Camera Control: Increment Iris** for that camera and **Value** `0.5`, and **Left** with the same action and **Value** `-0.5`.
3. Leave **Assignment** on **Click Select**.

The shader taps **Cam 2**, and both encoders iris camera 2. Tapping **Cam 3** moves them to camera 3. Iris is a typical relative control: auto iris or someone at the camera can change it, so **Left** and **Right** keep the shader working from the real aperture.

To set the iris absolutely instead, use **Encoder** with **Min** `0` and **Max** `20`, **Display** set to **Start**, and **Camera Control: Iris** with **Normalised** on and the value `$(self.encoderValue) / 20`. That gives 21 steps from closed to open.

### Turn through sources with an Encoder Selector

A floor manager's monitor is fed from an aux output, and they want to dial through cameras on it.

1. Make a **Floor monitor** button, turn on **Encoder**, and add **Aux/Output: Set source** for that aux.
2. On the **Input** field, open the **...** menu and select **Create Encoder Selector from choices**.

The encoder now steps through the inputs instead of counting numbers. **Initial**, **Min** and **Max** disappear, because the range is the list itself.

Select **Customize Encoder Selector** to shape the list. In **All Available Data**, select the eye next to an entry to leave it out, such as **Program** and **Preview** on a floor monitor:

![The Customize Encoder Data dialog in All Available Data view, listing the ATEM Mini's inputs for Aux/Output: Set source, with Program, Preview and TVS PGM Direct hidden and the hidden count showing 3](https://bitfocus.io/api/docs-media/file/encoder-selector-hide.png?prefix=docs-media)

In **Generated Values**, type a shorter name in an entry's **Label** column:

![The Generated Values view with the four remaining inputs labelled Cam 1 to Cam 4](https://bitfocus.io/api/docs-media/file/encoder-selector-labels.png?prefix=docs-media)

Put `$(self.encoderSelectorLabel)` in the button's text to show the selected source, and use **Single** display for one LED per source:

![A Stream Deck Studio with the Monitor button showing Cam 3, outlined in orange, and the right encoder's ring showing four positions with the third lit](https://bitfocus.io/api/docs-media/file/surface-encoder-selector.png?prefix=docs-media)

Every click switches the output straight away, passing through each source in between. Use an Encoder Selector for outputs where that's fine, such as monitors, multiviewer windows or clip selection, and not for a program bus.

### A fixed master knob

On a two-Studio position, the right encoder of the top unit is always the programme master, wherever the master button is placed.

1. Make a **Master** button, turn on **Encoder** with **Assignment** set to **Enc 2**.
2. Add **Fairlight Audio: Set master gain** with the gain set to **Encoder Value**.

**Enc 2** stays the master even while an operator has claimed the other encoders with **Click Select**.

## If you get stuck

| What you see | What to try |
| --- | --- |
| Turning the encoder does nothing. | With **Click Select**, tap the button first to claim the encoders. Check that no numbered or **Location** button has that encoder: those win over **Click Select**. With **Location**, check that the button is in the encoder's own cell, such as the touch-strip segment above it. |
| The level jumps when you start turning. | The value was changed somewhere else since the encoder last moved it. Buttons counts from its own value. Use **Left** and **Right** with an "Adjust" action instead. |
| A red warning sign appears on the button after a turn. | The action failed. Run it from the editor with the lightning button next to it to see the error, such as an ATEM input that has no **Stereo** source. |
| The value stops at the ends. | Expected: it stays between **Min** and **Max**. Widen the range, or scale it in the action. |
| The ring shows only a single LED going round. | The range has more than 24 steps. Use fewer steps and scale them in the action. |
| The device gets a value outside the range it expects. | Scale it in the action, such as `$(self.encoderValue) / 20` for a 0–1 value. |
| The encoder scrolls a section instead of turning the button. | No button holds that encoder. Tap a **Click Select** button, or give the button **Location** or a number. |
| An Encoder Selector sweeps the program bus through every source. | Expected: each click runs the action. Use the selector on a monitor or preview output, not on program. |

## Where to go next

- [Build more capable button actions](/docs/buttons/v1.8/positions/button-actions), for steps, hold and click patterns, and repeaters.
- [Control a workflow with an encoder](/docs/buttons/v1.8/workflows/control-a-workflow-with-an-encoder), to set or step a workflow variable or trigger a workflow's actions from an encoder.
- [Organize controls in a section](/docs/buttons/v1.8/positions/basic-sections), for scrolling sections with encoders.
- [Set device orientation](/docs/buttons/v1.8/surfaces/orientation), when a surface with encoders is mounted rotated.
- [Button Inspector reference](/docs/buttons/v1.8/reference/button-inspector), for **Encoder Color** and the other styles.
