extractor 1.0.0 copy "extractor: ^1.0.0" to clipboard
extractor: ^1.0.0 copied to clipboard

PlatformAndroid

A robust Flutter plugin for downloading videos and audio from 1000+ websites using yt-dlp. Features quality selection, format conversion, progress tracking, and more.

Extractor - Flutter Video Downloader Plugin #

A robust, production-ready Flutter plugin for downloading videos and audio from 1000+ websites using yt-dlp. Built with native Android (Kotlin) implementation.

Platform License

Platform Support #

Platform Status Implementation
Android βœ… Fully Supported Native Kotlin + youtubedl-android
iOS πŸ’‘ Open for Contributions See iOS Support below

πŸ“± Screenshots (example app) #

Main Screen - Quality Selection Download in Progress Downloads Page
Quality Selection
Browse and select video quality
Download Progress
Real-time progress with logs
Downloads Manager
View completed downloads
Settings - Version Info Settings - Features
Version Information
Check library versions
Features List
All plugin capabilities

✨ Features #

Core Functionality #

  • πŸŽ₯ Download videos from 1000+ websites (YouTube, Vimeo, Dailymotion, etc.)
  • 🎡 Extract audio with format conversion (MP3, M4A, WAV, FLAC, AAC, OPUS)
  • πŸ“Š Get video information (title, duration, formats, thumbnails, metadata)
  • 🎬 Format selection - Choose quality, resolution, codec
  • πŸ“ Subtitle support - Download and embed subtitles in multiple languages
  • πŸ–ΌοΈ Thumbnail embedding - Embed video thumbnails in audio files
  • πŸ“‹ Metadata embedding - Add title, artist, album info
  • ⚑ Aria2c integration - Faster downloads with external downloader
  • πŸ”„ Progress tracking - Real-time progress updates with ETA
  • ⏸️ Download management - Cancel, pause, resume downloads
  • πŸ”„ Update yt-dlp - Update to latest stable version

Advanced Features #

  • 🎯 Download templates - Pre-configured quality presets (Best, 1080p, 720p, 480p, Audio Only, Small Size)
  • 🎨 Custom format strings - Advanced format selection with yt-dlp syntax
  • πŸ”§ Custom yt-dlp options - Pass any yt-dlp command-line option
  • πŸ“¦ Playlist support - Download entire playlists or individual videos
  • 🎭 Chapter support - Preserve video chapters
  • 🌐 Multi-language subtitles - Download subtitles in any language
  • πŸ” Cookie support - Use cookies for authentication (planned)
  • πŸ“± Scoped storage - Android 10+ compliant storage handling

Architecture & Code Quality #

  • πŸ—οΈ Clean Architecture - SOLID principles with separation of concerns
  • πŸ”’ Type-safe Communication - Pigeon for compile-time type safety
  • 🧩 Service Layer Pattern - LibraryService, UpdateService, InfoService, DownloadService
  • 🧡 Thread Safety - Proper threading with coroutines (Android)
  • πŸ“ Well Documented - Comprehensive API documentation
  • βœ… Production Ready - Battle-tested architecture

Example App Features #

  • 🎨 Material Design 3 - Modern UI with dynamic colors
  • πŸ“± Inline Format Selection - Horizontal scrollable quality cards
  • πŸ“₯ Downloads Manager - View and manage downloaded files
  • πŸ’Ύ Save to Gallery - Export videos to public storage
  • πŸ“Š File Management - View info, share, delete files
  • βš™οΈ Settings Page - Version info, updates, library management
  • πŸŒ“ Dark Mode - Automatic theme switching

πŸ“¦ Installation #

Add to your pubspec.yaml:

dependencies:
  extractor: latest

Android Requirements #

Minimum SDK version (API 24+):

android {
    defaultConfig {
        minSdk = 24
    }
}

Required: Set extractNativeLibs in AndroidManifest.xml:

<application
    android:extractNativeLibs="true"
    ...>

πŸš€ Quick Start #

Initialize #

import 'package:extractor/extractor.dart';

final youtubeDL = YoutubeDLFlutter.instance;

// Initialize with FFmpeg and Aria2c
final result = await youtubeDL.initialize(
  enableFFmpeg: true,
  enableAria2c: true,
);

if (result.success) {
  print('Initialized successfully');
} else {
  print('Error: ${result.errorMessage}');
}

Get Video Information #

try {
  final info = await youtubeDL.getVideoInfo('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
  
  print('Title: ${info.title}');
  print('Duration: ${info.duration} seconds');
  print('Uploader: ${info.uploader}');
  print('Thumbnail: ${info.thumbnail}');
  print('Available formats: ${info.formats?.length}');
  
  // List all formats
  info.formats?.forEach((format) {
    print('Format: ${format?.formatId} - ${format?.resolution} - ${format?.ext}');
  });
} catch (e) {
  print('Error: $e');
}

Download Video #

import 'dart:io';
import 'package:path_provider/path_provider.dart';

// Get download directory
final dir = await getExternalStorageDirectory();
final downloadPath = '${dir!.path}/Downloads';

// Create download request
final request = DownloadRequest(
  url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
  outputPath: downloadPath,
  outputTemplate: '%(title)s.%(ext)s',
  format: 'bestvideo+bestaudio/best', // Best quality
  processId: 'download_${DateTime.now().millisecondsSinceEpoch}',
  embedThumbnail: true,
  embedMetadata: true,
  customOptions: {
    '--downloader': 'libaria2c.so', // Use Aria2c for faster downloads
  },
);

// Start download
try {
  final result = await youtubeDL.download(request);
  
  if (result.status == OperationStatus.success) {
    print('Downloaded to: ${result.outputPath}');
  } else {
    print('Download failed: ${result.errorMessage}');
  }
} catch (e) {
  print('Error: $e');
}

Download Audio Only #

final request = DownloadRequest(
  url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
  outputPath: downloadPath,
  outputTemplate: '%(title)s.%(ext)s',
  extractAudio: true,
  audioFormat: 'mp3',
  audioQuality: 0, // Best quality (0-9, 0 is best)
  embedThumbnail: true,
  embedMetadata: true,
  processId: 'audio_${DateTime.now().millisecondsSinceEpoch}',
);

final result = await youtubeDL.download(request);

Track Download Progress #

// Listen to progress updates
youtubeDL.onProgress.listen((progress) {
  print('Process: ${progress.processId}');
  print('Progress: ${progress.progress}%');
  print('ETA: ${progress.eta.inSeconds} seconds');
});

// Listen to state changes
youtubeDL.onStateChanged.listen((state) {
  print('Process: ${state.processId}');
  print('State: ${state.state}'); // started, completed, cancelled
});

// Listen to errors
youtubeDL.onError.listen((error) {
  print('Process: ${error.processId}');
  print('Error: ${error.error}');
});

Cancel Download #

final cancelled = await youtubeDL.cancelDownload(processId: 'download_123');
if (cancelled) {
  print('Download cancelled');
}

Update yt-dlp #

final result = await youtubeDL.updateYoutubeDL(channel: UpdateChannel.stable);

if (result.status == OperationStatus.success) {
  print('Updated to: ${result.version}');
} else {
  print('Update failed: ${result.errorMessage}');
}

Get Version Information #

final versionInfo = await youtubeDL.getVersion();

print('yt-dlp: ${versionInfo.youtubeDlVersion}');
print('FFmpeg: ${versionInfo.ffmpegVersion}');
print('Python: ${versionInfo.pythonVersion}');

πŸ“š Download Templates #

Pre-configured quality presets for common use cases:

import 'package:extractor/extractor.dart';

// Best Quality (highest resolution + audio)
final bestQuality = DownloadTemplates.bestQuality(
  url: videoUrl,
  outputPath: downloadPath,
);

// Audio Only (best quality)
final audioOnly = DownloadTemplates.audioOnly(
  url: videoUrl,
  outputPath: downloadPath,
  audioFormat: 'mp3',
);

// 1080p Video
final video1080p = DownloadTemplates.video1080p(
  url: videoUrl,
  outputPath: downloadPath,
);

// 720p Video
final video720p = DownloadTemplates.video720p(
  url: videoUrl,
  outputPath: downloadPath,
);

// 480p Video
final video480p = DownloadTemplates.video480p(
  url: videoUrl,
  outputPath: downloadPath,
);

// Small Size (best video under 100MB)
final smallSize = DownloadTemplates.smallSize(
  url: videoUrl,
  outputPath: downloadPath,
);

// Use template
final result = await youtubeDL.download(bestQuality);

🎯 Advanced Usage #

Custom Format Selection #

// Download specific format by ID
final request = DownloadRequest(
  url: videoUrl,
  outputPath: downloadPath,
  format: '137+140', // Format IDs from getVideoInfo()
);

// Download best video with height <= 720p
final request = DownloadRequest(
  url: videoUrl,
  outputPath: downloadPath,
  format: 'bestvideo[height<=720]+bestaudio/best[height<=720]',
);

// Download best MP4 video
final request = DownloadRequest(
  url: videoUrl,
  outputPath: downloadPath,
  format: 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]',
);

Subtitle Download #

final request = DownloadRequest(
  url: videoUrl,
  outputPath: downloadPath,
  writeSubtitles: true,
  writeAutoSubtitles: true,
  embedSubtitles: true,
  subtitlesLang: 'en,es,fr', // Multiple languages
);

Custom yt-dlp Options #

final request = DownloadRequest(
  url: videoUrl,
  outputPath: downloadPath,
  customOptions: {
    '--no-playlist': '', // Don't download playlist
    '--max-downloads': '5', // Limit downloads
    '--rate-limit': '1M', // Limit download speed
    '--retries': '10', // Retry attempts
    '--fragment-retries': '10',
    '--skip-unavailable-fragments': '',
    '--no-mtime': '', // Don't use Last-modified header
    '--no-update': '', // Suppress update warning
  },
);

Playlist Handling #

// Download entire playlist
final request = DownloadRequest(
  url: 'https://www.youtube.com/playlist?list=...',
  outputPath: downloadPath,
  noPlaylist: false, // Allow playlist
  outputTemplate: '%(playlist_index)s - %(title)s.%(ext)s',
);

// Download only first video from playlist
final request = DownloadRequest(
  url: 'https://www.youtube.com/playlist?list=...',
  outputPath: downloadPath,
  noPlaylist: true, // Skip playlist
);

πŸ“± Example App #

The example app demonstrates all features:

  • Main Page: URL input, video info display, inline format selection
  • Downloads Page: View downloaded files, save to gallery, file management
  • Settings Page: Version info, update yt-dlp, library information

Run the example:

cd example
flutter run

πŸ—οΈ Architecture #

Service Layer #

ExtractorPlugin (Main)
    └── YoutubeDLManager (Coordinator)
            β”œβ”€β”€ LibraryService (Initialization & Versions)
            β”œβ”€β”€ UpdateService (Binary Updates)
            β”œβ”€β”€ InfoService (Video Information)
            β”œβ”€β”€ DownloadService (Downloads & Progress)
            └── VideoInfoMapper (JSON Mapping)

Communication #

  • Pigeon: Type-safe communication between Dart and native code
  • Streams: Real-time progress updates via Dart streams
  • Coroutines: Async operations on Android

πŸ“Š Supported Platforms #

Video Platforms (1000+) #

YouTube, Vimeo, Dailymotion, Facebook, Instagram, Twitter, TikTok, Reddit, Twitch, SoundCloud, Bandcamp, and many more.

Audio Formats #

MP3, M4A, WAV, FLAC, AAC, OPUS, OGG, VORBIS

Video Formats #

MP4, MKV, WEBM, AVI, FLV, MOV

Subtitle Formats #

SRT, VTT, ASS, LRC

πŸ”§ Troubleshooting #

Android #

Build Error: NDK version mismatch

// In android/app/build.gradle
android {
    ndkVersion = "27.0.12077973"
}

Build Error: extractNativeLibs

  • Ensure android:extractNativeLibs="true" is set in AndroidManifest.xml
  • This is required for the plugin to extract native libraries

Update Failed

  • Check internet connection
  • Ensure sufficient storage space
  • Try again later (GitHub API rate limits)

Download Failed

  • Verify the URL is supported (check supported sites)
  • Check internet connection
  • Try updating yt-dlp to the latest version
  • Some sites may require cookies or authentication

πŸ’‘ iOS Support #

Currently, this plugin only supports Android. iOS implementation is open for contributions!

If you're interested in adding iOS support, here are some approaches to consider:

  1. Rust + FFI: Use Rust with flutter_rust_bridge for cross-platform yt-dlp integration
  2. Native Swift: Port the Android implementation to Swift/Objective-C
  3. Server-side: Implement a backend service for video processing (recommended for App Store apps)

Feel free to open an issue or pull request if you'd like to contribute iOS support!

πŸ“ API Reference #

Core Methods #

initialize()

Initialize the library with configuration.

Future<InitResult> initialize({
  bool enableFFmpeg = true,
  bool enableAria2c = false,
})

