Reputation: 11
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
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