flutter开发实战-video_player插件播放抖音直播实现(仅限Android端)

这篇具有很好参考价值的文章主要介绍了flutter开发实战-video_player插件播放抖音直播实现(仅限Android端)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

flutter开发实战-video_player插件播放抖音直播实现(仅限Android端)

在之前的开发过程中,遇到video_player播放视频,通过查看video_player插件描述,可以看到video_player在Android端使用exoplayer,在iOS端使用的是AVPlayer。由于iOS的AVPlayer不支持flv、m3u8格式的直播,这里video_player播放抖音直播仅仅在Android有效,在iOS端,如果需要播放抖音直播,可以使用fijkplayer插件进行播放,由于fijkplayer使用的是ijkplayer,可以播放flv、m3u8格式的直播。

一、引入

在pubspec.yaml中引入video_player

  # 播放器
  video_player: ^2.7.0
  # fijkplayer: ^0.11.0

二、实现VideoPlayer的Widget

2.1 在iOS中的设置

在iOS工程中info.plist添加一下设置,以便支持Https,HTTP的视频地址

<key>NSAppTransportSecurity</key>
<dict>
	<key>NSAllowsArbitraryLoads</key>
	<true/>
</dict>

2.2 在Android中的设置

需要在/android/app/src/main/AndroidManifest.xml文件中添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

2.3 播放的VideoPlayer

使用video_player插件,需要使用VideoPlayerController来控制播放、暂停、添加监听

初始化后添加监听,来获取VideoPlayerController中的Value值,可以看到一些状态。例如

VideoPlayerValue(duration: 0:00:00.001000, size: Size(1280.0, 720.0), position: 0:32:14.877000, caption: Caption(number: 0, start: 0:00:00.000000, end: 0:00:00.000000, text: ), captionOffset: 0:00:00.000000, buffered: [DurationRange(start: 0:00:00.000000, end: 0:32:17.868000)], isInitialized: true, isPlaying: true, isLooping: false, isBuffering: false, volume: 1.0, playbackSpeed: 1.0, errorDescription: null, isCompleted: false)

添加监听

// 添加监听
  void addListener() {
    if (_controller != null) {
      _controller!.addListener(videoListenerCallback);
    }
  }

移除监听

// 移除监听
  void removeListener() {
    if (_controller != null) {
      _controller!.removeListener(videoListenerCallback);
    }
  }

监听的callback回调

void videoListenerCallback() {
    // 监听结果
    if (_controller != null) {
      if (_controller!.value.hasError) {
        // 出现错误
        setState(() {});
      }

      if (_controller!.value.isCompleted) {
        // 直播完成
        setState(() {});
      }

      if (_controller!.value.isBuffering) {
        // 正在buffer
      }

      if (_controller!.value.hasError || _controller!.value.isCompleted) {
        // 是否处于错误状态 或者 播放完成
        if (widget.liveController.onOutLinkPlayerCompleted != null) {
          widget.liveController.onOutLinkPlayerCompleted!();
        }
      }

      if (_controller!.value.hasError == false) {
        // 可播放,隐藏封面
        if (widget.liveController.onOutLinkPlayerCanPlay != null) {
          widget.liveController.onOutLinkPlayerCanPlay!();
        }
      }
    }
  }

播放

Future<void> play() async {
if (_controller != null) {
	await _controller?.play();
    }
}

暂停

Future<void> play() async {
if (_controller != null) {
	await _controller?.pause();
    }
}

完整代码如下

//  视频播放测试
class VideoPlayerSkeleton extends StatefulWidget {
  const VideoPlayerSkeleton({
    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;

  
  State<VideoPlayerSkeleton> createState() => _VideoPlayerSkeletonState();
}

class _VideoPlayerSkeletonState extends State<VideoPlayerSkeleton> {
  VideoPlayerController? _controller;

  
  void initState() {
    super.initState();

    videoPlay();
    print("_VideoPlayerSkeletonState videoUrl:${widget.videoUrl}");
  }

  // 添加监听
  void addListener() {
    if (_controller != null) {
      _controller!.addListener(videoListenerCallback);
    }
  }

  void videoListenerCallback() {
    // 监听结果
    if (_controller != null) {
      if (_controller!.value.hasError) {
        // 出现错误
        setState(() {});
      }

      if (_controller!.value.isCompleted) {
        // 直播完成
        setState(() {});
      }

      if (_controller!.value.isBuffering) {
        // 正在buffer
      }
    }
  }

  // 移除监听
  void removeListener() {
    if (_controller != null) {
      _controller!.removeListener(videoListenerCallback);
    }
  }

  // 播放视频
  Future<void> videoPlay() async {
    _controller?.dispose();

    _controller = VideoPlayerController.networkUrl(
      Uri.parse(widget.videoUrl),
      videoPlayerOptions: VideoPlayerOptions(
        mixWithOthers: true,
        allowBackgroundPlayback: false,
      ),
    );

    addListener();

    await _controller?.initialize().then((_) {
      // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
      setState(() {});
    }).catchError((error) {
      // 是否处于错误状态 或者 播放完成
      if (widget.liveController.onOutLinkPlayerCompleted != null) {
        widget.liveController.onOutLinkPlayerCompleted!();
      }
    }).whenComplete(() {
      // print('checkAnimationTimeout whenComplete');
    });

    await _controller!.setLooping(widget.isLooping);
    if (widget.autoPlay) {
      await _controller?.play();
    } else {
      await _controller?.pause();
    }
  }

  
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      color: Colors.black87,
      child: Stack(
        alignment: Alignment.center,
        children: [
          buildVideoPlayer(context),
          buildStateIntro(context),
        ],
      ),
    );
  }

