XCamera

pub package

A high-performance Flutter camera plugin built for Linux.

It offers a simple Dart API for camera discovery and real-time video streaming, powered by a native C++ backend built on the Video4Linux2 API with zero-copy memory mapping for ultra-low latency.

Features

  • Device Discovery: Enumerate all connected camera devices and their detailed capabilities.
  • Live Camera Preview: Render a real-time video stream using the built-in CameraPreview widget.
  • Still Image Capture: Capture high-resolution still images directly from the video stream.
  • Multi-Camera Support: Create multiple CameraController instances to stream from several cameras simultaneously.
  • Raw Stream Access: Access raw image frames directly for real-time processing, analysis, or integration with external libraries.

Getting Started

To use XCamera, follow these steps:

1. Add dependency

Add xcamera to your pubspec.yaml file:

dependencies:
  xcamera: ^0.0.1

Then, fetch the package by running:

flutter pub get

2. Initialize and Preview Camera

Here’s a minimal example that lists available cameras, selects one, and shows the live camera feed in full screen.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:xcamera/xcamera.dart';

void main() {
  runApp(const XCameraExample());
}

class XCameraExample extends StatefulWidget {
  const XCameraExample({super.key});

  @override
  State<XCameraExample> createState() => _XCameraExampleState();
}

class _XCameraExampleState extends State<XCameraExample> {
  /// Manages camera operations like preview, capture, and streaming.
  CameraController? _cameraController;

  /// Used by the [FutureBuilder] to display a loading indicator while the
  /// camera is initializing.
  late Future<void> _initializeCameraFuture;

  @override
  void initState() {
    super.initState();

    // Begin camera initialization as soon as the widget is created.
    _initializeCameraFuture = _initializeCamera();
  }

  /// Discovers available cameras, then creates and initializes a [CameraController].
  Future<void> _initializeCamera() async {
    try {
      // First, get a list of available cameras.
      final cameras = await availableCameras();

      // If no cameras are found, throw an exception.
      if (cameras.isEmpty) {
        throw Exception('No cameras available.');
      }

      // Create a new [CameraController] with auto-detected settings for the first
      // available camera. The `create` factory handles finding the best
      // resolution and format.
      final controller = await CameraController.create(cameras.first);

      // Next, initialize the controller. This prepares the camera for streaming.
      await controller.initialize();

      // If the widget is still mounted, update the state with the new controller.
      if (mounted) {
        setState(() {
          _cameraController = controller;
        });
      }
    } catch (e) {
      // Log any errors that occur during camera initialization
      debugPrint('Error initializing camera: $e');
    }
  }

  @override
  void dispose() {
    // Dispose of the controller when the widget is disposed to release resources.
    _cameraController?.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: FutureBuilder<void>(
            future: _initializeCameraFuture,
            builder: (context, snapshot) {
              // While the camera is initializing, show a loading indicator.
              if (snapshot.connectionState == ConnectionState.waiting) {
                return const Center(child: CircularProgressIndicator());
              }

              // If an error occurs during initialization, display the error.
              if (snapshot.hasError) {
                return Center(child: Text('Error: ${snapshot.error}'));
              }

              // If the controller is null, it means initialization failed without an
              // error being thrown. Show a fallback message.
              if (_cameraController == null) {
                return const Center(child: Text('No camera found.'));
              }

              // Once initialized, display the camera preview.
              return CameraPreview(_cameraController!);
            },
          ),
        ),
      ),
    );
  }
}

Platform Support

This package is designed exclusively for Linux. It is not supported on Windows, macOS, Android, or iOS.

Native Implementation

XCamera’s performance is powered by a native C++ backend built on the Video4Linux2 API, featuring zero-copy memory mapping for ultra-low latency.

For more details about the native layer and its source code, visit the xcamera-native.

Libraries

xcamera