一步到位的 Android 视频播放:GSYVideoPlayer 快速上手指南
【免费下载链接】GSYVideoPlayerVideo players (IJKplayer, ExoPlayer, MediaPlayer), HTTPS, 16k page size, danmaku (bullet chat) support, external subtitles, support for filters, watermarks, and GIF screenshots, pre-roll and mid-roll ads, multiple simultaneous playback, basic seeking/dragging, volume and brightness adjustment, play-while-cache support项目地址: https://gitcode.com/GitHub_Trending/gs/GSYVideoPlayer
在 Android 应用里做视频播放,你要同时应付内核选型、边播边缓存、全屏旋转、列表自动播放一堆事情。GSYVideoPlayer 把 IJKPlayer、ExoPlayer(Media3)、MediaPlayer 统一封装到 UI 和 Manager 两层之下,弹幕、外挂字幕、滤镜、投屏这些能力也一并内置。目标是让开发者只管页面逻辑、不管内核差异,适合任何要在 App 里认真做视频播放的场景。
项目全景:一张图看懂设计
GSYVideoPlayer 把播放链路拆成几层,每层都可以独立替换。最上面是 UI 层:GSYVideoPlayer继承GSYBaseVideoPlayer处理大小屏切换业务,往下依次叠GSYVideoControlView(控制按钮)、GSYVideoView,再往下是渲染层,TextureView/SurfaceView/GLSurfaceView三选一。UI 之下是播放内核层,IjkMediaPlayer、ExoPlayer2、MediaPlayer都实现同一个IPlayerManager接口;本地缓存同样有ICacheManager接口,默认ProxyCacheManager,Exo 场景换ExoPlayerCacheManager。
工厂加接口:内核为什么能热插拔
这个项目有个挺巧的设计:业务代码从不直接new内核,一律从PlayerFactory、CacheFactory拿对象,具体实现按注册的类在运行时反射实例化。所以"换内核"只是一行全局设置,页面代码一行不用改。想接自己的内核,实现IPlayerManager注册进去就行——分层的价值就在这里。
五分钟跑起来
环境准备
Maven Central 已经发布了整包,依赖就一行:
allprojects { repositories { mavenCentral() } } // 模块 dependencies 里引入完整版 dependencies { implementation 'io.github.carguo:gsyvideoplayer:14.0.0' }想控制包体积,也可以拆成gsyvideoplayer-java加gsyvideoplayer-arm64这类 so 模块按需组合,别给同一 ABI 同时引入两套 native 库。另外播放页的 Activity 要在 manifest 里声明configChanges(orientation|screenSize等),否则旋转全屏时页面被系统重建,播放状态就丢了。
核心代码
布局里放一个标准控件,全类名com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer,宽度match_parent,高度自定。Activity 里:
StandardGSYVideoPlayer videoPlayer = findViewById(R.id.video_player); videoPlayer.setUp(videoUrl, true, "测试视频"); // 设置封面图 ImageView cover = new ImageView(this); cover.setImageResource(R.mipmap.xxx1); videoPlayer.setThumbImageView(cover); videoPlayer.startPlayLogic(); // 开始播放 // onPause 调 onVideoPause(),onResume 调 onVideoResume() // onDestroy 调 GSYVideoManager.releaseAllVideos()setUp(url, cacheWithPlay, title)第二个参数就是是否边播边缓存,到这里一条可播放的视频已经跑通了。
验证效果
仓库里app模块是个几十种场景的 Demo,先跑SimplePlayer最直接:一个播放器、封面、标题、全屏按钮和全部控制条都开箱即用。更完整的清单可以看 doc/USE.md,直接播放、列表、详情页三种入口各给了模式一/模式二两套写法。
视频播放核心能力拆解
三大播放内核切换
这是 GSYVideoPlayer 最大的卖点:IJK 基于 FFmpeg 兼容性最好(当前 n5.1.10),Media3 自适应码率和 DASH 做得好,系统内核最稳定。切换内核是一行全局设置:
PlayerFactory.setPlayManager(Exo2PlayerManager.class); // Media3 内核 PlayerFactory.setPlayManager(SystemPlayerManager.class); // 系统 MediaPlayer有阿里播放器的话还能注册AliPlayerManager。设置之后所有setUp都走新内核,同一套业务代码不用动。
边播边缓存:两套实现二选一
网络视频每次重新拉流太浪费。项目给两条缓存路径,都走CacheFactory切换:
// 代理缓存:所有内核通用,但不支持 m3u8 CacheFactory.setCacheManager(ProxyCacheManager.class); // Exo 缓存:支持 m3u8,需在创建缓存前设置上限(默认 512MB) ExoSourceManager.setCacheMaxSize(1024L * 1024L * 1024L); CacheFactory.setCacheManager(ExoPlayerCacheManager.class);两者共享preloadUrl、clearCache、getCacheFile这套接口,换成自己实现的缓存管理器,业务代码同样不用动。
GL 渲染:滤镜、LUT 与美颜
默认渲染是TextureView,做滤镜特效时切到GLSurfaceView就能挂自己的 shader:
// 创建渲染 View 前切到 GL 渲染 GSYVideoType.setRenderType(GSYVideoType.GLSURFACE); GSYVideoGLViewMultiPassRender render = new GSYVideoGLViewMultiPassRender(); render.setMultiPassEffect(new GaussianBlurMultiPassEffect(6.0f)); player.setCustomGLRenderer(render);LUT 调色、美颜、Glitch、CRT 这类单 pass 效果走setEffectFilter,仓库还自带lut/cyberpunk.png等 LUT 素材,完整清单见 doc/RECENT_FEATURES.md。外挂字幕也不挑内核——SRT/WebVTT 由 UI 层统一解析渲染,IJK、Exo、系统内核下位置行为一致。
真实场景怎么用
信息流列表视频自动播放
信息流页面,每个 item 一个小播放区,滑进来自动播、滑走就释放。关键是给每个 player 打上setPlayTag加setPlayPosition的身份标记,再在列表滚动回调里判断是否滑出可视区:
videoList.setOnScrollListener(new OnScrollListener() { @Override public void onScroll(AbsListView view, int first, int count, int total) { int lastVisibleItem = first + count; // 正在播放的视频滑出屏幕就释放 int pos = GSYVideoManager.instance().getPlayPosition(); if (pos >= 0 && (pos < first || pos > lastVisibleItem)) { GSYVideoManager.releaseAllVideos(); adapter.notifyDataSetChanged(); } } });如果还想在滑出屏幕后用小窗继续播,用GSYVideoHelper托管播放器即可,对应 Demo 是SimpleListVideoActivityMode2。
详情页全屏与沉浸背景
详情页标配两件事:全屏动画和沉浸式模糊背景。全屏内置在控件里,startWindowFullscreen会反射复刻出全屏播放器,不用自己管理两个实例;OrientationUtils负责横竖屏旋转,返回键回竖屏也是现成的。这里有个隐藏的好用点:仓库内置的"背景模糊填充播放"Demo,把当前帧放大填充背景再加模糊,竖屏详情页的观感一下就不一样了。✨
详情页的标准写法是 Activity 继承GSYBaseActivityDetail,参数全走GSYVideoOptionBuilder链式配置(封面、URL、setCacheWithPlay等),生命周期和全屏回调都在基类收口了。
DLNA 投屏到电视
需要做"投屏到电视"时,加上可选模块gsyvideoplayer-cast(真实 minSdk 为 26),核心库保持协议无关,只暴露CastCapability/CastProvider/CastSession这套 SPI。连上设备后,SetAVTransportURI → Play → Seek链路会把本地当前进度带过去,断开时本地从远端最后位置恢复播放。Demo 自带 Loopback Receiver,没有真电视也能端到端自测。
避坑与调优
混淆后 ClassNotFoundException→GSYBaseVideoPlayer靠反射复刻全屏实例,PlayerFactory用Class.newInstance实例化内核,R8 会把它们优化掉 → 按 README 加 keep 规则:ijk 包整体保留,播放器类保留(Context[, Boolean])构造器,IPlayerManager/ICacheManager实现类保留无参构造。
so 重复打包→ex_so已包含 arm64-v8a / armeabi-v7a / x86_64 三套完整库,再叠加gsyvideoplayer-arm64等独立模块,同一 so 进包两份,体积翻倍 →ex_so和独立 ABI 模块二选一,别混引。
m3u8 开缓存后一直转圈→ 代理缓存ProxyCacheManager不支持 m3u8,这是代理方案本身的限制 → m3u8 场景换 Exo 缓存ExoPlayerCacheManager,且setCacheMaxSize要在缓存创建前调用。
旋转全屏后播放中断或黑屏→ manifest 没写configChanges,旋转时系统重建了 Activity → 播放页补齐keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode,需要自控旋转再配合onConfigurationChanged处理。
IJK 日志刷屏→ IJK 模式下 native 层日志极吵,release 包里 App 自己的日志全被淹没 →IjkPlayerManager.setLogLevel(IjkMediaPlayer.IJK_LOG_SILENT)直接静音,调试期再按需放开。
写在最后
GSYVideoPlayer 解决的是"内核可换、接口不变"这件事:缓存、内核、渲染、UI 四层各自可替换,业务侧只关心页面逻辑。边播边缓存、内核切换、全屏动画、DLNA 投屏都是现成的,列表和详情页各给了两种成熟写法。
如果准备在 Android 上做视频业务,先去仓库的app模块跑一遍 Demo,那是最好的教程;遇到问题先翻 doc/QUESTION.md,FAQ 基本都有答案,再提 Issue 时带上 Demo 页面、复现步骤和机型信息,响应会快很多。
【免费下载链接】GSYVideoPlayerVideo players (IJKplayer, ExoPlayer, MediaPlayer), HTTPS, 16k page size, danmaku (bullet chat) support, external subtitles, support for filters, watermarks, and GIF screenshots, pre-roll and mid-roll ads, multiple simultaneous playback, basic seeking/dragging, volume and brightness adjustment, play-while-cache support项目地址: https://gitcode.com/GitHub_Trending/gs/GSYVideoPlayer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考