  // 播放视频
  Widget buildVideoPlayer(BuildContext context) {
    if (_controller != null && _controller!.value.isInitialized) {
      return AspectRatio(
        aspectRatio: _controller!.value.aspectRatio,
        child: VideoPlayer(_controller!),
      );
    }
    return Container();
  }

  // 播放过程中出现error
  Widget buildStateIntro(BuildContext context) {
    if (_controller != null) {
      String title = "";
      String message = "";
      bool showIntro = false;
      if (_controller!.value.hasError) {
        showIntro = true;
        title = "播放出现错误";
        message = _controller!.value.errorDescription ?? "";
      } else {
        if (_controller!.value.isCompleted) {
          showIntro = true;
          title = "播放结束";
        }
      }

      if (showIntro) {
        return Container(
          padding: EdgeInsets.symmetric(vertical: 50.r, horizontal: 50.r),
          color: Colors.transparent,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Expanded(child: Container()),
              Text(
                title,
                textAlign: TextAlign.center,
                softWrap: true,
                style: TextStyle(
                  fontSize: 28.r,
                  fontWeight: FontWeight.w500,
                  fontStyle: FontStyle.normal,
                  color: Colors.white,
                  decoration: TextDecoration.none,
                ),
              ),
              SizedBox(
                height: 25.r,
              ),
              Text(
                message,
                textAlign: TextAlign.center,
                softWrap: true,
                style: TextStyle(
                  fontSize: 22.r,
                  fontWeight: FontWeight.w500,
                  fontStyle: FontStyle.normal,
                  color: Colors.white,
                  decoration: TextDecoration.none,
                ),
              ),
              Expanded(child: Container()),
            ],
          ),
        );
      }
    }

    return Container();
  }

  
  void dispose() {
    // TODO: implement dispose
    removeListener();
    _controller?.dispose();
    super.dispose();
  }
}

三、从抖音网站上找到直播地址

由于使用抖音播放地址,这里简单描述一下从抖音网站上找到直播的flv地址。

进入抖音直播间,在网页点击鼠标右键,看到检查。
https://live.douyin.com/567752440034
flutter开发实战-video_player插件播放抖音直播实现(仅限Android端),移动开发,flutter开发实战,flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

找到网络,刷新页面,可以看到stream的一条,
flutter开发实战-video_player插件播放抖音直播实现(仅限Android端),移动开发,flutter开发实战,flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

复制地址即可,使用该地址播放直播
flutter开发实战-video_player插件播放抖音直播实现(仅限Android端),移动开发,flutter开发实战,flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

https://pull-hs-spe-f5.douyincdn.com/fantasy/stream-728687306789918920718_sd.flv?_neptune_token=MIGlBAxGexWdmRAYAAGs67QEgYIZi9nqbdY3bbfeK9dCVFBnlFTJNF1WNGRZ3AVrQ1ixrE_54JzkGsfuBjGER_2RhP5Qy_GzELSQuct4bK5aktJ2P2xnNznJG87KKhybkeCuefBAkOCI9Tx8eA1mz2GcmfcfqFNeR8DFPDcbzFp_sKyyJRnytmILegqrqjcjxgW04GYwBBDMFIKjhmF1jpi96O53wH7v&expire=1696731973&sign=38f51d46dcd5828fdbc212372bbb3522&volcSecret=38f51d46dcd5828fdbc212372bbb3522&volcTime=1696731973

四、查看直播结果

之后,我们将地址复制到VideoPlayerSkeleton中,运行后,可以看到播放的效果

flutter开发实战-video_player插件播放抖音直播实现(仅限Android端),移动开发,flutter开发实战,flutter,flutter,android,cocoa,抖音直播,video_player,exoplayer,avplayer

注意:直接在Container上设置大小后,child是AspectRatio(
aspectRatio: _controller!.value.aspectRatio,
child: VideoPlayer(_controller!),
);
会出现画面变形,可以使用Stack嵌套一下。

