Integrations
Browser constraints
WebSocket server and feedback nodes Supported; Chrome extension Beta. Named web platforms are examples only, not confirmed integrations.
This page lists what browser neurofeedback can and cannot do today, independent of the EEG device. Any device or signal that reaches the classifier can drive the browser, so everything here applies to every device. For how the pieces fit together see Browser neurofeedback. For a test you can run without hardware see Browser test workflow. Device-specific constraints live with the device: for BrainBit see BrainBit constraints, and for other hardware see Devices and BrainFlow boards.
Safety: Feedback can change screen brightness and volume quickly. Avoid this setup if you are sensitive to flashing or flickering light. Keep volume moderate. Stop if you feel uncomfortable. To stop feedback, end the session with the stop button in the Session Control window (tooltip “End the Session”), or click Disconnect in the Chrome extension popup.
The labels on this page mean:
- Supported: implemented in the code and intended for use.
- Beta: implemented and available, with documentation and validation still in progress.
- R&D: designed or explored, not implemented end to end.
- Not available: no build of the extension exists for this browser.
Browser compatibility
Section titled “Browser compatibility”| Browser | Status | Notes |
|---|---|---|
| Google Chrome (Manifest V3) | Beta | The only target the extension is written for. |
| Other Chromium browsers (Edge, Brave) | R&D | Not a target of the extension today. |
| Firefox | Not available | No build or test exists for this browser. |
| Safari | Not available | No build or test exists for this browser. |
The browser and neuromore Studio are meant to run on the same machine, because the extension connects to a fixed local address (see below).
Extension limitations
Section titled “Extension limitations”The extension is described in the Chrome extension guide. These are the limits that matter when you plan a test:
- Manual installation. You install the extension with “Load unpacked” in Chrome’s developer mode. The extension is not in the Chrome Web Store.
- Hard-coded local address. The extension always connects to
ws://127.0.0.1:4547. There is no settings screen. If you change the WebSocket port in Studio, the extension can no longer connect until you edit theWS_URIline inextension/src/js/websocket.jsand reload the extension onchrome://extensions. - One tab per Connect. Clicking Connect injects the connection script into the active tab of the current window only. Other tabs are not affected unless you connect them too.
- Pages Chrome does not allow. Chrome refuses to inject the script into some pages, such as
chrome://pages and the Chrome Web Store. The popup then shows “Cannot connect on this page. Open a normal website, reopen the extension, then click Connect.” - No reconnect. A full page load drops the connection, and so does restarting Studio. The extension does not retry, so you click Connect again. In-page navigation on single-page sites does not load a new page, so the connection should stay open.
- Repeated Connect. The popup disables Connect and shows “Connected” while the tab is connected. A click on Connect before the connection opens reuses the attempt in progress, so a tab has only one connection.
- Several tabs at once. Studio sends every message to every connected client, so all connected tabs receive the same values.
- Pause does not stop feedback. A paused session still counts as running, so frames keep arriving and the page can keep changing. To stop the changes, end the session or click Disconnect.
- Restoring the page. The extension saves each media element’s volume and the target element’s inline filter before it changes them. It puts them back when the session stops, when the connection closes, and when you click Disconnect. While feedback runs, it sets the volume again on every frame, so a site’s own volume control has no lasting effect.
- Player events. The extension listens for play, pause and ended events at document level. This covers
<video>and<audio>elements added after Connect, and it leaves the site’s own handlers alone. Elements inside iframes or shadow DOM are not covered. - Player commands. Studio’s Stop Browser Player action is not implemented in the extension. Start Browser Player and Pause Browser Player are, and they act on the first
<video>in the page only. If there is no video, nothing happens. Start Browser Player treats its “Progress (s)” attribute as a fraction of the media’s length, 0 to 1, despite the label. Its default of 1.0 seeks to the end, so set a lower value in the action.
Site behaviour
Section titled “Site behaviour”YouTube, Netflix, Spotify, Prime Video and Apple Music appear in the extension popup as links only, not confirmed integrations. The extension is written for plain <video> and <audio> elements.
| Case | Behaviour | Status |
|---|---|---|
Plain <video> and <audio> elements |
Volume sets the volume property of every audio and video element in the top-level document on every frame. |
Beta |
| Volume outside 0 to 1 | The extension limits the value to 0 to 1 and ignores values that are not finite numbers. Studio still reports the error, so clamp in the classifier (see Feedback value range). | Beta |
| Value of 0 | The content under the brightness filter turns black and media is silent. The filter sits on <body>, or on YouTube on the video container, and a background painted on the page’s canvas can stay bright. A negative value does the same as 0. A connected node whose source has delivered no samples also sends 0, so a silent source, such as an OSC Input with no sender, can black out that content and mute media, and look like a failure. Start your source first. Set Output Min above 0 on a Remap node to keep a floor while the signal is running. |
Beta |
| Brightness on most pages | A CSS filter: brightness() on <body>, not opacity. Only the filter property changes, so other inline styles stay. The extension limits the value to 1, so feedback can dim the page but not brighten it above normal. |
Beta |
| Brightness on YouTube | On youtube.com and its subdomains, the filter targets the first element with class html5-. If that element is missing, the filter goes on <body>, so the whole page dims. Whether a given YouTube page has that element depends on YouTube’s markup. |
Beta |
| Rapid brightness or volume changes | Each value is applied as it arrives, about 10 times per second, with no smoothing or rate limit in the extension. The content under the filter can go from black to normal between frames. Smooth the signal, and avoid on/off thresholds on brightness. | Beta |
| Local network access, site security policies | Chrome can block the connection to Studio. See Local network access. | R&D |
| Web Audio API players | May ignore the volume property. |
R&D |
| DRM-protected or custom players | May ignore volume or render outside the filtered element. | R&D |
| Players inside iframes or shadow DOM | The extension searches the top-level document only, so volume, player events and player commands do not reach these media elements. A brightness filter on <body> should still cover iframe content. |
Beta |
| Site fullscreen modes | Native fullscreen video may not show the effect. | R&D |
Local network access
Section titled “Local network access”The connection to ws://127.0.0.1:4547 is opened from the script injected into the page, so Chrome treats it as a connection made by that site. If the connection fails, the popup shows “Could not connect. Check that neuromore Studio is running on port 4547, and that this site is allowed to access your local network.”
- Pages from a public HTTPS address: Chrome blocks the connection unless the site has the local network access permission (Local Network Access). If Chrome prompts you, allow it, then reopen the popup if it closed. If the button shows “Connected”, you don’t need to do anything. If it shows “Connect”, click it. If Chrome does not prompt you, open the site’s settings from the icon to the left of the address bar, allow Local network access, reload the page, then click Connect again.
- Public
http://pages: Chrome only lets secure pages request this permission, so use an HTTPS page instead. - Pages served from a local address, such as
127.0.0.1: these are outside this check.
A site’s security policy can also block the connection.
Signal and protocol constraints
Section titled “Signal and protocol constraints”| Item | Constraint | Status |
|---|---|---|
| Feedback value range | Volume Control and Brightness Control expect 0.0 to 1.0. Studio does not clamp. Out-of-range input shows “Value not in range” on the node and the raw value is still sent. Use Remap with “Clamp Output” switched on in front of the feedback nodes. | Supported |
| Channels | The extension reads the first value of each frame only. Studio repeats the channel 0 value in every slot of a frame. | Supported |
| Update rate | One binary frame per feedback node every 100 ms (about 10 Hz) while a session runs, regardless of the node’s Resolution setting or the classifier’s sample rate. | Supported |
| Node matching | The extension acts only on nodes named exactly “Volume Control” or “Brightness Control”, the default names from the Output category. Matching is by node name and case sensitive, so renaming a node breaks the match. Output Name and Custom Name change the name of the output channel. They do not affect matching. | Supported |
| Other feedback nodes | Custom Feedback nodes and the other control nodes are also sent over the WebSocket, but the extension ignores them unless their name matches one of the two names above. | Supported |
| Volume Control Mode | The Mode attribute defaults to “Studio Volume”, which also sets Studio’s own volume. The WebSocket value is sent whatever the Mode. | Supported |
| WebSocket transport | Plain ws:// on TCP 4547 by default. See the caution below this table. |
Supported |
| WebSocket port setting | NMStudio > Settings > Network > Websocket Server > Listen TCP Port. A new port takes effect after restarting Studio. If the port is already in use, the server does not start and Studio shows no message. | Supported |
| neuromore Studio version | 1.7.0 or newer, per the extension README. These docs describe Studio 1.8.2, and the latest public download is 1.7.3. This page was written from the 1.8.2 and 1.7.3 source only; earlier versions were not read. The WebSocket protocol and the extension’s behaviour are the same in both. See What changed since 1.7.3. | Supported |
| Session start | Begin Session needs a loaded classifier and permission to run it. Any error in the classifier or state machine also disables it, unless your account type skips this check. That includes a missing device: a classifier that reads from a device which is not connected shows “Device not connected”. A classifier driven only by OSC Input has no device to miss. If the design parameters cannot be loaded, the start fails with “Session start failed”. See Running a session. | Supported |
| Range error before a session | The classifier also updates outside sessions, so an out-of-range input while idle sets the “Value not in range” error, and that graph error disables Begin Session in the same way. The error clears on the next in-range sample or with NMStudio > Reset Engine. Clamp before you start. A running session is not stopped by this error and keeps sending the raw value. | Supported |
| During a session | A device that disappears stops the session, with the message “The session was stopped automatically because a device disappeared.” | Supported |
| OSC input | UDP 4545 by default; NMStudio > Settings > Network > OSC Server > Input UDP port. Send one float per message per address (several floats in one message become consecutive samples). Studio does not resample these values, so send at a steady rate and set the OSC Input node’s Sample rate (default 128) to the actual rate. Any OSC source can drive the browser path this way. See OSC Tutorial. | Supported |
| OSC output | UDP 4546 to 127.0.0.1 by default, one float per message. Resolution Low = 4, Mid = 10, High = 30 messages per second; Original = input rate. OSC output is a separate path, and the browser does not use it. | Supported |
In 1.7.3: Output Name has only Use Node Name and Use Channel Name. There is no Custom Name. Matching by node name is the same.
Caution: The WebSocket interface is an unauthenticated local protocol. Keep its port (4547 by default) firewalled and don’t expose it to untrusted networks.
Known limitations
Section titled “Known limitations”- Manual extension installation and a hard-coded local address (Beta).
- Name-based node matching instead of node type (Supported, fragile).
- No reconnect, and one tab per Connect (Beta).
- Pausing a session does not pause the page (Beta).
- Only plain media elements in the top-level document are covered; see Site behaviour.
What would change this
Section titled “What would change this”These are possible changes, not commitments.
| Limitation | Possible work | Status of the work |
|---|---|---|
| Manual installation | A Chrome Web Store release of the extension. | R&D |
| Reconnect, multi-tab, hard-coded address, name matching | Extension changes: automatic reconnect, a configurable address and port, matching by node type. | R&D |
| Streaming sites and custom players | Site-by-site tests and, where needed, site-specific handling in the extension. | R&D |