flutter_ytdlp_plugin 0.0.3 copy "flutter_ytdlp_plugin: ^0.0.3" to clipboard
flutter_ytdlp_plugin: ^0.0.3 copied to clipboard

A Flutter plugin for YouTube video streaming using yt-dlp. Supports fetching video formats, related videos, and more.

example/lib/main.dart

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'YT-DLP Plugin Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: YTDLPClass(),
    );
  }
}

class YTDLPClass extends StatefulWidget {
  const YTDLPClass({super.key});

  @override
  State<YTDLPClass> createState() => _YTDLPExamplePageState();
}

class _YTDLPExamplePageState extends State<YTDLPClass> {
  final ytdlp = FlutterYtdlpPlugin();

  String output = 'Initializing...';
  bool isInitialized = false;

  @override
  void initState() {
    super.initState();
    _initializePlugin();
  }

  Future<void> _initializePlugin() async {
    try {
      await ytdlp.initialize();
      setState(() {
        isInitialized = true;
        output = 'YT-DLP Initialized Successfully!';
      });
    } catch (e) {
      setState(() {
        isInitialized = false;
        output = 'Initialization failed: $e';
      });
    }
  }

  Future<void> testGetStreamingLinks() async {
    try {
      final links = await FlutterYtdlpPlugin.getStreamingLinks(
        title: "Flutter Tutorial",
        channelName: "Flutter",
      );
      setState(() {
        output = 'Streaming Links:\n${links.toString()}';
      });
    } catch (e) {
      setState(() => output = 'Error: $e');
    }
  }

  Future<void> testGetVideoDetails() async {
    try {
      final details = await FlutterYtdlpPlugin.getVideoDetailsWithFormats(
        videoId: "dQw4w9WgXcQ", // Example video ID
      );
      setState(() {
        output = 'Video Details:\n${details.toString()}';
      });
    } catch (e) {
      setState(() => output = 'Error: $e');
    }
  }

  Future<void> testSearchVideos() async {
    try {
      final results = await FlutterYtdlpPlugin.searchVideos(
        query: "Flutter Tutorial",
        maxResults: 5,
      );
      setState(() {
        output = 'Search Results (${results.length}):\n';
        for (var video in results.take(3)) {
          // output += '${video.title}\n'; Can get upto 20 video details at once
        }
      });
    } catch (e) {
      setState(() => output = 'Error: $e');
    }
  }

  Future<void> testGetTrendingVideos() async {
    try {
      final videos = await FlutterYtdlpPlugin.getTrendingVideos(count: 5);
      setState(() {
        output = 'Trending Videos (${videos.length}):\n';
        for (var video in videos.take(3)) {
          // output += '${video.title}\n'; Can get upto 200 video details at once
        }
      });
    } catch (e) {
      setState(() => output = 'Error: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('YT-DLP Plugin Demo')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Expanded(child: SingleChildScrollView(child: Text(output))),
            const SizedBox(height: 20),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton(
                  onPressed: testGetStreamingLinks,
                  child: const Text('Get Streaming Links'),
                ),
                ElevatedButton(
                  onPressed: testGetVideoDetails,
                  child: const Text('Get Video Details'),
                ),
                ElevatedButton(
                  onPressed: testSearchVideos,
                  child: const Text('Search Videos'),
                ),
                ElevatedButton(
                  onPressed: testGetTrendingVideos,
                  child: const Text('Get Trending'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// Model Classes aligned with the output of above methods

// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================

/// Represents a video stream format with all technical details
/// Example: 1080p MP4 stream with H.264 codec
class VideoFormat {
  final String formatId; // Unique identifier for this format (e.g., "137")
  final String url; // Direct URL to the video stream
  final String ext; // File extension (e.g., "mp4", "webm")
  final int quality; // Quality score (higher is better)
  final String resolution; // Display resolution (e.g., "1920x1080")
  final int height; // Video height in pixels
  final int width; // Video width in pixels
  final int fps; // Frames per second
  final int filesize; // File size in bytes
  final int tbr; // Total bitrate (kbps)
  final int vbr; // Video bitrate (kbps)
  final int abr; // Audio bitrate (kbps)
  final String acodec; // Audio codec (e.g., "mp4a.40.2")
  final String vcodec; // Video codec (e.g., "avc1.640028")
  final String formatNote; // Human-readable format description
  final String protocol; // Streaming protocol (e.g., "https")

  VideoFormat({
    required this.formatId,
    required this.url,
    required this.ext,
    required this.quality,
    required this.resolution,
    required this.height,
    required this.width,
    required this.fps,
    required this.filesize,
    required this.tbr,
    required this.vbr,
    required this.abr,
    required this.acodec,
    required this.vcodec,
    required this.formatNote,
    required this.protocol,
  });

  /// Example:
  /// {
  ///   "formatId": "137",
  ///   "url": "https://example.com/video.mp4",
  ///   "ext": "mp4",
  ///   "quality": 1080,
  ///   "resolution": "1920x1080",
  ///   "height": 1080,
  ///   "width": 1920,
  ///   "fps": 30,
  ///   "filesize": 25678900,
  ///   "tbr": 1500,
  ///   "vbr": 1350,
  ///   "abr": 150,
  ///   "acodec": "mp4a.40.2",
  ///   "vcodec": "avc1.640028",
  ///   "formatNote": "1080p",
  ///   "protocol": "https"
  /// }
  factory VideoFormat.fromJson(Map<String, dynamic> json) => VideoFormat(
    formatId: json['formatId'] ?? '',
    url: json['url'] ?? '',
    ext: json['ext'] ?? '',
    quality: json['quality'] ?? 0,
    resolution: json['resolution'] ?? '',
    height: json['height'] ?? 0,
    width: json['width'] ?? 0,
    fps: json['fps'] ?? 0,
    filesize: json['filesize'] ?? 0,
    tbr: json['tbr'] ?? 0,
    vbr: json['vbr'] ?? 0,
    abr: json['abr'] ?? 0,
    acodec: json['acodec'] ?? '',
    vcodec: json['vcodec'] ?? '',
    formatNote: json['formatNote'] ?? '',
    protocol: json['protocol'] ?? '',
  );
}

// ==================================================================================================================

/// Represents an audio-only stream format
/// Example: 256kbps AAC audio stream
class AudioFormat {
  final String formatId; // Unique format identifier (e.g., "140")
  final String url; // Direct URL to audio stream
  final String ext; // File extension (e.g., "m4a")
  final int abr; // Audio bitrate in kbps
  final String acodec; // Audio codec (e.g., "mp4a.40.2")
  final String formatNote; // Description (e.g., "medium quality")
  final String protocol; // Protocol used (e.g., "https")

  AudioFormat({
    required this.formatId,
    required this.url,
    required this.ext,
    required this.abr,
    required this.acodec,
    required this.formatNote,
    required this.protocol,
  });

  /// Example:
  /// {
  ///   "formatId": "140",
  ///   "url": "https://example.com/audio.m4a",
  ///   "ext": "m4a",
  ///   "abr": 256,
  ///   "acodec": "mp4a.40.2",
  ///   "formatNote": "256k",
  ///   "protocol": "https"
  /// }
  factory AudioFormat.fromJson(Map<String, dynamic> json) => AudioFormat(
    formatId: json['formatId'] ?? '',
    url: json['url'] ?? '',
    ext: json['ext'] ?? '',
    abr: json['abr'] ?? 0,
    acodec: json['acodec'] ?? '',
    formatNote: json['formatNote'] ?? '',
    protocol: json['protocol'] ?? '',
  );
}

// ==================================================================================================================

/// Contains complete information about a video including all available formats
/// Example: YouTube video metadata with 5 format options
class VideoInfo {
  final String videoId; // Unique video identifier
  final String title; // Video title
  final String? channelName; // Uploader channel name
  final String? channelId; // Uploader channel ID
  final int? duration; // Duration in seconds
  final int? viewCount; // Total views
  final String? uploadDate; // Upload date (ISO format)
  final String? thumbnail; // URL to thumbnail image
  final String? description; // Video description
  final String? webpageUrl; // Original page URL
  final String? originalUrl; // Source URL if different
  final String timestamp; // When this info was fetched
  final List<VideoFormat>? videoFormats; // Available video formats
  final List<AudioFormat>? audioFormats; // Available audio-only formats

  VideoInfo({
    required this.videoId,
    required this.title,
    this.channelName,
    this.channelId,
    this.duration,
    this.viewCount,
    this.uploadDate,
    this.thumbnail,
    this.description,
    this.webpageUrl,
    this.originalUrl,
    required this.timestamp,
    this.videoFormats,
    this.audioFormats,
  });

  /// Example:
  /// {
  ///   "videoId": "dQw4w9WgXcQ",
  ///   "title": "Never Gonna Give You Up",
  ///   "channelName": "Rick Astley",
  ///   "duration": 213,
  ///   "viewCount": 1500000000,
  ///   "thumbnail": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
  ///   "videoFormats": [...],
  ///   "audioFormats": [...]
  /// }
  factory VideoInfo.fromJson(Map<String, dynamic> json) => VideoInfo(
    videoId: json['videoId'] ?? '',
    title: json['title'] ?? '',
    channelName: json['channelName'],
    channelId: json['channelId'],
    duration: json['duration'],
    viewCount: json['viewCount'],
    uploadDate: json['uploadDate'],
    thumbnail: json['thumbnail'],
    description: json['description'],
    webpageUrl: json['webpageUrl'],
    originalUrl: json['originalUrl'],
    timestamp: json['timestamp'] ?? DateTime.now().toIso8601String(),
    videoFormats: (json['videoFormats'] as List?)
        ?.map((e) => VideoFormat.fromJson(e))
        .toList(),
    audioFormats: (json['audioFormats'] as List?)
        ?.map((e) => AudioFormat.fromJson(e))
        .toList(),
  );
}

// ==================================================================================================================

/// Pre-selected best quality URLs for quick access
/// Example: Pre-filtered 1080p video + 256k audio URLs
class BestFormatUrls {
  final String videoId; // Original video ID
  final String title; // Video title
  final String? bestVideoUrl; // Highest quality video URL
  final String? bestAudioUrl; // Highest quality audio URL
  final String? bestCombinedUrl; // Best combined stream URL
  final int formatsAvailable; // Total formats found

  BestFormatUrls({
    required this.videoId,
    required this.title,
    this.bestVideoUrl,
    this.bestAudioUrl,
    this.bestCombinedUrl,
    required this.formatsAvailable,
  });

  /// Example:
  /// {
  ///   "videoId": "dQw4w9WgXcQ",
  ///   "bestVideoUrl": "https://example.com/video_1080.mp4",
  ///   "bestAudioUrl": "https://example.com/audio_256k.m4a",
  ///   "formatsAvailable": 12
  /// }
  factory BestFormatUrls.fromJson(Map<String, dynamic> json) => BestFormatUrls(
    videoId: json['videoId'] ?? '',
    title: json['title'] ?? '',
    bestVideoUrl: json['bestVideoUrl'],
    bestAudioUrl: json['bestAudioUrl'],
    bestCombinedUrl: json['bestCombinedUrl'],
    formatsAvailable: json['formatsAvailable'] ?? 0,
  );
}

// ==================================================================================================================

/// Represents a video search result
/// Example: YouTube search result item
class SearchResult {
  final String videoId; // Unique video ID
  final String title; // Video title
  final String? channelName; // Channel name
  final String? channelId; // Channel ID
  final String? thumbnail; // Thumbnail URL
  final int? duration; // Duration in seconds
  final int? viewCount; // View count
  final String? uploadDate; // Upload date (ISO)
  final String? webpageUrl; // Original page URL
  final String? searchQuery; // Query that found this
  final int? searchRank; // Position in results

  SearchResult({
    required this.videoId,
    required this.title,
    this.channelName,
    this.channelId,
    this.thumbnail,
    this.duration,
    this.viewCount,
    this.uploadDate,
    this.webpageUrl,
    this.searchQuery,
    this.searchRank,
  });

  /// Example:
  /// {
  ///   "videoId": "dQw4w9WgXcQ",
  ///   "title": "Never Gonna Give You Up",
  ///   "channelName": "Rick Astley",
  ///   "duration": 213,
  ///   "searchRank": 1
  /// }
  factory SearchResult.fromJson(Map<String, dynamic> json) => SearchResult(
    videoId: json['videoId'] ?? '',
    title: json['title'] ?? '',
    channelName: json['channelName'],
    channelId: json['channelId'],
    thumbnail: json['thumbnail'],
    duration: json['duration'],
    viewCount: json['viewCount'],
    uploadDate: json['uploadDate'],
    webpageUrl: json['webpageUrl'],
    searchQuery: json['searchQuery'],
    searchRank: json['searchRank'],
  );
}

// ==================================================================================================================

/// Represents a video related to another video
/// Example: "Recommended" or "Up next" videos
class RelatedVideo {
  final String videoId; // Unique video ID
  final String title; // Video title
  final String? channelName; // Channel name
  final String? channelId; // Channel ID
  final String? thumbnail; // Thumbnail URL
  final int? duration; // Duration in seconds
  final int? viewCount; // View count
  final String? uploadDate; // Upload date (ISO)
  final String? webpageUrl; // Original page URL

  RelatedVideo({
    required this.videoId,
    required this.title,
    this.channelName,
    this.channelId,
    this.thumbnail,
    this.duration,
    this.viewCount,
    this.uploadDate,
    this.webpageUrl,
  });

  /// Example:
  /// {
  ///   "videoId": "dQw4w9WgXcQ",
  ///   "title": "Never Gonna Give You Up",
  ///   "channelName": "Rick Astley"
  /// }
  factory RelatedVideo.fromJson(Map<String, dynamic> json) => RelatedVideo(
    videoId: json['videoId'] ?? '',
    title: json['title'] ?? '',
    channelName: json['channelName'],
    channelId: json['channelId'],
    thumbnail: json['thumbnail'],
    duration: json['duration'],
    viewCount: json['viewCount'],
    uploadDate: json['uploadDate'],
    webpageUrl: json['webpageUrl'],
  );
}

// ==================================================================================================================

/// Represents a randomly selected video
/// Example: Video from discovery/recommendation system
class RandomVideo {
  final String videoId; // Unique video ID
  final String title; // Video title
  final String? channelName; // Channel name
  final String? channelId; // Channel ID
  final String? thumbnail; // Thumbnail URL
  final int? duration; // Duration in seconds
  final int? viewCount; // View count
  final String? uploadDate; // Upload date (ISO)
  final String? category; // Content category
  final String? searchTerm; // Term used to find this
  final String? webpageUrl; // Original page URL

  RandomVideo({
    required this.videoId,
    required this.title,
    this.channelName,
    this.channelId,
    this.thumbnail,
    this.duration,
    this.viewCount,
    this.uploadDate,
    this.category,
    this.searchTerm,
    this.webpageUrl,
  });

  /// Example:
  /// {
  ///   "videoId": "dQw4w9WgXcQ",
  ///   "title": "Never Gonna Give You Up",
  ///   "category": "Music"
  /// }
  factory RandomVideo.fromJson(Map<String, dynamic> json) => RandomVideo(
    videoId: json['videoId'] ?? '',
    title: json['title'] ?? '',
    channelName: json['channelName'],
    channelId: json['channelId'],
    thumbnail: json['thumbnail'],
    duration: json['duration'],
    viewCount: json['viewCount'],
    uploadDate: json['uploadDate'],
    category: json['category'],
    searchTerm: json['searchTerm'],
    webpageUrl: json['webpageUrl'],
  );
}

// ==================================================================================================================

/// Represents a trending/popular video
/// Example: Currently viral video
class TrendingVideo {
  final String videoId; // Unique video ID
  final String title; // Video title
  final String? channelName; // Channel name
  final String? channelId; // Channel ID
  final String? thumbnail; // Thumbnail URL
  final int? duration; // Duration in seconds
  final int? viewCount; // View count
  final String? uploadDate; // Upload date (ISO)
  final String? trendingQuery; // Trending category
  final bool isTrending; // Currently trending flag
  final String? webpageUrl; // Original page URL

  TrendingVideo({
    required this.videoId,
    required this.title,
    this.channelName,
    this.channelId,
    this.thumbnail,
    this.duration,
    this.viewCount,
    this.uploadDate,
    this.trendingQuery,
    required this.isTrending,
    this.webpageUrl,
  });

  /// Example:
  /// {
  ///   "videoId": "dQw4w9WgXcQ",
  ///   "title": "Never Gonna Give You Up",
  ///   "isTrending": true,
  ///   "trendingQuery": "Music"
  /// }
  factory TrendingVideo.fromJson(Map<String, dynamic> json) => TrendingVideo(
    videoId: json['videoId'] ?? '',
    title: json['title'] ?? '',
    channelName: json['channelName'],
    channelId: json['channelId'],
    thumbnail: json['thumbnail'],
    duration: json['duration'],
    viewCount: json['viewCount'],
    uploadDate: json['uploadDate'],
    trendingQuery: json['trendingQuery'],
    isTrending: json['isTrending'] ?? false,
    webpageUrl: json['webpageUrl'],
  );
}


// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================
4
likes
0
points
49
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for YouTube video streaming using yt-dlp. Supports fetching video formats, related videos, and more.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on flutter_ytdlp_plugin

Packages that implement flutter_ytdlp_plugin