screen_record_plus 1.1.0 copy "screen_record_plus: ^1.1.0" to clipboard
screen_record_plus: ^1.1.0 copied to clipboard

Native screen recording with coordinate-based capture for Android and iOS.

Screen Record Plus #

Native screen recording library for Flutter using platform-specific APIs (Android MediaProjection and iOS ReplayKit) with FFmpeg-powered region cropping.

Features #

  • ✅ Native screen recording (Android & iOS)
  • ✅ Region-specific recording with automatic video cropping
  • ✅ Widget-based recording using GlobalKey
  • ✅ Video export with customizable settings
  • ✅ High-quality MP4 output with H.264 encoding

Demo

Platform Support #

Platform Minimum Version API Used
Android API 21 (Lollipop) MediaProjection + MediaRecorder
iOS 11.0 ReplayKit (RPScreenRecorder)

Installation #

Add to your pubspec.yaml:

dependencies:
  screen_record_plus: ^1.0.0

Usage #

Basic Recording #

import 'package:screen_record_plus/screen_record_plus.dart';

// Create controller
final controller = ScreenRecorderController();

// Start recording (full screen)
await controller.start();

// Stop recording
await controller.stop();

// Export video
final file = await controller.exporter.exportVideo(
  multiCache: true,
  cacheFolder: "my_recordings",
);

print('Video saved to: ${file?.path}');

Recording with Coordinates #

Capture a specific region of the screen. The full screen is recorded, then the video is automatically cropped to the specified region during export:

// Record a 400x400 region starting at position (100, 100)
final controller = ScreenRecorderController(
  recordingRect: Rect.fromLTWH(100, 100, 400, 400),
);

await controller.start();
// ... recording ...
await controller.stop();
final file = await controller.exporter.exportVideo(); // Automatically cropped

How it works: The native APIs record the full screen, then FFmpeg crops the video to your specified region during export. This ensures you only get the part of the screen you want.

Recording a Specific Widget #

Easily record a specific widget using GlobalKey:

// Create a GlobalKey and attach it to your widget
final key = GlobalKey();

Widget build(BuildContext context) {
  return Container(
    key: key,
    child: YourWidget(),
  );
}

// Get the widget's position and size
final rect = ScreenRecorderController.getWidgetRect(key);
if (rect != null) {
  final controller = ScreenRecorderController(recordingRect: rect);
  await controller.start();
  // ... recording ...
  await controller.stop();
  final file = await controller.exporter.exportVideo();
}

Check Platform Support #

final isSupported = await NativeScreenRecorder.isSupported();
if (isSupported) {
  // Start recording
}

Export with Progress Callback #

await controller.exporter.exportVideo(
  multiCache: false,
  cacheFolder: "recordings",
  onProgress: (result) {
    print('Status: ${result.status}, Progress: ${result.percent}');
  },
);

Platform-Specific Setup #

Android #

Add permissions to AndroidManifest.xml:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

Note: User will be prompted for screen recording permission on first use.

iOS #

Add to your Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access for screen recording</string>

Minimum iOS version: 11.0

API Reference #

ScreenRecorderController #

Main controller for screen recording.

ScreenRecorderController({
  Rect? recordingRect,  // Optional: specify recording region
})

Methods:

  • Future<void> start() - Start recording
  • Future<void> stop() - Stop recording
  • Future<void> clearCacheFolder(String cacheFolder) - Clear cached files
  • Exporter get exporter - Get exporter instance
  • Duration? get duration - Get recording duration

Exporter #

Handles video export operations.

Methods:

  • Future<File?> exportVideo({...}) - Export recorded video

Parameters:

  • ValueChanged<ExportResult>? onProgress - Progress callback
  • bool multiCache - Create unique filename for each export (default: false)
  • String cacheFolder - Cache folder name (default: "ScreenRecordVideos")

NativeScreenRecorder #

Static class for native platform operations.

Methods:

  • static Future<bool> startRecording({double? x, y, width, height}) - Start native recording
  • static Future<bool> stopRecording() - Stop recording
  • static Future<String?> exportVideo({required String outputPath}) - Export video
  • static Future<bool> isSupported() - Check if native recording is supported
  • static Future<bool> isRecording() - Check if currently recording

Example #

See the example folder for a complete working example.

Technical Details #

Recording Process #

  1. Capture: Native APIs (MediaProjection/ReplayKit) record the full screen
  2. Export: Video is exported to temporary location
  3. Crop: If recordingRect is specified, FFmpeg crops the video to that region
  4. Output: Final cropped video is saved to cache folder

Android Implementation #

  • Uses MediaProjection API for screen capture
  • MediaRecorder for video encoding
  • H.264 codec at 30fps, 5 Mbps bitrate
  • Outputs MP4 format

iOS Implementation #

  • Uses ReplayKit (RPScreenRecorder) for screen capture
  • AVAssetWriter for video encoding
  • H.264 codec with configurable quality
  • Outputs MP4 format

Video Cropping #

  • Uses FFmpeg for post-recording video cropping
  • Cropping happens automatically during export when recordingRect is specified
  • No quality loss during cropping (uses stream copy for audio)
  • Note: Package size increases by ~100MB due to FFmpeg inclusion

Migration from v0.x #

Version 1.0.0 removed widget-based recording mode. Version 1.1.0 re-adds FFmpeg for video cropping functionality. If you were using:

Before (v0.x):

ScreenRecorderController(
  recordingMode: RecordingMode.widget,  // Removed
  pixelRatio: 3.0,                      // Removed
  skipFramesBetweenCaptures: 2,         // Removed
)

After (v1.0.0):

ScreenRecorderController(
  recordingRect: Rect.fromLTWH(0, 0, 400, 400),  // Optional
)

The ScreenRecorder widget is no longer needed. All recording is now done using native platform APIs.

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

See LICENSE file for details.

App Demo #

Store: