document_camera_frame 2.2.0 copy "document_camera_frame: ^2.2.0" to clipboard
document_camera_frame: ^2.2.0 copied to clipboard

Flutter package for capturing and cropping document images with a customizable camera interface.

Document Camera Frame #

Pub Version Pub Points Likes

DocumentCameraFrame is a powerful Flutter package for document scanning via a live camera feed. It offers a fully customizable UI and professional-grade capture workflows for IDs, passports, and general documents.

Key Features:

  • Smart Capture: Choose between single-sided or dual-sided modes (Front/Back) with built-in side indicators and smooth transitions.
  • Edge Detection: Real-time automatic document detection and precise cropping.
  • On-Device OCR: Set enableExtractText: true for instant text extraction (frontOcrText / backOcrText). No API keys, no internet, and 100% privacy (supports Latin scripts).
  • Fully Customizable: Modern modular styling for frames, buttons, animations, and instructions.
  • Offline-First: All processing happens on-device for maximum speed and security.

Demo #

Here's a quick preview of DocumentCameraFrame in action:

Auto Detection Example
Auto document edge detection in real-time
example1
Driver license dual-side capture (320×200) with auto-capture and side indicators
example2
Passport scanning (300×450) with manual capture button, no side indicators, and custom instructions
example3
ID card dual-side capture (320×200) with auto-capture, hidden side indicators, and smooth transitions

Features #

  • 📸 Live Camera Preview with adjustable document frame
  • ✂️ Custom Frame Dimensions for precise cropping
  • 🔎 Automatic Document Detection
  • 🔄 Dual-Side Capture Support (e.g., ID front/back)
  • 📝 Optional on-device OCR — set enableExtractText: true to get extracted text in the save callback (no API key, no internet). OCR is Latin-only (no Arabic).
  • 🎛️ Fully Customizable UI — titles, padding, button styles
  • 🪝 Easy Event CallbacksonDocumentSaved, onFrontCaptured, onBackCaptured, onRetake

Quick Start #

Installation #

Add the package to your Flutter project using:

flutter pub add document_camera_frame

Minimal Example #

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

class QuickExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DocumentCameraFrame(
      frameWidth: 320,
      frameHeight: 200,
      requireBothSides: false,
      enableAutoCapture: true, // Enable automatic capture
      onDocumentSaved: (documentData) {
        print('Document saved: ${documentData.frontImagePath}');
        Navigator.pop(context);
      },
    );
  }
}

OCR (Text extraction) #

Note: OCR is Latin-only (no Arabic). The on-device ML Kit model supports English and other Latin-script languages only.

Set enableExtractText: true to run on-device text recognition after capture. The onDocumentSaved callback then receives DocumentCaptureData with:

  • frontImagePath / backImagePath — image file paths (unchanged)
  • frontOcrText / backOcrText — extracted text (when enableExtractText is true)

No API key or internet is required. OCR uses Google ML Kit and supports Latin script (English and other Latin-based languages). Arabic is not supported by the on-device model.

DocumentCameraFrame(
  frameWidth: 320,
  frameHeight: 200,
  enableExtractText: true,
  onDocumentSaved: (data) {
    print('Front text: ${data.frontOcrText}');
    print('Back text: ${data.backOcrText}');
  },
)

For custom OCR (e.g. from file paths elsewhere), use the exported OcrService class and its extractText(String imagePath) method.

Setup Requirements #

iOS Setup #

  1. Set the minimum iOS deployment target to 15.5 or higher in your ios/Podfile:
platform :ios, '15.5'  # or newer version
  1. Add the following keys to your ios/Runner/Info.plist file to request camera and microphone permissions:

<plist version="1.0">
    <dict>
        <!-- Add the following keys inside the <dict> section -->
        <key>NSCameraUsageDescription</key>
        <string>We need camera access to capture documents.</string>
        <key>NSMicrophoneUsageDescription</key>
        <string>We need microphone access for audio-related features.</string>
    </dict>
</plist>

Android Setup #

  1. Update the minSdkVersion to 21 or higher in android/app/build.gradle:
android {
    defaultConfig {
        minSdk 21
    }
}
  1. Add these permissions to your AndroidManifest.xml file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <application android:label="MyApp" android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <!-- Activities and other components -->
    </application>

</manifest>

Handling Camera Access Permissions #

Permission errors may occur when initializing the camera. You must handle them appropriately. Below are the possible error codes:

Error Code Description
CameraAccessDenied User denied camera access permission.
CameraAccessDeniedWithoutPrompt iOS only. User previously denied access and needs to enable it manually via Settings.
CameraAccessRestricted iOS only. Camera access is restricted (e.g., parental controls).
AudioAccessDenied User denied microphone access permission.
AudioAccessDeniedWithoutPrompt iOS only. User previously denied microphone access and needs to enable it manually via Settings.
AudioAccessRestricted iOS only. Microphone access is restricted (e.g., parental controls).

Common Use Cases #

Driver's License (Both Sides) #

DocumentCameraFrame(
  frameWidth: 320,
  frameHeight: 200,
  frontSideTitle: Text('Scan Front of License', 
    style: TextStyle(color: Colors.white)),
  backSideTitle: Text('Scan Back of License',
    style: TextStyle(color: Colors.white)),
  requireBothSides: true,
  enableAutoCapture: true, // Automatically capture when document is aligned
  onFrontCaptured: (imagePath) => print('Front: $imagePath'),
  onBackCaptured: (imagePath) => print('Back: $imagePath'),
  onDocumentSaved: (data) => handleDocument(data),
)

Passport (Single Side) #

DocumentCameraFrame(
  frameWidth: 300,
  frameHeight: 450,
  title: Text('Scan Passport', style: TextStyle(color: Colors.white)),
  requireBothSides: false,
  showSideIndicator: false,
  enableAutoCapture: false, // Manual capture only
  frontSideInstruction: "Position passport within the frame",
  onDocumentSaved: (data) => handlePassport(data),
)

ID Card with Custom Styling #

DocumentCameraFrame(
  frameWidth: 320,
  frameHeight: 200,
  requireBothSides: true,
  enableAutoCapture: true,
  captureButtonText: "Take Photo",
  saveButtonText: "Done",
  retakeButtonText: "Try Again",
  progressIndicatorColor: Colors.blue,
  outerFrameBorderRadius: 16.0,
  onDocumentSaved: (data) => processIdCard(data),
)

Widget Parameters #

Core Parameters #

Parameter Type Description Required Default Value
frameWidth double Width of the document capture frame.
frameHeight double Height of the document capture frame.
enableAutoCapture bool Enables automatic capture when a document is properly aligned in the frame. false
requireBothSides bool Whether to require both sides (if false, can save with just front side). true
showCloseButton bool Flag to control the visibility of the CloseButton (optional). false
cameraIndex int? Index to specify which camera to use (e.g., 0 for back, 1 for front) (optional). 0 (back)
bottomFrameContainerChild Widget? Custom content for the bottom container (optional). null
bottomHintText String? Optional bottom hint text shown in the bottom container. null
sideInfoOverlay Widget? Optional widget shown on the right (e.g. a check icon). null
showDetectionStatusText bool Show the (dynamic) live detection status text (e.g. "Move closer"). true

Styling Classes #

Parameter Type Description Required Default Value
animationStyle DocumentCameraAnimationStyle Animation styling configuration for the camera widget. DocumentCameraAnimationStyle()
frameStyle DocumentCameraFrameStyle Frame styling configuration for borders and appearance. DocumentCameraFrameStyle()
buttonStyle DocumentCameraButtonStyle Button styling configuration for all buttons. DocumentCameraButtonStyle()
titleStyle DocumentCameraTitleStyle Title styling configuration for screen titles. DocumentCameraTitleStyle()
sideIndicatorStyle DocumentCameraSideIndicatorStyle Side indicator styling configuration. DocumentCameraSideIndicatorStyle()
progressStyle DocumentCameraProgressStyle Progress indicator styling configuration. DocumentCameraProgressStyle()
instructionStyle DocumentCameraInstructionStyle Instruction text styling configuration. DocumentCameraInstructionStyle()

Callbacks #

Parameter Type Description Required Default Value
onFrontCaptured Function(String)? Callback triggered when front side is captured. null
onBackCaptured Function(String)? Callback triggered when back side is captured. null
onDocumentSaved Function(DocumentCaptureData)? Callback when document is saved (one-sided e.g. passport, or both sides). One of onDocumentSaved or onBothSidesSaved required. ✅*
onBothSidesSaved Function(DocumentCaptureData)? Deprecated. Use onDocumentSaved instead. Still supported for backward compatibility. ✅*
enableExtractText bool When true, runs on-device OCR and sets documentData.frontOcrText / backOcrText before the callback. false
onRetake VoidCallback? Callback triggered when the "Retake" button is pressed. null
onCameraError void Function(Object error)? Callback triggered when a camera-related error occurs (e.g., initialization, streaming, or capture failure). null

*At least one of onDocumentSaved or onBothSidesSaved must be provided. Prefer onDocumentSaved.

Styling Classes Details #

DocumentCameraAnimationStyle #

Property Type Description Default Value
capturingAnimationDuration Duration? Duration for the capturing animation (optional). null
capturingAnimationColor Color? Color for the capturing animation (optional). null
capturingAnimationCurve Curve? Curve for the capturing animation (optional). null
frameFlipDuration Duration Duration for the flip animation between sides. Duration(milliseconds: 1200)
frameFlipCurve Curve Curve for the flip animation between sides. Curves.easeInOut

DocumentCameraFrameStyle #

Property Type Description Default Value
outerFrameBorderRadius double Radius of the outer border of the frame. 12.0
innerCornerBroderRadius double Radius of the inner corners of the frame. 8.0
frameBorder BoxBorder? Border for the displayed frame (optional). null

DocumentCameraButtonStyle #

Property Type Description Default Value
captureOuterCircleRadius double? Radius of the outer circle of the capture button. null
captureInnerCircleRadius double? Radius of the inner circle of the capture button. null
captureButtonText String? Text for the "Capture" button. null
captureFrontButtonText String? Text for capture button when capturing front side. null
captureBackButtonText String? Text for capture button when capturing back side. null
saveButtonText String? Text for the "Save" button. null
nextButtonText String? Text for "Next" button (when moving from front to back). null
previousButtonText String? Text for "Previous" button (when going back to front). null
retakeButtonText String? Text for the "Retake" button. null
captureButtonStyle ButtonStyle? Style for the "Capture" button (optional). null
actionButtonStyle ButtonStyle? Style for action buttons (optional). null
retakeButtonStyle ButtonStyle? Style for the "Retake" button (optional). null
captureButtonAlignment Alignment? Alignment of the "Capture" button (optional). null
captureButtonPadding EdgeInsets? Padding for the "Capture" button (optional). null
captureButtonWidth double? Width for the "Capture" button (optional). null
captureButtonHeight double? Height for the "Capture" button (optional). null
actionButtonAlignment Alignment? Alignment of action buttons (optional). null
actionButtonPadding EdgeInsets? Padding for action buttons (optional). null
actionButtonWidth double? Width for action buttons (optional). null
actionButtonHeight double? Height for action buttons (optional). null
captureButtonTextStyle TextStyle? Text style for the "Capture" button text (optional). null
actionButtonTextStyle TextStyle? Text style for action buttons (optional). null
retakeButtonTextStyle TextStyle? Text style for the "Retake" button text (optional). null

DocumentCameraTitleStyle #

Property Type Description Default Value
title Widget? Widget to display as the screen's title (optional). null
frontSideTitle Widget? Custom title for front side capture. null
backSideTitle Widget? Custom title for back side capture. null
screenTitleAlignment Alignment? Alignment of the screen title (optional). null
screenTitlePadding EdgeInsets? Padding for the screen title (optional). null

DocumentCameraSideIndicatorStyle #

Property Type Description Default Value
showSideIndicator bool Show the side indicator (optional). true
topPosition double? Side indicator position from the top (optional). null
rightPosition double? Side indicator position from the right (optional). null
sideIndicatorBackgroundColor Color? Background color for side indicator. null
sideIndicatorBorderColor Color? Border color for side indicator. null
sideIndicatorActiveColor Color? Active color for side indicator. null
sideIndicatorInactiveColor Color? Inactive color for side indicator. null
sideIndicatorCompletedColor Color? Completed color for side indicator. null
sideIndicatorTextStyle TextStyle? Text style for side indicator text. null

DocumentCameraProgressStyle #

Property Type Description Default Value
progressIndicatorColor Color? Color for the progress indicator (optional). null
progressIndicatorHeight double Height of the progress indicator. 4.0

DocumentCameraInstructionStyle #

Property Type Description Default Value
showInstructionText bool Show the (static) top instruction text. true
frontSideInstruction String? Instruction text for front side capture. null
backSideInstruction String? Instruction text for back side capture. null
instructionTextStyle TextStyle? Text style for instruction text (optional). null

🔧 Troubleshooting #

Common Issues #

Camera not initializing:

  • ✅ Check camera permissions in device settings
  • ✅ Ensure minSdkVersion is at least 21 (Android)
  • ✅ Verify camera permissions in Info.plist (iOS)

Build errors:

  • 💡 Run flutter clean && flutter pub get
  • 💡 Confirm all platform-specific setup is complete
  • 💡 Ensure minimum iOS deployment target is 15.5 or higher in your ios/Podfile

Permission denied errors:

  • ⚠️ Handle permission errors gracefully in your app UI
  • ⚠️ Guide users to enable permissions in device settings

⚙️ Performance Tips #

  • 📱 The package automatically manages camera resources
  • 🗂️ Images are saved to the temporary directory by default
  • 🚫 Consider implementing proper error handling for production apps

📌 Full Example #

For a comprehensive example with multiple document types, see
example/main.dart.

Contributing #

Contributions are welcome! If you find a bug or have a feature request, please open an issue or submit a pull request.

🙌 Support #

License #

This project is licensed under the MIT License. See the LICENSE file for details.