The app's own guide to the overlay, published as it is. Source: ondographics-local/OBS-OVERLAY.md
Now-playing overlay for OBS
The app serves its own overlay. No third-party page, no token in a URL, no account, nothing to update when someone else's widget is discontinued.
http://127.0.0.1:9863/overlay
That address only works while the app is running, which is fine, because OBS only needs it while you are playing music.
Replacing the old widget
Your scene collection (Naamloos) has exactly one browser source pointing at http://nuttylmao.github.io/youtube-music-widget?token=…. It is named playing. To swap it:
- Start Ondographics and play something.
- In OBS, select the
playingsource in the Sources list and click Properties. - Replace the whole URL with
http://127.0.0.1:9863/overlay. - Leave Width 1920 / Height 1080 (or whatever you use) and keep Shutdown source when not visible unchecked.
- OK. The card should appear, bottom-centre, as soon as a track is playing.
That one field is the whole change. The old page only ever read state from localhost:9863, so nothing else in your scene needs touching.
Why the old source is already dead
The old widget is a static page that opens a socket.io connection to http://localhost:9863/api/v1/realtime, authenticating with the long token in its URL. That endpoint belonged to the old app, which cannot start on this machine (Smart App Control blocks its unsigned executable), and nothing else implements that protocol, so that source was showing nothing well before this change. Its token is worthless now and safe to discard; it was only ever sent to localhost, never to a third party.
To sanity-check before touching OBS, paste the URL into any browser and start a song, if the card shows there, it will show in OBS.
When it appears
The card fades in while music is playing and fades out when it pauses, exactly like the old widget did. Album art, title, artist, elapsed and remaining time, and a progress bar.
Cover art is requested at the largest size YouTube has, rather than whatever the player bar happened to be using for that track, so covers do not range from sharp to soft from one song to the next.
Two things it does that the old widget did not:
- One fixed card, always. The card is a fixed fraction of the source width, 70% by default, and each style has its own, with a height derived from the same number, and both come from the source rather than from the text. A three-word title and a sixty-word one occupy exactly the same rectangle, so nothing on your scene moves when the track changes. If that rectangle is not quite the shape of your scene, the width is one number you can change (see Sizing it).
- Long text scrolls instead of being cut off. If a title or artist is wider than its line, it slides right to left, forever, at a steady speed. Nothing is truncated with an ellipsis and nothing shrinks to fit.
Full-screen background visualisers
These are separate from the small now-playing card. In OBS add a Browser source, set its width/height to 1920×1080, and use tray → Visualiser → Copy URL for OBS. The default endpoint is http://127.0.0.1:9863/visualiser (/stage is an alias). The app's visualiser window loads this exact same served page. It is an ordinary movable, resizable window, and it does not stay above other windows by default; F11 toggles full screen inside it (Esc leaves full screen, and closes the window otherwise). H toggles track text.
Choosing a scene is a window of its own, tray → Visualiser → Choose a scene…, the Scenes button in the visualiser, or G, showing a live preview of every scene: the real served page, each running a sample track, so the tiles animate rather than sitting as still pictures. Tiles load and animate as they scroll into view, so the window costs about what the visible handful of scenes cost. Clicking applies without restarting the audio stream, and reaches the app's window and any OBS browser source on their own. App menu and tray organize scenes into the same three groups.
| Group | scene= → name |
|---|---|
| Energy | orbit → Halo, tunnel → Hyperspace, spectrum → Prism, grid → Horizon, nova → Nova, monolith → Monolith, laser → Laser, equalizer → Skyline |
| Calm | waves → Tidal, bloom → Lotus, aurora → Aurora, ocean → Ocean, rain → Rainfall, embers → Fireplace, constellation → Constellation, ribbons → Silk, terrain → Alpine, ink → Ink |
| Seasonal | christmas → Christmas, winter → Winter, spring → Spring, summer → Summer, autumn → Autumn, halloween → Halloween |
| Parameter | Effect |
|---|---|
scene=grid | Pin this source to a scene; without it, follow the app's selection |
palette=midnight | Midnight, Daylight, Mono, Sunset; seasonal artwork has its own colours except in Mono |
bg=transparent | Transparent over your own OBS art; also black and gradient |
intensity=1.4 | Visual reach, 0.4–2.5 (default 1); does not change the sound |
motion=low | Gentle travel and a 30 fps render cap; normal overrides OS reduced motion |
fps=1 | Cap the render rate without changing the motion, for a source that does not need the display's rate (the scene picker's wall of tiles uses 1; its one large preview runs uncapped) |
speed=1.5 | How fast the scene travels, 0.25–3 (default 1) |
glow=0.5 | Soft light, 0–2 (default 1); 0 draws none at all |
detail=low | How much is drawn: low (half), medium (three quarters) or high (default) |
backdrop=0 | Switch off the drifting lights behind the scene |
camera=0 | Switch off the drift on the whole frame |
webcam=1280x720 | Leave a 16:9 opening in the middle of the picture for your camera, or off to close it. Any WxH is accepted, and the size is kept exactly |
logoSize=20 | Logo height as a percentage of the short side, 4–40 (default 14) |
logoOpacity=0.5 | Logo opacity, 0.1–1 (default 0.85) |
logoCorner=top-left | Also top-right, bottom-left, bottom-right (the default) and middle; ignored when the app has a hand placement for that scene |
logoX=0.5 | Pin the mark's centre across the source, 0–1, in fractions of the width. Needs logoY as well, and overrides the app's placement |
logoY=0.32 | Pin the mark's centre down the source, 0–1, in fractions of the height |
logoDisc=1 | Draw the lit circle behind the mark: a wash, a ring, and a ring of ticks that vibrate with the music |
logoPulse=0 | Hold the logo still instead of letting it breathe with the music |
logoShape=circle | square (default) serves the file as it is; circle cuts the mark out and clears everything outside it |
logoZoom=2.4 | Crop in before shaping, 1–3 (default 1). This is what removes a ring drawn around a mark |
logoAnchor=sun | Bind the mark to a feature of the scene: sun, moon, star or core, where that scene has one. It is drawn into that feature rather than over the frame, and no lit circle is drawn with it |
logoRoam=1 | Walk the mark across the source as a screensaver, lighting the scene as it passes. It takes the place of the corner and the placement while it runs |
title=0 | Hide the track title |
bar=1 | Keep the scene name and status strip visible (omit in a live source) |
demo=1 | Clearly labelled generated sample only when the app is not playing |
token=… | Required if you configured a companion-server token; copied URLs include it |
Examples:
http://127.0.0.1:9863/visualiser?scene=christmas&title=0
http://127.0.0.1:9863/visualiser?scene=ocean&motion=low&bg=transparent&title=0
http://127.0.0.1:9863/visualiser?scene=grid&intensity=1.5&title=0
http://127.0.0.1:9863/visualiser?scene=liquid&bg=transparent&webcam=1280x720&title=0
No artificial beat clock runs under these scenes. Actual RMS controls overall energy, the spectral reading controls shape, and positive changes in the sound produce transient accents. Each band is read against its own slow-decaying peak, an automatic gain per band, so a quiet track still fills the frame and a loud one cannot clip it, with an empty band still reading zero. Travel is integrated from audio energy, so changing volume cannot jump the scene's phase. Calm scenes use slow atmospheric motion. With no audio a scene keeps a slow, beatless ambient drift, never a still frame, and never an invented beat. No strobing full-frame flashes.
Two layers are shared by every scene and do most of the work of making it move: a drifting backdrop that breathes with the low end, and a slow camera that drifts the whole frame with the music. Both stay translucent, so bg=transparent still composites cleanly over your own art, and each has a switch of its own.
Four dials shape everything above: intensity (how far the music pushes the scene), speed (how fast it travels), glow (how much soft light it puts out) and detail (how much is drawn at all, the one that trades the machine for richness). All four are live: they are applied in place, so moving one never reloads the page, restarts the audio reading, or disturbs a browser source mid-stream. Each also has a URL form above, so a source can pin its own value while still following the app's scene.
The logo
Visualiser → Choose a scene… → Logo puts your own image over every scene: the file, its corner, its size, its opacity, whether it breathes with the music, and how it is cut out. The app reads the file and serves it from its own address at /logo, which is why the page needs no file access and a browser source in OBS gets the mark from the same origin as the scene.
Square and Circle are what that mark is cut into. square serves the file exactly as it is, no re-encoding at all, so an animated GIF or an SVG keeps everything it had. circle clears every pixel outside the largest circle the crop leaves, which is what an image drawn on a card needs before it can sit over a scene: the paper, any border painted around it and any drop shadow all go. Crop (1–3×) closes in first, and it is the dial that actually removes a ring drawn around a mark, at 1 the circle only trims the corners of the picture, which is never enough to lose a sunburst.
The lit circle. A mark centred on the frame reads as deliberate only if something put it there; on a scene with no circle of its own it looks dropped on. The circle is the answer, and it belongs to the logo rather than to any scene, a dim wash, a ring, and a ring of 64 ticks that vibrate with the music, one band each, so it works in all forty scenes and in a browser source with a transparent fill. In a scene that already draws a circle of its own (Halo's radial spectrum, a lotus, a portal) the mark simply lands inside it. It is off by default, because it is the right look for a centred mark and too much for one tucked into a corner.
The placement is per scene, and can be dragged. The five corners are a fallback: a mark belongs in the sun of Summer and clear of the lotus in Lotus, and no list of five positions can say that. So the mark is dragged in the visualiser window and the place it is dropped is stored against the scene it was dropped in, which is why placing it in one scene leaves every other scene on its corner. Choosing a corner, or Put it back on the corner in the picker, puts one scene back. The position is the mark's centre as fractions of the frame, so it reads the same in the window and in a source of a different size, and a browser source may pin its own with logoX and logoY rather than following the app's.
A mark can be bound to the scene's own sun or moon, and then it is part of the picture rather than something laid over it. The scene reports where its feature is as it draws it, and the mark goes there: it drifts with the camera, it is covered by whatever the scene paints in front of it, and it has no lit circle, because a ring round a mark that is already inside the sun is exactly the second circle the binding exists to remove. Size follows the feature too, since a mark fixed at 20% of the frame cannot sit inside a sun 12% across, so a feature smaller than that keeps a legible floor under the size rather than taking the mark down with it. Fourteen scenes have one to offer: Summer's sun, Ocean's and Tidal's moon, Horizon's setting sun, Synthwave's and Mirage's retro sun, Alpine's sun, Winter's and Halloween's moon, Graveyard's and Ghosts' moon, Pulsar's neutron star, Plasma's electrode and the core of Galaxy. The picker shows the row only in those, because a mark bound to a feature that is not there is a mark that has gone. Binding one takes back a hand placement for the same scene, and placing one by hand takes back the binding.
The mark can also walk the frame. ?logoRoam=1 sends it travelling instead of holding a place, and the scene answers to the light it carries: the light goes through the environment layer every scene sits in, so a hollow follows it through the backdrop and the scenery of whichever scene is running. The music sets the speed, a quiet passage drifting and a loud one crossing the frame, and the path curves as it goes rather than running straight lines between the walls. The frame's own camera drift is left out while it runs, so the light always sits under the mark. It takes the place of the corner, the hand placement and the binding, all three of which are kept and come back when it is switched off.
The app's own picture of the crop is shown next to those controls, so the result is chosen by looking at it; the file on disk is never written to, and replacing it is picked up without restarting anything. The scene previews still do not draw the logo, it is placed over the whole frame rather than inside a tile, so open the visualiser window to see it in place, and drag it there to move it.
A shaped logo is re-encoded as a PNG, so an animated GIF is flattened and an SVG is rasterised; leave those at square and 1 to keep them as they are. PNG with transparency is what works best; GIF, WebP, JPEG, BMP and SVG are served too. A path that has been moved or deleted is treated as no logo rather than as an error.
A page process that dies is loaded again by the app, the visualiser and the scene picker have no menu bar and no reload shortcut, so a renderer that stopped used to be a blank window until the app was restarted. Crashes are counted over a rolling minute; after a handful the app stops trying and says so in logs/main.log, because a page that dies during every load must not become a reload loop.
Canvas backing stores are capped at 2.4 million pixels / 1.5 device-pixel ratio. Gentle mode renders at up to 30 fps. The scene picker's settings (intensity, fill, palette and motion) are saved across restarts; in a browser they update the URL.
The webcam opening
The visualiser can be built round your camera rather than behind your scene. With Visualiser → Choose a scene… → Webcam opening in the middle switched on, or ?webcam=1280x720 in a source's URL, the middle of the page is cleared to nothing at all and the scene is drawn in the band around it, with a lit rim between the two.
The opening is a real 16:9 hole rather than a black rectangle: the pixels are removed from the finished frame as the last thing it does, so what shows through is your camera, and nothing the page draws can put anything back into it. That is the whole point of the mode and the reason it is drawn last. Put the camera source under this one in your OBS scene, and the browser source over it:
- Add your camera (Video Capture Device) first, and size it to the middle of the canvas.
- Add this page as a Browser source above it, at 1920×1080 or whatever your canvas is, and use
?bg=transparent&webcam=1280x720&title=0. - The scene fills the band around the opening and the rim lights up on the beat.
The size asked for is the size you get: a 1280×720 request is a 1280×720 opening in the middle of a 1920×1080 source, and it is never stretched to fill a bigger window. It is only ever scaled down, when the source is too small to hold it plus the band the scene is drawn in, so the picture never becomes an empty frame with a camera in it.
The meter, the pet and the logo are placed in that band rather than behind the camera, and the meter is sized to it: a reading half cut away by the opening reads as a fault, so what is placed by a fraction of the frame is moved out of the opening it would have fallen in. In the visualiser's own window the opening shows the fill, because the window is opaque; in OBS, which is what this is for, it shows the camera.
Styles
Ten looks, all sharing the same behaviour: a fixed box, never resized by the track, and long text that scrolls instead of being cut off.
theme= | What it looks like |
|---|---|
card | The default: rounded panel with cover, title, artist and a progress bar. 70% wide. |
minimal | No panel and no cover. Just the title, the artist and elapsed / total above a thin accent line. For busy scenes, where a panel would be too heavy. |
vinyl | The cover as a record with a spindle, spinning while it plays and stopping when it pauses. |
ticker | One wide bar across the bottom: thumbnail, title, artist scrolling on a single line, elapsed / total, and the progress running along the bottom edge. |
neon | Dark box with an accent border and glow, condensed uppercase title. |
poster | An album tile: the cover large, with the title and artist underneath it. Good in a corner. |
capsule | One compact rounded pill, just title, artist and a hairline progress bar. No cover. |
split | No panel at all: the cover as a full-height slab, with the words beside it. Meant for people compositing this into their own graphic, the cover is cropped tall rather than square, and the words carry a shadow instead of sitting on a panel. |
backdrop | The cover itself becomes the panel: blurred, scaled, and washed so the words stay legible. The most photographic of the styles. |
ring | A circular cover with the progress drawn as a ring around it, so there is no progress bar to sit under it. |
Pick one from tray → Overlay → Choose a style…, which opens a window showing every style at once, each tile is this same overlay page running a sample track, not a drawing of it, so what you click is what you get. Clicking a tile applies it immediately.
Nothing in OBS has to change, and it happens live: the app bakes the style into the page it serves, and an overlay already open reloads itself into the new look within about a second, so you can leave the picker up next to OBS and click through them while you watch.
Colours
The style and the colour are two independent settings, so you can mix any of the seven styles above with any of these four palettes.
palette= | What it looks like |
|---|---|
midnight | The default: dark glass panel, white text, YouTube red accent. |
daylight | Light frosted panel with dark text, for bright scenes. |
mono | Dark panel with a white accent and no colour anywhere: black and white only. |
sunset | Warm dark panel with amber text and an orange accent. |
Pick a colour in the same picker, from the swatch row under the styles; it switches live the same way. A style never names a colour of its own, it names a palette variable, which is why every style gets every palette, and why the two lists stay independent. Swatches preview the style you have chosen, in each colour, so the row always shows the actual choice in front of you.
If you want one specific colour instead of a whole palette, ?accent= (below) still wins over the palette for the progress bar, the ticker's edge stripe and the neon border.
Preview with a sample track in that same menu opens the overlay with ?demo=1, which fills it with a sample track so you can see and position it without music playing. Its title is deliberately far too long, which also shows the scrolling at work.
Motion follows what you put on screen, not an ambient setting: ?motion=off is the way to hold a source still, and Windows' "reduced motion" preference is deliberately ignored here. An overlay is content you chose to display and are looking at, and Windows reports reduced motion for anyone who has merely turned off interface animations, silently freezing the scrolling title and the spinning record would look like a bug, not an accommodation.
Optional URL parameters
Add these after /overlay, separated by &:
| Parameter | What it does |
|---|---|
?alwaysShow=1 | Stay on screen while paused (useful for checking your layout) |
?hideAlbumArt=1 | Text only, no cover art |
?accent=%23ff0033 | Progress bar colour (%23 is #, URL-encoded) |
?align=left / ?align=right | Move the card to a corner instead of the bottom centre |
?pos=center / ?pos=top | Where the card sits vertically: bottom (the default), the middle, or the top |
?scale=1.5 | Grow the whole card; 0.75 shrinks it. Everything scales together |
?width=55 | How much of the source width the box takes, in percent (8–100). Replaces that style's own default, without scaling the text |
?theme=vinyl | Override the app's style for this one browser source |
?palette=daylight | Override the app's colour for this one browser source |
?vis=bars | Draw an audio visualiser inside the card: bars, mirror, peaks, blocks, wave, area, dots, ribbon, spikes, meter, blast, or off |
?motion=off | Hold still: no scrolling text, no spinning record |
?demo=1 | Show a sample track with an over-long title, to size and place the source |
Example: http://127.0.0.1:9863/overlay?hideAlbumArt=1&accent=%2300e5ff&align=left
Style and palette can be combined with anything else, for example http://127.0.0.1:9863/overlay?demo=1&theme=poster&palette=sunset.
?demo=1 is the one to use while setting up: it fills the card with a sample track (temporarily switching on alwaysShow) so you can see and move it without having to keep music playing.
The visualiser
?vis=bars, or any of the eleven other shapes, draws the music inside the card, under the words. It is a setting as well as a URL parameter, tray → Overlay → Choose a style… has a row for it, with live previews, and it is off by default.
| Style | What it draws |
|---|---|
bars | The spectrum, one bar per band, rising from the bottom |
mirror | The same spectrum reflected about the middle, so it grows both ways |
peaks | Bars with a cap that holds the loudest moment and falls back |
blocks | A segmented meter: each band is a column of lit cells |
wave | An oscilloscope, the waveform itself, with a soft glow under it |
area | The spectrum as a filled curve with a bright crest |
dots | A row of dots that rise and swell with the level |
ribbon | The waveform as a band: the wave and its mirror, filled between |
spikes | Ninety-six needles to the top of the card, with a crest line through their tips |
meter | One big level bar across the whole card, left to right, with a cap that holds the loudest recent moment |
blast | The spectrum filling the card, with the panel itself washing and flashing on a hit |
The last three take the whole card rather than a strip at the bottom of it, and they are the ones to use when the question is "can I see it when the song is loud": the same reading drawn at a scale where a band at 0.5 and a band at 0.95 are a hundred pixels apart instead of ten. spikes and the two waveform shapes are the most literal, a kick is a wall of needles in the same instant, and blast moves the card itself, which is the one thing you notice without looking at it.
There is deliberately nothing radial here. A ring or a fan is drawn from a fixed radius, and this canvas is a strip, a card's height is a fraction of its width, so an arc that fits the strip covers only the middle of it and an arc wide enough to span the strip is taller than the box. (Measured on a 977x41 canvas: a half-circle fan painted 0.2% of the strip, all of it within 60 px of the centre.)
It follows the music you hear, which is the same bus the mixer's meters read. Two things are worth knowing about how it is fed:
- The app only reads audio while an overlay asks for it. The page asks when it is actually drawing a visualiser, and the reading stops when the last browser source drawing one is closed. Nothing is read for a source with it switched off.
- Switching it on changes nothing about how the app sounds. It uses the same measured pass-through path the virtual mixer uses when it is switched off, the music still goes straight to your normal output at the same level, because there is only one tap available per media element and a second one is not possible.
- It is pushed, not polled. The page reads twenty frames a second and sends them; if the reading stops, the app restarted, the page reloaded, the last reading is held and bled off rather than freezing on screen, and the app notices the gap - a frame that has not arrived for a second and a half - and asks the page for a fresh one, logging how long the outage lasted once readings come back.
What is in a frame, and why it looks the way it does
Thirty-two bands across 30 Hz to 16 kHz, geometrically spaced so the low end gets the columns the eye looks at, each one the mean power of its bins rather than the loudest of them, a band holding one loud bin and nine quiet ones is quieter than one holding ten loud ones, and taking the maximum cannot see that. Plus ninety-six points of the waveform, plus the full-buffer RMS and unfiltered sample peak. Twenty frames a second, read from the same bus you are listening to. The 96-point display trace passes through a 700 Hz, four-pole low-pass before downsampling, then starts at a fractional rising zero crossing. This prevents upper frequencies folding into a false low-frequency scribble; it is a bass-focused trace, not a full-band oscilloscope. The spectrum, meters, and audible output are not filtered.
Two decisions in there are worth knowing, because both exist to stop the picture from looking like it has nothing to do with the music:
- The bands are drawn at a slope. A mix is not flat: measured on the live app against a loud master, the bass arrives around -23 dB and the top band around -71, about 5 dB of fall per octave. Drawn straight, that is a wedge, the left of the card pinned high, the right end on the floor, and neither end moving, because the bottom of a mix is as steady as the top of it is busy. Each band is lifted 4 dB per octave as the frequency rises, which is what an analyser's slope control does, and the whole width of the card reacts instead of its left edge.
- The wave is triggered. The analyser hands over a sliding window, so a trace drawn from the start of it begins at an arbitrary point of the waveform and slides sideways at a speed that has nothing to do with the sound, measured on a loud track, consecutive frames of the ninety-six points differed by 0.38 of full scale, which is exactly what "it moves at random" looks like. It now starts at the first rising zero crossing in the buffer, the way an oscilloscope does, so every frame begins at the same phase of the wave and the trace holds still and changes only when the sound does.
With ?demo=1 the visualiser draws a generated sample, so you can choose a style and size it before anything is playing. The sample is the same shape a real frame arrives in, thirty-two bands and a ninety-six-point wave, so what you pick against it is what the live one looks like. And whenever there is something playing, a ?demo=1 page reads it: the sample is what fills the gap, not what replaces the reading, so the previews in the style picker move with your music and only fall back to the sample while nothing is playing.
Where the bars sit is part of each style: across the bottom of a panel, above a ticker's progress line, to the right of a cover slab. ?motion=off does not hide them, a visualiser that held still would be a picture of nothing, it stops the smoothing, so the bars move only when the numbers change.
Sizing it
There are two things to size, and they are separate on purpose: how wide the box is and how big it is drawn.
The card is a fixed fraction of the width of the browser source, 70% by default, and each style names its own (a ticker bar is meant to cross the frame, a poster tile is not). So how big it looks on your canvas is decided by the source, in two parts:
- The source's own Width / Height in its Properties. OBS defaults a new browser source to 800×600, and if you never set these, that is what the page renders into.
- The source item's scale in the scene, which then stretches that result.
Both multiply, so a source left at 800×600 and scaled to 0.47 in the scene shows the page at about 373×280 on the canvas and the card at about 233×51.
If the box is the wrong shape for your scene, too wide, usually, when it has to sit inside a corner of a larger graphic, that is the width setting rather than the scale. Choose a style… has a slider for it, and ?width= does the same for a single source:
?width=55makes the box 55% of the source width instead of that style's own default. The text does not shrink with it; a narrower box means the title scrolls sooner, exactly as it would for a long title in the default width.- It is stored as "whatever the style says" until you move the slider, so changing style changes the shape rather than carrying the last width over.
If the box is the right shape but too small, the fix is to let the page render at a bigger size rather than to stretch a small one:
- Easiest: append
?scale=1.6to the URL. This grows the card inside the source. There is a ceiling, the card cannot be wider than its source, so if it stops growing, use one of the next two. - Better: open the source's Properties, set Width 1920 / Height 1080 (or whatever region you want the overlay to occupy), then set the scene item's scale so it fits. The card becomes 1344px wide and the text is rendered at full size instead of being stretched up from a small one, which is the difference between crisp text and slightly soft text.
- Either way, right-click the source → Transform → Fit to screen if you just want it centred and matching your canvas.
Controlling it
- Tray icon → Overlay (or Settings in the app menu):
- Copy URL for OBS puts the address on your clipboard.
- Open overlay in browser previews it.
- Serve the now-playing overlay turns the whole thing off, which closes port 9863.
- If you would rather the port not be served at all, untick that switch. Nothing else in the app depends on it.
If nothing shows
- It is hidden because playback is paused. That is deliberate. Add
?alwaysShow=1, or?demo=1, to check the layout while paused. - It is there but tiny. See Sizing it above, the card is a fraction of the browser source's width, and OBS starts a new source at 800×600.
- It behaves like an older version. OBS holds the page it loaded until the source is refreshed, so a change to the overlay cannot reach it on its own. Right-click the source → Refresh once. From then on the overlay notices by itself: the app reports a hash of the page it is serving, and the page reloads when that stops matching the copy it loaded with.
- Check the app is running.
http://127.0.0.1:9863/overlayonly exists while Ondographics is open. - Check the port. If the log says the overlay server could not start, port 9863 is taken by something else. Close that program, or change the port and use the new URL (nothing else is listening on 9863 by default any more). The log is Help → Open log file, or
%APPDATA%\Ondographics\logs\main.log. - OBS cached an old page. Right-click the browser source → Refresh.
What it does not do, on purpose
- It listens on 127.0.0.1 only, so nothing on your network can reach it.
- It sends no CORS headers, so a website you visit cannot read what you are playing. (The old app had a "CORS wildcard" setting that allowed exactly that.)
- It answers only GET, and it cannot control playback.
- It sends no data anywhere. The only outbound request is your browser fetching the album art from YouTube's image CDN, same as the old widget.
- If you want a token anyway, set
integrations.companionServerTokenin%APPDATA%\Ondographics\config.json. The state and event endpoints then answer401without it, so append?token=…to the overlay URL, the page forwards it for you. The overlay HTML itself is not gated, because it contains no data and cannot do anything until the event stream lets it in.
Cleaning up the old setup
- Replace the browser source URL (above), that removes the dependency on the discontinued widget.
- The old app's Desktop shortcut (
YouTube Music Desktop App.lnk) still points at the executable Windows refuses to launch. The new app has its own Start Menu and Desktop shortcuts.