FFmpeg开发笔记(二十七)解决APP无法访问ZLMediaKit的直播链接问题

简介: 本文讲述了在使用ZLMediaKit进行视频直播时,遇到移动端通过ExoPlayer和微信小程序播放HLS直播地址失败的问题。错误源于ZLMediaKit对HTTP地址的Cookie校验导致401无权限响应。通过修改ZLMediaKit源码,注释掉相关鉴权代码并重新编译安装,解决了此问题,使得ExoPlayer和小程序能成功播放HLS视频。详细解决方案及FFmpeg集成可参考《FFmpeg开发实战:从零基础到短视频上线》一书。

​上一篇文章介绍了如何通过ZLMediaKit实现视频推拉流,并使用VLC播放器验证视频直播地址。即使不用VLC播放器,直接在Qt工程的C++代码中调用FFmpeg的API,也能访问ZLMediaKit的直播地址,并正常渲染视频画面。关于如何在Qt工程中引入FFmpeg,可参考《FFmpeg开发实战:从零基础到短视频上线》一书的“第11章 FFmpeg的桌面开发”。

《FFmpeg开发实战:从零基础到短视频上线》一书的“第12章 FFmpeg的移动开发”介绍了如何在手机APP上集成FFmpeg。根据该书的操作步骤,在APP工程的JNI代码中调用FFmpeg的API,也能正常播放ZLMediaKit的直播画面。
但是如果手机APP不走FFmpeg,通过其他途径访问直播地址之时,却发现无法播放ZLMediaKit的HLS直播地址 http://124.xxx.xxx.xxx:8080/live/test/hls.m3u8 。无论采用谷歌官方的ExoPlayer,还是采用微信小程序的video标签,都播放不了ZLMediaKit的HLS视频。查看APP的报错日志,发现ExoPlayer扔出以下的错误信息:

E/ExoPlayerImplInternal: Playback error
      com.google.android.exoplayer2.ExoPlaybackException: Source error
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:641)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:613)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loopOnce(Looper.java:206)
        at android.os.Looper.loop(Looper.java:296)
        at android.os.HandlerThread.run(HandlerThread.java:67)
     Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 401
        at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:396)
        at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:258)
        at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
        at com.google.android.exoplayer2.source.hls.HlsMediaChunk.prepareExtraction(HlsMediaChunk.java:495)
        at com.google.android.exoplayer2.source.hls.HlsMediaChunk.feedDataToExtractor(HlsMediaChunk.java:468)
        at com.google.android.exoplayer2.source.hls.HlsMediaChunk.loadMedia(HlsMediaChunk.java:437)
        at com.google.android.exoplayer2.source.hls.HlsMediaChunk.load(HlsMediaChunk.java:394)
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:930)

原来是流媒体服务端丢出了401错误,意思是没有权限拒绝访问。这个问题着实难搞,寻寻觅觅、反反复复,总也找不到为啥会没有权限,分明使用VLC播放器是可以正常播放的呀。
于是检查ZLMediaKit的源代码,发现ZLMediaKit内部对于HTTP地址增加了Cookie校验,原来这套校验规则适配了FFmpeg,却尚未适配ExoPlayer,也未适配小程序。问题代码位于ZLMediaKit源代码的src/Http/HttpFileManager.cpp里的accessFile函数,代码片段如下:

auto strongSession = weakSession.lock();
if (!strongSession) {
    // http客户端已经断开,不需要回复
    return;
}
if (!err_msg.empty()) {
    //文件鉴权失败
    StrCaseMap headerOut;
    if (cookie) {
        headerOut["Set-Cookie"] = cookie->getCookie(cookie->getAttach<HttpCookieAttachment>()._path);
    }
    cb(401, "text/html", headerOut, std::make_shared<HttpStringBody>(err_msg));
    return;
}

原来accessFile函数内部对于HTTP链接的Cookie校验失败时会固定返回401错误。那么修改HttpFileManager.cpp里的accessFile函数,把这里的401鉴权代码注释掉,并将修改后的代码文件上传到Linux服务器。
然后回到build目录运行make和make install命令重新编译安装ZLMediaKit,也就是依次执行下面命令。

kill -s 9 `ps -aux | grep MediaServer | awk '{print $2}'`
cd /usr/local/src/ZLMediaKit/build
make
make install

编译安装完毕,执行下面命令,重新启动MediaServer服务。

cd /usr/local/src/ZLMediaKit/release/linux/Debug
./MediaServer -d &

执行以下命令,将本地视频推流给ZLMediaKit。

ffmpeg -re -stream_loop -1 -i "/usr/local/src/test/2018s.mp4" -vcodec h264 -f rtsp rtsp://127.0.0.1/live/test

然后在APP代码中使用ExoPlayer播放HLS地址 http://124.xxx.xxx.xxx:8080/live/test/hls.m3u8 ,发现可以正常播放HLS视频了。接着使用真机调试微信小程序,发现通过video标签也能正常播放HLS视频了。更多详细的FFmpeg开发知识参见《FFmpeg开发实战:从零基础到短视频上线》一书。

