为啥iOS启动片刻后画中画立即停止?

Posted

技术标签:

【中文标题】为啥iOS启动片刻后画中画立即停止?【英文标题】:Why does Picture in Picture immediately stops after starting for a moment iOS?为什么iOS启动片刻后画中画立即停止? 【发布时间】:2021-12-17 14:17:51 【问题描述】:

当我从自定义视频播放器启动画中画时,pip 会启动片刻然后失败。 在调试控制台中发现如下错误日志:

PGPictureInPictureProxy (0x12710a280) _updateAutoPIPSettingsAndNotifyRemoteObjectWithReason:] - Acquiring remote object proxy for connection <NSXPCConnection: 0x2825a32a0> connection to service with pid 63 named com.apple.pegasus failed with error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service with pid 63 named com.apple.pegasus was invalidated from this process." UserInfo=NSDebugDescription=The connection to service with pid 63 named com.apple.pegasus was invalidated from this process.

这是我在代码中管理 pip 的方法:-

CustomVideoPlayer 设置 pip vc 的代码:

    private func setupPIPIfEligible() 
    if AVPictureInPictureController.isPictureInPictureSupported() 
        // Create a new controller, passing the reference to the AVPlayerLayer.
        pipVC = nil
        if let layer = playerLayer 
            pipVC = AVPictureInPictureController(playerLayer: layer)
            pipVC?.delegate = self
        
    

CustomVideoPlayer 在按下按钮时切换 pip 的代码:

private func togglePIP() 
    if pipVC?.isPictureInPictureActive ?? false 
        pipVC?.stopPictureInPicture()
     else 
        pipVC?.startPictureInPicture()
    

自定义视频播放器 VC 将 pip 委托方法转发给它的委托:

extension CustomVideoPlayerViewController: AVPictureInPictureControllerDelegate 
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) 
    videoPlayerDelegate?.playerViewControllerWillStartPictureInPicture(self)


func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) 
    videoPlayerDelegate?.playerViewControllerWillStopPictureInPicture(self)


func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) 
    videoPlayerDelegate?.playerViewController(self, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler: completionHandler)

CustomVideoPlayerViewController 的委托处理 pip 方法:

extension TabBarViewController: CustomVideoPlayerDelegate 

func playerViewController(_ playerViewController: UHVideoPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) 
    shouldReleaseVideoPlayer = false
    let currentviewController = navigationController?.visibleViewController
    if currentviewController != playerViewController, currentviewController != nil 
        if !(currentviewController?.isKind(of: CustomVideoPlayerViewController.self) ?? false) 
            currentviewController?.present(playerViewController, animated: false) 

            
        
    


func playerViewControllerWillStartPictureInPicture(_ playerViewController: UHVideoPlayerViewController) 
    playerViewController.dismiss(animated: true, completion: nil)


func playerViewControllerWillStopPictureInPicture(_ playerViewController: UHVideoPlayerViewController) 
    if shouldReleaseVideoPlayer 
        currentVideoPlayer = nil
    
    shouldReleaseVideoPlayer = true

var currentVideoPlayer: CustomVideoPlayerViewController? 是我为视频播放器保留的重要参考。

我已经检查过:没有内存泄漏/视频播放器参考的提前发布。

我在这里做错了什么?

【问题讨论】:

你打开Signing & Capabilities > Background Modes > Audio, AirPlay, and Picture in Picture了吗? 是的,已经开启了。 【参考方案1】:

不要忘记,如果您不使用AVPlayerViewController,而是使用一些具有自己图层的自定义视图AVPLayerLayer,则在以画中画模式播放视频时,您需要在屏幕上显示AVPLayerLayer。如果您从屏幕上删除自定义视图,画中画视频也将结束。您还需要设置AVAudiosession 来播放长格式音频,将此代码添加到您的AppDelegate 类中:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
    setupAudioSession()
    return true


private func setupAudioSession() 
    let audioSession = AVAudioSession.sharedInstance()
    do 
        try audioSession.setCategory(.playback)
        try audioSession.setActive(true, options: [])
     catch 
        print("Setting category to AVAudioSessionCategoryPlayback failed.")
    

编辑:

如果用户转到后台,画中画点仍然存在,视频将继续在其他应用程序顶部的画中画窗口中播放。好吧,如果您想通过所有应用程序屏幕呈现画中画视频,您基本上只有两个选项(据我所知)。要么使用 AVPlayerViewController ,无论您当前在哪个屏幕上都将继续播放视频,或者在您的应用程序的关键窗口中显示视频,如果用户导航到其他屏幕,您可以缩小 AVPlayerlayer 的大小并在那里显示视频(就像 YouTube 那样),或触发画中画,但在应用程序底部的某处保留一小部分 AVPlayerlayer。还有第三种选择(但我没有尝试过),它将您的自定义视频视图控制器合并为其他一些呈现的视图控制器的子级。但是我有一种感觉,以这种方式使用它可能太痛苦了。希望这些答案对您有所帮助。祝你好运!。

【讨论】:

当我即将开始播放视频时,我的 AudioSesison 设置为 .playback,模式为 .movi​​ePlayback 我使用带有 AVPlayerLayer 的自定义视图控制器。当我获得 pipWillStart 委托方法的回调时,此自定义 VC 将被解除。我评论了解雇 VC 部分,当时 PIP 正在工作。但是,如果用户在 pip 处于活动状态时无法在应用程序中执行任何其他操作,那么 pip 的意义何在 @SPS 我试图给你写回复评论,但它太长了,所以我在原来的答案中将它设为“编辑”。 您是否设法解决了这个问题?此外,如果您发现我的回答有帮助,您可以点赞或接受回答。

以上是关于为啥iOS启动片刻后画中画立即停止?的主要内容,如果未能解决你的问题,请参考以下文章

启动停止mysql时报:服务正在启动或停止中,请稍候片刻后再试一次。

Xcode 启动屏幕上的图像视图出现片刻然后消失

在 GWT 中渲染视图时浏览器会冻结片刻

Vue Router 推送有效,但片刻后返回到原始组件

jQuery.mobile 弹出窗口在显示后立即隐藏

AIR 移动应用程序上 TextArea 中的文本显示片刻后消失