chewie icon indicating copy to clipboard operation
chewie copied to clipboard

Video disappear on exiting full screen

Open imcoffeefreak opened this issue 4 years ago • 23 comments
trafficstars

Flutter Web

Video plays absolutely fine in normal screen, but fails to play after exiting from Full screen Flutter_Web

imcoffeefreak avatar Nov 25 '20 13:11 imcoffeefreak

tested in iOS Simulator. it is the same. Video disappears on exiting full screen

sravanpabolu avatar Jan 01 '21 20:01 sravanpabolu

I encountered the same. I will investigate ASAP. Maybe something with the old fashioned InheritedWidget. Maybe we should change to Provider or Riverpod here.

Ahmadre avatar Jan 04 '21 08:01 Ahmadre

following. also experiencing this In flutter web

yuhao-nyc avatar Jan 05 '21 21:01 yuhao-nyc

Same here for flutter web.

Depixen avatar Jan 12 '21 11:01 Depixen

@Ahmadre any workaround for this issue?

imcoffeefreak avatar Feb 02 '21 04:02 imcoffeefreak

I spend the last two days rewriting the existing code in order to make the fullscreen work on Flutter Web. The problem is that its somehow not working correctly if there is only 1 instance of VideoPlayerController used. So, you would need a separate instance of a ChewieController for the fullscreen widget and also for the default widget. Each instance needs to be initialized separately.

Unfortunately it is not that easy to implement because the entire code is written to work only with a single instance. If someone is interested I can share it, but had not yet the time to clean it up and optimize it.

Uni2K avatar Mar 09 '21 18:03 Uni2K

Currently, the only workaround that I found in building this is to use HTML concept in a flutter.

Widget _iframeWidget; html.VideoElement iFrameWidgets;

So in the initState you can define widget

iFrameWidgets = html.VideoElement(); iFrameWidgets.src = "link"; iFrameWidgets.controls = true;

use dart:ui as ui

