About

Oi! is a VSD Craft plugin that gives your Stream Dock N4 Pro deep, native control over Resolume Arena. 10 actions covering clip triggers, column and deck switching, layer controls, rotary encoders for opacity and speed, a touch bar crossfader, and a custom OSC escape hatch for anything else.

Direct OSC + REST
Live thumbnails
Setup in minutes
Mascot character explaining what Oi! is

Features

Key Actions

Alpha

Trigger Clip

Fire clips via OSC with live LCD thumbnails and green border on active clips.

Trigger Column

Trigger an entire column with one press. Switch scenes instantly.

Deck Select

Switch the active deck on the fly. One key per deck, instant access.

Layer Controls

Toggle bypass, solo a layer, or clear all clips. Three modes, one action.

Custom OSC

Send any OSC message you want. Address, type, value. The escape hatch for everything.

Encoder Actions

New

Encoder Opacity

Rotate to control layer opacity. Push to toggle 0% / 100%.

Encoder Speed

Dial controls playback speed (0-2x). Push resets to 1x.

Touch Bar

New

Touch Crossfader

Slide your finger to control the crossfader or any float parameter via OSC.

Hardware

The N4 Pro's rotary encoders, LCD keys, and touch bar go beyond what most controller plugins support. Oi! uses all of them: direct opacity control on the dials, live clip thumbnails on every key, and a touch crossfader that maps to any OSC float.

Thanks to the OpenSDK, plugins built for the Elgato Stream Deck ecosystem also work here. Oi! is built specifically for these extra inputs, so you get control surfaces that generic integrations can't match.

Mascot characters showcasing N4 Pro hardware compatibility

Tech Stack

Oi! is built with vanilla JavaScript. No frameworks, no bundlers, no bloat. The plugin communicates with Resolume Arena via its REST API for state and thumbnails, and OSC protocol for low-latency clip triggering.

The website is pure static HTML, CSS, and JS served by Apache2. The plugin communicates over your local network. No cloud, no accounts, no telemetry.

HTML5 CSS3 JavaScript OSC REST API Apache
Mascot character explaining the tech stack

Requirements

Hardware Stream Dock N4 Pro
Software VSD Craft (latest)
VJ Software Resolume Arena 7+
OS Windows 10 / 11

Pricing

Free during alpha / beta

Oi! is completely free for anybody willing to test it, report bugs, and help make it brilliant. Real feedback from real VJs before we even think about pricing.

Early adopters who help shape the project will always be looked after. to stay in the loop.

Mascot character discussing pricing

Download

Free

ArenaM8 Alpha

v0.8.1

10 actions, free for testers. Direct Resolume Arena control with live thumbnails, encoders, and touch bar support.

Download Latest
Install instructions
  1. Extract the zip file
  2. Copy uk.gamingworld.arenam8.sdPlugin folder
  3. Paste into %APPDATA%\HotSpot\StreamDock\plugins\
  4. Restart VSD Craft

Developer

Oi! is built by saintpetejackboy, a programmer who builds tools, game servers, and web platforms for fun. He also runs Gaming World, an indie game dev community with its own news platform, mailing system, and multiplayer game servers.

When the existing Stream Dock integrations didn't cut it for Resolume Arena, he did what any self-respecting developer does and built one from scratch. Check out more projects on GitHub or .

Mascot character representing the developer

Feedback

Bug reports, feature requests, mailing list, or just want to say hello.

Contact

I'm always open to a conversation or cool project idea!

Email: ArenaM8@gamingworld.uk

GitHub: saintpetejackboy

Or just directly.

Mascot character waving for contact

Changelog

v0.8.5 2026-04-11

