我差点就放弃了,蘑菇视频 iOS 的小窗播放问题我终于定位到原因了

先说结论:问题最后并不是网络、播放器库的 bug,也不是系统版本的兼容性问题,而是播放器在项目里“被放置”的方式和 Web 与原生播放器配置之间的一处不匹配。把视频从嵌入式 Web 播放强制迁移到原生 AVPlayer/AVPlayerLayer(或者保证 WKWebView 的配置允许 PiP)并正确打开相关开关后,小窗播放恢复正常。下面是我定位问题的全过程和可直接复用的修复步骤。
一、症状描述(我遇到的具体表现)
- iPhone 真机上,开始播放后点击小窗(Picture-in-Picture)按钮,界面要么没有响应,要么进入小窗后画面变黑但有声音,或者小窗一段时间后自动消失。
- 模拟器上有时看似正常,但真机测试才会复现问题(PiP 有些行为仅在真机上体现)。
- 控制台没有明显崩溃日志,仅有少量 AVFoundation 的警告。
二、我做过的初步排查(按顺序)
- 用真机复现,确保不是模拟器差异导致的假象。
- 在 Xcode 控制台观察 AVFoundation、AVPlayer 的日志,留意 AVPictureInPictureController 相关输出。
- 在网络层抓包,排除视频流本身(HLS/MP4)被拦截或格式问题。
- 切换播放器(第三方播放器 → 原生 AVPlayer)对比行为。
- 检查 Info.plist、后台模式(Background Modes)设置,看是否因后台音频等未打开造成 PiP 失效。
- 查看项目中是否通过 WKWebView 嵌入网页播放视频,且该网页有自定义 JS/样式影响 video 标签属性。
三、真正的“罪魁祸首”是什么
- 根因:播放器是通过嵌入网页(WKWebView)来播放视频,而 WKWebView 的默认配置和页面上 video 标签的属性(例如没有 playsinline、或者页面用了会干扰 video 的 CSS/JS)导致系统无法正确把 video 关联到可被 AVPictureInPictureController 控制的层,进而导致小窗不可用或异常。
- 进一步分析:iOS 的 PiP 与 AVPlayer/AVPlayerLayer 配合最可靠;当使用 WKWebView 播放时,需要保证 web 配置和 video 标签允许内联播放与 PiP,否则浏览器层面的播放策略、用户手势要求或 JS 动态创建方式可能阻止 PiP 的正常创建。
四、修复方案(直接可用) 如果你使用原生播放器(推荐)
- 使用 AVPlayer + AVPlayerLayer 或 AVPlayerViewController。
- 确保启用 PiP:
- 对于 AVPlayerViewController: playerViewController.allowsPictureInPicturePlayback = true
- 对于 AVPlayerLayer,可配合 AVPictureInPictureController: if AVPictureInPictureController.isPictureInPictureSupported() { … }
- 在需要后台播放时,设置 AVAudioSession: try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback) try AVAudioSession.sharedInstance().setActive(true)
- 在真机测试 PiP(模拟器行为有差异)。
如果你必须使用 WKWebView(页面内播放)
- 在创建 WKWebView 的配置时打开: webConfiguration.allowsInlineMediaPlayback = true // iOS 10+,可视具体 API 调整 mediaTypesRequiringUserActionForPlayback
- 确保页面上的
- 开启允许 PiP 的设置(有些情况下需要): webConfiguration.allowsPictureInPictureMediaPlayback = true
- 避免通过过度复杂的 JS 动态创建或替换 video 元素,若必须创建,确保附带 playsinline 并在用户手势触发下播放。
- 如果 Web 端不可控,考虑将关键播放改为原生层来保证 PiP 体验一致。
五、额外优化与注意点
- PiP 在不同 iOS 版本和设备上行为略有差异,始终以 iPhone/iPad 真机和系统版本为准测试。
- 如果用户同时需要后台音频,打开 Xcode 的 Background Modes -> Audio, AirPlay, and Picture in Picture(按需)。
- HLS(.m3u8)通常比单文件 MP4 对移动端更友好,稳定性更高,但与 PiP 无直接冲突。
- 在使用 WKWebView 时,跨域/跨源策略或 CORS 有时会影响媒体资源加载,留意控制台网络错误。
- 对用户做好降级处理:当 PiP 不可用时给出合理的交互提示或自动进入全屏播放。
六、我的小结(为什么这条线索当初被我忽略) 我起初以为是网络或播放器 bug,所以把注意力放在流媒体、解码和第三方 SDK。真正浪费时间的是没意识到“播放层级”问题:同样是播放视频,把它放在 WebView 里和放在原生 AVPlayer 层,系统对 PiP 的连通性和控制能力完全不同。找出这一点后,问题迎刃而解,现在线上用户反馈的小窗体验恢复正常。