Skip to main content
Stims toys can respond to multiple audio sources. The shared audio controls provide microphone access, demo audio fallback, and YouTube tab capture with clear permission guidance.

Audio sources

Toys that support audio offer three input modes:
SourceDescriptionPermission required
MicrophoneLive audio from your device microphoneYes (browser prompt)
Demo audioBuilt-in procedural audio trackNo
YouTube tab captureAudio from a YouTube video in a separate tabYes (tab audio permission)

Microphone setup

Microphone input delivers the most responsive experience for audio-reactive toys.
1

Click the microphone button

When a toy loads, click Start with microphone (or Retry microphone access if previously blocked).
2

Grant permission

Your browser will prompt for microphone access. Click Allow to continue.
If you see a timeout or “blocked” error, check your browser’s site permissions:
  • Chrome/Edge: Click the lock icon in the address bar → Site settingsMicrophone → Allow
  • Firefox: Click the shield icon → PermissionsMicrophone → Allow
  • Safari: Safari menuSettings for this websiteMicrophone → Allow
3

Audio starts

Once connected, you’ll see:
Microphone connected! Enjoy the visuals.
The toy now reacts to your microphone input in real time.

Microphone troubleshooting

If microphone access is blocked:
  1. Open your browser’s site permissions (see above)
  2. Set Microphone to Allow
  3. Refresh the page
  4. Click Retry microphone access
Alternatively, use demo audio to keep playing without microphone access.
If the microphone request times out (20 seconds):
// From microphone-flow.ts:163
const timeoutMs = 20000; // 20 seconds
  1. Close the permission prompt
  2. Re-open permissions in your browser settings
  3. Click Retry microphone access
If timeouts persist, use demo audio or YouTube tab capture instead.
If your browser cannot access the microphone:
This browser cannot capture microphone audio. Switch browsers or load the demo audio.
Fallback options:
  • Use demo audio (no permission needed)
  • Switch to Chrome, Edge, Firefox, or Safari
  • Use YouTube tab capture for shared audio playback

Demo audio

Demo audio provides instant playback without microphone permissions. It uses a procedural audio track generated by the app.
1

Click the demo button

Click Preview instantly with demo audio (or Use demo audio on the fallback row).
2

Audio starts

You’ll see:
Demo audio connected. Visuals will react to the procedural track.
The toy now reacts to the built-in audio. No browser permission is required.
Demo audio is the fastest way to start if you’re testing toys or your microphone is unavailable.

YouTube tab capture

YouTube tab capture lets you play a toy with audio from a YouTube video running in a separate tab.
1

Paste a YouTube URL

In the YouTube audio section, paste a full YouTube link:
https://youtube.com/watch?v=dQw4w9WgXcQ
Supported formats:
  • youtube.com/watch?v=...
  • youtu.be/...
  • youtube.com/embed/...
  • youtube.com/shorts/...
2

Load the video

Click Load. The YouTube player will embed in the control panel and start playing.
3

Capture tab audio

Click Use YouTube audio. Your browser will prompt you to select a tab to capture.Select the tab with the YouTube video, then click Share.
Tab audio capture requires Chrome 91+ or Edge 91+. Firefox and Safari do not support this API.
4

Audio starts

Once tab audio is captured:
Select tab to capture audio.
The toy now reacts to the YouTube video’s audio track.

Recent videos

The YouTube controller stores your 5 most recent video IDs in localStorage:
// From youtube-controller.ts:44-45
private static STORAGE_KEY = 'stims_recent_youtube';
private static MAX_RECENT = 5;
Recent videos appear below the URL input for quick re-loading.

Audio flow lifecycle

The microphone flow helper (microphone-flow.ts) manages permission requests, retries, and fallback guidance:
// From microphone-flow.ts:7
export type ToyAudioStartSource = 'microphone' | 'demo' | 'tab' | 'youtube';

Flow states

1

Requesting

Requesting microphone access...
The system waits for the user to grant or deny the permission prompt.
2

Success

Microphone connected! Enjoy the visuals.
Audio input is active and the toy is rendering.
3

Error

If access fails, the status updates with a reason and fallback options:
  • Denied: “Microphone access is blocked. Allow it in your browser or system privacy settings, then retry or load the demo audio.”
  • Timeout: “Microphone request timed out. Re-open permissions and click retry, or load the demo audio fallback.”
  • Unsupported: “This browser cannot capture microphone audio. Switch browsers or load the demo audio.”

Error recovery

When microphone access fails, the flow automatically:
  1. Updates the start button to Retry microphone access
  2. Shows the demo audio fallback button
  3. Displays a toast with recovery instructions:
Microphone was blocked or timed out. Re-open permissions in your browser bar,
then press Retry microphone or load the demo audio.
The toast dismisses after 7 seconds:
// From microphone-flow.ts:149-152
globalThis.setTimeout(() => {
  toastElement?.remove();
  toastElement = null;
}, 7000);

Frequency analysis

Once audio is active, the FrequencyAnalyser extracts multi-band energy for toys to react to:
// From audio-handler.ts:144-150
getMultiBandEnergy() {
  const data = this.getFrequencyData();
  // Bass (20-200Hz), Mid (200-2kHz), Treble (2k-20kHz)
  const bassEnd = Math.floor(len * 0.1);
  const midEnd = Math.floor(len * 0.3);
  // ...
}
Toys can read these energy bands to drive particle density, color intensity, or camera motion.

Next steps

Performance

Adjust quality presets and pixel ratio for smooth playback

Accessibility

Configure motion comfort and reduced-motion modes

Build docs developers (and LLMs) love