flutter_uvc_camera
A Flutter plugin based on AndroidUSBCamera to enable Flutter apps to use external UVC cameras.
Features
- Connect to and control external UVC cameras through USB
- Display camera preview in your Flutter app
- Take photos and save to local storage
- Record videos with time tracking
- Stream video frames (H264) and audio frames (AAC) for further processing
- Control camera features like brightness, contrast, focus, etc.
- Monitor camera connection status
- Support for different preview resolutions
Limitations
- Currently, only supports Android
- For Android 10+, you may need to reduce targetSdkVersion to 27
- Some device models may have compatibility issues (e.g., Redmi Note 10)
Installation
1. Add Dependency
Add the flutter_uvc_camera
plugin dependency to your Flutter project's pubspec.yaml
file:
dependencies:
flutter_uvc_camera: ^latest_version
2. Configure Android Project
Add Permissions
Add the following permissions to the AndroidManifest.xml file of your Android project:
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.usb.host" />
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
Add Repository
In your project's android/build.gradle
, add the JitPack repository:
allprojects {
repositories {
// other repositories
maven { url "https://jitpack.io" }
}
}
Configure USB Device Detection
Add an action for USB device connection in the intent-filter of your main Activity, and reference the corresponding XML file in meta-data:
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
Create the device_filter.xml
file in the android/app/src/main/res/xml/
directory:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- USB device vendor-id and product-id values for your camera -->
<!-- You can use wildcard configuration below or specify your camera IDs -->
<usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
</resources>
3. Configure ProGuard (for release mode)
If you're building in release mode with minification enabled, add these rules to your android/app/proguard-rules.pro
:
-keep class com.jiangdg.uvc.UVCCamera {
native <methods>;
long mNativePtr;
}
-keep class com.jiangdg.uvc.IStatusCallback {
*;
}
-keep interface com.jiangdg.uvc.IButtonCallback {
*;
}
And update your android/app/build.gradle
:
buildTypes {
release {
// your existing configs
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
minifyEnabled true
}
}
Usage
Basic Usage
import 'package:flutter/material.dart';
import 'package:flutter_uvc_camera/flutter_uvc_camera.dart';
class CameraScreen extends StatefulWidget {
@override
State<CameraScreen> createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
late UVCCameraController cameraController;
bool isCameraOpen = false;
@override
void initState() {
super.initState();
cameraController = UVCCameraController();
// Set up camera state callback
cameraController.cameraStateCallback = (state) {
setState(() {
isCameraOpen = state == UVCCameraState.opened;
});
};
}
@override
void dispose() {
cameraController.closeCamera();
cameraController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('UVC Camera')),
body: Column(
children: [
// Camera preview
Container(
height: 300,
child: UVCCameraView(
cameraController: cameraController,
width: 300,
height: 300,
),
),
// Camera control buttons
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: isCameraOpen ? null : () => cameraController.openUVCCamera(),
child: Text('Open Camera'),
),
ElevatedButton(
onPressed: isCameraOpen ? () => cameraController.closeCamera() : null,
child: Text('Close Camera'),
),
ElevatedButton(
onPressed: isCameraOpen ? () => takePicture() : null,
child: Text('Take Picture'),
),
],
),
],
),
);
}
Future<void> takePicture() async {
final path = await cameraController.takePicture();
if (path != null) {
print('Picture saved at: $path');
}
}
}
Video Recording
// Start recording a video
Future<void> recordVideo() async {
final path = await cameraController.captureVideo();
print('Video saved at: $path');
}
Video Streaming
// Set up frame callbacks
cameraController.onVideoFrameCallback = (frame) {
// Process H264 encoded video frame
// frame.data contains the encoded data
// frame.timestamp contains the timestamp
// frame.size contains the size in bytes
// frame.fps contains the current frame rate
};
cameraController.onAudioFrameCallback = (frame) {
// Process AAC encoded audio frame
};
// Start streaming
cameraController.captureStreamStart();
// Stop streaming
cameraController.captureStreamStop();
Camera Features Control
// Set auto focus
await cameraController.setAutoFocus(true);
// Set zoom level
await cameraController.setZoom(5);
// Set brightness
await cameraController.setBrightness(128);
// Get all camera features
final features = await cameraController.getAllCameraFeatures();
API Reference
UVCCameraController
The main controller class for interacting with the UVC camera.
Properties
cameraStateCallback
: Callback for camera state changesmsgCallback
: Callback for messages from the cameraclickTakePictureButtonCallback
: Callback when the camera's physical button is pressedonVideoFrameCallback
: Callback for video frame dataonAudioFrameCallback
: Callback for audio frame dataonRecordingTimeCallback
: Callback for recording time updatesonStreamStateCallback
: Callback for stream state changes
Methods
initializeCamera()
: Initialize the cameraopenUVCCamera()
: Open the UVC cameracloseCamera()
: Close the UVC cameracaptureStreamStart()
: Start capturing video streamcaptureStreamStop()
: Stop capturing video streamtakePicture()
: Take a photo and save to storagecaptureVideo()
: Start/stop video recordingsetVideoFrameRateLimit(int fps)
: Limit the frame ratesetVideoFrameSizeLimit(int maxBytes)
: Limit the frame sizegetAllPreviewSizes()
: Get available preview sizesupdateResolution(PreviewSize size)
: Update camera resolutionsetCameraFeature(String feature, int value)
: Set camera feature valueresetCameraFeature(String feature)
: Reset camera feature to default
UVCCameraView
Widget to display the camera preview.
Properties
cameraController
: The UVCCameraController instancewidth
: The width of the viewheight
: The height of the viewparams
: Optional parameters for camera initializationautoDispose
: Whether to automatically dispose the camera when the view is disposed
Common Issues
Release Mode Build Failure
If you encounter NoSuchMethodError
when running in release mode, make sure you've properly configured ProGuard rules as described in the installation section.
USB Permission Issues
If the camera is not being detected, check that:
- Your device supports USB OTG
- You've correctly configured the USB device filter
- You have proper permissions declarations in AndroidManifest.xml
Example
For a complete example, check the example project.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Issue Reporting
If you encounter any problems or have any suggestions during usage, please report them on GitHub Issues.