五、小结

flutter开发实战-video_player插件播放抖音直播实现(仅限Android端)。描述可能不是特别准确,请见谅。

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

学习记录,每天不停进步。文章来源地址https://www.toymoban.com/news/detail-743226.html

到了这里,关于flutter开发实战-video_player插件播放抖音直播实现(仅限Android端)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter 视频video_player与缓存flutter_cache_manager

    参考官方DefaultCacheManager代码,这里引入Config可以指定天数与最大个数. 文件名 video_cache.dart 使用 await MyDefaultCacheManager().getSingleFile(url)) 即可

    2024年02月07日
    浏览(37)
  • Flutter:文件读取—— video_player、chewie、image_picker、file_picker

    简单学习一下几个比较好用的文件读取库 简介 用于视频播放 官方文档 https://pub-web.flutter-io.cn/packages/video_player 安装 加载网络视频 加载本地视频 设置倍速和进度条 video_player 虽然是官方提供的插件,但是很明显它只适合拿来简单的播放视频,就比如前端的 video 标签功能也很

    2024年02月13日
    浏览(52)
  • vue 视频播放插件vue-video-player自定义样式、自动播放设置、设置一开始全屏播放视频

    1、背景 项目中有涉及视频播放的需求,并且UI设计了样式,与原生的视频video组件有差异,所以使用了vue-video-player插件,并对vue-video-player进行样式改造,自定义播放暂停按钮、全屏按钮、时间进度条样式等,自动播放设置、设置一开始全屏播放视频、监听全屏事件等。 2、效

    2024年02月05日
    浏览(48)
  • vue 视频播放插件vue-video-player自定义样式、自动播放设置、设置一开始全屏播放视频、监听全屏事件

    1、背景 项目中有涉及视频播放的需求,并且UI设计了样式,与原生的视频video组件有差异,所以使用了vue-video-player插件,并对vue-video-player进行样式改造,自定义播放暂停按钮、全屏按钮、时间进度条样式等,自动播放设置、设置一开始全屏播放视频、监听全屏事件等。 2、效

    2024年02月08日
    浏览(58)
  • Unity视频播放之Video Player的简单使用

    使用Unity自带的VideoPlayer来播放视频 一、准备视频 Unity3D常用视频格式:.mov、.mpg、.mpeg、.mp4、.avi、.asf 如果都不识别,试试转换成ogv格式。转换完成之后,将视频素材文件拖入Unity Assets 文件夹内。 二、创建UI及添加组件 创建RenderTexture资源,设置分辨率,跟视频分辨率一致

    2024年01月18日
    浏览(87)
  • Unity2020Video player发布后无法播放视频问题

    我也是小白,用Unity过程中也是遇到很多草蛋问题,我在做demo的时候第一次用到Unity的video player,听说ogv格式能直接播放,我就把视频转了ogv格式,然后放到clip里,编辑器里运行完全没问题,发布打包后就播放不了,黑屏都没有,直接视频没了,百度搜的绝对路径说是放到

    2024年02月15日
    浏览(53)
  • 前端实现视频播放功能----vue-video-player --save

    步骤一: npm安装插件 : npm install vue-video-player --save 如果报错 安装具体版本 如下所示: npm install --save vue-video-player@4.0.6  如果package.json文件内显示则为安装成功 步骤二: 局部引入---这里因为只有一个页面需要所有采用的局部引入 在需要的页面引入(这里注意路径不要写错

    2024年02月10日
    浏览(47)
  • vue-video-player,springboot实现视频分段下载播放

    事情的起因是在博主把项目部署到服务器上后,发现由于视频太大,加上服务器太垃圾,导致稍微大点的视频加载很久才能播放(指十多分钟…),然后就上网查找资料,看下咋实现。 这里涉及到有关http请求的知识“HTTP Header里的Range和Content-Range参数,Range是在请求头里 Ra

    2023年04月13日
    浏览(76)
  • 【vue】 vue 实现视频播放 vue-video-player

    注:用来测试的在线视频url地址 1.下载依赖 vue2 推荐下载指定版本依赖,不然可能下载不下来报错。 2.全局注册main.js 3.新建vue文件 下班`

    2024年02月16日
    浏览(45)
  • Unity播放带Alpha通道的视频【WebM+Video Player】(替代播放GIF方案)

    在Unity中播放GIF或者动态效果,可以通过Video Player播放带透明通道的WebM视频来实现。 制作带Alpha的MOV视频 制作带Alpha通道的MOV视频有多重方式,如AE、PR、PS等等,具体制作过程可以自行百度。 将MOV视频格式转化为WebM格式 将WebM格式导入Unity,设置视频播放 完成动态效果展示

    2024年02月13日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包