flutterdartyoutube-apiflutter-windows

Flutter: play youtube videos on flutter windows app


Packages like youtube_player_flutter and youtube_player_iframe don't play youtube videos on windows flutter application. The first package says it support windows, but we have always got controller is not ready for method calls and video never plays.


Solution

  • I found a solution for this problem:

    for example: if you wanna play some youtube video that has this link : https://www.youtube.com/watch?v=lllllllllll

    Note the above youtube link is an arbitrary link and it may be wrong link, this program can take this link and converts it to a direct video link, generally direct video links end with valid video extensions like .mp4.

    You can find this program on its repo right here. go to release section and download the .exe installer to install it on your windows machine.

    remember to add the path of the program (where .exe file exists) to the System Environment variables of your OS, so the OS can recognize the program's commands when used on cmd.

    Now you can run the program through cmd and convert youtube links to direct video links.

    You should ensure the yt-dlp program correctly works on OS cmd before making your flutter app interact with it.

    So far so good, it's just a program.


    How will the flutter windows app deal with this program to play youtube videos?

    The answer is simple, your flutter app should encapsulate this program within its assets to use it when needed, it's a utility program for your app.

    in your assets directory, create a directory called programs and put yt-dlp.exe within, and for sure add it to your yaml file.

    run flutter pub get command

    Now the flutter app sees the yt-dpl program.

    Suppose you have a button when pressed it goes to a video screen to play a youtube video:

    the video screen should make sure firstly the yt-dlp exists to use it through this function, the function just stores the program within the temp directory of the OS, finally it saves the path of the program to run it later.

      Future<void> _prepareYtDlp() async {
        final tempDir = Directory.systemTemp;
        final file = File('${tempDir.path}/yt-dlp.exe');
    
        if (!file.existsSync()) {
          final bytes = await rootBundle.load('assets/programs/yt-dlp.exe');
          await file.writeAsBytes(bytes.buffer.asUint8List(), flush: true);
          await Process.run('chmod', ['+x', file.path]).catchError((e) {
            print('i caught an error: $e');
          });
        }
    
        ytDlpPath = file.path;
      }
    

    Now, you have the yt-dlp exists on the machine (user machine), your flutter app should call this program to get the direct video link through this method:

      Future<String?> _getYoutubeDirectUrl(String youtubeVideoLink) async {
        final result = await Process.run(ytDlpPath, [
          '-f',
          'best[ext=mp4][height<=720]', // decide required video quality
          '-g',
          youtubeVideoLink,
        ]);
    
        if (result.exitCode == 0) {
          return result.stdout.toString().trim();
        } else {
          debugPrint('yt-dlp failed: ${result.stderr}');
          return null;
        }
      }
    

    this method runs the yt-dlp within the cmd and passes arguments such as youtubeVideoLink and the required video quality within the convert command.

    Generally it takes around 10 seconds to return the direct video link.

    Now you are ready, you have a direct video link not a youtube link, you can use any media player package that support windows app just like media-kit and media_kit_video to play the video through its link.

    This's just a demo exmple from the package docs:

    class MyScreen extends StatefulWidget {
      const MyScreen({Key? key}) : super(key: key);
      @override
      State<MyScreen> createState() => MyScreenState();
    }
    
    class MyScreenState extends State<MyScreen> {
      
      late final player = Player();
     
      late final controller = VideoController(player);
    
      @override
      void initState() {
        super.initState();
        
        player.open(Media(ytdlpVideoLink));
      }
    
      @override
      void dispose() {
        player.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: SizedBox(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.width * 9.0 / 16.0,
            // Use [Video] widget to display video output.
            child: Video(controller: controller),
          ),
        );
      }
    }
    

    All you need to do, is to merge the 2 methods _prepareYtDlp() and _getYoutubeDirectUrl(String youtubeVideoLink) within the above MyScreen class to play the video, and you are done.

    Important Note:

    I have tried this scenario with windows OS and it worked, if you are targeting linux or macOS OSs through flutter and you didn't find a direct way to play youtube videos on these platforms, you should download the yt-dlp program that's compatible with those OSs and follow the same idea. it should work.