Skip to content
Document DB v7.1: Temporal Support, Telemetry Collection, & Orleans Storage Providers! Feed The Machine Here

CameraView

Shiny.Maui.Controls.Camera is a cross-platform CameraView for .NET MAUI — live preview with zoom, torch, lens selection, photo & video capture, and live color filters — backed by AVFoundation (iOS / Mac Catalyst / macOS AppKit), CameraX (Android) and Media Capture (Windows). A matching Shiny.Blazor.Controls.Camera brings the same control to Blazor WebAssembly via getUserMedia.

What sets it apart from other camera controls is the pluggable frame-analysis pipeline: drop one or more analyzers onto the view and it streams frames to them off the UI thread. Each analyzer raises its own strongly-typed event (or a bindable Command), can be declared right in XAML, and returns styled bounding boxes drawn by the built-in CameraOverlayView. Ships with analyzers for barcode/QR scanning, face detection, motion detection, OCR, and structured documents — invoices (with order lines), AAMVA driver’s licenses, health cards, credit cards, and passports (MRZ). Each document is a strong record with nullable fields.

  • NuGet downloads for Shiny.Maui.Controls.Camera
  • NuGet downloads for Shiny.Blazor.Controls.Camera
Frameworks
.NET MAUI
Blazor
Shiny.Maui.Controls.CameraNuGet package Shiny.Maui.Controls.Camera
  • Live preview with AspectFill / AspectFit scaling.
  • Lens & device selectionFacing (Back / Front) or pick an exact device (multiple back lenses, USB webcams on macOS) via GetAvailableCamerasAsync() + CameraId.
  • Zoom (clamped to the device’s reported range) and torch / flashlight.
  • Photo capture → JPEG bytes, and video recording with optional audio.
  • Live color filters — Mono, Noir, Sepia, Invert, Vivid, Cool, Warm, Fade, Chrome, Instant, Tonal (Apple Core Image, Android RenderEffect, Blazor CSS).
  • Frame-analysis pipeline — pluggable IFrameAnalyzers with per-analyzer back-pressure (drop-on-busy); each surfaces its result via its own typed event/Command and draws styled boxes via the built-in CameraOverlayView. See Frame Analyzers.
  • Modular analyzer packages — add only what you need: .Camera.Barcode, .Camera.Face, .Camera.Motion, .Camera.Ocr, .Camera.Documents.
claude plugin marketplace add shinyorg/skills
claude plugin install shiny-client@shiny
BLE, GPS, Jobs, Notifications, Push, HTTP Transfers, OBD, Music, Health, DataSync — iOS, Android, Windows, MacOS, Linux, Web
claude plugin install shiny-maui@shiny
Shell, Contact Store
claude plugin install controls@shiny
TableView, BottomSheet, PillView, ImageViewer, Scheduler, Markdown, Mermaid Diagrams — MAUI and Blazor
claude plugin install shiny-mediator@shiny
Mediator/CQRS with middleware and source generators
claude plugin install shiny-data@shiny
DocumentDB and Spatial data libraries
claude plugin install shiny-aspire@shiny
Orleans and Gluetun Aspire integrations
claude plugin install shiny-extensions@shiny
DI, Stores, Reflector, Localization, Hosting modules
copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny-client@shiny
BLE, GPS, Jobs, Notifications, Push, HTTP Transfers, OBD, Music, Health, DataSync — iOS, Android, Windows, MacOS, Linux, Web
copilot plugin install shiny-maui@shiny
Shell, Contact Store
copilot plugin install controls@shiny
TableView, BottomSheet, PillView, ImageViewer, Scheduler, Markdown, Mermaid Diagrams — MAUI and Blazor
copilot plugin install shiny-mediator@shiny
Mediator/CQRS with middleware and source generators
copilot plugin install shiny-data@shiny
DocumentDB and Spatial data libraries
copilot plugin install shiny-aspire@shiny
Orleans and Gluetun Aspire integrations
copilot plugin install shiny-extensions@shiny
DI, Stores, Reflector, Localization, Hosting modules
View Skills Repository
Terminal window
dotnet add package Shiny.Maui.Controls.Camera

Register the handler alongside UseShinyControls():

builder
.UseShinyControls()
.UseShinyCamera();
xmlns:cam="http://shiny.net/maui/camera"

Add the platform permissions your app needs:

  • iOS / Mac Catalyst / macOSNSCameraUsageDescription (and NSMicrophoneUsageDescription for video with audio) in Info.plist; the macOS camera entitlement when sandboxed.
  • Android<uses-permission android:name="android.permission.CAMERA" /> (and RECORD_AUDIO for video with audio). Minimum SDK 23 (CameraX requirement).
  • Windows — the webcam (and microphone) capability in Package.appxmanifest.
Terminal window
dotnet add package Shiny.Blazor.Controls.Camera
@using Shiny.Blazor.Controls.Camera
@using Shiny.Controls.Camera

See Blazor Usage for the WebAssembly specifics.

<cam:CameraView x:Name="Camera"
Facing="Back"
ScaleMode="AspectFill"
Zoom="1"
IsTorchOn="False"
Filter="None" />
protected override async void OnAppearing()
{
base.OnAppearing();
if (await this.Camera.RequestPermissionAsync())
await this.Camera.StartAsync();
}
protected override async void OnDisappearing()
{
base.OnDisappearing();
await this.Camera.StopAsync();
}
// Capture a still
var photo = await this.Camera.CapturePhotoAsync();
await File.WriteAllBytesAsync(path, photo.Data);
// Flip the lens
this.Camera.Facing = this.Camera.Facing == CameraFacing.Back
? CameraFacing.Front
: CameraFacing.Back;

VideoRecordingOptions.IncludeAudio defaults to true; the audio permission is requested only when audio is requested.

await this.Camera.StartVideoRecordingAsync(new VideoRecordingOptions { IncludeAudio = true });
// ... later ...
var video = await this.Camera.StopVideoRecordingAsync(); // CameraVideo { FilePath, Duration }

On Android, CameraX allows a limited number of concurrent use-cases, so video recording and the analysis pipeline are mutually exclusive — StartVideoRecordingAsync throws a clear error while analyzers are attached. Clear CameraView.Analyzers to record.

<cam:CameraView Filter="Noir" />

Filter accepts None, Mono, Noir, Sepia, Invert, Vivid, Cool, Warm, Fade, Chrome, Instant, Tonal. Filtering is applied to the live preview (Apple CIFilter — the Fade/Chrome/Instant/Tonal set maps to the Core Image CIPhotoEffect* filters; Android RenderEffect color matrix on API 31+; Blazor CSS); on Windows it is best-effort.

Facing picks by position, but you can enumerate every physical camera and pin an exact one — essential for phones with multiple back lenses or desktops with several webcams:

var cameras = await this.Camera.GetAvailableCamerasAsync();
// CameraInfo { Id, Name, Facing, IsDefault }
this.Camera.CameraId = cameras.First(c => c.Name.Contains("USB")).Id;

Set CameraId back to null to fall back to Facing.

PropertyTypeDefaultDescription
FacingCameraFacingBackBack / Front / External lens position
CameraIdstring?nullExact device id from GetAvailableCamerasAsync(); overrides Facing
IsActivebooltrueWhether the session is running
Zoomdouble1Zoom factor, clamped to MinZoom..MaxZoom
MinZoom / MaxZoomdouble1Supported zoom range (reported by the handler)
IsTorchOnboolfalseContinuous flashlight/torch
FlashModeCameraFlashModeOffFlash behaviour for still capture (Off/On/Auto)
ScaleModePreviewScaleModeAspectFillHow the preview fills the view
FilterCameraFilterNoneLive color filter
ShowDetectionOverlaybooltrueWhether overlay boxes are surfaced for the overlay
AnalyzersIList<IFrameAnalyzer>emptyFrame analyzers (also the XAML content property) — see Frame Analyzers
IsRecordingbool (read-only)falseWhether a recording is in progress
OverlaysIReadOnlyList<OverlayBox>emptyLatest aggregated overlay boxes (read-only)
MemberDescription
RequestPermissionAsync()Request camera permission
StartAsync() / StopAsync()Start / stop the session
CapturePhotoAsync()Capture a still → CameraPhoto
StartVideoRecordingAsync() / StopVideoRecordingAsync()Record video → CameraVideo
GetAvailableCamerasAsync()Enumerate cameras → IReadOnlyList<CameraInfo>
MediaCaptured / VideoCapturedRaised after a photo / video is captured
OverlaysChangedRaised with the latest aggregated overlay boxes (presentation only)
CameraErrorRaised on a camera or pipeline error

For results, subscribe to each analyzer’s own typed event (BarcodeDetected, FacesDetected, MotionChanged, TextRecognized, DocumentDetected) or bind its Command. OverlaysChanged is only the styled boxes for drawing.

  • Scan a barcode / QR → add a BarcodeAnalyzer (Frame Analyzers).
  • Detect / box faces → add a FaceAnalyzer.
  • Trigger on movement → add a MotionAnalyzer.
  • Read raw text → add an OcrAnalyzer (TextRecognized).
  • Parse an invoice / receipt (header + order lines) → add an InvoiceAnalyzer.
  • Scan a driver’s license / health card → add a DriversLicenseAnalyzer (deterministic AAMVA) or HealthCardAnalyzer from .Camera.Documents.
  • Scan a passport → add a PassportAnalyzer (deterministic MRZ → number, names, nationality, DOB, expiry).
  • Read a credit card → add a CreditCardAnalyzer (brand + number deterministic; name/expiry best-effort).
  • Just take a photo or record video → no analyzers required; use CapturePhotoAsync / StartVideoRecordingAsync.