# Troubleshooting

## Black Screen / No Video

{% hint style="danger" %}
**Symptom:** The stream connects but the video area is black or empty.
{% endhint %}

**Solutions:**

* Verify your `appId` is correct and the project is active in the Streampixel dashboard
* Ensure the UE application is running and connected
* Check that you're appending `appStream.rootElement` in the `onVideoInitialized` callback
* Inspect the DOM to confirm a `<video>` element exists and has a `srcObject`

## Audio Not Working

{% hint style="warning" %}
**Symptom:** Stream is playing but there's no sound.
{% endhint %}

**Solutions:**

* The SDK creates two media elements (video and audio). Both must be unmuted:

  ```javascript
  const video = appStream.stream.videoElementParent.querySelector('video');
  const audio = appStream.stream._webRtcController?.streamController?.audioElement;
  video.muted = false;
  audio.muted = false;
  if (audio.paused) audio.play().catch(() => {});
  ```
* Browser autoplay policy requires a user gesture before playing audio. Unmute in response to a button click
* Use `UIControl.toggleAudio()` as a shortcut

## Connection Fails Behind Firewall

{% hint style="danger" %}
**Symptom:** Connection stalls at "Establishing WebRTC connection..." or "Negotiating stream parameters..."
{% endhint %}

**Solutions:**

* Ensure `forceTurn: true` is set (this is the default). TURN relays bypass most firewalls
* Corporate firewalls may block WebSocket connections on non-standard ports. Check with your IT team
* Verify the browser allows WebRTC (some enterprise browsers disable it)

## Default Pixel Streaming UI Showing Through

{% hint style="warning" %}
**Symptom:** You see unfamiliar buttons, panels, or overlays from the default PS UI.
{% endhint %}

**Solutions:**

* Add CSS to hide the default UI:

  ```css
  #uiFeatures { display: none !important; }
  #afkOverlay { display: none !important; }
  ```
* Also hide programmatically after initialization:

  ```javascript
  const uiEl = appStream.rootElement?.querySelector('#uiFeatures');
  if (uiEl) uiEl.style.display = 'none';
  ```
* The `#uiFeatures` element may re-appear after `onVideoInitialized`, so hide it in that callback too

## Video Codec Shows Raw ID Instead of Name

{% hint style="info" %}
**Symptom:** Stats show something like `RTCCodec_1_Inbound_120` instead of `H264`.
{% endhint %}

**Solution:** Resolve the codec ID from the codecs Map:

```javascript
pixelStreaming.addEventListener('statsReceived', (e) => {
  const stats = e.data.aggregatedStats;
  const codecId = stats.inboundVideoStats.codecId;
  const codec = stats.codecs.get(codecId);
  console.log('Codec:', codec?.mimeType); // "video/H264"
});
```

## Webpack Polyfill Errors

{% hint style="info" %}
**Symptom:** Build errors like `Module not found: Error: Can't resolve 'crypto'` or similar.
{% endhint %}

**Solution:** The SDK requires Node.js polyfills for browser use. See the [Installation](https://docs.streampixel.io/resources/getting-started/installation) page for the complete `config-overrides.js` setup.

## "StreamPixelApplication called more than once"

{% hint style="warning" %}
**Symptom:** Console warning and SDK returns empty object `{}`.
{% endhint %}

**Solution:** `StreamPixelApplication` is a singleton -- it can only be initialized once per page. This commonly happens in React when:

* The component re-renders and calls `StreamPixelApplication` again
* `useEffect` dependencies change, triggering reinitialization

Fix: Use a ref or flag to ensure single initialization:

```javascript
const initialized = useRef(false);

useEffect(() => {
  if (initialized.current) return;
  initialized.current = true;

  StreamPixelApplication({ appId }).then(/* ... */);
}, [appId]);
```

## Reconnection Not Working

{% hint style="info" %}
**Symptom:** After a disconnect, the SDK doesn't attempt to reconnect.
{% endhint %}

**Solutions:**

* Automatic reconnection only triggers for WebSocket close codes **1005** and **1006** (abnormal closures). All other codes (project inactive, max runtime, etc.) are intentional disconnects
* The reconnection window is **60 seconds**. If the server doesn't respond within that time, reconnection fails with code 4007
* Listen to `reconnectStream.on('state', ...)` to see the exact state transitions and codes

## Mobile Disconnects When Switching Apps

{% hint style="info" %}
**Symptom:** On iOS/Android, the stream disconnects when the user switches to another app.
{% endhint %}

**Explanation:** This is intentional. The SDK disconnects after 60 seconds of the browser tab being hidden to free resources. When the user returns within 60 seconds, the stream continues normally. After 60 seconds, they will need to reconnect.

## Stream Works Locally but Not in Production

{% hint style="warning" %}
**Symptom:** Everything works on `localhost` but fails when deployed.
{% endhint %}

**Solutions:**

* The SDK validates `window.location.origin` against the project's allowed URLs list in the dashboard. Add your production domain to the `validPathUrl` setting
* `localhost` is always allowed for development
* Wildcard patterns are supported (e.g., `*.example.com`)
