Native screen recording library using platform-specific APIs.
Main controller for managing native screen recording operations.
ScreenRecorderController({
Rect? recordingRect,
})recordingRect(Rect?): Optional recording area. If null, records the entire screen
exporter(Exporter): Get the exporter instance for this controllerduration(Duration?): Get the duration of the recordingrecordingRect(Rect?): The recording region coordinates
static Rect? getWidgetRect(GlobalKey key)Get the screen position and size of a widget using its GlobalKey.
Parameters:
key(GlobalKey): The GlobalKey attached to the widget
Returns: Rect? - The widget's position and size, or null if not mounted/visible
Example:
final key = GlobalKey();
// ... attach key to widget ...
final rect = ScreenRecorderController.getWidgetRect(key);
if (rect != null) {
final controller = ScreenRecorderController(recordingRect: rect);
}Future<void> start()Starts native screen recording.
Returns: Future
Throws: May throw if recording fails to start
Example:
final controller = ScreenRecorderController(
recordingRect: Rect.fromLTWH(0, 0, 400, 400),
);
await controller.start();Future<void> stop()Stops the current recording.
Returns: Future
Example:
await controller.stop();Future<void> clearCacheFolder(String cacheFolder)Clears all files in the specified cache folder.
Parameters:
cacheFolder(String): Name of the cache folder to clear
Returns: Future
Example:
await controller.clearCacheFolder("my_recordings");Static class for native screen recording operations.
static Future<bool> startRecording({
double? x,
double? y,
double? width,
double? height,
})Starts native screen recording with optional coordinates.
Parameters:
x(double?): X coordinate of recording areay(double?): Y coordinate of recording areawidth(double?): Width of recording areaheight(double?): Height of recording area
Returns: Future - true if recording started successfully
Example:
// Record entire screen
final success = await NativeScreenRecorder.startRecording();
// Record specific region
final success = await NativeScreenRecorder.startRecording(
x: 100,
y: 100,
width: 400,
height: 400,
);static Future<bool> stopRecording()Stops the current native recording.
Returns: Future - true if stopped successfully
Example:
final success = await NativeScreenRecorder.stopRecording();static Future<String?> exportVideo({
required String outputPath,
})Exports the recorded video to a file.
Parameters:
outputPath(String): Path where video should be saved
Returns: Future<String?> - Path to exported video or null if failed
Example:
final videoPath = await NativeScreenRecorder.exportVideo(
outputPath: '/path/to/output.mp4',
);static Future<bool> isSupported()Checks if native screen recording is supported on this platform.
Returns: Future - true if supported (Android 21+ or iOS 11.0+)
Example:
final supported = await NativeScreenRecorder.isSupported();
if (supported) {
// Use native recording
}static Future<bool> isRecording()Checks if recording is currently active.
Returns: Future - true if recording
Example:
final recording = await NativeScreenRecorder.isRecording();Handles video export operations.
Exporter(ScreenRecorderController controller)Created automatically via controller.exporter.
Future<File?> exportVideo({
ValueChanged<ExportResult>? onProgress,
bool multiCache = false,
String cacheFolder = "ScreenRecordVideos",
})Exports the recorded content as a video file. If a recordingRect was specified in the controller, the video will be automatically cropped to that region using FFmpeg.
Parameters:
onProgress(ValueChanged?): Progress callbackmultiCache(bool): Create unique filename for each export. Default: falsecacheFolder(String): Folder for cached videos. Default: "ScreenRecordVideos"
Returns: Future<File?> - Exported (and optionally cropped) video file or null if failed
Export Process:
- Export full screen recording to temporary location
- If
recordingRectis set, crop video using FFmpeg - Save final video to cache folder
- Delete temporary files
Example:
final file = await controller.exporter.exportVideo(
multiCache: true,
cacheFolder: "my_videos",
onProgress: (result) {
print('Progress: ${result.status} - ${result.percent}');
},
);Status of export operation.
enum ExportStatus {
exporting, // Export in progress
cropping, // Cropping video (FFmpeg)
encoding, // Encoding video
encoded, // Encoding complete
exported, // Export complete
failed, // Export failed
}Result of export operation.
status(ExportStatus): Current export statusfile(File?): Exported file (when status is exported)percent(double?): Progress percentage (0.0 to 1.0)
ExportResult({
required ExportStatus status,
File? file,
double? percent,
})Example:
ExportResult(
status: ExportStatus.exported,
file: myVideoFile,
percent: 1.0,
)import 'package:flutter/material.dart';
import 'package:screen_record_plus/screen_record_plus.dart';
class RecordingExample extends StatefulWidget {
@override
State<RecordingExample> createState() => _RecordingExampleState();
}
class _RecordingExampleState extends State<RecordingExample> {
late ScreenRecorderController controller;
bool isRecording = false;
@override
void initState() {
super.initState();
// Check native support
NativeScreenRecorder.isSupported().then((supported) {
if (supported) {
// Initialize controller
controller = ScreenRecorderController(
recordingRect: Rect.fromLTWH(0, 0, 400, 400),
);
}
});
}
Future<void> startRecording() async {
await controller.start();
setState(() => isRecording = true);
}
Future<void> stopAndExport() async {
await controller.stop();
setState(() => isRecording = false);
final file = await controller.exporter.exportVideo(
multiCache: true,
onProgress: (result) {
print('Export: ${result.status} - ${result.percent}');
},
);
if (file != null) {
print('Video saved to: ${file.path}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: isRecording ? stopAndExport : startRecording,
child: Icon(isRecording ? Icons.stop : Icons.play_arrow),
),
);
}
}- Requires user permission for screen recording
- Permission dialog appears on first recording attempt
- Minimum API level: 21 (Android 5.0 Lollipop)
- Uses MediaProjection + MediaRecorder
- Output: MP4 with H.264 encoding at 30fps, 5 Mbps
- Requires
NSMicrophoneUsageDescriptionin Info.plist - Works on iOS 11.0 and later
- Uses ReplayKit (RPScreenRecorder)
- Output: MP4 with H.264 encoding
- FFmpeg is used for post-recording video cropping
- Cropping happens automatically during export when
recordingRectis specified - Full screen is recorded, then cropped to specified region
- Package size increases by ~100MB due to FFmpeg inclusion
- No quality loss during cropping (uses stream copy for audio)
-
Always check native support before using:
final supported = await NativeScreenRecorder.isSupported();
-
Handle errors gracefully:
try { await controller.start(); } catch (e) { print('Recording failed: $e'); }
-
Clean up resources:
await controller.clearCacheFolder("recordings");
-
Monitor export progress:
await exporter.exportVideo( onProgress: (result) { // Update UI with progress }, );
-
Use coordinate recording for specific regions:
// Record only a specific area ScreenRecorderController( recordingRect: Rect.fromLTWH(100, 100, 400, 400), )