Skip to content

Repository files navigation

@snap/react-camera-kit

The official React wrapper for the Camera Kit Web SDK. It provides declarative components and hooks that handle SDK bootstrapping, session lifecycle, media sources, and Lens management — so you can integrate Snap AR into React apps with minimal boilerplate.

Live Demo · Camera Kit Docs

Installation

npm install @snap/react-camera-kit @snap/camera-kit

Requirements

  • @snap/camera-kit^1.13.0 (peer dependency)
  • react>=16.8.0 and react-dom>=16.8.0
  • rxjs>=7
  • https:// for deployed apps (http://localhost works for local development)

You'll need a Camera Kit API token, Lens ID, and Lens Group ID from the Snap Developer Portal. See Setting Up Accounts if you're new to Camera Kit.

Quick start

import{CameraKitProvider,LensPlayer}from"@snap/react-camera-kit";functionApp(){return(<CameraKitProviderapiToken="YOUR_API_TOKEN"><LensPlayerlensId="YOUR_LENS_ID"lensGroupId="YOUR_LENS_GROUP_ID"/></CameraKitProvider>);}

That's it — CameraKitProvider initializes the SDK, and LensPlayer sets up the camera, applies the Lens, and renders the output canvas.

Components

CameraKitProvider

The root provider that initializes the Camera Kit SDK. All other components and hooks must be descendants of this provider.

import{CameraKitProvider,createConsoleLogger}from"@snap/react-camera-kit";<CameraKitProviderapiToken="YOUR_API_TOKEN"logger={createConsoleLogger()}logLevel="info">{children}</CameraKitProvider>;
PropTypeDefaultDescription
apiTokenstringrequiredCamera Kit API token
loggerCameraKitLoggernoopLoggerLogger instance — use createConsoleLogger() for development
logLevel"debug" | "info" | "warn" | "error""info"Log verbosity
renderWhileTabHiddenbooleanfalseContinue rendering when the browser tab is hidden
stabilityKeystring | numberautoManual control over when the SDK re-initializes
extendContainer(container) => containerCustomize the SDK's DI container
createBootstrapEventHandlerMetricEventHandlerFactoryFactory for tracking bootstrap success/failure

LensPlayer

All-in-one component that handles source setup, Lens application, and playback. Defaults to the user's camera if no source is provided.

<LensPlayerlensId="YOUR_LENS_ID"lensGroupId="YOUR_LENS_GROUP_ID"className="camera-canvas"/>
PropTypeDefaultDescription
lensIdstringLens to apply
lensGroupIdstringLens Group containing the Lens
sourceSourceInput{ kind: "camera" }Media source (camera, video, or image)
outputSizeOutputSizeRendering canvas size
lensLaunchDataLensLaunchDataLaunch parameters passed to the Lens
lensReadyGuard() => Promise<void>Async guard called while Lens is loading (2s timeout)
refreshTriggerunknownWhen this value changes, the Lens is removed and reapplied
canvasType"live" | "capture""live"Which canvas to render. For custom layouts, use LiveCanvas/CaptureCanvas as children instead
fpsLimitnumberMaximum rendering framerate
mutedbooleanfalseMute audio output
screenRegionsScreenRegionsScreen regions for Lens-aware UI layout
onError(error, lens) => voidCallback for playback errors
classNamestringCSS class name
styleCSSPropertiesInline styles
childrenReactNodeCustom children (use with LiveCanvas/CaptureCanvas)

LiveCanvas / CaptureCanvas

Render the live preview or capture canvas as children of LensPlayer:

<LensPlayerlensId="YOUR_LENS_ID"lensGroupId="YOUR_LENS_GROUP_ID"><div><LiveCanvasstyle={{width: "100%"}}/></div><div><CaptureCanvasstyle={{width: "100%"}}/></div></LensPlayer>

Both accept className and style props.

Hooks

useCameraKit

Access the full Camera Kit context — SDK status, source/Lens state, and imperative methods. Must be called within a CameraKitProvider.

import{useCameraKit}from"@snap/react-camera-kit";functionControls(){const{ sdkStatus, lens, lenses, isMuted, toggleMuted, applyLens, removeLens, fetchLenses }=useCameraKit();if(sdkStatus!=="ready")return<p>Loading SDK...</p>;return(<div><p>Lens: {lens.lensId??"None"}</p><buttononClick={toggleMuted}>{isMuted ? "Unmute" : "Mute"}</button><buttononClick={removeLens}>Remove Lens</button></div>);}

State properties:

PropertyTypeDescription
sdkStatus"uninitialized" | "initializing" | "ready" | "error"SDK initialization status
sdkErrorError | undefinedError from SDK initialization
sourceCurrentSourceCurrent source status, input, and error
lensCurrentLensCurrent Lens status, IDs, and error
lensesLens[]Array of loaded Lens objects
liveCanvasHTMLCanvasElement | undefinedLive preview canvas element
captureCanvasHTMLCanvasElement | undefinedCapture canvas element
keyboardKeyboard | undefinedKeyboard API for Lens keyboard requests
isMutedbooleanWhether audio is muted
fpsLimitnumber | undefinedCurrent FPS limit
screenRegionsScreenRegions | undefinedCurrent screen regions

Methods:

MethodDescription
applySource(input, size?)Apply a media source (camera, video, or image)
removeSource()Remove the current source
fetchLens(lensId, groupId)Load a single Lens (returns cached if already loaded)
fetchLenses(groupId)Load all Lenses in a group (accepts string or string[])
applyLens(lensId, groupId, launchData?, readyGuard?)Apply a Lens by ID
removeLens()Remove the current Lens
refreshLens()Remove and reapply the current Lens
reinitialize()Re-bootstrap the SDK (useful after errors)
setMuted(muted)Set the muted state
toggleMuted()Toggle audio mute
setFPSLimit(fps)Set maximum rendering FPS
setScreenRegions(regions)Set screen regions for Lens-aware layout

useApplyLens

Declaratively apply a Lens — it updates automatically when parameters change.

import{useApplyLens}from"@snap/react-camera-kit";useApplyLens("YOUR_LENS_ID","YOUR_LENS_GROUP_ID");
ParameterTypeDescription
lensIdstring | undefinedLens ID — pass undefined to remove
lensGroupIdstring | undefinedLens Group ID
lensLaunchDataLensLaunchDataOptional launch parameters
lensReadyGuard() => Promise<void>Optional async ready guard
refreshTriggerunknownReapply with current parameters when changed

useApplySource

Declaratively apply a media source. Defaults to camera if no source is provided.

import{useApplySource}from"@snap/react-camera-kit";// Video source with fixed output sizeuseApplySource({kind: "video",url: "/demo.mp4",autoplay: true},{mode: "fixed",width: 720,height: 1280});
ParameterTypeDefaultDescription
sourceSourceInput{ kind: "camera" }Media source
outputSizeOutputSizeRendering size

usePlaybackOptions

Declaratively set playback options.

import{usePlaybackOptions}from"@snap/react-camera-kit";usePlaybackOptions({fpsLimit: 30,muted: false,onError: (error)=>console.error("Playback error:",error),});
OptionTypeDescription
fpsLimitnumberMaximum rendering FPS
mutedbooleanMute audio
screenRegionsScreenRegionsScreen regions for Lens layout
onError(error, lens) => voidPlayback error callback

Media sources

Pass a SourceInput to LensPlayer's source prop or to useApplySource:

// Camera (default){kind: "camera"}{kind: "camera",deviceId: "abc123",options: {cameraFacing: "environment"}}// Video{kind: "video",url: "/demo.mp4",autoplay: true}// Image{kind: "image",url: "/photo.jpg"}

Camera source options

OptionTypeDefaultDescription
cameraFacing"user" | "environment""user"Front or back camera
cameraConstraintsMediaTrackConstraints{ width: 1280, height: 720 }Camera resolution constraints
cameraRotation0 | -90 | 90 | 1800Camera rotation
fpsLimitnumberMax FPS for the source
outputSizeOutputSizeRendering canvas size

Output size

// Fixed resolution{mode: "fixed",width: 720,height: 1280}// Match input source resolution{mode: "match-input"}

Handling loading and error states

Use useCameraKit() to track the status of the SDK, source, and Lens. Each progresses through "none" → "loading" → "ready" (or "error"):

functionPreview(){const{ sdkStatus, sdkError, source, lens }=useCameraKit();if(sdkStatus==="error")return<p>SDK failed: {sdkError?.message}</p>;if(sdkStatus!=="ready")return<p>Initializing...</p>;if(source.status==="loading")return<p>Setting up camera...</p>;if(lens.status==="error")return<p>Lens error: {lens.error?.message}</p>;return(<LensPlayerlensId="YOUR_LENS_ID"lensGroupId="YOUR_LENS_GROUP_ID">{lens.status!=="ready"&&<divclassName="spinner"/>}<LiveCanvas/></LensPlayer>);}

Frame Metrics

Use useLensFrameMetrics to monitor lens rendering performance:

import{useLensFrameMetrics}from"@snap/react-camera-kit";functionPerformanceOverlay(){constmetrics=useLensFrameMetrics({interval: 500});if(!metrics)returnnull;return(<div><p>FPS: {metrics.avgFps.toFixed(1)}</p><p>Frame time: {metrics.lensFrameProcessingTimeMsAvg.toFixed(1)}ms</p></div>);}

The hook accepts:

  • interval (required) — polling interval in milliseconds
  • enabled (optional, defaults to true) — set to false to disable measurement without unmounting

Full example: Lens switcher

import{CameraKitProvider,LensPlayer,LiveCanvas,useCameraKit}from"@snap/react-camera-kit";import{useEffect}from"react";constLENS_GROUP_ID="YOUR_LENS_GROUP_ID";functionLensSwitcher(){const{ sdkStatus, lenses, lens, fetchLenses, applyLens, isMuted, toggleMuted, reinitialize, sdkError }=useCameraKit();useEffect(()=>{if(sdkStatus==="ready")fetchLenses(LENS_GROUP_ID);},[sdkStatus]);if(sdkStatus==="error"){return(<div><p>SDK error: {sdkError?.message}</p><buttononClick={reinitialize}>Retry</button></div>);}return(<div><selectvalue={lens.lensId??""}onChange={(e)=>applyLens(e.target.value,LENS_GROUP_ID)}><optionvalue=""disabled>
Select a Lens
</option>{lenses.map((l)=>(<optionkey={l.id}value={l.id}>{l.name}</option>))}</select><buttononClick={toggleMuted}>{isMuted ? "Unmute" : "Mute"}</button><LensPlayerlensId={lens.lensId}lensGroupId={LENS_GROUP_ID}><LiveCanvasstyle={{width: "100%",maxWidth: 640}}/></LensPlayer></div>);}exportdefaultfunctionApp(){return(<CameraKitProviderapiToken="YOUR_API_TOKEN"><LensSwitcher/></CameraKitProvider>);}

Utilities

ExportDescription
createConsoleLogger()Returns a logger that prints to the browser console
createNoopLogger()Returns a silent logger (default)
isCameraSource(source)Type guard for CameraSourceInput
isVideoSource(source)Type guard for VideoSourceInput
isImageSource(source)Type guard for ImageSourceInput
CameraRotationOptionsValid rotation values: [0, -90, 90, 180]

Development

npm install # Install dependencies
npm run build # Build ESM + CJS
npm run watch # Build in watch mode
npm run typecheck # Type checking
npm test# Run tests
npm run clean # Clean dist folder

Demo app

A Vite demo app is available in demo/:

npm run demo:install
cp demo/.env.example demo/.env
npm run demo:dev

Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

License

MIT

About

Official React bindings for Snap Camera Kit — create interactive, lens-powered AR experiences on the web.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

23 stars

Watchers

3 watching

Forks

Releases

Contributors

Languages