ui.platformViewRegistry.registerViewFactory( 'videoElement, (int viewId) => iFrameWidgets, );

And then render it

_iframeWidget = HtmlElementView( key: UniqueKye(), viewType: "videoElement", );

imcoffeefreak avatar Mar 10 '21 04:03 imcoffeefreak

I spend the last two days rewriting the existing code in order to make the fullscreen work on Flutter Web. The problem is that its somehow not working correctly if there is only 1 instance of VideoPlayerController used. So, you would need a separate instance of a ChewieController for the fullscreen widget and also for the default widget. Each instance needs to be initialized separately.

Unfortunately it is not that easy to implement because the entire code is written to work only with a single instance. If someone is interested I can share it, but had not yet the time to clean it up and optimize it.

That would be great, if you would share it! Thanks in advance!

artur-baginski avatar Mar 16 '21 10:03 artur-baginski

Greetings, any update or tips for this one?

zambetpentru avatar May 30 '21 21:05 zambetpentru

Do you have any solution for this problem?

gbsoares12 avatar Jun 21 '21 16:06 gbsoares12

Is there any solution to this problem?

aramisromero89 avatar Aug 19 '21 14:08 aramisromero89

I encountered the same problem. Is there a solution yet?

AnmLobby avatar Oct 19 '21 20:10 AnmLobby

Same problem facing. Please Provide solution or Tip ASAP. Thank you

KartikSinghMedcyte avatar Nov 07 '21 12:11 KartikSinghMedcyte

You can use the listener and reinitialize the chewiecontroller it will work fine

chewieController.addListener(() { if (_chewieController.isFullScreen) { // can leave empty } else { print("Full screen exit"); // initialize controller again } });

ShivaniVani avatar Jan 07 '22 13:01 ShivaniVani

Here's a complete workaround Widget without using dart:html. It might have a small glitch on exiting the full screen (because of re-initialization and seeking), but is acceptable for now.

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

class MyVideoPlayer extends StatefulWidget {
 const MyVideoPlayer({Key? key, required this.videoUrl}) : super(key: key);

 final String videoUrl;

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

class _MyVideoPlayerState extends State<MyVideoPlayer> {
 late VideoPlayerController _videoController;
 late ChewieController _chewieController;

 Duration _currentPosition = Duration.zero;
 bool _isPlaying = false;

 void _initControllers() {
   _videoController = VideoPlayerController.network(widget.videoUrl)
     ..initialize().then((value) {
       _videoController.seekTo(_currentPosition);
       setState(() {});
     });
   _chewieController = ChewieController(
     videoPlayerController: _videoController,
   )..addListener(_reInitListener);
   if (_isPlaying) {
     _chewieController.play();
   }
 }

 void _reInitControllers() {
   _chewieController.removeListener(_reInitListener);
   _currentPosition = _videoController.value.position;
   _isPlaying = _chewieController.isPlaying;
   _initControllers();
 }

 void _reInitListener() {
   if (!_chewieController.isFullScreen) {
     _reInitControllers();
   }
 }

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

 @override
 Widget build(BuildContext context) {
   return Container(
     child: _videoController.value.isInitialized
       ? Chewie(controller: _chewieController)
       : null,
   );
 }

 @override
 void dispose() {
   _videoController.dispose();
   _chewieController.dispose();
   super.dispose();
 }
}

slovnicki avatar Jan 11 '22 23:01 slovnicki

This unfortunately does not work for me. Would love for this to just work straight out of the package :-(.

martinralfreindl avatar May 07 '22 04:05 martinralfreindl

Any updates???

magno-castro avatar May 02 '23 13:05 magno-castro

It's 2023! still the same issue.

mehroze-zaidi avatar Jun 14 '23 12:06 mehroze-zaidi

Any updates on this issue? This issue makes this package almost unusable for Flutter Web apps 😞

sbis04 avatar Sep 23 '23 04:09 sbis04

Here is the workaround I found for it. It's a minimal example which you can adapt to your own case.

Key steps :

  • Create a separate widget containing the Chewie component, in this case, named VideoView.
  • Pass a callback function (refresh() in this example) to the VideoView widget. This callback is used to handle the specific moment when the bug occurs.
  • Add a listener to the ChewieController to track changes in fullscreen mode.
  • When exiting the full screen, store the _controller.position (here in a global gStartAt).
  • Fire the callback function (refresh()) to handle the bug at this specific moment.

Now, when using the VideoView:

  • Wrap it into a StatefulBuilder (not necessary if you already use a StatefulWidget as a parent)
  • By passing setState as a callback function and changing the key, it creates a new Instance of the VideoView directly from the parent
  • The video will autoplay if gStartAt!=null
  • When popping it from the AppBar, set gStartAt = null.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:chewie/chewie.dart';
import 'package:video_player/video_player.dart';

Duration? gStartAt;

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StatefulBuilder(
        builder: (context, setState) {
          Key key = Key('${Random().nextInt(100000)}');
          return VideoView(
            key: key,
            refreshing: () => setState(() {}),
          );
        },
      ),
    );
  }
}

class VideoView extends StatefulWidget {
  final Function() refreshing;

  const VideoView({
    Key? key,
    required this.refreshing,
  }) : super(key: key);

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

class _VideoViewState extends State<VideoView> {
  late final VideoPlayerController _controller;
  late final ChewieController _chewieController;

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

    _controller = VideoPlayerController.networkUrl(Uri.parse('your_url_here'),);

    _chewieController = ChewieController(
      videoPlayerController: _controller,
      autoPlay: gStartAt != null,
      autoInitialize: true,
      startAt: gStartAt,
    )..addListener(() async {
        if (!_chewieController.isFullScreen) {
          gStartAt = await _controller.position;
          widget.refreshing();
        }
      });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        leading: IconButton(
          onPressed: () {
            gStartAt = null;
            Navigator.pop(context);
          },
          icon: const Icon(Icons.arrow_back_ios),
        ),
      ),
      body: Chewie(
        controller: _chewieController,
      ),
    );
  }
}

redbnlrg avatar Nov 24 '23 16:11 redbnlrg

Here is the workaround I found for it. It's a minimal example which you can adapt to your own case.

Key steps :

  • Create a separate widget containing the Chewie component, in this case, named VideoView.
  • Pass a callback function (refresh() in this example) to the VideoView widget. This callback is used to handle the specific moment when the bug occurs.
  • Add a listener to the ChewieController to track changes in fullscreen mode.
  • When exiting the full screen, store the _controller.position (here in a global gStartAt).
  • Fire the callback function (refresh()) to handle the bug at this specific moment.

Now, when using the VideoView:

  • Wrap it into a StatefulBuilder (not necessary if you already use a StatefulWidget as a parent)
  • By passing setState as a callback function and changing the key, it creates a new Instance of the VideoView directly from the parent
  • The video will autoplay if gStartAt!=null
  • When popping it from the AppBar, set gStartAt = null.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:chewie/chewie.dart';
import 'package:video_player/video_player.dart';

Duration? gStartAt;

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StatefulBuilder(
        builder: (context, setState) {
          Key key = Key('${Random().nextInt(100000)}');
          return VideoView(
            key: key,
            refreshing: () => setState(() {}),
          );
        },
      ),
    );
  }
}

class VideoView extends StatefulWidget {
  final Function() refreshing;

  const VideoView({
    Key? key,
    required this.refreshing,
  }) : super(key: key);

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

class _VideoViewState extends State<VideoView> {
  late final VideoPlayerController _controller;
  late final ChewieController _chewieController;

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

    _controller = VideoPlayerController.networkUrl(Uri.parse('your_url_here'),);

    _chewieController = ChewieController(
      videoPlayerController: _controller,
      autoPlay: gStartAt != null,
      autoInitialize: true,
      startAt: gStartAt,
    )..addListener(() async {
        if (!_chewieController.isFullScreen) {
          gStartAt = await _controller.position;
          widget.refreshing();
        }
      });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        leading: IconButton(
          onPressed: () {
            gStartAt = null;
            Navigator.pop(context);
          },
          icon: const Icon(Icons.arrow_back_ios),
        ),
      ),
      body: Chewie(
        controller: _chewieController,
      ),
    );
  }
}

your key recreate widget and it impossibe to continue play video

any updates without flickering?

B0yma avatar Dec 26 '23 09:12 B0yma

Same problem here

JohnKeven avatar Jan 27 '24 01:01 JohnKeven