# Use Nosmai Effects with Agora on iOS

> Publish processed iOS CVPixelBuffer frames to Agora while Nosmai owns the camera and renders the local preview.

> 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/agora/ios/

## The streaming path

![Camera frames pass through Nosmai Effects before Agora publishes them](/images/docs/agora-streaming-flow-v1.svg)

Nosmai owns and processes the camera feed. Agora publishes only the processed
output while the application keeps its local preview and session controls.

## Prerequisites

- Configure Agora broadcaster authentication, audio, and channel lifecycle.
- Configure Agora to publish external video instead of its camera track.
- Pin and test the Agora version used by your application.

## Receive processed frames

```objective-c
[NosmaiCore shared].liveFrameStreamCallback =
    ^(CVPixelBufferRef pixelBuffer, double timestamp) {
        CVPixelBufferRetain(pixelBuffer);

        dispatch_async(agoraQueue, ^{
            [agoraAdapter pushPixelBuffer:pixelBuffer timestamp:timestamp];
            CVPixelBufferRelease(pixelBuffer);
        });
    };
```

`agoraAdapter` is the application layer that converts the Nosmai callback into
the external-video API used by the pinned Agora release. Do not start Agora's
camera while Nosmai owns it.

## Preserve ownership and timing

- The callback runs off the main thread.
- Retain the pixel buffer when Agora consumes it asynchronously.
- Preserve the timestamp and configure matching orientation and dimensions.
- Do not block the callback with network, file, or UIKit work.

## Stop in the correct order

Stop Agora publishing before clearing the callback:

```objective-c
[NosmaiCore shared].liveFrameStreamCallback = nil;
```

Then leave the channel and release Agora according to its lifecycle. Keep
Nosmai alive if the local camera experience continues.

## Common errors

| Symptom | Cause | Fix |
| --- | --- | --- |
| Remote stream is unfiltered | Agora is publishing its own camera track | Disable the camera track and publish the Nosmai processed source |
| Frames corrupt or crash later | The buffer outlived the callback without being retained | Retain before asynchronous use and release after Agora finishes |
| Preview is smooth but remote video rotates | Provider orientation does not match the buffer contract | Test portrait and landscape with the pinned Agora version |

## Verify it worked

Apply a visible effect, join from a second device, and confirm the remote video
is filtered, correctly oriented, and stable through background and rejoin.

## Next steps

- [Compare live-streaming routes](/docs/effects/integrations/live-streaming/)
- [Understand off-screen rendering](/docs/effects/concepts/off-screen-rendering/)
- [Review iOS platform support](/docs/effects/platforms/ios/)

## References

- [Off-screen rendering](/docs/effects/concepts/off-screen-rendering/)
- [iOS platform guide](/docs/effects/platforms/ios/)
- [Agora documentation](https://docs.agora.io/en/video-calling/advanced-features/custom-video)
