• flutter开发实战-video_player播放多个视频MediaCodecVideoRenderer error问题


    flutter开发实战-video_player播放多个视频MediaCodecVideoRenderer error问题

    在开发过程中,我这里使用video_player播放多个视频的时候,出现了MediaCodecVideoRenderer error

    一、使用video_player播放视频

    使用video_player播放单个视频请查看
    https://blog.csdn.net/gloryFlow/article/details/132124837

    这里记录一下解决多个视频MediaCodecVideoRenderer error问题。

    二、在app/build.gradle下添加依赖

    在app/build.gradle下添加依赖

    dependencies{
        implementation 'com.google.android.exoplayer:exoplayer:2.17.1'
    }
    
    • 1
    • 2
    • 3

    实现播放视频的Widget,在播放测试过程中,出现只能播放一个视频,可以设置VideoPlayerOptions,将VideoPlayerOptions的mixWithOthers设置为true。

    Future waitVideoPlay() async {
        _controller?.dispose();
    
        _controller = VideoPlayerController.networkUrl(
          Uri.parse(widget.videoUrl),
          videoPlayerOptions: VideoPlayerOptions(
            mixWithOthers: true,
            allowBackgroundPlayback: false,
          ),
        );
    
        await _controller?.initialize().then((_) {
          // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
          setState(() {});
        });
    
        await _controller!.setLooping(true);
        if (widget.autoPlay) {
          await _controller?.play();
        } else {
          await _controller?.pause();
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    完整VideoPlayerWidget代码如下

    import 'package:flutter/material.dart';
    import 'package:video_player/video_player.dart';
    
    //  视频播放测试
    class VideoPlayerWidget extends StatefulWidget {
      const VideoPlayerWidget({
        Key? key,
        required this.videoUrl,
        required this.isLooping,
        this.autoPlay = true,
        required this.width,
        required this.height,
      }) : super(key: key);
    
      final String videoUrl;
      final bool isLooping;
      final bool autoPlay;
      final double width;
      final double height;
    
      @override
      State createState() => _VideoPlayerWidgetState();
    }
    
    class _VideoPlayerWidgetState extends State {
      VideoPlayerController? _controller;
    
      @override
      void initState() {
        super.initState();
        waitVideoPlay();
      }
    
      Future waitVideoPlay() async {
        _controller?.dispose();
    
        _controller = VideoPlayerController.networkUrl(
          Uri.parse(widget.videoUrl),
          videoPlayerOptions: VideoPlayerOptions(
            mixWithOthers: true,
            allowBackgroundPlayback: false,
          ),
        );
    
        await _controller?.initialize().then((_) {
          // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
          setState(() {});
        });
    
        await _controller!.setLooping(true);
        if (widget.autoPlay) {
          await _controller?.play();
        } else {
          await _controller?.pause();
        }
      }
    
      @override
      Widget build(BuildContext context) {
        if (_controller != null && _controller!.value.isInitialized) {
          return Container(
            width: widget.width,
            height: widget.height,
            child: AspectRatio(
              aspectRatio: _controller!.value.aspectRatio,
              child: VideoPlayer(_controller!),
            ),
          );
        }
    
        return Container(
          width: widget.width,
          height: widget.height,
          color: Colors.orange,
        );
      }
    
      @override
      void dispose() {
        // TODO: implement dispose
        _controller?.dispose();
        super.dispose();
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    三、video_player播放界面播放多个视频

    在使用VideoPlayerWidget播放多个视频,

    Widget buildVideoContainer(BuildContext context) {
        Size screenSize = MediaQuery.of(context).size;
        return Container(
          width: screenSize.width,
          height: screenSize.height,
          color: Colors.white,
          child: Wrap(
            spacing: 24.0.r, // 主轴(水平)方向间距
            runSpacing: 12.0.r, // 纵轴(垂直)方向间距
            alignment: WrapAlignment.center, //沿主轴方向居中
            children: buildVideoListWidget(context),
          ),
        );
      }
    
      List buildVideoListWidget(BuildContext context) {
        List list = [];
        for (int i = 0; i < 4; i++) {
          String videoUrl = videoList[i];
          VideoPlayerWidget widget = VideoPlayerWidget(
            key: GlobalKey(),
            videoUrl: videoUrl,
            isLooping: true,
            width: 320.r,
            height: 480.r,
            delayDuration: Duration(seconds: i),
          );
          list.add(widget);
        }
    
        return list;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    完整video_page代码如下

    class VideoPage extends StatefulWidget {
      const VideoPage({super.key});
    
      @override
      State createState() => _VideoPageState();
    }
    
    class _VideoPageState extends State
        with AutomaticKeepAliveClientMixin {
      List videoList = [];
    
      @override
      void initState() {
        // TODO: implement initState
        initVideoList();
        super.initState();
      }
    
      void initVideoList() {
        videoList.add(
            "https://v-qiniu.laikeshuo.com/1648693943358lkGhcDwFQzw3Ix266OsW7WWkzhY0.mp4");
    
        videoList.add("https://v-qiniu.laikeshuo.com/833134651693235939767");
        videoList
            .add("https://v-qiniu.laikeshuo.com/fb52e680058440a8b220ff7d2d555632");
        videoList
            .add("https://v-qiniu.laikeshuo.com/f6967489119040319a5fdda8be3e5662");
        videoList
            .add("https://v-qiniu.laikeshuo.com/7364b2eb14d54234b205d77147106b7f");
        videoList
            .add("https://v-qiniu.laikeshuo.com/ceee6bedf4814fbcaf4178ea5fb84fc0");
        videoList
            .add("https://v-qiniu.laikeshuo.com/3f7a60531042461eb10bf29f0c31ec6b");
        videoList
            .add("https://v-qiniu.laikeshuo.com/515211835007418da0e6b26425de907c");
        videoList
            .add("https://v-qiniu.laikeshuo.com/0bd0eaf2d30e4a66a4d7a5eb9970ed2a");
        videoList
            .add("https://v-qiniu.laikeshuo.com/35b2548bcf5140bc93425dcd69054294");
        videoList
            .add("https://v-qiniu.laikeshuo.com/3f7a60531042461eb10bf29f0c31ec6b");
    
        // videoList
        //     .add("https://dphoto.qiniu.laikeshuo.com/bc7a2df5143a4d3a84c8a8407b22e933.mp4");
        // videoList
        //     .add("https://dalat-qiniu.laikeshuo.com/31c5040167ec43168d7ec80c9bf33104.mp4");
      }
    
      @override
      void dispose() {
        // TODO: implement dispose
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: ProviderWidget(
            model: VideoModel(),
            onModelReady: (model) => model.initData(),
            builder: (context, model, child) {
              if (model.isBusy) {
                return Container();
              } else if (model.isError) {
                return Container();
              } else if (model.isEmpty) {
                return Container();
              }
    
              return buildVideoContainer(context);
            },
          ),
        );
      }
    
      Widget buildVideoContainer(BuildContext context) {
        Size screenSize = MediaQuery.of(context).size;
        return Container(
          width: screenSize.width,
          height: screenSize.height,
          color: Colors.white,
          child: Wrap(
            spacing: 24.0.r, // 主轴(水平)方向间距
            runSpacing: 12.0.r, // 纵轴(垂直)方向间距
            alignment: WrapAlignment.center, //沿主轴方向居中
            children: buildVideoListWidget(context),
          ),
        );
      }
    
      List buildVideoListWidget(BuildContext context) {
        List list = [];
        for (int i = 0; i < 4; i++) {
          String videoUrl = videoList[i];
          VideoPlayerWidget widget = VideoPlayerWidget(
            key: GlobalKey(),
            videoUrl: videoUrl,
            isLooping: true,
            width: 320.r,
            height: 480.r,
            delayDuration: Duration(seconds: i),
          );
          list.add(widget);
        }
    
        return list;
      }
    
      @override
      // TODO: implement wantKeepAlive
      bool get wantKeepAlive => true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

    经过测试,发现播放多个视频,播放三个正常,多于三个时候,会报告如下错误。(我使用的是低配置的Android主板,设备性能差)

    [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(VideoError, Video player had error x0.q: MediaCodecVideoRenderer error, index=0, format=Format(1, null, null, video/avc, avc1.64001E, -1, null, [1080, 1920, 30.0], [-1, -1]), format_supported=YES, null, null)

    三、小结

    flutter开发实战-video_player播放多个视频MediaCodecVideoRenderer error问题。

    https://blog.csdn.net/gloryFlow/article/details/132676760

    学习记录,每天不停进步。

  • 相关阅读:
    Spring Cloud Ribbon:负载均衡的服务调用
    准备蓝桥杯的宝贝们看过来,二分法一网打尽(基础篇)
    远程教育:低代码重塑教育技术
    工具类Utils
    搭建数字孪生车间需要哪些关键技术?
    在Windows11上安装ubuntu虚拟机
    AXI总线流程
    docker 部署es 集群 elasticsearch
    开源规则引擎LiteFlow项目应用实践
    C语言学生成绩管理系统
  • 原文地址:https://blog.csdn.net/gloryFlow/article/details/132676760