# Connection Lifecycle

## Event Sequence

When a stream connects successfully, events fire in this order:

1. **`webRtcAutoConnect`** -- Auto-connect initiated (only if `AutoConnect: true`)
2. **`webRtcConnecting`** -- WebRTC peer connection is being established
3. **`webRtcSdp`** -- SDP offer/answer exchanged between browser and UE
4. **`webRtcConnected`** -- Peer connection established, media channels open
5. **`streamLoading`** -- Video data arriving from UE
6. **`playStream`** -- Video is about to start playback
7. **`videoInitialized`** -- Video element is ready (via `appStream.onVideoInitialized`)

## Listening for Events

{% hint style="info" %}
`videoInitialized` is handled via a callback (`appStream.onVideoInitialized`), not through `addEventListener` like the other events. This is because it fires from the application wrapper, not from the `pixelStreaming` instance.
{% endhint %}

```javascript
pixelStreaming.addEventListener('webRtcConnecting', () => {
  console.log('Establishing connection...');
});

pixelStreaming.addEventListener('webRtcConnected', () => {
  console.log('Connected!');
});

pixelStreaming.addEventListener('playStream', () => {
  console.log('Stream is playing');
});

// videoInitialized is handled via callback, not addEventListener
appStream.onVideoInitialized = () => {
  document.getElementById('container').appendChild(appStream.rootElement);
};
```

## Building a Loading Screen

Map each event to a progress percentage for a smooth loading experience:

{% code lineNumbers="true" %}

```javascript
const PROGRESS_MAP = {
  webRtcAutoConnect: 15,
  webRtcConnecting: 30,
  webRtcSdp: 50,
  webRtcConnected: 70,
  streamLoading: 80,
  playStream: 90,
};

Object.entries(PROGRESS_MAP).forEach(([event, progress]) => {
  pixelStreaming.addEventListener(event, () => {
    updateProgressBar(progress);
  });
});

appStream.onVideoInitialized = () => {
  updateProgressBar(100);
  hideLoadingScreen();
  document.getElementById('container').appendChild(appStream.rootElement);
};
```

{% endcode %}

## Failure Events

### `webRtcFailed`

Fires when the WebRTC connection fails to establish.

```javascript
pixelStreaming.addEventListener('webRtcFailed', () => {
  showError('Connection failed. Please try again.');
});
```

### `webRtcDisconnected`

Fires when an established connection drops.

```javascript
pixelStreaming.addEventListener('webRtcDisconnected', () => {
  showError('Connection lost.');
});
```

> **Note:** When automatic reconnection is active, `webRtcDisconnected` may fire during the reconnection process. Check `reconnectStream` state to differentiate between a temporary disconnect (reconnecting) and a permanent one. See [Reconnection](https://docs.streampixel.io/resources/getting-started/features/reconnection).

## Manual Connection Control

{% hint style="success" %}
Use `AutoConnect: true` for the simplest setup -- the stream connects immediately on initialization. Use `AutoConnect: false` (the default) when you want to show a "Play" button or loading screen before connecting, giving you full control over when the connection starts.
{% endhint %}

If `AutoConnect` is `false`, connect manually:

```javascript
const { pixelStreaming } = await StreamPixelApplication({
  appId: 'your-project-id',
  AutoConnect: false,
});

// Connect when the user clicks a button
document.getElementById('play-btn').addEventListener('click', () => {
  pixelStreaming.connect();
});

// Disconnect
pixelStreaming.disconnect();

// Reconnect after disconnect
pixelStreaming.reconnect();
```

## Mobile Background Handling

{% hint style="warning" %}
On iOS and Android, the SDK automatically disconnects the stream if the browser tab is hidden (user switches apps) for more than 60 seconds. This prevents idle resource consumption on mobile devices. When the user returns within 60 seconds, the stream continues normally.
{% endhint %}