目录
相关文章
|
1天前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
2天前
|
编解码 Windows
FFmpeg开发笔记(二十九)Windows环境给FFmpeg集成libxvid
XviD是开源MPEG-4视频编码器,与DivX相似但后者非开源。早期MP4常使用XviD或DivX编码,现已被H.264取代。在Windows上集成FFmpeg的XviD编解码库libxvid,需访问<https://labs.xvid.com/source/>下载源码,解压后在MSYS环境中配置、编译和安装。之后重新配置FFmpeg,启用libxvid并编译安装。详细步骤包括configure命令、make和make install。成功后,通过`ffmpeg -version`检查是否启用libxvid。更多音视频开发技术可参考《FFmpeg开发实战:从零基础到短视频上线》。
23 0
FFmpeg开发笔记(二十九)Windows环境给FFmpeg集成libxvid
|
3天前
|
编解码 Linux
FFmpeg开发笔记(二十八)Linux环境给FFmpeg集成libxvid
XviD是开源的MPEG-4视频编解码器,曾与DivX一起用于早期MP4视频编码,但现在已被H.264取代。要集成XviD到Linux上的FFmpeg,首先下载源码,解压后配置并编译安装libxvid。接着,在FFmpeg源码目录中,重新配置FFmpeg以启用libxvid,然后编译并安装。成功后,通过`ffmpeg -version`检查是否启用libxvid。详细步骤包括下载、解压libxvid,使用`configure`和`make`命令安装,以及更新FFmpeg配置并安装。
13 2
FFmpeg开发笔记(二十八)Linux环境给FFmpeg集成libxvid
|
4天前
|
前端开发 JavaScript Android开发
手机APP开发|基于安卓APP实现掌上党支部——党员app
手机APP开发|基于安卓APP实现掌上党支部——党员app
|
6天前
|
存储 Android开发 Kotlin
Kotlin开发安卓app,在使用 MediaPlayer 播放 res/raw 中的音乐时遇到突然中断的问题,而 onErrorListener 没有接收到任何报错
在使用 Android MediaPlayer 播放 res/raw 中的音乐时遇到中断问题,可能的原因包括资源问题、媒体文件编码格式、生命周期管理和设备资源配置。要排查问题,检查音频文件是否正确包含,格式编码是否支持,MediaPlayer 是否正确管理及释放,以及设备是否有足够存储和配置。通过设置 onErrorListener 日志和确保在 onDestroy 中释放资源来调试。如果文件过大,考虑使用 AssetManager。遵循这些步骤可帮助诊断并解决播放中断的问题。
|
6天前
|
Android开发 Kotlin
kotlin开发安卓应用 如何修改app安装后的名称
在 Android 应用中,要修改安装后的显示名称,需更新 AndroidManifest.xml 文件中 application 标签的 android:label 属性。可直接在该属性内设置新名称,或在 res/values/strings.xml 文件中修改 app_name 并在 manifest 中引用。推荐使用 strings.xml 方式,以便支持多语言和集中管理。
|
6天前
|
缓存 Android开发 Kotlin
【安卓app开发】kotlin Jetpack Compose框架 | 先用OKhttp下载远程音频文件再使用ExoPlayer播放
使用 Kotlin 的 Jetpack Compose 开发安卓应用时,可以结合 OkHttp 下载远程音频文件和 ExoPlayer 进行播放。在 `build.gradle` 添加相关依赖后,示例代码展示了如何下载音频并用 ExoPlayer 播放。代码包括添加依赖、下载文件、播放文件及简单的 Compose UI。注意,示例未包含完整错误处理和资源释放,实际应用需补充这些内容。
|
7天前
|
存储 Android开发 Kotlin
开发安卓app OKhttp下载后使用MediaPlayer播放
在Android Jetpack Compose应用程序中,要使用OkHttp下载远程音频文件并在本地播放,你需要完成以下几个步骤: 1. **添加依赖**:确保`build.gradle`文件包含OkHttp和Jetpack Compose的相关依赖。 2. **下载逻辑**:创建一个`suspend`函数,使用OkHttp发起网络请求下载音频文件到本地。 3. **播放逻辑**:利用`MediaPlayer`管理音频播放状态。 4. **Compose UI**:构建用户界面,包含下载和播放音频的按钮。
|
7天前
|
存储 Android开发
安卓app,MediaPlayer播放本地音频 | 按钮控制播放和停止
在Jetpack Compose中,不直接操作原生Android组件如`Button`和`MediaPlayer`,而是使用Compose UI构建器定义界面并结合ViewModel管理音频播放逻辑。以下示例展示如何播放本地音频并用按钮控制播放/停止:创建一个`AudioPlayerViewModel`管理`MediaPlayer`实例和播放状态,然后在Compose UI中使用`Button`根据`isPlaying`状态控制播放。记得在`MainActivity`设置Compose UI,并处理相关依赖和权限。
|
1月前
|
移动开发 小程序
如何让uni-app开发的H5页面顶部原生标题和小程序的顶部标题不一致?
如何让uni-app开发的H5页面顶部原生标题和小程序的顶部标题不一致?

热门文章

最新文章