getVideoInfo()

Get video information without downloading.

Future<VideoInfo> getVideoInfo(String url)

Returns: VideoInfo with title, duration, formats, thumbnail, uploader, etc.

download()

Download a video with specified configuration.

Future<DownloadResult> download(DownloadRequest request)

cancelDownload()

Cancel an active download by process ID.

Future<bool> cancelDownload(String processId)

updateYoutubeDL()

Update yt-dlp binary to the latest version.

Future<UpdateResult> updateYoutubeDL({
  UpdateChannel channel = UpdateChannel.stable,
})

getVersion()

Get version information for yt-dlp, FFmpeg, and Python.

Future<VersionInfo> getVersion()

Streams #

Listen to real-time updates:

// Progress updates
Stream<DownloadProgress> get onProgress

// State changes (started, completed, cancelled)
Stream<DownloadState> get onStateChanged

// Errors
Stream<DownloadError> get onError

// Logs (yt-dlp output)
Stream<LogMessage> get onLog

Key Models #

DownloadRequest

DownloadRequest({
  required String url,
  required String outputPath,
  String? outputTemplate,        // e.g., '%(title)s.%(ext)s'
  String? format,                 // e.g., 'bestvideo+bestaudio/best'
  bool noPlaylist = true,
  bool extractAudio = false,
  String? audioFormat,            // 'mp3', 'm4a', 'wav', etc.
  int? audioQuality,              // 0-9 (0 is best)
  bool embedThumbnail = false,
  bool embedMetadata = false,
  bool embedSubtitles = false,
  String? subtitlesLang,
  bool writeSubtitles = false,
  bool writeAutoSubtitles = false,
  Map<String, String>? customOptions,
  String? processId,
})

VideoInfo

class VideoInfo {
  String? id, title, description;
  String? uploader, uploaderId, uploaderUrl;
  String? channelId, channelUrl;
  int? duration, viewCount, likeCount;
  String? thumbnail, url;
  List<VideoFormat?>? formats;
  String? ext;
  int? width, height, fps;
  String? vcodec, acodec;
}

VideoFormat

class VideoFormat {
  String? formatId, formatNote, ext, url;
  int? width, height, fps, filesize, tbr;
  String? vcodec, acodec, resolution;
}

FormatHelper Utilities #

// Get best video/audio formats
FormatHelper.getBestVideo(formats)
FormatHelper.getBestAudio(formats)

// Filter by resolution
FormatHelper.getFormatsByResolution(formats, minHeight, maxHeight)

// Get specific format types
FormatHelper.getAudioFormats(formats)
FormatHelper.getVideoFormats(formats)

// Format utilities
FormatHelper.formatFileSize(bytes)        // "50.00 MB"
FormatHelper.formatResolution(format)     // "1920x1080"
FormatHelper.getFormatDescription(format) // "1080p β€’ mp4 β€’ 50.00 MB"

🀝 Contributing #

See CONTRIBUTING.md for contribution guidelines.

πŸ“„ License #

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

This plugin uses open-source libraries including youtubedl-android (GPL-3.0). See LICENSE file for third-party acknowledgments.

πŸ™ Credits #

πŸ“š Documentation #

⚑ Performance #

  • Fast Downloads: Aria2c integration for multi-connection downloads
  • Efficient: Lazy extractors for faster startup
  • Optimized: Native code for best performance
  • Scalable: Handle multiple concurrent downloads

πŸ”’ Security #

  • Scoped Storage: Android 10+ compliant
  • Permission Minimal: Only requests necessary permissions
  • Type-Safe: Compile-time type checking with Pigeon

πŸ“ˆ Version Information #

  • Plugin Version: 1.0.0
  • youtubedl-android: v0.18.1
  • yt-dlp: 2025.11.12 (bundled, updatable)
  • FFmpeg: 6.0 (bundled)
  • Python: 3.8 (bundled)
  • Minimum Android: API 24 (Android 7.0)

Made with ❀️ by Ashish Pipaliya

⭐ Star this repo if you find it useful!

41
likes
160
points
128
downloads

Publisher

verified publisherashiish.space

Weekly Downloads

A robust Flutter plugin for downloading videos and audio from 1000+ websites using yt-dlp. Features quality selection, format conversion, progress tracking, and more.

Repository (GitHub)
View/report issues
Contributing

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on extractor

Packages that implement extractor