如何使用swift持续播放视频背景?

时间:2016-04-18 01:34:40

标签: ios swift video uiviewcontroller avfoundation

我有一个视频播放作为我的登陆视图控制器的背景,每当我退出应用程序然后重新进入,视频冻结,直到我要么去另一个视图然后回来,或者只是重新启动应用程序将一起它正常发挥。即使应用程序退出并重新进入,如何让它继续播放?

这是逻辑:

import UIKit
import AVFoundation
class FirstViewController: UIViewController {

    var player: AVPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
        let path = NSBundle.mainBundle().pathForResource("sunny", ofType: "mp4")
        player = AVPlayer(URL: NSURL(fileURLWithPath: path!))
        player!.actionAtItemEnd = AVPlayerActionAtItemEnd.None;
        let playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = self.view.frame
        playerLayer.videoGravity = AVLayerVideoGravityResize
        self.view.layer.insertSublayer(playerLayer, atIndex: 0)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.playerItemDidReachEnd), name: AVPlayerItemDidPlayToEndTimeNotification, object: player!.currentItem)
        player!.seekToTime(kCMTimeZero)
        player!.play()

    }

    func playerItemDidReachEnd() {
        player!.seekToTime(kCMTimeZero)
    }

}

3 个答案:

答案 0 :(得分:1)

首先,您需要在VideoCutter.swift文件中创建一个名为VideoCutter的类:

import UIKit
import AVFoundation

extension String {
  var convert: NSString { return (self as NSString) }
}

public class VideoCutter: NSObject {
  public func cropVideoWithUrl(videoUrl url: NSURL, startTime: CGFloat, duration: CGFloat, completion: ((videoPath: NSURL?, error: NSError?) -> Void)?) {
    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
    dispatch_async(dispatch_get_global_queue(priority, 0)) {
      let asset = AVURLAsset(URL: url, options: nil)
      let exportSession = AVAssetExportSession(asset: asset, presetName: "AVAssetExportPresetHighestQuality")
      let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
      var outputURL = paths.objectAtIndex(0) as! String
      let manager = NSFileManager.defaultManager()
      do {
        try manager.createDirectoryAtPath(outputURL, withIntermediateDirectories: true, attributes: nil)
      } catch _ {
      }
      outputURL = outputURL.convert.stringByAppendingPathComponent("sunny.mp4")
      do {
        try manager.removeItemAtPath(outputURL)
      } catch _ {
      }
      if let exportSession = exportSession as AVAssetExportSession? {
        exportSession.outputURL = NSURL(fileURLWithPath: outputURL)
        exportSession.shouldOptimizeForNetworkUse = true
        exportSession.outputFileType = AVFileTypeMPEG4
        let start = CMTimeMakeWithSeconds(Float64(startTime), 600)
        let duration = CMTimeMakeWithSeconds(Float64(duration), 600)
        let range = CMTimeRangeMake(start, duration)
        exportSession.timeRange = range
        exportSession.exportAsynchronouslyWithCompletionHandler { () -> Void in
          switch exportSession.status {
          case AVAssetExportSessionStatus.Completed:
            completion?(videoPath: exportSession.outputURL, error: nil)
          case AVAssetExportSessionStatus.Failed:
            print("Failed: \(exportSession.error)")
          case AVAssetExportSessionStatus.Cancelled:
            print("Failed: \(exportSession.error)")
          default:
            print("default case")
          }
        }
      }
      dispatch_async(dispatch_get_main_queue()) {
      }
    }
  }
}

然后你需要在VideoSplashViewController.swift文件中创建一个类VideoSplashViewController

import UIKit
import MediaPlayer
import AVKit

public enum ScalingMode {
  case Resize
  case ResizeAspect
  case ResizeAspectFill
}

public class VideoSplashViewController: UIViewController {

  private let moviePlayer = AVPlayerViewController()
  private var moviePlayerSoundLevel: Float = 1.0
  public var contentURL: NSURL = NSURL() {
    didSet {
      setMoviePlayer(contentURL)
    }
  }

  public var videoFrame: CGRect = CGRect()
  public var startTime: CGFloat = 0.0
  public var duration: CGFloat = 0.0
  public var backgroundColor: UIColor = UIColor.blackColor() {
    didSet {
      view.backgroundColor = backgroundColor
    }
  }
  public var sound: Bool = true {
    didSet {
      if sound {
        moviePlayerSoundLevel = 1.0
      }else{
        moviePlayerSoundLevel = 0.0
      }
    }
  }
  public var alpha: CGFloat = CGFloat() {
    didSet {
      moviePlayer.view.alpha = alpha
    }
  }
  public var alwaysRepeat: Bool = true {
    didSet {
      if alwaysRepeat {
        NSNotificationCenter.defaultCenter().addObserver(self,
          selector: "playerItemDidReachEnd",
          name: AVPlayerItemDidPlayToEndTimeNotification,
          object: moviePlayer.player?.currentItem)
      }
    }
  }
  public var fillMode: ScalingMode = .ResizeAspectFill {
    didSet {
      switch fillMode {
      case .Resize:
        moviePlayer.videoGravity = AVLayerVideoGravityResize
      case .ResizeAspect:
        moviePlayer.videoGravity = AVLayerVideoGravityResizeAspect
      case .ResizeAspectFill:
        moviePlayer.videoGravity = AVLayerVideoGravityResizeAspectFill
      }
    }
  }

  override public func viewDidAppear(animated: Bool) {
    moviePlayer.view.frame = videoFrame
    moviePlayer.showsPlaybackControls = false
    view.addSubview(moviePlayer.view)
    view.sendSubviewToBack(moviePlayer.view)
  }

  override public func viewWillDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
  }

  private func setMoviePlayer(url: NSURL){
    let videoCutter = VideoCutter()
    videoCutter.cropVideoWithUrl(videoUrl: url, startTime: startTime, duration: duration) { (videoPath, error) -> Void in
      if let path = videoPath as NSURL? {
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
        dispatch_async(dispatch_get_global_queue(priority, 0)) {
          dispatch_async(dispatch_get_main_queue()) {
            self.moviePlayer.player = AVPlayer(URL: path)
            self.moviePlayer.player?.play()
            self.moviePlayer.player?.volume = self.moviePlayerSoundLevel
          }
        }
      }
    }
  }

  override public func viewDidLoad() {
    super.viewDidLoad()
  }

  override public func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  func playerItemDidReachEnd() {
    moviePlayer.player?.seekToTime(kCMTimeZero)
    moviePlayer.player?.play()
  }
}

最后,在你的FirstViewController中:

import UIKit

class FirstViewController: VideoSplashViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    setupVideoBackground()
}

func setupVideoBackground() {

    let url = NSURL.fileURLWithPath(NSBundle.mainBundle().pathForResource("sunny", ofType: "mp4")!)

    videoFrame = view.frame
    fillMode = .ResizeAspectFill
    alwaysRepeat = true
    sound = true
    startTime = 2.0
    alpha = 0.8

    contentURL = url
    view.userInteractionEnabled = false

    }
}

答案 1 :(得分:0)

在ViewController类中使用此解决方法:

override func viewDidLoad() {
    super.viewDidLoad()
    ...
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(willEnterForeground),
                                           name: NSNotification.Name.UIApplicationWillEnterForeground,
                                           object: nil)
}

func willEnterForeground() {
    player!.play()
}

希望对任何人都有帮助。祝你好运!

答案 2 :(得分:0)

Swift 4 在AppDelegate.swift中

    func applicationDidEnterBackground(_ application: UIApplication) {
    if let item = yourAVPlayer.currentItem {
        if item.tracks.first!.assetTrack.hasMediaCharacteristic(AVMediaCharacteristic.visual) {
            item.tracks.first!.isEnabled = false
        }
    }
}

func applicationWillEnterForeground(_ application: UIApplication) {
    if let item = yourAVPlayer.currentItem {
        if item.tracks.first!.assetTrack.hasMediaCharacteristic(AVMediaCharacteristic.visual) {
            item.tracks.first!.isEnabled = true
        }
    }
}

当然不要忘记打开TARGETS - >能力 - >背景模式 - >音频,AirPlay和画中画,并在AppDelegate中输入所需的AVAudioSession。