【原创不易,转载请注明出处:https://blog.csdn.net/email_jade/article/details/86650561】
【20190222更新】
flutter_ijk 是flutter端的ijkplayer播放器,在IOS和Android native端都使用的是bilibili的ijkplayer,由于GitHub大小限制,本项目的ijkplayer源码放在https://gitee.com/jadennn/flutter_ijkplayer_source.git,已经定制过编译脚本和部分的功能代码,可以参考以下步骤来获取:
1. ijkplayer的源码如下,支持ios和Android编译:
编译步骤请查看源码根目录的readme.txt
默认使用的是module-rtsp.sh,如果要增加配置,请修改此文件。
ijkplayer源代码:
https://gitee.com/jadennn/flutter_ijkplayer_source.git
2. 对于Android ijk的编译,参考如下链接,请注意,使用上面的ijkplayer代码,不用再通过脚本重复下载ijkplayer了:
a.配置jdk,sdk,ndk环境
b.查看ijkplayer下的readme.txt,参考编译Android so库
c.拷贝修复bug后的编译完成的so库替换flutter_ijk Android目录下的so库,注意的是多平台支持
https://blog.csdn.net/coder_pig/article/details/79134625
a. 配置环境
b.查看ijkplayer下的readme.txt,编译ios代码
c.制作framework(需要注意的是我的IJKMediaPlayer里面有一些关于CVPixelBufferRef的定制,都加了//add for flutter的注释,这些修改不能去掉)
d.拷贝修复bug后的编译完成的IJKMediaFramework.framework替换flutter_ijk IOS目录下的IJKMediaFramework.framework库
https://www.jianshu.com/p/3108c8a047ee
以上步骤可以得到ijkplayer在Android端的so库和IOS的framework文件,dart层见GitHub仓库。
【前言】
项目中要用到rtsp视频流的播放,但是flutter原生播放器video_player不支持rtsp,因为原生播放器在安卓native采用的是EXOPlayer,而在IOS端采用的是AVPlayer,这两个播放器目前都不支持rtsp(可以自定义支持,但是video_player集成的版本不支持),因此必须自己来封装一个播放器,以便进行rtsp的播放。
github地址 【https://github.com/jadennn/flutter_ijk】
【正文】
播放器的选择,因为之前做安卓项目用过ijkplayer,并且只要重新编译一下就可以支持rtsp了,因此,在Android和IOS的native层都采用的是ijkplayer。
先放上效果图:
首先来了解一下flutter的插件开发,就是利用平台通道在原生与flutter之间建立一个桥梁,以便在flutter中使用native的功能,具体见https://book.flutterchina.club/chapter11/platform-channel.html,所以插件的开发一般分为三个部分:native,flutter以及平台通道相关。由于平台通道部分比较简单,一般的插件都大同小异,我们本篇文章就着重讲一下ijkplayer的native和flutter部分。
要使用ijkplayer并且支持rtsp,无论是Android还是IOS,都必须配置脚本重新编译,而在这之前,我们要先了解一下flutter的纹理渲染方式,也就是我们的视频怎么展示到屏幕上的,详见http://www.cocoachina.com/ios/20180926/25027.html,大意是说在flutter中采用的是OpenGL来进行渲染的,并且Android端和IOS端还是有一些差别的。对于Android而言,可以直接通过
TextureRegistry textures = registrar.textures();
TextureRegistry.SurfaceTextureEntry handle = textures.createSurfaceTexture();
Surface surface = new Surface(handle .surfaceTexture());
这样简单几步得到我们常见的surface,然后就可以直接将ijkplayer的视频流输出到surface上了。对于IOS而言,要渲染到屏幕上,系统提供了一个api:
@protocol FlutterTexture
- (CVPixelBufferRef _Nullable)copyPixelBuffer;
因此我们需要得到ijkplayer的视频流CVPixelBufferRef,但是对于ios而言,ijkplayer并没有这样的接口,也就是说,我们需要去对ijkplayer做一些简单的修改,让我们能够直接获取CVPixelBufferRef流,这里参考的是ARVRSchool的三篇文章:
https://www.jianshu.com/p/8c8dceb86915
https://www.jianshu.com/p/852d7429897b
https://www.jianshu.com/p/1802b45ed612
理清了Android和IOS对flutter的渲染方式后我们就可以着手修改编译ijkplayer了,要支持rtsp,首先要修改一下config下面的module脚本,建议基于module-lite.sh修改,这样编出来的库不至于太大,当然,除了rtsp,其他的协议格式或者编解码格式也是在module.sh里面修改配置的,如下:
##新增
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=sdp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=tcp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=udp"
##修改
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
Android端编译即可,IOS端,前文说到过,要修改源码,支持获取CVPixelBufferRef, 参考以上链接即可。
有了Android和IOS的库然后可以开始ijkplayer flutter库的封装了,本代码参考的是官方库video_player进行封装的,值得注意的是,要保持Android和IOS native端接口的统一,因为它们最终都是通过平台通道映射到flutter中的,对于Android和IOS,ijkplayer的时间单位分别为ms和s, 这点尤其注意。为了提升rtsp的播放质量,在播放之前配置了一些ijkplayer的option,具体可以参考GitHub的源代码。
由于本篇内容实在太多,很多细节只有在阅读代码的时候才能体现出来,因此就不再赘述了,详见https://github.com/jadennn/flutter_ijk 。
当然,如果不想了解实现过程,想直接体验一下本文的库,参考如下步骤即可:
1. 在pubspec.yaml中引用库:
flutter_ijk:
git:
url: https://github.com/jadennn/flutter_ijk
2. 使用:
class VideoPageState extends State {
IjkPlayerController _controller;
@override
void initState(){
super.initState();
_controller = IjkPlayerController.network("rtsp://admin:[email protected]/h264/ch1/main/av_stream")
..initialize().then((_) {
setState(() {});
_controller.play();
});
}
@override
Widget build(BuildContext context) {
return Material(
child: _controller == null ? Container(): Center(
child:
_controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: IjkPlayer(_controller),
)
: Container(),
),
);
}
}
详细接口api请阅读源码。
flutter很好,路还很长,让我们一起奋斗前行!