I am trying to play videos obtained from the web with its original aspect ratio. With the code I have the videos are returned with a stretched aspect ratio. I am not sure why this is. I have been doing research but cannot find a solution. How do I fix this?
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
class VideoTile1 extends StatefulWidget {
const VideoTile1({Key? key}) : super(key: key);
#override
_VideoTileState createState() => _VideoTileState();
}
class _VideoTileState extends State<VideoTile1> {
late VideoPlayerController _videoController;
late Future _intitializeVideoPlayer;
#override
void initState() {
_videoController = VideoPlayerController.network(
'https://res.cloudinary.com/nifty-gateway/video/upload/v1610827323/A/Billelis/%CE%A0%CE%91%CE%98%CE%9F%CE%A3_qyarem.mp4');
_intitializeVideoPlayer = _videoController.initialize();
_videoController.setLooping(true);
_videoController.play();
super.initState();
}
#override
void dispose() {
_videoController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: _intitializeVideoPlayer,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return VideoPlayer(_videoController);
} else {
return Container(color: Colors.grey[800]);
}
},
),
);
}
}
You can try using AspectRatio Widget with aspectRatio: _videoController.value.aspectRatio,
VideoPlayer widget wrapper
https://api.flutter.dev/flutter/widgets/AspectRatio-class.html
I am also new to flutter, here is my way to use and play/pause video , i hope can help you.
return _videoPlayerController.value.isInitialized
? Center(
child: GestureDetector(
onTap: () {
setState(() {
_videoPlayerController.value.isPlaying
? _videoPlayerController.pause()
: _videoPlayerController.play();
});
},
child: AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
child: Stack(
children: [
VideoPlayer(
_videoPlayerController,
),
_videoPlayerController.value.isPlaying
? Container()
: Center(
child: Icon(
Icons.play_arrow,
size: 80,
color: Colors.white.withOpacity(0.4),
),
)
],
),
),
),
)
: const CircularProgressIndicator();
Related
I get a list of video files now I want to play the video using path, for example, video path is 'storage/emulated/0/vedio1.mp4'. how can I play it? now.
with video_player package with that controller VideoPlayerController.file(...
https://pub.dev/documentation/video_player/latest/video_player/VideoPlayerController/VideoPlayerController.file.html
Use flutter's video_player
Example:
class _ButterFlyAssetVideo extends StatefulWidget {
#override
_ButterFlyAssetVideoState createState() => _ButterFlyAssetVideoState();
}
class _ButterFlyAssetVideoState extends State<_ButterFlyAssetVideo> {
late VideoPlayerController _controller;
#override
void initState() {
super.initState();
_controller = VideoPlayerController.asset('assets/Butterfly-209.mp4');
_controller.addListener(() {
setState(() {});
});
_controller.setLooping(true);
_controller.initialize().then((_) => setState(() {}));
_controller.play();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(top: 20.0),
),
const Text('With assets mp4'),
Container(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
VideoPlayer(_controller),
_ControlsOverlay(controller: _controller),
VideoProgressIndicator(_controller, allowScrubbing: true),
],
),
),
),
],
),
);
}
}
Refer Flutter CookBook
// Inject video_player & chewie dependencies in your pubspec.yaml
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:chewie/chewie.dart';
import 'package:video_player/video_player.dart';
class ChewiePlayer extends StatefulWidget {
static const routeName = '/VideoScreen';
final File? videoUrl;
final String? dimension; //1920*1080
const ChewiePlayer({this.videoUrl, this.dimension,});
#override
State<ChewiePlayer> createState() => _ChewiePlayerState();
}
class _ChewiePlayerState extends State<ChewiePlayer> {
VideoPlayerController? _controller;
ChewieController? chewieController;
#override
void initState() {
initialize();
super.initState();
}
#override
void dispose() {
print('VideoScreen dispose');
chewieController?.videoPlayerController.dispose();
chewieController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: Center(
child: AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: Chewie(controller: chewieController!),
),
),
),
);
}
Future<void> initialize() async {
_controller = VideoPlayerController.file(widget.videoUrl!);
/// you can also play network and asset video, than declare accordingly example: VideoPlayerController.network( paste your link )
await _controller!.initialize().then((value) => setState(() {}));
chewieController = ChewieController(
videoPlayerController: _controller!,
autoInitialize: false,
autoPlay: false,
allowPlaybackSpeedChanging: true,
materialProgressColors:
ChewieProgressColors(playedColor: Colors.blue, handleColor: Colors.blue, bufferedColor: Colors.grey),
looping: false,
errorBuilder: (context, errorMessage) {
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(errorMessage, style: const TextStyle(color: Colors.white)),
),
);
},
);
}
}
// And use like this...
SizedBox(
child: ChewiePlayer(videoUrl: File(filePath), dimension: '1920*1080'),
),
I'm having a hard time displaying a video using the video_player package. I'm new to flutter and am trying to create a simple website with a title, some text, and a local video displayed in the center of the screen with a title. The video is local and is in an assets folder, and I have also added the video_player and video location to the pubspec.yaml file. Any advice or suggestions are appreciated, I would like to improve at this language. Below is the code I have put together so far. Thanks!
import 'package:video_player/video_player.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Center(
child: Text(
"My Website",
textScaleFactor: 2,
style: TextStyle(color: Colors.white),
),
),
),
body: Column(
children: [
MyHomePage(),
],
),
),
);
}
}
MyHomePage class:
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Expanded(
/*1*/
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/*2*/
Container(
padding: const EdgeInsets.only(bottom: 8),
child: Center(
child: Text(
'More photos & videos coming soon',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
Container(
padding: const EdgeInsets.only(bottom: 8),
child: Center(child: BackgroundVideo()),
),
],
),
),
],
),
);
}
}
Stateful video player that I would like to embed in the home page:
//need to ensure this video fits on the screen and doesn't overflow the bottom.
class BackgroundVideo extends StatefulWidget {
const BackgroundVideo({super.key});
#override
_BackgroundVideoState createState() => _BackgroundVideoState();
}
class _BackgroundVideoState extends State<BackgroundVideo> {
late VideoPlayerController _controller;
late Future<void> _initializeBackgroundVideoFuture;
#override
void initState() {
super.initState();
//Create and store the BackgroundVideoController.
_controller = VideoPlayerController.asset(
"build\assets\welcomescreen.mp4",
);
_initializeBackgroundVideoFuture = _controller.initialize();
_controller.setLooping(true);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Video'),
),
// Use a FutureBuilder to display a loading spinner while waiting for the
// VideoPlayerController to finish initializing.
body: FutureBuilder(
future: _initializeBackgroundVideoFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the video.
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: VideoPlayer(_controller),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Wrap the play or pause in a call to `setState`. This ensures the
// correct icon is shown.
setState(() {
// If the video is playing, pause it.
if (_controller.value.isPlaying) {
_controller.pause();
} else {
// If the video is paused, play it.
_controller.play();
}
});
},
// Display the correct icon depending on the state of the player.
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
}
I was trying to create a videoplayer in a stateless widget in flutter. I could not do it.... this is the code I used ...Is it possible to create a video player in a stateless widget?
class VideoWidget extends StatelessWidget {
VideoWidget({Key? key}) : super(key: key);
final videoController =
VideoPlayerController.network('https://youtu.be/_EoLNs5m-7Y?t=4')
..initialize();
#override
Widget build(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
//height: 500,
child: Column(
children: [
//VideoPlayer(videoController!),
ValueListenableBuilder(
valueListenable: videoPlayerNotifier,
builder: (BuildContext cxt, play, widget_) {
return videoController.value.isInitialized
? AspectRatio(
aspectRatio: videoController.value.aspectRatio,
child: VideoPlayer(videoController))
: Container();
}),
const Text(
'movieName',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const Text('Description'),
FloatingActionButton(onPressed: () {
videoPlayerNotifier.value = true;
})
],
),
);
}
}
VideoPlayer from the video_player pub package is quite stateful, due especially to VideoPlayerController. However, you can wrap it in a StatefulWidget to be used within a StatelessWidget. E.g. use this wrapper within a stateless widget:
class VideoPlayerWrapper extends StatefulWidget {
final String videoUri;
const VideoPlayerWrapper({Key? key, required this.videoUri}) : super(key: key);
#override
_VideoPlayerWrapperState createState() => _VideoPlayerWrapperState(videoUri);
}
class _VideoPlayerWrapperState extends State<VideoPlayerWrapper> {
late VideoPlayerController _controller;
final String videoUri;
_VideoPlayerWrapperState(this.videoUri);
#override
void initState() {
super.initState();
_controller = VideoPlayerController.network(videoUri)
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
_controller.play();
}
#override
Widget build(BuildContext context) {
return Center(
child: _controller.value.isInitialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
Camera preview is stretching when changing aspect ratio from 16:9 to 4:3.
I am changing previewSize on IconButton click
camera plugin version: 0.8.1+3
Device information: Zenfone Max Pro M1 • android-arm64 • Android 11 (API 30)
Default preview size of camera is 1280x720 and aspect ration is 16/9. i am changing aspect ratio by changing preview size to 320x240. so my aspect ratio will be 4/3.
I am using below code:
class CameraScreenGithub extends StatefulWidget {
const CameraScreenGithub({Key? key}) : super(key: key);
#override
_CameraScreenGithubState createState() => _CameraScreenGithubState();
}
class _CameraScreenGithubState extends State<CameraScreenGithub> {
CameraController? _cameraController;
Future<void>? _initializeControllerFuture;
List<CameraDescription> _cameraDescription = [];
#override
void initState() {
super.initState();
_initializeCamera();
}
Future<void> _initializeCamera() async {
_cameraDescription.addAll(await availableCameras());
_setCamera(_cameraDescription[0]);
}
_setCamera(CameraDescription description) {
_cameraController = CameraController(description, ResolutionPreset.high);
_initializeControllerFuture = _cameraController?.initialize();
if (mounted) setState(() {});
}
#override
void dispose() {
_cameraController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: Column(
children: [
Expanded(
child: Stack(
children: [
Center(
child: _cameraPreview(),
),
Positioned(
top: 20,
left: 20,
right: 20,
child: _aspectRatioButton(),
),
],
),
),
],
),
),
);
}
Widget _cameraPreview() => ClipRRect(
borderRadius: BorderRadius.circular(16),
child: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return CameraPreview(_cameraController!);
}
return Container();
},
),
);
Widget _aspectRatioButton() => IconButton(
icon: Icon(
Icons.aspect_ratio,
color: Colors.white,
),
onPressed: () {
_cameraController?.value =
_cameraController!.value.copyWith(previewSize: Size(320, 240));
setState(() {});
},
);
}
try to follow the code what i provided:
camera aspect ratio
you need to use Transform scale
Can anyone help?
Currently, the Text that I am displaying over a video has a fixed size and position.
I'm wondering how I can change this dynamically/responsively to match the size of its parent widget (the Video).
I tried a method using a GlobalKey but got an error, I think it's because the video hadn't loaded..
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
NavBar(),
Body(),
Footer(),
],
),
),
),
);
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ResponsiveLayout(
largeScreen: LargeScreen(),
mediumScreen: LargeScreen(),
smallScreen: LargeScreen(),
);
}
}
class LargeScreen extends StatefulWidget {
#override
_LargeScreenState createState() => _LargeScreenState();
}
class _LargeScreenState extends State<LargeScreen> {
VideoPlayerController _videoPlayerController;
Future<void> _initializeVideoPlayerFuture;
#override
void initState() {
_videoPlayerController = VideoPlayerController.asset(
'assets/videos/video.mp4',
);
_initializeVideoPlayerFuture = _videoPlayerController.initialize();
super.initState();
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: <Widget>[
FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
!_videoPlayerController.value.isBuffering) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the VideoPlayer.
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: Stack(
children: <Widget>[
VideoPlayer(_videoPlayerController),
Positioned(
bottom: 20,
left: 20,
child: FittedBox(
child: Text(
'Text over\na video',
style: TextStyle(
color: Colors.white,
fontSize:50),
),
),
)
],
),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
],
),
);
}
#override
void dispose() {
super.dispose();
_videoPlayerController.dispose();
}
}
LayoutBuilder can provide you with width and height properties which corresponds to the currently available space. Check this documentation here. It provides the builder with a BoxConstraints instance as in here. You can use this information to size your text.
Check the Align widget. It can place the child on specific location within the parent widget's coordinate system. In your case it will be on the coordinates of the Stack widget.
I would try something like the following.
Wrap the Text widget inside a Align widget and use FractionalOffset to place align the widget. You can directly use the Alignment instance also. The origin will vary vary for both the approach. Check the docs here
Then Wrap my Align widget inside a LayoutBuilder widget to get the available size and decide my font size based on it. Something like fontSize: constraints.maxWidth / 25
Below is sample working code.
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
// drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
// NavBar(),
Body(),
// Footer(),
],
),
),
),
);
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
// return ResponsiveLayout(
// largeScreen: LargeScreen(),
// mediumScreen: LargeScreen(),
// smallScreen: LargeScreen(),
// );
return LargeScreen();
}
}
class LargeScreen extends StatefulWidget {
#override
_LargeScreenState createState() => _LargeScreenState();
}
class _LargeScreenState extends State<LargeScreen> {
VideoPlayerController _videoPlayerController;
Future<void> _initializeVideoPlayerFuture;
#override
void initState() {
_videoPlayerController = VideoPlayerController.network(
'http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4',
);
_initializeVideoPlayerFuture =
_videoPlayerController.initialize().then((onValue) {
setState(() {});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: <Widget>[
FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
!_videoPlayerController.value.isBuffering) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the VideoPlayer.
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: Stack(
children: <Widget>[
VideoPlayer(_videoPlayerController),
LayoutBuilder(
builder: (context, constraints) {
return Align(
// this decides the position of the text.
alignment: FractionalOffset(0.05, 0.95),
child: FittedBox(
child: Text(
'Text over\na video',
style: TextStyle(
color: Colors.white,
// here font size is ratio of the maxwidth available for this widget.
fontSize: constraints.maxWidth / 25,
),
),
),
);
},
)
],
),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
FloatingActionButton(
onPressed: () {
setState(() {
_videoPlayerController.value.isPlaying
? _videoPlayerController.pause()
: _videoPlayerController.play();
});
},
child: Icon(
_videoPlayerController.value.isPlaying
? Icons.pause
: Icons.play_arrow,
),
),
],
),
);
}
#override
void dispose() {
super.dispose();
_videoPlayerController.dispose();
}
}
It's easily accessible via MediaQuery.of(context).size (Documentation).
Remember that you have to call inside your build method since it demands the context