You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在macOS上为WKWebView启用Picture-in-Picture功能?

在macOS上为WKWebView启用Picture-in-Picture功能的方法

macOS上WKWebView的画中画支持逻辑和iOS不同,allowsPictureInPictureMediaPlayback属性确实仅在iOS/iPadOS生效,但你可以通过以下两种方式实现需求:

方法一:利用WebKit原生支持(macOS 10.15+)

从macOS Catalina(10.15)开始,WKWebView已经原生支持画中画功能,无需额外配置属性,只需满足几个前提:

  • 网页中的视频元素需带有webkit-playsinline属性,且视频播放由用户手动触发(或页面已获得自动播放权限)
  • 在App的Info.plist中添加NSPictureInPictureUsageDescription键,填写画中画功能的使用说明(系统要求的权限描述)
  • 视频播放时,用户可右键点击视频选择「进入画中画」,若网页的视频控件支持,也会显示画中画按钮

方法二:自定义实现(兼容旧版本或灵活控制)

如果需要自动触发画中画、自定义触发逻辑,或兼容macOS 10.15之前的版本,可以通过拦截网页视频事件,结合AVPictureInPictureController实现:

步骤1:配置WKWebView并注入监听脚本

创建WKWebView时,注入JavaScript监听视频播放事件,并通过脚本消息通知原生代码:

let config = WKWebViewConfiguration()
let userContentController = WKUserContentController()
// 添加脚本消息处理器,用于接收网页的视频播放通知
userContentController.add(self, name: "pipTrigger")

// 注入JS脚本,监听页面中所有视频的播放事件
let videoMonitorScript = WKUserScript(source: """
document.addEventListener('play', (e) => {
    if (e.target.tagName === 'VIDEO') {
        window.webkit.messageHandlers.pipTrigger.postMessage({videoId: e.target.id});
    }
}, true);
""", injectionTime: .atDocumentEnd, forMainFrameOnly: true)
userContentController.addUserScript(videoMonitorScript)

config.userContentController = userContentController
let webView = WKWebView(frame: view.bounds, configuration: config)
view.addSubview(webView)

步骤2:接收脚本消息并启动画中画

实现WKScriptMessageHandler协议,获取网页中的视频元素,初始化AVPictureInPictureController并启动画中画:

extension YourViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard let payload = message.body as? [String: String],
              let videoId = payload["videoId"] else { return }
        
        // 执行JS获取网页中的视频元素
        webView.evaluateJavaScript("document.getElementById('\(videoId)')") { [weak self] result, error in
            guard let self = self,
                  let videoElement = result as? WKHTMLElement,
                  let playerLayer = videoElement.layer as? AVPlayerLayer,
                  AVPictureInPictureController.isPictureInPictureSupported() else {
                return
            }
            
            // 初始化并启动画中画
            let pipController = AVPictureInPictureController(playerLayer: playerLayer)
            pipController.delegate = self
            pipController.startPictureInPicture()
        }
    }
}

步骤3:监听画中画状态(可选)

实现AVPictureInPictureControllerDelegate协议,处理画中画的启动、停止等状态变化:

extension YourViewController: AVPictureInPictureControllerDelegate {
    func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        // 画中画启动后的自定义逻辑
    }
    
    func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
        // 画中画停止后的自定义逻辑
    }
}

注意事项

  • 自定义实现要求App部署目标至少为macOS 10.13(AVPictureInPictureController从该版本开始支持)
  • 原生支持方式下,部分自定义视频控件的网页可能不显示画中画按钮,但右键菜单的选项始终可用
  • 自定义实现需注意处理多视频场景,避免重复创建画中画控制器

内容的提问来源于stack exchange,提问作者fer0n

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:55:14