Skip to content

Video player window disappears when dragging progress bar #4

Open
@LukeDickerson19

Description

@LukeDickerson19

Hey, awesome package! The video im using is 6 min so the un-smoothness of the slider track movement is unnoticable; I was just using this package cause its progress bar looks better than the default VideoProgressIndicator(). For some reason the video disappeared on my website when showing my friend (who was using chrome on a mac) when dragging the progress bar. I use chrome on linux, idk why it happened for him, but he sent me a short video (see below). I resolved this for myself by just using the slider in this part of your example, but i thought I'd still let you know.

Video:
https://github.com/timcreatedit/smooth_video_progress/assets/13493467/fb5ab9fb-7b8c-47af-b7b2-86b422b7f464
sidenote: facebook wouldn't let me download it cause "URL signature expired", so it a recording of a recording.

My website's code doesn't show the video player unless _controller.value.isInitialized is true, so I hypothesize moving the progress bar causes this to be false.

Relevant Code:

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:smooth_video_progress/smooth_video_progress.dart';

class VideoPlayerWidget extends StatefulWidget {
  final String filepath;
  final double width;

  VideoPlayerWidget(this.filepath, {required this.width});

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

class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
  late VideoPlayerController _controller;
  late Duration _currentPosition;
  bool showVideoControls = false;
  bool showInitialPlayButton = true;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(widget.filepath,
        videoPlayerOptions: VideoPlayerOptions(
          mixWithOthers: true,
        ))
      ..addListener(() {
        setState(() {
          _currentPosition = _controller.value.position;
        });
      })
      ..initialize().then((_) {
        // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
        setState(() {});
      });
  }

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

  String formatTime(Duration duration) {
    return duration.inHours == 0
        ? "${duration.inMinutes}:${duration.inSeconds.remainder(60).toString().padLeft(2, '0')}"
        : "${duration.inHours}:${duration.inMinutes.remainder(60).toString().padLeft(2, '0')}:${duration.inSeconds.remainder(60).toString().padLeft(2, '0')}";
    // if (duration.inHours == 0) {
    //   return "${duration.inMinutes}:${duration.inSeconds.toString().padLeft(2, '0')}";
    // } else {
    //   return "${duration.inHours}:${duration.inMinutes.toString().padLeft(2, '0')}:${duration.inSeconds.toString().padLeft(2, '0')}";
    // }

    // // Format the duration into hh:mm:ss format
    // String twoDigits(int n) => n.toString().padLeft(2, '0');
    // String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
    // String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
    // return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        width: widget.width,
        child: MouseRegion(
            onEnter: (e) => setState(() {
                  if (!showInitialPlayButton) {
                    showVideoControls = true;
                  }
                }),
            onExit: (e) => setState(() {
                  showVideoControls = false;
                }),
            child: Stack(children: [
              _controller.value.isInitialized
                  ? AspectRatio(
                      aspectRatio: _controller.value.aspectRatio,
                      child: VideoPlayer(_controller),
                    )
                  : Container(),
              if (showInitialPlayButton)
                Positioned.fill(
                    child: Center(
                  child: IconButton(
                    onPressed: () {
                      setState(() {
                        showInitialPlayButton = false;
                        showVideoControls = true;
                        _controller.play();
                      });
                    },
                    splashRadius: 0.01,
                    iconSize: widget.width * 0.20,
                    color: Theme.of(context).canvasColor.withOpacity(0.50),
                    icon: Icon(Icons.play_circle),
                  ),
                )),
              if (showVideoControls)
                Positioned.fill(
                    child: Align(
                        alignment: Alignment.bottomCenter,
                        child: SizedBox(
                            height: 40,
                            child: Row(children: [
                              IconButton(
                                onPressed: () {
                                  setState(() {
                                    _controller.value.isPlaying
                                        ? _controller.pause()
                                        : _controller.play();
                                  });
                                },
                                splashRadius: 0.01,
                                icon: Icon(
                                  _controller.value.isPlaying
                                      ? Icons.pause
                                      : Icons.play_arrow,
                                ),
                              ),
                              Text(
                                  "${formatTime(_currentPosition)} / ${formatTime(_controller.value.duration)}",
                                  style: TextStyle(
                                      color: Theme.of(context).canvasColor)),
                              Expanded(
                                child: SmoothVideoProgress(
                                  controller: _controller,
                                  builder: (context, position, duration, _) =>
                                      Slider(
                                    min: 0,
                                    max: duration.inMilliseconds.toDouble(),
                                    value: position.inMilliseconds.toDouble(),
                                    onChanged: (value) => _controller.seekTo(
                                        Duration(milliseconds: value.toInt())),
                                    onChangeStart: (_) => _controller.pause(),
                                    onChangeEnd: (_) => _controller.play(),
                                  ),
                                ),
                                // child: ValueListenableBuilder<VideoPlayerValue>(
                                //   valueListenable: _controller,
                                //   builder: (context, value, _) => Slider(
                                //     min: 0,
                                //     max: value.duration.inMilliseconds
                                //         .toDouble(),
                                //     value: value.position.inMilliseconds
                                //         .toDouble(),
                                //     onChanged: (value) => _controller.seekTo(
                                //         Duration(milliseconds: value.toInt())),
                                //     onChangeStart: (_) => _controller.pause(),
                                //     onChangeEnd: (_) => _controller.play(),
                                //   ),
                                // ),
                              ),
                            ])))),
            ])));
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions