flutter_web_record

pub package GitHub

A powerful Flutter web package for screen recording with audio support, pause/resume controls, customizable UI, and built-in preview functionality.

Features

  • πŸŽ₯ Screen Recording - Capture screen with customizable quality settings
  • 🎀 Multiple Audio Modes - System audio, microphone, both, or none
  • ⏸️ Pause/Resume - Full control during recording
  • 🎨 Customizable UI - Fully customizable recording indicator and controls
  • πŸ‘οΈ Preview Dialog - Optional preview before saving
  • πŸ“¦ Easy Integration - Returns video as bytes for upload/storage
  • 🌐 Web Only - Uses browser MediaRecorder API

Screenshots

Screen Share Selection

Screen Share Dialog

Recording Controls

Recording Controls

Preview Dialog

Preview Dialog

Recordings List

Recording List

Video Details & Playback

Video Details

Platform Support

Platform Support
Web βœ…
Android ❌
iOS ❌
Windows ❌
macOS ❌
Linux ❌

Browser Compatibility

Browser Support Notes
Chrome βœ… 72+ Full support
Edge βœ… 79+ Full support
Opera βœ… 60+ Full support
Safari βœ… tested on V26 Supported
Firefox ⚠️ Requires flag

Installation

Add this to your package's pubspec.yaml:

dependencies:
  flutter_web_record: ^0.1.0

Then run:

flutter pub get

Quick Start

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

class MyRecordingScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await ScreenRecorder.startRecording(
              context,
              onRecordingComplete: (result) {
                print('Recording saved: ${result.fileName}');
                print('Size: ${result.fileBytes.length} bytes');
                // Upload or process the video
              },
              onRecordingCancelled: () {
                print('Recording cancelled');
              },
            );
          },
          child: Text('Start Recording'),
        ),
      ),
    );
  }
}

Usage Examples

Basic Recording

final result = await ScreenRecorder.startRecording(
  context,
  onRecordingComplete: (result) {
    // Handle completed recording
    print('Duration: ${result.durationSeconds}s');
    print('File: ${result.fileName}');
  },
);

With Preview Dialog

await ScreenRecorder.startRecording(
  context,
  showPreview: true, // User can preview before saving
  onRecordingComplete: (result) {
    // Only called if user confirms in preview
    uploadVideo(result.fileBytes);
  },
);

Custom Quality Settings

await ScreenRecorder.startRecording(
  context,
  recordingConfig: RecordingConfig(
    idealWidth: 1920,
    idealHeight: 1080,
    idealFrameRate: 60,
    videoBitsPerSecond: 8000000, // 8 Mbps
    captureAudio: true,
    showCursor: true,
    audioCaptureMode: AudioCaptureMode.both, // System + Mic
  ),
);

Custom UI Styling

await ScreenRecorder.startRecording(
  context,
  indicatorConfig: RecordingIndicatorConfig(
    recordingColor: Colors.red,
    pausedColor: Colors.orange,
    backgroundColor: Colors.black87,
    position: Alignment.topLeft,
    borderRadius: 16.0,
    timeTextStyle: TextStyle(
      fontSize: 16,
      fontWeight: FontWeight.bold,
    ),
  ),
  controlConfig: ControlButtonConfig(
    pauseColor: Colors.blue,
    stopColor: Colors.red,
    cancelColor: Colors.grey,
    buttonSize: 40.0,
    iconSize: 20.0,
  ),
);

Audio Capture Modes

// No audio
audioCaptureMode: AudioCaptureMode.none

// System audio only (what you hear on computer)
audioCaptureMode: AudioCaptureMode.system

// Microphone only
audioCaptureMode: AudioCaptureMode.microphone

// Both system and microphone
audioCaptureMode: AudioCaptureMode.both

Custom Position

indicatorConfig: RecordingIndicatorConfig(
  // Use predefined positions
  position: Alignment.bottomRight,
  
  // Or use custom offset
  customOffset: Offset(20, 20),
)

With Logging

await ScreenRecorder.startRecording(
  context,
  enableLogging: true, // Logs to DevTools (debug mode only)
  onLog: (message, {level, error, stackTrace}) {
    // Custom logging callback
    if (level == RecordingLogLevel.error) {
      print('❌ ERROR: $message');
    } else {
      print('πŸ“Ή $message');
    }
  },
);

Disable Logging

await ScreenRecorder.startRecording(
  context,
  enableLogging: false, // Silent mode
);

Configuration Options

RecordingConfig

