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

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 recordingFuture<void> stop()- Stop recordingFuture<void> clearCacheFolder(String cacheFolder)- Clear cached filesExporter get exporter- Get exporter instanceDuration? get duration- Get recording duration
Exporter
Handles video export operations.
Methods:
Future<File?> exportVideo({...})- Export recorded video
Parameters:
ValueChanged<ExportResult>? onProgress- Progress callbackbool 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 recordingstatic Future<bool> stopRecording()- Stop recordingstatic Future<String?> exportVideo({required String outputPath})- Export videostatic Future<bool> isSupported()- Check if native recording is supportedstatic Future<bool> isRecording()- Check if currently recording
Example
See the example folder for a complete working example.
Technical Details
Recording Process
- Capture: Native APIs (MediaProjection/ReplayKit) record the full screen
- Export: Video is exported to temporary location
- Crop: If
recordingRectis specified, FFmpeg crops the video to that region - 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
recordingRectis 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: