# Use Nosmai Effects with WebRTC on Android

> Publish Nosmai's processed Android texture output through a custom WebRTC video capturer and your own signalling layer.

> For AI agents: the complete documentation index is at https://nosmai.com/llms/effects.txt

Product: Nosmai Effects
Group: integrations
Source: https://nosmai.com/docs/effects/integrations/webrtc/android/

## Streaming path

![Nosmai processes Android camera frames before WebRTC publishes them](/images/docs/webrtc-streaming-flow-v1.svg)

Raw WebRTC has no managed rooms or token service. Nosmai provides processed
video, while your application owns peer connections, signalling, ICE, audio,
and reconnect behaviour.

## Prerequisites

- Android API 21 or later on a physical `arm64-v8a` device
- The verified Nosmai 3.0.4 AAR
- A WebRTC library and signalling service
- A working Nosmai camera preview

```kotlin
dependencies {
    implementation(files("libs/nosmai-sdk-3.0.4.aar"))
    implementation("io.github.webrtc-sdk:android:125.6422.07")
}
```

## Share the encoder context

Create one `EglBase`, register it with Nosmai before initialization, and use it
for WebRTC's encoder, decoder, and `SurfaceTextureHelper`.

```kotlin
val eglBase = EglBase.create()

System.loadLibrary("nosmai")
NosmaiSDK.setAgoraShareContext(
    eglBase.eglBaseContext.nativeEglContext
)
NosmaiSDK.initialize(applicationContext, nosmaiLicenseKey)
```

## Create the processed video track

Use the `NosmaiVideoCapturer` from the official example. It implements WebRTC's
`VideoCapturer`, receives processed Nosmai textures, and returns every producer
slot after the frame is handed off.

```kotlin
val source = factory.createVideoSource(false)
val helper = SurfaceTextureHelper.create(
    "NosmaiCapture",
    eglBase.eglBaseContext,
)

val capturer = NosmaiVideoCapturer()
capturer.initialize(helper, context, source.capturerObserver)
capturer.startCapture(720, 1280, 30)

val videoTrack = factory.createVideoTrack("nosmai-video", source)
peerConnection.addTrack(videoTrack, listOf("nosmai-stream"))
```

Add the microphone as a normal WebRTC audio track. WebRTC must not open a
second camera.

## Connect through your signalling layer

Exchange SDP offers, answers, and ICE candidates through your own authenticated
service. The viewer server in the example is a local test fixture, not a
production signalling service.

## Stop in the correct order

1. Stop and dispose `NosmaiVideoCapturer`.
2. Close the peer connection and signalling socket.
3. Dispose WebRTC sources and the factory.
4. Release Nosmai and the shared `EglBase` when capture ends.

## Common errors

| Symptom | Cause | Fix |
| --- | --- | --- |
| Local preview works but the peer receives black video | WebRTC cannot read Nosmai's texture context | Register and reuse one EGL context before Nosmai initialization |
| Stream freezes after several frames | A producer texture slot was not released | Release slots exactly once on success, drop, and error paths |
| Peer never connects | SDP, ICE, TURN, or signalling is incomplete | Inspect peer and ICE state separately from the Nosmai frame path |

## Verify it worked

Use the example browser viewer to confirm decoded resolution, frame rate,
orientation, codec, and visible effects.

## Complete example

The [native Android WebRTC example](https://github.com/nosmai/nosmai-webrtc-android-example)
contains the tested capturer, peer connection, signalling client, and local
browser viewer.

## Next steps

- [Compare live-streaming routes](/docs/effects/integrations/live-streaming/)
- [Render frames off-screen on Android](/docs/effects/guides/streaming/render-frames-off-screen/android/)
- [Review Android requirements](/docs/effects/platforms/android/)

## References

- [Nosmai WebRTC Android example](https://github.com/nosmai/nosmai-webrtc-android-example)
- [WebRTC native APIs](https://webrtc.googlesource.com/src/)