Property Type Default Description
idealWidth int 1920 Target video width
idealHeight int 1080 Target video height
idealFrameRate int 30 Target frame rate
videoBitsPerSecond int 5000000 Video bitrate (5 Mbps)
captureAudio bool true Enable audio capture
showCursor bool true Show cursor in recording
audioCaptureMode AudioCaptureMode system Audio source

RecordingIndicatorConfig

Property Type Default Description
recordingColor Color Colors.red Recording indicator color
pausedColor Color Colors.orange Paused state color
backgroundColor Color Colors.black87 Indicator background
borderWidth double 2.0 Border thickness
borderRadius double 12.0 Corner radius
position Alignment topRight Indicator position
customOffset Offset? null Custom position
timeTextStyle TextStyle? null Time display style
statusTextStyle TextStyle? null Status text style

ControlButtonConfig

Property Type Default Description
pauseIcon IconData? Icons.pause Pause button icon
playIcon IconData? Icons.play_arrow Resume button icon
stopIcon IconData? Icons.stop Stop button icon
cancelIcon IconData? Icons.close Cancel button icon
pauseColor Color Colors.orange Pause button color
stopColor Color Colors.red Stop button color
cancelColor Color Colors.grey Cancel button color
buttonSize double 32.0 Button size
iconSize double 18.0 Icon size
spacing double 8.0 Button spacing

RecordingResult

The RecordingResult object contains:

class RecordingResult {
  final Uint8List fileBytes;      // Video data
  final String fileName;           // Generated filename
  final String mimeType;           // 'video/webm'
  final String blobUrl;            // Blob URL for preview
  final int durationSeconds;       // Recording duration
  
  Map<String, dynamic> toMap();    // Convert to map
}

Logging

The package provides flexible logging options:

// View logs in Flutter DevTools (debug mode only)
enableLogging: true  // Default

// Custom logging callback
onLog: (message, {level, error, stackTrace}) {
  switch (level) {
    case RecordingLogLevel.debug:
      debugPrint('πŸ” $message');
      break;
    case RecordingLogLevel.info:
      print('ℹ️ $message');
      break;
    case RecordingLogLevel.warning:
      print('⚠️ $message');
      break;
    case RecordingLogLevel.error:
      print('❌ $message: $error');
      break;
  }
}

// Completely disable logging
enableLogging: false

Log Levels

  • RecordingLogLevel.debug - Detailed info (tracks, chunks)
  • RecordingLogLevel.info - General info (started, stopped)
  • RecordingLogLevel.warning - Warnings (mic unavailable)
  • RecordingLogLevel.error - Errors with stack traces

Permissions

The browser will prompt users to:

  1. Select screen/window/tab - Choose what to record
  2. Grant audio permissions - If audio capture is enabled

Users must grant these permissions for recording to work.

Common Use Cases

Upload to Server

onRecordingComplete: (result) async {
  final response = await http.post(
    Uri.parse('https://api.example.com/upload'),
    headers: {'Content-Type': 'video/webm'},
    body: result.fileBytes,
  );
  print('Uploaded: ${response.statusCode}');
}

Save to Local Storage

onRecordingComplete: (result) {
  // Trigger browser download
  final anchor = html.AnchorElement(href: result.blobUrl)
    ..setAttribute('download', result.fileName)
    ..click();
}

Convert to Base64

onRecordingComplete: (result) {
  final base64Video = base64Encode(result.fileBytes);
  // Send to API or save to database
}

Example App

Check the example folder for a complete working demo with all features.

To run the example:

cd example
flutter run -d chrome

Troubleshooting

Recording doesn't start

  • Ensure you're running on web platform
  • Check browser compatibility
  • User must grant screen capture permission

No audio in recording

  • Some browsers don't support system audio capture
  • Check audioCaptureMode setting
  • User must grant microphone permission

Poor video quality

  • Increase videoBitsPerSecond in RecordingConfig
  • Increase idealWidth and idealHeight
  • Increase idealFrameRate for smoother video

Large file sizes

  • Decrease videoBitsPerSecond
  • Lower idealWidth and idealHeight
  • Reduce idealFrameRate

Limitations

  • Web platform only (uses browser MediaRecorder API)
  • Safari not supported (no Screen Capture API)
  • System audio may not work in all browsers
  • WebM format only
  • Maximum recording length depends on browser memory

Contributing

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

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

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

Support

  • πŸ“§ Report issues on GitHub
  • πŸ’¬ Questions? Open a discussion
  • ⭐ Star the repo if you find it useful!

Changelog

See CHANGELOG.md for version history.

Libraries

flutter_web_record