How to play a List of video in Flutter?

邮差的信 提交于 2020-01-29 21:26:20

问题


I'm using flutter video_player package to play a list of video.

List sourceList;

sourceList = [
  {
    "size": 69742504,
    "name": "lucky-roulette.mp4",
    "mimetype": "video/mp4",
  },
  {
    "size": 69742504,
    "name": "BigBuckBunny.mp4",
    "mimetype": "video/mp4",
  }
];

I've checked out this issue, and did some custom codes upon it.

void play() {
  log.fine("Now playing: $_nowPlayingUrl");
  _adController = VideoPlayerController.network(_nowPlayingUrl);
  _adController.initialize().then((_) => setState(() {}));
  _adController.play();
  _adController.addListener(checkIfVideoFinished);
}

void checkIfVideoFinished() {
  if (_adController == null ||
      _adController.value == null ||
      _adController.value.position == null ||
      _adController.value.duration == null) return;
  if (_adController.value.position.inSeconds ==
      _adController.value.duration.inSeconds) {
    _adController.removeListener(checkIfVideoFinished);
    _adController.dispose();
    // Change _nowPlayingIndex
    setState(() {
      _nowPlayingIndex = (_nowPlayingIndex + 1) % _totalIndex;
    });
    play();
  }
}

But use this code snippet would send out an exception Another exception was thrown: A VideoPlayerController was used after being disposed.

Is there a better way to play and loop a list of video in Flutter?


回答1:


I also think it is ok to not call dispose before disposing Widget.

In my case, I paused every video files. I used FutureBuilder with VideoPlayerController.

dependencies
video_player: ^0.10.1
chewie: ^0.9.7
code
VideoPlayerController _controller;
ChewieController _chewieController; // custom ui
Future<void> _initializeVideoPlayerFuture;

var _clips = List<PoseClip>(); // video list
int _playingIndex = -1;
bool _disposed = false;
var _isPlaying = false;
var _isEndPlaying = false;

@override
void dispose() {
  _disposed = true;
  // By assigning Future is null,
  // prevent the video controller is using in widget before disposing that.
  _initializeVideoPlayerFuture = null;
  // In my case, sound is playing though controller was disposed.
  _controller?.pause()?.then((_){
    // dispose VideoPlayerController.
    _controller?.dispose();
  });
  super.dispose();
}


Future<bool> _clearPrevious() async {
  await _controller?.pause();
  _controller?.removeListener(_controllerListener);
  return true;
}

Future<void> _startPlay(int index) async {
  print("play ---------> $index");
  setState(() {
    _initializeVideoPlayerFuture = null;
  });
  Future.delayed(const Duration(milliseconds: 200), () {
    _clearPrevious().then((_){
      _initializePlay(index);
    });
  });
}

Future<void> _initializePlay(int index) async {
  final file = await _localStorage.localFile(_clips[index].filePath());
  print("file.exists: ${file.existsSync()}");
  print("file.path: ${file.path}");
  _controller = VideoPlayerController.file(file);
  _controller.addListener(_controllerListener);
  _chewieController = ChewieController(videoPlayerController: _controller);
  _initializeVideoPlayerFuture = _controller.initialize();

  setState(() {
    _playingIndex = index;
  });
}

// tracking status
Future<void> _controllerListener() async {
  if (_controller == null || _disposed) {
    return;
  }
  if (!_controller.value.initialized) {
    return;
  }
  final position = await _controller.position;
  final duration = _controller.value.duration;
  final isPlaying = position.inMilliseconds < duration.inMilliseconds;
  final isEndPlaying = position.inMilliseconds > 0 && position.inSeconds == duration.inSeconds;

  if (_isPlaying != isPlaying || _isEndPlaying != isEndPlaying) {
    _isPlaying = isPlaying;
    _isEndPlaying = isEndPlaying;
    print("$_playingIndex -----> isPlaying=$isPlaying / isCompletePlaying=$isEndPlaying");
    if (isEndPlaying) {
      final isComplete = _playingIndex == _clips.length - 1;
      if (isComplete) {
        print("played all!!");
      } else {
        _startPlay(_playingIndex + 1);
      }
    }
  }
}

// play view area
Widget _playView() {
  // FutureBuilder to display a loading spinner until finishes initializing
  return FutureBuilder(
    future: _initializeVideoPlayerFuture,
    builder: (BuildContext context, AsyncSnapshot snapshot) {
      if (snapshot.connectionState == ConnectionState.done) {
        _chewieController.play();
        return AspectRatio(
          aspectRatio: _controller.value.aspectRatio,
          child: Chewie(controller: _chewieController),
        );
      } else {
        return SizedBox(
          height: 300,
          child: Center(child: CircularProgressIndicator()),
        );
      }
    },
  );
}



回答2:


You must call the video controller dispose method in Override dispose method. Need not call dispose method when removevideo.



来源:https://stackoverflow.com/questions/55466602/how-to-play-a-list-of-video-in-flutter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!