A Windows application that bridges media playback information from Windows Media Session to WebSocket clients. Designed for integration with Resonite VR and other applications.
- Real-time media info (title, artist, album, cover art, playback state)
- Synchronized lyrics from multiple sources (LRCLib, NetEase, local database)
- Word-by-word sync mode for karaoke-style display
- Public album cover art URLs (iTunes/Deezer APIs)
- Optional Discord status integration
- Dual WebSocket architecture for flexible integration
Tip
Want a nice lyrics UI? Download OBS Templates.zip from the latest release and open full.html in any web browser. You get a full Apple Music-style lyrics viewer with album art, scrolling lyrics, and word sync — no extra software needed.
| Port | Protocol | Purpose |
|---|---|---|
| 8080 | WebSocket | Media info + lyrics |
| 6555 | WebSocket | Lyrics only (dedicated) |
Configuration is stored in config.json:
{
"port": 8080,
"lyrics_port": 6555,
"ignorePlayers": [],
"offset_ms": 0,
"cache_folder": "cache",
"filter_cjk_lyrics": true,
"offline_mode": false,
"lrclib_database_path": "db.sqlite3",
"plain_lyrics_fallback": false,
"discord_token": "",
"discord_emoji": "🎶",
"discord_show_prefix": true
}| Option | Description |
|---|---|
port |
Main WebSocket port for media info |
lyrics_port |
Dedicated lyrics WebSocket port |
ignorePlayers |
Array of player names to ignore |
offset_ms |
Global lyrics timing offset in milliseconds |
cache_folder |
Folder for cached lyrics files |
filter_cjk_lyrics |
Skip lyrics that are mostly CJK characters |
offline_mode |
Only use local sources, no API calls |
lrclib_database_path |
Path to LRCLib SQLite database for offline use |
plain_lyrics_fallback |
Use plain (unsynced) lyrics if no synced available |
discord_token |
Discord user token for status sync (leave empty to disable) |
discord_emoji |
Emoji shown in Discord status |
discord_show_prefix |
Add prefix to Discord status text |
All messages use a simple key:value format. Each message is sent separately (not combined).
| Message | Description | Example |
|---|---|---|
title:<text> |
Song title | title:Never Gonna Give You Up |
artist:<text> |
Artist name | artist:Rick Astley |
album:<text> |
Album name | album:Whenever You Need Somebody |
dur:<ms> |
Duration in milliseconds | dur:213000 |
source:<name> |
Media player source | source:Spotify |
cover:<url> |
Album cover URL (public) | cover:https://is1-ssl.mzstatic.com/... |
| Message | Description | Example |
|---|---|---|
status:<bool> |
Playing (true) or paused (false) | status:true |
shuffle:<bool> |
Shuffle enabled | shuffle:false |
repeat:<mode> |
Repeat mode (none/track/list) | repeat:none |
pos:<ms> |
Current position in ms (every 1 second) | pos:45000 |
| Message | Description | Example |
|---|---|---|
lyric:<text> |
Current lyric line | lyric:Never gonna give you up |
prog:<0-1> |
Song progress (every 1 second) | prog:0.472 |
lyricsrc:<source> |
Lyrics source | lyricsrc:lrclib |
wordsync:<bool> |
Word sync mode enabled | wordsync:false |
offset:<ms> |
Current offset in ms | offset:-50 |
| Command | Short | Description |
|---|---|---|
play |
Resume playback | |
pause |
Pause playback | |
next |
Skip to next track | |
prev |
Previous track | |
previous |
Previous track | |
stop |
Stop playback |
| Command | Short | Description |
|---|---|---|
toggle:wordsync |
w |
Toggle word-by-word sync mode |
toggle:offline |
o |
Toggle offline mode |
toggle:cjk |
c |
Toggle CJK lyrics filter |
toggle:plain |
p |
Toggle plain lyrics fallback |
nextlyrics |
n |
Cycle to next lyrics source |
refresh |
r |
Re-fetch lyrics for current song |
clearcache |
x |
Clear cache for current song |
| Command | Short | Description |
|---|---|---|
offset:+50 |
+ |
Increase offset by 50ms |
offset:-50 |
- |
Decrease offset by 50ms |
offset:+500 |
Increase offset by 500ms | |
offset:-500 |
Decrease offset by 500ms | |
offset:save |
s |
Save current offset to config |
| Command | Short | Description |
|---|---|---|
getstatus |
? |
Resend all current state |
status |
? |
Resend all current state |
getfulllyrics |
Get full lyrics text (newline separated) | |
help |
h |
List available commands |
Dedicated connection for lyrics display. Receives high-frequency lyric updates.
| Message | Description | Example |
|---|---|---|
lyric:<text> |
Current lyric line | lyric:Never gonna let you down |
prog:<0-1> |
Song progress | prog:0.523 |
wordsync:<bool> |
Word sync mode | wordsync:true |
lyricsrc:<source> |
Lyrics source | lyricsrc:lrclib |
offset:<ms> |
Current offset | offset:0 |
| Command | Short | Description |
|---|---|---|
wordsync:on |
Enable word sync mode | |
wordsync:off |
Disable word sync mode | |
toggle:wordsync |
w |
Toggle word sync mode |
toggle:offline |
o |
Toggle offline mode |
toggle:cjk |
c |
Toggle CJK filter |
toggle:plain |
p |
Toggle plain lyrics fallback |
next |
n |
Cycle to next lyrics source |
refresh |
r |
Re-fetch lyrics |
clearcache |
x |
Clear cache for current song |
offset:+50 |
+ |
Increase offset by 50ms |
offset:-50 |
- |
Decrease offset by 50ms |
offset:+500 |
Increase offset by 500ms | |
offset:-500 |
Decrease offset by 500ms | |
offset:save |
s |
Save offset to config |
status |
? |
Resend current lyrics state |
getfulllyrics |
Get full lyrics text | |
help |
h |
List commands |
| Key | Description |
|---|---|
Q / Esc |
Quit application |
H |
Toggle help display |
W |
Toggle word sync mode |
O |
Toggle offline mode |
C |
Toggle CJK filter |
P |
Toggle plain lyrics fallback |
N |
Cycle to next lyrics source |
R |
Re-fetch lyrics |
X |
Clear cache for current song |
+ |
Increase offset by 50ms |
- |
Decrease offset by 50ms |
Shift++ |
Increase offset by 500ms |
Shift+- |
Decrease offset by 500ms |
S |
Save offset to config |
Lyrics are fetched in this priority order:
- Cache - Previously fetched and cached lyrics
- Local Database - SQLite database (for offline use)
- LRCLib - Online synced lyrics database
- NetEase - Chinese music service (fallback)
| Source | Description |
|---|---|
cache |
Loaded from cache |
localdb |
From local SQLite database |
lrclib |
From LRCLib API |
netease |
From NetEase API |
lrclib (plain) |
Plain lyrics with estimated timing |
None |
No lyrics found |
Album covers are fetched from public APIs (no API key required):
- iTunes Search API - Primary source
- Deezer API - Fallback
If no cover is found, a default image is used.
Optional feature to show current lyrics in Discord custom status.
- Get your Discord token:
- Open Discord in browser (discord.com/app)
- Press F12 → Network tab
- Refresh page, filter by "api"
- Find "authorization" header in any request
- Add token to
config.json:{ "discord_token": "your_token_here" }
- Updates status with current lyric line
- Clears status when no lyrics or playback stopped
- Rate limited to 1 update per second
- Status auto-expires after 5 minutes
- Strips color tags from word sync mode
Messages use key:value format. In ProtoFlux:
- Use
String Containsto check for prefix (e.g., "title:") - Use
String Replaceto remove prefix and get value - Or use
String Splitwith ":" delimiter
Connect to ws://localhost:8080
↓
Receive initial state:
title:Song Name
artist:Artist
status:true
...
↓
Receive updates:
lyric:Current line
prog:0.523
pos:112000
full.html showing the Apple Music-style immersive view with album art, scrolling full-song lyrics, and blurred background. Alongside it, the OMB console showing live lyric sync.
Browser-source overlays for OBS Studio included in the OBS Templates folder (also available as a zip in each release).
Tip
Want a lyrics UI without OBS?
full.html works as a standalone lyrics viewer — just open it in any web browser while OpenMediaBridge is running. You get the full Apple Music-style experience with album art, scrolling lyrics, word sync, and progress bar, no streaming software needed.
| File | Description | Size |
|---|---|---|
mini.html |
Compact corner widget — art, title, artist, current lyric, progress bar | 420 × 110 px |
full.html |
Apple Music-style immersive view — art on left, full song lyrics on right, blurred art background | 1920 × 1080 px |
transparent.html |
Same as full but transparent background, anchored to top for OBS cropping | 1920 × 1080 px |
lyrics-only.html |
Scrolling lyrics only, transparent background, progress bar at bottom | 1920 × 1080 px |
- Add a Browser Source to your scene
- Check Local file and browse to the
.htmlfile - Set the width/height as listed above
- Check Shutdown source when not visible (optional, saves resources)
- Make sure OpenMediaBridge is running on the same machine
If you changed the ports in config.json, update WS_MEDIA_URL and WS_LYRICS_URL at the top of the <script> block in each file.
The panel is 260px tall. To hide the empty canvas below it:
- Right-click the source → Filters
- Add Crop/Pad
- Set Bottom to
820(for 1080p)
All overlays support word-by-word highlighting. The current word highlights in amber within the active line. Toggle with the w key or toggle:wordsync command.
CSS variables at the top of each file's <style> block:
| Variable | Description |
|---|---|
--active-opacity |
Opacity of the current lyric line |
--idle-opacity |
Opacity of surrounding lines |
--sung-opacity |
Opacity of past lines |
--ts |
Transition speed |
--panel-height |
Panel height (transparent.html only) |
--art-size |
Album art size (transparent.html only) |
Requires .NET 8.0 SDK with Windows 10 SDK.
dotnet build
dotnet run