skip to Main Content

I’ve taken a file object which I received from the Flutter camera library. Then passed that file into the Flutter video_player controller. Something like this.

_controller = VideoPlayerController.file(widget.video!);

When I do that the video shows completely blank. If I include timestamps it does seem to know roughly the length of the video but nothing plays – no audio nothing. I’ve been able to get it to work just fine in the exact same file if I replace the call to .file with a call to .networkUrl and pass in a known working video. I would think that it should take a file object without too much issue.

I’ve also tried using a different library, Chewie. Although I wasn’t expecting much considering is uses video_player under the hood. It also didn’t work just as I expected but I wasn’t sure what else to try.

There are no errors logged to the terminal.

Edit to add more code context:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:loading_animation_widget/loading_animation_widget.dart';
import 'package:revvy/utils/getEnv.dart';
import 'package:revvy/utils/styles.dart';
import 'package:revvy/utils/svgs.dart';
import 'package:revvy/widgets/BouncingButton.dart';
import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart';

final String S3_BASE_URL = getEnv('S3_BASE_URL');

class VideoPlayerWidget extends StatefulWidget {
  final File? video;
  final String videoKey;
  final bool displayProgress;
  final bool tapToPlay;
  const VideoPlayerWidget({Key? key, this.video, this.videoKey = '', this.displayProgress = false, this.tapToPlay = false}) : super(key: key);

  @override
  VideoPlayerWidgetState createState() => VideoPlayerWidgetState();
}

class VideoPlayerWidgetState extends State<VideoPlayerWidget> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;
  double volume = 0;
  double prevVisibleFraction = 0.0;

  @override
  void initState() {
    if (widget.video == null) {
      String url = '$S3_BASE_URL/${widget.videoKey}';
      Uri uri = Uri.parse(url);
      _controller = VideoPlayerController.networkUrl(uri);
    } else {
      _controller = VideoPlayerController.file(widget.video!);
    }

    _initializeVideoPlayerFuture = _controller.initialize();

    _controller.setVolume(1);
    _controller.setLooping(true);

    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  void setState(VoidCallback fn) {
    if (mounted) {
      super.setState(fn);
    }
  }

  @override
  Widget build(BuildContext context) {
    final query = MediaQuery.of(context);
    final double width = query.size.width;
    final double height = query.size.height;

    return Container(
      color: Colors.black,
      width: width,
      height: height,
      child: FutureBuilder(
        future: _initializeVideoPlayerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Stack(
              children: [
                ClipRect(
                  clipBehavior: Clip.hardEdge,
                  child: SizedBox.expand(
                    child: FittedBox(
                      fit: BoxFit.cover,
                      child: SizedBox(
                        width: _controller.value.size.width,
                        height: _controller.value.size.height,
                        child: GestureDetector(
                          onTap: () {
                            if (widget.tapToPlay) {
                              if (_controller.value.isPlaying) {
                                _controller.pause();
                              } else {
                                _controller.play();
                              }
                            }
                          },
                          child: VideoPlayer(_controller),
                        ),
                      )
                    )
                  ),
                ),
                Positioned(
                  bottom: 132,
                  left: CONTENT_SPACING_3,
                  right: CONTENT_SPACING_3,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      if (!widget.tapToPlay) (
                        BouncingButton(
                          onPress: () {
                            setState(() {
                              if (_controller.value.isPlaying) {
                                _controller.pause();
                              } else {
                                _controller.play();
                              }
                            });
                          },
                          child: SizedBox(
                            width: ICON_SIZE_LG,
                            height: ICON_SIZE_LG,
                            child: SvgPicture.string(_controller.value.isPlaying ? faPauseSolid : faPlaySolid, color: Colors.white)
                          ),
                        )
                      ) else (
                          const SizedBox()
                      ),
                      if (widget.displayProgress) (
                        SizedBox(
                          width: width - 200,
                          child: VideoProgressIndicator(
                            _controller,
                            allowScrubbing: true,
                          ),
                        )
                      ),
                      if (widget.displayProgress) (
                        ValueListenableBuilder(
                          valueListenable: _controller,
                          builder: (context, VideoPlayerValue value, child) {
                            final currentTime = value.position.toString();
                            final duration = _controller.value.duration.toString();

                            String formatVideoTime(time) {
                              final values = time.split(':');
                              return '0:' + values[2].split('.')[0];
                            }

                            return Text('${formatVideoTime(currentTime)}/${formatVideoTime(duration)}', style: const TextStyle(fontSize: FONT_SIZE_MD, color: Colors.white));
                          },
                        )
                      ),
                    ]
                  )
                ),
              ]
            );
          } else {
            // If the VideoPlayerController is still initializing, show a
            // loading spinner.
            return Center(
              child: LoadingAnimationWidget.prograssiveDots(
                color: COLOR_PRIMARY,
                size: 64,
              ),
            );
          }
        },
      )
    );
  }
}

2

Answers


  1. You need to initialize the video player.

    _controller = VideoPlayerController.file(widget.video!))..initialize()

    Please look at the example code in the documentation.

    Login or Signup to reply.
  2. class MediaPlayer extends StatefulWidget {
      final MediaModel? mediaModelLocal;
    
      const MediaPlayer({Key? key, this.mediaModelLocal}) : super(key: key);
    
      @override
      State<MediaPlayer> createState() => _MediaPlayerState();
    }
    
    class _MediaPlayerState extends State<MediaPlayer> {
      ChewieController? chewieController;
      late VideoPlayerController videoPlayerController;
      bool anErrorOccured = false;
    
      @override
      void initState() {
        initializeVideoPlayer();
        super.initState();
      }
    
      Future<void> initializeVideoPlayer() async {
        try {
          late ImageProvider coverImage;
          if (widget.mediaModelLocal?.file is File) {
            videoPlayerController =
                VideoPlayerController.file(widget.mediaModelLocal!.file!);
            coverImage = FileImage(widget.mediaModelLocal!.thumbnailImage!);
          }
    
          if (widget.mediaModelLocal?.file is String) {
            videoPlayerController = VideoPlayerController.networkUrl(
                Uri.parse(widget.mediaModelLocal!.file!));
    
            String thumbnailImage;
            if (widget.mediaModelLocal?.thumbnailImage != null &&
                widget.mediaModelLocal?.thumbnailImage is String) {
              thumbnailImage = widget.mediaModelLocal!.thumbnailImage!;
              thumbnailImage = thumbnailImage.getFullImagePath();
              coverImage = NetworkImage(thumbnailImage);
            }
          }
    
          await videoPlayerController.initialize();
          chewieController = ChewieController(
            showControls: true,
            deviceOrientationsOnEnterFullScreen: [
              DeviceOrientation.portraitUp,
              DeviceOrientation.landscapeLeft,
              DeviceOrientation.landscapeRight
            ],
            allowFullScreen: true,
            videoPlayerController: videoPlayerController,
            autoPlay: false,
            looping: false,
            placeholder: Container(
              decoration: BoxDecoration(
                color: const Color(0XFF281E4F),
                image: DecorationImage(
                  fit: BoxFit.cover,
                  image: coverImage,
                ),
              ),
              child: BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
                child: Container(
                  decoration: BoxDecoration(color: Colors.black.withOpacity(0.7)),
                ),
              ),
            ),
          );
          setState(() {});
        } catch (e) {
          setState(() {
            anErrorOccured = true;
          });
        }
      }
    
      @override
      void dispose() {
        videoPlayerController.dispose();
        chewieController?.dispose();
        super.dispose();
      }
    
      double radius = 8;
      Widget backgroundLayout({required Widget child}) {
        return Container(
            decoration: BoxDecoration(
                color: const Color(0XFF281E4F),
                borderRadius: BorderRadius.all(Radius.circular(radius))),
            child: Center(child: child));
      }
    
      @override
      Widget build(BuildContext context) {
        var theme = Theme.of(context);
        TextStyle? textStyle =
            theme.textTheme.bodyLarge?.copyWith(color: Colors.white, fontSize: 13);
        if (anErrorOccured == true ||
            chewieController != null &&
                chewieController!.videoPlayerController.value.hasError) {
          return backgroundLayout(
              child: Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Padding(
                padding: EdgeInsets.only(right: 5.0),
                child: Icon(
                  Icons.error_outline_outlined,
                  color: Colors.white,
                ),
              ),
              Text(
                'Failed to play video',
                style: textStyle,
              )
            ],
          ));
        }
        if (chewieController != null &&
            chewieController!.videoPlayerController.value.isInitialized) {
          return ClipRRect(
            borderRadius: BorderRadius.circular(radius),
            child: Chewie(
              controller: chewieController!,
            ),
          );
        }
    
        return backgroundLayout(
            child: const SystemCircularProgressIndicator(
          color: Colors.white,
        ));
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search