# WebRTC Camera Example

## Introduction

`resources/examples/02-Media/webrtc_camera.py` sends the Sensor output to VENC, then pushes it to the browser via `webrtc.PeerConnection`. The example includes a lightweight HTTP signaling service and a web page; when the development board and the browser are on the same network, open the address in the browser and click **Connect** to view the video.

The default configuration is H.265, `1280 x 720`, `512 Kbit/s`, no audio. This configuration prioritizes control over encoding, memory, and Wi-Fi load; H.264 can be used for browsers where compatibility is the priority.

## File Location

```text
resources/examples/02-Media/webrtc_camera.py
```

The firmware needs to enable `CONFIG_ENABLE_MODULE_WEBRTC`. This option is enabled by default and automatically depends on libpeer.

## Configuration Items

Modify the following constants at the beginning of the script:

| Configuration Item | Description | Default Value |
| :-- | :-- | :-- |
| `NETWORK_MODE` | `"lan"`, `"wifi_sta"`, or `"wifi_ap"` | `"lan"` |
| `WIFI_SSID` / `WIFI_PASSWORD` | Credentials used by Wi-Fi STA/AP | Example values |
| `HTTP_PORT` | Web page and HTTP signaling port | `8080` |
| `WIDTH` / `HEIGHT` | Video encoding resolution | `1280` / `720` |
| `VIDEO_CODEC` | `"h265"` or `"h264"` | `"h265"` |
| `BIT_RATE` | VENC target bitrate, in Kbit/s | `512` |
| `AUDIO_CODEC` | WebRTC audio encoding type | `webrtc.CODEC_NONE` |

The example sets default devices for the selected network mode: `u0` for LAN, `w0` for Wi-Fi STA, and `w1` for Wi-Fi AP. If the firmware does not have the corresponding device, the script will report an error at startup.

## How to Run

1. Modify `NETWORK_MODE` and Wi-Fi credentials according to the network environment.
1. Run the script in CanMV IDE, or place the script on the development board and run it.
1. The serial port will output information similar to:

```text
WebRTC camera: http://192.168.1.108:8080 (H265, 512 Kbit/s, audio disabled)
```

1. Open this address in a browser on the same interoperable network and click **Connect**.

The web page displays SDP negotiation, browser candidate collection, ICE/DTLS connection, and first frame waiting status in sequence. The overlay tip only disappears when the video actually starts playing; the page will not mistakenly report that playback has started just because a video track has been received.

## Encoding and First Frame Behavior

The script continuously caches the `STREAM_TYPE_HEADER` parameter sets output by VENC. When each I frame arrives, it first sends the cached H.264 SPS/PPS or H.265 VPS/SPS/PPS, then sends the I frame.

When WebRTC enters the `COMPLETED` state, the script calls `Encoder.RequestIDR()` to request an immediate keyframe. Therefore, after the connection is complete, there is no need to wait for a full GOP cycle before there is a chance to decode the first frame. The VENC acquisition timeout is 100 ms, so the main loop can promptly detect connection state changes.

## Performance and Compatibility Suggestions

- `512 Kbit/s` is the low-load default value. When image detail is insufficient, first try `768` or `1024` Kbit/s, and observe CPU, encoding, and network stability.
- When the network is weak, prioritize lowering `WIDTH`/`HEIGHT`, for example using `800 x 480`; only lowering the bitrate may cause excessive compression artifacts.
- H.265 has higher bandwidth efficiency, but some browsers or systems do not support H.265 WebRTC decoding. When there is no image, change to:

```python
VIDEO_CODEC = "h264"
```

- Audio is disabled by default. Enabling audio also requires you to create your own audio capture/encoding pipeline and call `peer.send_audio()`; merely modifying `AUDIO_CODEC` will not automatically generate audio.

## FAQ

| Symptom | Cause and Handling |
| :-- | :-- |
| `RuntimeError: libpeer initialization failed` | The firmware has not enabled WebRTC/libpeer, or there is an unclosed WebRTC object. Update the firmware and ensure the previous script has exited. |
| `not find network interface device` | `NETWORK_MODE` does not match the actual network device. Confirm that `u0`, `w0`, or `w1` exists in `network.get_dev_list()`. |
| Page stays at Connecting for a long time | Confirm that the browser and the development board can communicate with each other, disable AP client isolation, and check whether UDP is blocked by a firewall. |
| Connected but no image | Retry with H.264; also confirm that the browser supports H.265, and that the page has received a new keyframe. |
| Web page still shows old state | The browser may have cached the old embedded web page. Reload or force-refresh the page; the script has already sent the `Cache-Control: no-store` response header. |
| HTTP output `ECONNRESET` | It is normal for the browser to close the short connection after the request is complete; the example ignores common `ECONNRESET`/`EPIPE`. |

## Security Scope

This example is only intended for trusted LAN development and verification. The HTTP signaling has no access control and does not enable TLS; it should not be exposed directly to the public network. Public network deployment requires at least adding authentication, HTTPS/WSS signaling, and STUN/TURN services.

For related APIs, please refer to the [`webrtc` Module API](../../api/mpp/k230_canmv_webrtc_module_api_manual.md) and the [VENC Module API](../../api/mpp/k230_canmv_venc_module_api_manual.md).