Plugin Fixes — Thumbnails Finally Working

  • **Root cause of the red question marks**: Resolume REST paths require 1-based array **indices** (`/layers/1/clips/1/thumbnail`), but the PI was storing `clip.id` and `layer.id` in the settings — those are internal Resolume GUIDs like `1621342719991`, not indices. Every thumbnail and every `/connected` call 404d. Fixed pi-clip-selector.js to use `String(idx + 1)` as option values so only the numeric position is ever passed to the plugin
  • Dropped the broken `/api/v1/composition/layers/{l}/clips/{c}/connected` endpoint entirely — it doesn't exist in Resolume's API. Active-clip detection now reads `clip.connected.value` from the cached composition (it's already there, zero extra HTTP calls)
  • Fixed SVG data URI corruption in `createErrorSvg` and `createBorderedSvg` — raw hex colors like `#1a1a2e` and `#66ff99` were terminating the URL at the first `#`. SVG bodies now go through `encodeURIComponent`
Older versions

v0.8.4 2026-04-11

Plugin Fixes

  • Fixed clip thumbnails showing red question mark (binary HTTP response was being decoded as utf-8, corrupting PNG data). REST client now buffers chunks as Buffer and base64-encodes in getClipThumbnail
  • Fixed active-clip border detection — getClipConnected was treating Resolume's ParamChoice response object as a bare boolean, so every clip appeared "connected". Now parses `.value === 'Connected'` properly

Website

  • Changelog on /oi now auto-generates from CHANGELOG.md on every bump — no more stale entries
  • Bump script backfills changelog.html and rewrites hardcoded download href to the new version

v0.8.3 2026-04-11

Website

  • Dropped `arenam8-latest.zip` alias — recurring browser-cache problem where users kept downloading stale builds
  • main.js now rewrites the Download button href to `/downloads/arenam8-v<VERSION>.zip` by reading `/version.txt` (which is served with no-cache). Versioned URLs can be cached forever, each release gets a fresh URL
  • bump-version.sh also rewrites the hardcoded fallback href in download.html for no-JS users

v0.8.2 2026-04-11

Plugin Fixes

  • Fixed Test Connection always returning 404 — Resolume's REST API doesn't expose `/api/v1` as a resource, only sub-paths. Ping now hits `/api/v1/product` (lightweight version endpoint). Same fix applied to the runtime health poll and the `just check-resolume` helper

v0.8.1 2026-04-11

Plugin Rebrand

  • Renamed plugin from "Oi! (N4 ArenaM8)" to "ArenaM8" (was showing as "custom" in VSD Craft sidebar)
  • Category changed from "Resolume Arena" to "ArenaM8"
  • Added root-level UUID `uk.gamingworld.arenam8` (was missing)
  • Dedicated category-icon.png + plugin-icon.png generated from the mascot logo — side menu now shows the ArenaM8 character instead of reusing the trigger-clip svg
  • All action Icon/Image paths switched to extensionless (loader picks .png or .svg)
  • Plugin folder renamed `uk.gamingworld.arenam8.oi.sdPlugin` → `uk.gamingworld.arenam8.sdPlugin`

Critical Settings-Persistence Fix

  • Property Inspector never called `getSettings` on open, so stored per-instance settings never hydrated the UI — every PI open showed blank fields. Bridge now sends `getSettings` immediately after register (matches StreamDock SDK pattern) and also reads initial settings from `inActionInfo.payload.settings` as a fallback
  • `saveSettings` also fires `sendToPlugin` with a settings-sync payload so the plugin reflects changes without a reload
  • `routeEvent` in plugin.js synthesizes a `didReceiveSettings` event from the sync payload — all action handlers update automatically

Robust Argument Parsing

  • plugin.js argv parsing used fixed indices (`argv[3]`, `argv[5]`) — brittle, would silently die if VSD Craft changed launch order. Replaced with a flag parser (`-port`, `-pluginUUID`, `-registerEvent`) plus positional fallback, mirroring the e3 plugin's approach

Trigger Clip Improvements

  • Composition auto-fetches on PI open instead of waiting for a manual Test Connection click
  • Fixed selection restore: `applySelection` ran before `populate`, wiping the saved layer/clip. Now buffered in a `pending` variable and re-applied after composition arrives
  • New "Show clip name as button title" checkbox — plugin sets the button title from the live Resolume clip name after every thumbnail refresh. Rename a clip in Resolume → the button title updates on the next 30s cache tick

v0.8.0 2026-04-08

Website Overhaul

  • Replaced Bangers font with Orbitron (display) + Exo 2 (alt display)
  • Added Lucide SVG icon sprite, replaced all emojis with proper SVG icons
  • Glassmorphism cards with backdrop-filter, gradient overlays, corner ribbons
  • 9 scroll-triggered animations (added scale, rotate, blur, flip, bounce)
  • 3 title text animations (gradient sweep, glow pulse, letter breathe)
  • Custom scrollbar (dark blue track, cyan thumb)
  • Split CSS into 18 focused files from 7
  • Renamed all slang section titles to professional names
  • Built feedback modal (Bug Report, Feature Request, Mailing List, Support, General)
  • Replaced standalone subscribe section with unified modal
  • Fixed CORS on gamingworld.uk for subscribe API endpoint
  • Rewrote hardware and tech stack sections
  • Fixed contact section (first person, general GitHub profile)
  • Added background logo on splash page, removed "No middleware" tagline
  • Added tablet responsive breakpoint (768px)
  • Added hover/focus states to all interactive elements

Plugin Fixes

  • Fixed connection test (was using no-cors, always reported success)
  • Fixed composition cache memory leak (listeners never removed)
  • Fixed logger date zero-padding (log files now sort correctly)
  • Fixed encoder throttling (30ms debounce prevents OSC message flood)
  • Fixed touch crossfader min/max validation (prevents inverted values)
  • Fixed custom OSC address validation (must start with /)
  • Fixed parse bugs (zero values now handled correctly)
  • Fixed plugin shutdown cleanup (stops timers before exit)
  • Fixed encoder speed settings change (resets state on address change)
  • Fixed custom OSC test status (clears after timeout)
  • Synced package.json version, bump script now updates package.json too

Documentation

  • Complete rewrite of docs/quick-start.md with full architecture reference
  • Updated docs/web/design-system.md (Orbitron/Exo 2, Lucide icons)
  • Comprehensive TODO document at docs/482026-todo.md
  • Removed dead files (orphaned subscribe.html, unused Bangers fonts)

v0.7.0 2026-04-07

  • 10 total actions: Trigger Clip, Encoder Opacity, Encoder Speed, Trigger Column, Deck Select, Layer Bypass, Layer Solo, Layer Clear, Touch Crossfader, Custom OSC
  • Touch Bar crossfader: map touch position to any OSC float parameter
  • Encoder Speed: dial controls playback speed (0-2x), push resets to 1x
  • Custom OSC: user-defined address, type (int/float), and value for extensibility
  • Thumbnail auto-refresh: clips update on 30s cache cycle, green border on active clips
  • Clip connected state: queries REST API for active clip status
  • Auto-update notification: checks version.txt, shows banner in PI if outdated
  • Global settings: connection config (IP, ports, debug) shared across all actions
  • Composition cache: 30s auto-refresh, deduplicates REST calls
  • Debug toggle: verbose logging via PI checkbox
  • PI module split: connection UI, clip selector, and bridge as separate reusable modules
  • Update banner: yellow notification in any PI when new version available

v0.5.0 2026-04-07

  • 7 actions: Trigger Clip, Encoder Opacity, Trigger Column, Deck Select, Layer Bypass/Solo/Clear
  • Global settings infrastructure, PI module split, composition cache, debug toggle

v0.3.0 2026-04-07

  • Self-contained .sdPlugin packaging — users extract zip and drop folder into plugins dir
  • Stable download URL: /downloads/oi-latest.zip (always current version)
  • Bundled node_modules in zip — no npm install needed on target device
  • Plugin folder uses reverse-DNS naming: uk.gamingworld.arenam8.oi.sdPlugin
  • Fixed bump script to not corrupt Nodejs.Version in manifest
  • Website: scroll-triggered animations, image processing pipeline, section partials

v0.2.0 2026-04-07

  • Implement VSD Craft plugin with StreamDock SDK integration
  • Connection manager: health checks, auto-reconnect with exponential backoff
  • REST client: composition tree, clip thumbnails, clip connect
  • OSC client: clip trigger and float values via native UDP (no external deps)
  • Trigger Clip action: key press triggers clip, LCD shows live thumbnails
  • Property Inspector: connection settings, test button, layer/clip selectors
  • Main plugin entry: WebSocket registration, event routing, PI bridge
  • OSC binary encoder using native Node.js Buffers
  • File-based logger (replaces console.log per coding rules)
  • Plugin packaging includes node_modules for ws dependency

v0.1.0 2026-04-06

  • Initial project scaffolding
  • Landing page deployed to ArenaM8.GamingWorld.uk
  • CI/CD pipeline established (Justfile → GitHub → namek.top)
Exhausted mascot character by the changelog