如何获得视频的实际纵横比?

时间:2019-10-31 02:32:42

标签: flutter dart flutter-layout flutter-test

我不希望我的视频看起来很拉伸。我正在使用Chewie flutter包作为我的视频播放器。

我尝试使用_controller.value.size.aspectRatio,但返回错误 The getter 'aspectRatio' was called on null.

这是我从图库获取视频的代码:

Future uploadVideoFromGallery() async {
    print("CALLED");
    Map<PermissionGroup, PermissionStatus> permissions =
        await PermissionHandler().requestPermissions(
            [PermissionGroup.storage, PermissionGroup.camera]);

    if (permissions[PermissionGroup.storage] == PermissionStatus.granted) {
      var videoFile = await ImagePicker.pickVideo(source: ImageSource.gallery);
      if (videoFile != null) {
        getVideoThumbnail(videoFile.path);
        setState(() {
          isFileImage = false;
          image = videoFile;
          _controller = VideoPlayerController.file(image);
        });

        print(videoFile.path);
      }
    } else {
      debugPrint('permission not granted');
    }
  }

这是我放置videoFile的代码:

Chewie(
                        controller: ChewieController(
                          videoPlayerController: _controller,
                          aspectRatio: _controller.value.size.aspectRatio,
                          materialProgressColors: ChewieProgressColors(
                            playedColor: Color(colorSecondary),
                            handleColor: Color(colorPrimary),
                            bufferedColor: Color(colorPrimary),
                          ),
                          placeholder: Container(
                            color: Colors.grey,
                          ),
                          autoInitialize: true,
                          looping: false,
                          errorBuilder: (context, errorMessage) {
                            return Center(
                              child: Text(
                                errorMessage,
                                style: TextStyle(color: Color(colorText)),
                              ),
                            );
                          },
                        ),
                      )

6 个答案:

答案 0 :(得分:6)

github上有一个与此有关的问题。

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

class MyVideoPlayer extends StatefulWidget {
  final String path;

  MyVideoPlayer({Key key, @required this.path}) : super(key: key);

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

class _MyVideoPlayerState extends State<MyVideoPlayer> {

  VideoPlayerController _videoPlayerController;
  ChewieController _chewieController;
  Future<void> _future;

  Future<void> initVideoPlayer() async {
    await _videoPlayerController.initialize();
    setState(() {
      print(_videoPlayerController.value.aspectRatio);
      _chewieController = ChewieController(
        videoPlayerController: _videoPlayerController,
        aspectRatio: _videoPlayerController.value.aspectRatio,
        autoPlay: false,
        looping: false,
      );
    });
  }

  @override
  void initState() {
    super.initState();
    // _controller = VideoPlayerController.network('https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4');
    _videoPlayerController = VideoPlayerController.file(File(widget.path));
    _future = initVideoPlayer();
  }

  @override
  Widget build(BuildContext context) {
    return new FutureBuilder(
      future: _future,
      builder: (context, snapshot) {
        return new Center(
          child: _videoPlayerController.value.initialized
          ? AspectRatio(
            aspectRatio: _videoPlayerController.value.aspectRatio,
            child: Chewie(
              controller: _chewieController,
            ),
          )
          : new CircularProgressIndicator(),
        );
      }
    );
  }

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

This is the github url

答案 1 :(得分:3)

如果您只是使用常规的 video_player 包,则可以使用以下代码显示未拉伸的视频版本:

return FittedBox(
      fit: BoxFit.cover,
      child: SizedBox(
        height: model.videoPlayerController.value.size?.height ?? 0,
        width: model.videoPlayerController.value.size?.width ?? 0,
        child: VideoPlayer(model.videoPlayerController),
      ),
    );

我也写了一篇关于 displaying videos from a URL in Flutter 的文章。

答案 2 :(得分:0)

您必须等到视频播放器控制器初始化。仅在 ChewieController 完成后(在 _playerController.initialize() 块中)将纵横比值分配给 then

@override
  void initState() {
    super.initState();
    Uri videoUrl = VideoProvider.fromUri(_post.url).getVideos().first.uri;
    _playerController = VideoPlayerController.network(videoUrl.toString());
    _initializeVideoPlayerFuture = _playerController.initialize().then((_) {
      _chewieController = ChewieController(
        videoPlayerController: _playerController,
        aspectRatio: _playerController.value.aspectRatio,
        allowedScreenSleep: false,
        errorBuilder: (context, error) => Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(Icons.error),
            Text(error),
          ],
        )),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initializeVideoPlayerFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return AspectRatio(
            aspectRatio: _playerController.value.aspectRatio,
            child: Chewie(
              controller: _chewieController,
            ),
          );
        } else {
          return Center(child: CircularProgressIndicator());
        }
      },
    );

答案 3 :(得分:0)

首先,尝试将 _controller.value.size.aspectRatio 更改为 _controller.value.aspectRatio

然后,确保您使用 _controller.initialize() 初始化控制器。

如果它仍然给出错误,则添加一个空检查。

_controller != null
    ? // Do your code
    : Text("Controller is null")

这应该可以解决您的问题。

答案 4 :(得分:0)

better_player 插件解决方案。

在 initState 中:

betterPlayerController = BetterPlayerController(
      betterPlayerConfiguration,
      betterPlayerDataSource: betterPlayerDataSource,
);

betterPlayerController.addEventsListener((BetterPlayerEvent event) {
      if (event.betterPlayerEventType == BetterPlayerEventType.initialized) {
        betterPlayerController.setOverriddenAspectRatio(
            betterPlayerController.videoPlayerController.value.aspectRatio);
        setState(() {});
      }
});

正文:

BetterPlayer(controller: betterPlayerController),

答案 5 :(得分:0)

我只使用原始 videoController 的纵横比,没有为 Chewie 的视频控制器设置它,这对我来说很好用。要获得纵横比,您需要确保首先初始化原始视频控制器,并使用它添加一个侦听器,以便在调用 setState 时,您的小部件会使用正确的纵横比视频重建。同时,您可以在未初始化之前显示循环进度项。

这是我将 Chewie 与 VideoPlayer 一起使用的方式,并且纵横比对我来说是正确的:

class _VideoWidget extends StatefulWidget {

  String videoURL;

  _VideoWidget({required this.videoURL});

  @override
  _VideoWidgetState createState() => _VideoWidgetState(videoURL: videoURL);
}

class _VideoWidgetState extends State<_VideoWidget> {
  late VideoPlayerController _controller;
  late Chewie _chewie;
  late ChewieController _chewieController;
  String videoURL;

  _VideoWidgetState({required this.videoURL});


  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
      videoURL,
      videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
    );
    _controller.addListener(() {
      setState(() {});
    });
    _controller.setLooping(true);
    _controller.initialize();
    _chewieController = ChewieController(
      videoPlayerController: _controller,
      autoPlay: false,
      looping: false,
    );
    _chewie = Chewie(
      controller: _chewieController,
    );
    _chewieController.addListener(() {
      if (!_chewieController.isFullScreen)
        {
          SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
        }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          Container(padding: const EdgeInsets.only(top: 20.0)),
          Padding(padding: EdgeInsets.only(top: 20)),
          Text("Video",
              style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
          Center(
            child: Container(
              height: 300,
              padding: const EdgeInsets.all(20),
              child: _controller.value.isInitialized
                  ? AspectRatio(
                      aspectRatio: _controller.value.aspectRatio,
                      child: Chewie(
                        controller: _chewieController,
                      ),
                    )
                  : Center(
                      child: SizedBox(
                          height: 30.0,
                          width: 30.0,
                          child: CircularProgressIndicator(
                              valueColor: AlwaysStoppedAnimation(Colors.blue),
                              strokeWidth: 1.0))),
            ),
          ),
        ],
      ),
    );
    return _chewie;
  }