拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Android IjkPlayer播放RTSP/RTMP流媒体实战指南

简介Android IjkPlayer 播放RTSP/RTMP视频流 Demo 是一份可运行的 Android 示例工程面向需要处理实时流媒体播放的移动端开发者针对系统默认 MediaPlayer 对 RTSP/RTMP 支持有限的问题提供了基于 Bilibili 开源 IjkPlayer 的完整集成方案适用于视频监控、在线直播等场景。资源共 147 个文件压缩后 13.68MB文件类型涵盖 xml 布局资源、so 动态链接库、kotlin 源码、gradle 构建配置以及 ijkplayer-java-release.aar 核心库等工程模块划分清晰可直接导入 Android Studio 构建运行。目前已有 980 人学习下载。Demo 中详细演示了 IjkMediaPlayer 的初始化、SurfaceView/TextureView 关联、RTSP 地址注入、prepareAsync 异步准备、start 播放以及 onPrepared/onError 回调处理同时包含暂停、停止、释放资源等常见控制逻辑帮助开发者避开集成中的典型坑点快速将实时流播放能力落地到实际项目。 在项目里第一次接到“在Android平板上实时看监控摄像头画面”的需求时我差点直接用系统MediaPlayer上生产。结果不到半天就发现RTSP流在Android原生播放器面前根本不是一个“能播就播”的小事海康的H.264主码流能出一帧就卡死大华某些设备的SDP格式直接让MediaPlayer报不支持RTMP更是连门都进不去。后来老老实实切到B站开源的IjkPlayer花几天时间把Android IjkPlayer播放RTSP/RTMP视频流的Demo跑通才摸清楚这套东西的正确玩法。这篇文章我不聊理论空中楼阁直接把可运行的Demo代码、参数含义、集成方式、真机排错经验全放出来适合刚开始接触Android流媒体播放、或者正在纠结“用什么播放器拉RTSP/RTMP”的朋友。1. 为什么RTSP/RTMP在Android上总让人想摔手机1.1 系统播放器的边界MediaPlayer和ExoPlayer为什么不够用先给结论Android原生MediaPlayer确实能播一部分RTSP流但能不能播、播得稳不稳完全看设备和厂商ROM的心情。底层逻辑其实不复杂。MediaPlayer走的是Stagefright/NuPlayer链路它对RTSP有一套默认实现这套实现针对的是标准SDP会话和常见的H.264/AAC组合。问题在于海康、大华这些摄像头厂商做RTSP不是照标准文档一板一眼来的会在SDP里塞不少私有扩展字段有些编码参数也比较特殊。结果就是同一个播放器在A设备上能拉流到B设备上要么起播慢要么直接抛ERROR_UNKNOWN。RTMP就更直接了。NuPlayer原生协议清单里根本没有RTMPMediaPlayer拿到rtmp://地址基本就是拒绝。ExoPlayer作为Google力推的播放器确实有RTSP扩展模块但它的思路是模块化拼装RTSP模块、MediaSource、Extractor、Renderer都要自己接对“我只想拉一路摄像头画面”这种需求来说学习成本偏高而且对H.265等编码的兼容性依然依赖设备或解码器兜底。1.2 选IjkPlayer不是情怀是协议层的兼容性IjkPlayer是B站开源出来的播放器核心简单说就是在Android上包了一层FFmpeg再提供一套类似MediaPlayer的API。最核心的价值在于所有协议解析、解封装、解码优先交给FFmpeg处理。FFmpeg在流媒体协议上的积累确实不是短期能追上的。RTSP的OPTIONS/DESCRIBE/SETUP/PLAY四步握手RTP-over-UDP和RTP-over-TCP两种传输模式RTMP的握手和chunked编码FFmpeg都有一套非常成熟的实现。这意味着IjkPlayer面对各种私有化RTSP实现时兼容性比系统播放器高出一大截。我选它不是因为性能多神而是为了一个“稳”字。同一台摄像头MediaPlayer可能只有50%概率不出错IjkPlayer基本能做到95%。项目里同时面对不同品牌IPC的时候用IjkPlayer能把“播放器不一致”这个变量压到最小。这也是它长期占据国内流媒体播放方案主流位置的原因。方案来源RTSP/RTMP支持上手成本稳定性MediaPlayerAndroid系统RTSP弱支持RTMP不支持低低ExoPlayerGoogleRTSP扩展RTMP需额外模块中中IjkPlayerB站/FFmpegRTSP/RTMP完整支持中低高2. 播放器核心准备先解决so库和依赖再谈代码2.1 自己编译全格式播放器 vs 使用现成产物网上很多教程一上来就让人拉IjkPlayer源码、配NDK、跑compile-ffmpeg.sh但这个Demo我没有走这条路。原因很现实IjkPlayer的官方编译脚本要拉FFmpeg源码和一堆依赖完整编译一次在普通机器上可能要一两个小时网络不好的时候光拉依赖就够折腾。如果只是想把Demo跑通别把时间浪费在编译环境上。更稳的做法是直接使用社区已经编译好的产物两条路都可行从GitHub上下载IjkPlayer release里的jar包和so文件放进app/libs和src/main/jniLibs目录手动管理依赖。优点是完全可控不依赖任何远程仓库缺点是文件要自己整理放错目录会引发so找不到的崩溃。使用基于IjkPlayer的二次封装库比如GSYVideoPlayer内部就是IjkPlayer维护活跃、有现成release产物依赖方式简单。还需要注意一个坑IjkPlayer官方0.8.8那套依赖原本挂在jcenter仓库而jcenter已经进入只读状态新工程直接配tv.danmaku.ijk.media:ijkplayer-java:0.8.8大概率拉不到包。所以不要一上来就抄老博客的Gradle依赖写法建议走手动引入或二次封装库路线。如果选择手动引入Gradle配置大概长这样android { defaultConfig { ndk { abiFilters arm64-v8a, armeabi-v7a } } } dependencies { implementation files(libs/ijkplayer-java-0.8.8.jar) // 把对应abi的so放进 src/main/jniLibs/arm64-v8a、src/main/jniLibs/armeabi-v7a 等目录 }2.2 ABI、ndkVersion与AGP8的现代注意事项很多新手把so放进工程后一运行就崩日志里最常见的一句话是Library ijkffmpeg.so not found。这个错误八成是ABI不匹配手机上装的是arm64-v8a的包工程里只放了armeabi-v7a的so或者反过来。Android安装APK时会优先选abiFilters指定的版本如果主工程同时包含第三方库而某个第三方库强制要求x86架构打包器可能把arm64挤掉也会间接导致so找不到。如果你现在用的Android Studio是Hedgehog2023.1.1或者更新的版本AGP基本都在8.x以上。AGP 8对NDK版本管理更严格报NDK相关构建错误时需要在Gradle里显式声明android { ndkVersion 25.2.9519653 }这个版本号不能乱写要跟你本机SDK Manager里实际安装的NDK对应。很多编译不过的莫名其妙错误最后都是因为这里没写明。真机调试前也建议先在Android Studio的设备列表确认能看到你的手机而不是只看提示上的“install and ready to use devices”否则后面全白搭。3. 最小可运行Demo播放器初始化、Surface绑定与生命周期3.1 选TextureView还是SurfaceView播放视频一般有两个选择SurfaceView和TextureView。SurfaceView会在WindowManager里单独开一个图层性能好但没法做旋转、变形、截图这些操作TextureView是普通View的子类可以随便布局、加动画、用getBitmap()截图缺点是多一次纹理转换性能略低但播一路摄像头画面完全够用。我的Demo选TextureView因为后续要加截图、水印、画面调整都方便。当然如果项目已经明确只做全屏播放用SurfaceView性能会好一点具体看场景。3.2 完整代码播放RTSP的最小实现布局文件就一个TextureView占满全屏TextureView android:idid/textureView android:layout_widthmatch_parent android:layout_heightmatch_parent/播放器核心代码public class MainActivity extends AppCompatActivity { private TextureView textureView; private IjkMediaPlayer ijkMediaPlayer; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textureView findViewById(R.id.textureView); textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { startPlay(rtsp://your_ip:554/live); } Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {} Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; } Override public void onSurfaceTextureUpdated(SurfaceTexture surface) {} }); } private void startPlay(String url) { releasePlayer(); ijkMediaPlayer new IjkMediaPlayer(); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, rtsp_transport, tcp); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, rtsp_flags, prefer_tcp); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, timeout, 10000000); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT p a hrefhttps://download.csdn.net/download/weixin_43820639/89066471 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门