美文网首页App自动化测试
关于 AVPlayer 播放黑屏问题的解决

关于 AVPlayer 播放黑屏问题的解决

作者: 蛮荒星域 | 来源:发表于2020-08-27 13:37 被阅读0次

原因

If the AVPlayer's current item is displaying video on the device's display, playback of the AVPlayer is automatically paused when the app is sent to the background.

参考:Playing media while in the background using AV Foundation on iOS

一般情况下不会有有黑屏,但是因为这个原因导致可能会发生。我们的App里有openGL的使用,导致性能消耗过大,当退回到后台后系统会释放AVPlayer的资源,所以再次返回的时候会出现短暂的黑屏。

我们的App有一个更加严重的问题,当一个视频播放完之后会停留在当前页面,退回后台再返回会明显黑屏。(如果是视频播放中的话系统会重新加载资源,黑屏时间是短暂发生,但是视频播放完会长期黑屏)

一般解决方式

目前暂时没有好的办法,苹果有两个推荐方案,但是不太试用于我们项目。如下:

  • Disable the video tracks in the player item (file-based content only).
  • Remove the AVPlayerLayer from its associated AVPlayer (set the AVPlayerLayer player property to nil).

Disabling the video tracks in the player item

import AVFoundation
 
let playerItem = <#Your player item#>
 
let tracks = playerItem.tracks
for playerItemTrack in tracks {
 
    // Find the video tracks.
    if playerItemTrack.assetTrack.hasMediaCharacteristic(AVMediaCharacteristicVisual) {
 
        // Disable the track.
        playerItemTrack.isEnabled = false
    }
}

Remove/Restore the AVPlayerLayer and its associated AVPlayer

import UIKit
import AVFoundation
 
...
 
// A `UIView` subclass that is backed by an `AVPlayerLayer` layer.
class PlayerView: UIView {
    var player: AVPlayer? {
        get {
            return playerLayer.player
        }
 
        set {
            playerLayer.player = newValue
        }
    }
 
    var playerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }
 
    override class var layerClass: AnyClass {
        return AVPlayerLayer.self
    }
}
 
...
 
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
 
    var window: UIWindow?
 
    @IBOutlet weak var playerView: PlayerView!
 
    /*
     Remove the AVPlayerLayer from its associated AVPlayer
     once the app is in the background.
     */
    func applicationDidEnterBackground(_ application: UIApplication) {
 
        // Remove the player.
        playerView.player = nil
    }
 
    // Restore the AVPlayer when the app is active again.
    func applicationDidBecomeActive(_ application: UIApplication) {
 
        // Restore the player.
        playerView.player = <#Your player#>
    }
}

方法一比较通用。方法二只能作用于本地视频。

最终解决方式

我们采用了截屏的方式,截取最后一帧放到PlayerView上,遮挡黑屏

附上截屏方法:

extension AVPlayer {
  func getPlayerScreenShot(screenSize: CGSize, callback: @escaping (UIImage?) ->Void) {
    //1. 获取当前时间
    let currentTime = self.currentTime().value / 1000
    if currentTime < 1 {
      callback(nil)
      return
    }
    
    guard let urlAsset = currentItem?.asset else {
      callback(nil)
      return
    }
    
    //2. 截图配置
    let generator = AVAssetImageGenerator(asset: urlAsset)
    generator.appliesPreferredTrackTransform = true
    generator.maximumSize = screenSize
    generator.requestedTimeToleranceBefore = .zero
    generator.requestedTimeToleranceAfter = .zero
    
    //3. 分段截图时间数组
    var times: [NSValue] = []
    let timeM = CMTimeMake(value: currentTime, timescale: self.currentTime().timescale)
    let timeV = NSValue(time: timeM)
    times.append(timeV)
    
    //4. 开始截图
    generator.generateCGImagesAsynchronously(forTimes: times) {
      (requestedTime, cgimage, actualTime, result, error) in
      
      switch result {
      case .cancelled, .failed: callback(nil)
      case .succeeded:
        guard let image = cgimage else {
          callback(nil)
          return
        }
        let displayImage = UIImage(cgImage: image)
        callback(displayImage)
      }
    }
  }
}

相关文章

网友评论

    本文标题:关于 AVPlayer 播放黑屏问题的解决

    本文链接:https://www.haomeiwen.com/subject/ceycsktx.html