Home > database >  Flutter: youtube_player_flutter Unable to fetch the metadata
Flutter: youtube_player_flutter Unable to fetch the metadata

Time:04-11

How can I fetch the video metadata?

I'm using youtube_player_flutter

When I start the app the video play correctly but the metadata like the 'author' or the 'title' always start at 'null'. Only when I 'Hot Reload' the app they are initialize with the correct value.

I'm new to flutter and I think this can be solved with some asynchronous function but I don't know where I should put it

Code:

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

class YoutubePlayerContainer extends StatefulWidget {
  const YoutubePlayerContainer({Key? key}) : super(key: key);

  @override
  State<YoutubePlayerContainer> createState() => _YoutubePlayerContainerState();
}

class _YoutubePlayerContainerState extends State<YoutubePlayerContainer> {
  late YoutubePlayerController controller;

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

    const url = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';

    controller = YoutubePlayerController(
      initialVideoId: YoutubePlayer.convertUrlToId(url)!,
      flags: const YoutubePlayerFlags(),
    );
  }

  @override
  Widget build(BuildContext context) => YoutubePlayerBuilder(
        player: YoutubePlayer(
          controller: controller,
        ),
        builder: (context, player) => Scaffold(
          appBar: AppBar(title: const Text('Video MetaData')),
          body: Padding(
            padding: EdgeInsets.all(8),
            child: Column(
              children: [
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(3),
                    color: const Color(0xFF434D58),
                  ),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Padding(
                        padding: const EdgeInsets.all(8),
                        child: Text(
                          controller.metadata.author,
                          style: const TextStyle(
                            fontWeight: FontWeight.w600,
                            fontSize: 12,
                            color: Colors.white,
                          ),
                        ),
                      ),
                      Container(
                        child: player,
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8),
                        child: Text(
                          controller.metadata.title,
                          style: const TextStyle(
                            fontWeight: FontWeight.bold,
                            fontSize: 12,
                            color: Colors.white,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      );
}

What am I missing here?

CodePudding user response:

Looking at the documentation for the package, it is pretty visible to see that the call is asynchronous and you need to add a listener to it.

YoutubePlayer(
    controller: _controller,
    showVideoProgressIndicator: true,
    videoProgressIndicatorColor: Colors.amber,
    progressColors: ProgressColors(
        playedColor: Colors.amber,
        handleColor: Colors.amberAccent,
    ),
    onReady () {
        _controller.addListener(listener);
    },
),

In the code you provided, there is no listener for the YoutubePlayer and because of this, the first time it is viewed, the metadata is null since the call has not been completed yet.

 void listener() {
    if (_isPlayerReady && mounted && !_controller.value.isFullScreen) {
      setState(() {
        _playerState = _controller.value.playerState;
        _videoMetaData = _controller.metadata;
      });
    }
  }

I would suggest only showing the data once the call has completed. You could do this using a boolean flag and showing a spinner.

  • Related