Sitam Sardar
Sitam Sardar

Reputation: 11

How to make video fullscreen in portrait mode like a youtube short video with chewie in flutter?

I have tried to build an short video player application (like youtube shorts, tiktok etc.) where I have to play short videos from network with .m3u8 format. Thats why I choosed chewie over video_player. But with chewie I am not able to play the video with fullscreen in potrait mode but can be done with video_player. In chewie if I put the aspectratio of my video then also their exist some weired padding(Not fullscreen). Here the problem is with only video_player, we can't play video with .m3u8 extension.

I have fixed the issue by manipulating the chewie library's code. I have changed at player_with_controls.dart file. I have simply commented their code which was causing the issue and used VideoPlayer only.

import 'package:chewie/src/chewie_player.dart';
import 'package:chewie/src/helpers/adaptive_controls.dart';
import 'package:chewie/src/notifiers/index.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:video_player/video_player.dart';

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

  @override
  Widget build(BuildContext context) {
    final ChewieController chewieController = ChewieController.of(context);

    double calculateAspectRatio(BuildContext context) {
      final size = MediaQuery.of(context).size;
      final width = size.width;
      final height = size.height;

      return width > height ? width / height : height / width;
    }

    Widget buildControls(
      BuildContext context,
      ChewieController chewieController,
    ) {
      return chewieController.showControls
          ? chewieController.customControls ?? const AdaptiveControls()
          : const SizedBox();
    }

    Widget buildPlayerWithControls(
      ChewieController chewieController,
      BuildContext context,
    ) {
      return Stack(
        children: <Widget>[
          if (chewieController.placeholder != null)
            chewieController.placeholder!,
          InteractiveViewer(
            transformationController: chewieController.transformationController,
            maxScale: chewieController.maxScale,
            panEnabled: chewieController.zoomAndPan,
            scaleEnabled: chewieController.zoomAndPan,
            child: Center(
              child: AspectRatio(
                aspectRatio: chewieController.aspectRatio ??
                    chewieController.videoPlayerController.value.aspectRatio,
                child: VideoPlayer(chewieController.videoPlayerController),
              ),
            ),
          ),
          if (chewieController.overlay != null) chewieController.overlay!,
          if (Theme.of(context).platform != TargetPlatform.iOS)
            Consumer<PlayerNotifier>(
              builder: (
                BuildContext context,
                PlayerNotifier notifier,
                Widget? widget,
              ) =>
                  Visibility(
                visible: !notifier.hideStuff,
                child: AnimatedOpacity(
                  opacity: notifier.hideStuff ? 0.0 : 0.8,
                  duration: const Duration(
                    milliseconds: 250,
                  ),
                  child: const DecoratedBox(
                    decoration: BoxDecoration(color: Colors.black54),
                    child: SizedBox.expand(),
                  ),
                ),
              ),
            ),
          if (!chewieController.isFullScreen)
            buildControls(context, chewieController)
          else
            SafeArea(
              bottom: false,
              child: buildControls(context, chewieController),
            ),
        ],
      );
    }

    // return LayoutBuilder(
    //     builder: (BuildContext context, BoxConstraints constraints) {
    //   return Center(
    //     child: SizedBox(
    //       // height: constraints.maxHeight,
    //       // width: constraints.maxWidth,
    //       child: AspectRatio(
    //         aspectRatio: calculateAspectRatio(context),
    //         child: buildPlayerWithControls(chewieController, context),
    //       ),
    //     ),
    //   );
    // });
    return VideoPlayer(chewieController.videoPlayerController);
  }
}

That actually resolved the issue but changing library directly is not a good practise for production. Is there anything else or any other way to solve this issue?

Upvotes: 1

Views: 77

Answers (1)

Fozle Rabbi
Fozle Rabbi

Reputation: 1

You can use the BetterPlayer package for improved performance and seamless video streaming.

Example:

class ShortVideoPage extends StatefulWidget {
  const ShortVideoPage({super.key});

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

class ShortVideoPageState extends State<ShortVideoPage> {
  final List<String> videoUrls = [
    "https://test.m3u8",
    "https://test2.m3u8",
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView.builder(
        scrollDirection: Axis.vertical,
        itemCount: videoUrls.length,
        itemBuilder: (context, index) {
          return VideoPlayerItem(videoUrl: videoUrls[index]);
        },
      ),
    );
  }
}
    
class VideoPlayerItem extends StatefulWidget {
  final String videoUrl;

  const VideoPlayerItem({super.key, required this.videoUrl});

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

class VideoPlayerItemState extends State<VideoPlayerItem> {
  late BetterPlayerController _betterPlayerController;

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

    BetterPlayerConfiguration betterPlayerConfiguration =
    const BetterPlayerConfiguration(
      aspectRatio: 9 / 16,
      autoPlay: true,
      looping: true,
      controlsConfiguration: BetterPlayerControlsConfiguration(
        showControls: false
      ),
      autoDispose: true,
    );

    _betterPlayerController = BetterPlayerController(betterPlayerConfiguration);
    _betterPlayerController.setupDataSource(
      BetterPlayerDataSource(
        BetterPlayerDataSourceType.network,
        widget.videoUrl,
        videoFormat: BetterPlayerVideoFormat.hls, //for added m3u8
        cacheConfiguration: BetterPlayerCacheConfiguration(
          useCache: true,
          maxCacheSize: 100 * 1024 * 1024, // 100 MB cache
        ),
      ),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: AspectRatio(aspectRatio: 16/9,child: BetterPlayer(controller: _betterPlayerController,),),),
    );
  }
}

Upvotes: 0

Related Questions