video作为iOS背景最有效的方法

也许你已经注意到iOS应用程序的最新趋势之一:使用video作为背景 – 主要是在login或“首次启动”屏幕。 昨天我试图用一个非常简单的testing项目(只有一个视图控制器)模仿这个,除了性能 ,我对结果感到满意。 在iOS模拟器(在模拟iPhone 6上)尝试时, CPU使用率70-110%之间波动。 这对于简单的login屏幕来说似乎是非常不合理的。

这就是它在行动中的样子: http : //oi57.tinypic.com/nqqntv.jpg

那么问题是: 有没有一种更有效的CPU方法来实现这一点? 像Vine,Spotify和Instagram这样的应用程序如何做到这一点?

在你回答之前, 我使用的方法是使用MPMoviePlayerController播放的全高清video:

- (void)viewDidLoad { [super viewDidLoad]; // find movie file NSString *moviePath = [[NSBundle mainBundle] pathForResource:@"arenaVideo" ofType:@"mp4"]; NSURL *movieURL = [NSURL fileURLWithPath:moviePath]; // load movie self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:movieURL]; self.moviePlayer.controlStyle = MPMovieControlStyleNone; self.moviePlayer.view.frame = self.view.frame; self.moviePlayer.scalingMode = MPMovieScalingModeAspectFill; [self.view addSubview:self.moviePlayer.view]; [self.view sendSubviewToBack:self.moviePlayer.view]; [self.moviePlayer play]; // loop movie [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(replayMovie:) name: MPMoviePlayerPlaybackDidFinishNotification object: self.moviePlayer]; } #pragma mark - Helper methods -(void)replayMovie:(NSNotification *)notification { [self.moviePlayer play]; } 

当然,video的边缘可能已经被修剪,使得分辨率会更多地沿着700×1080而不是1920×1080的线条,但是这会在性能上产生巨大的差异吗? 还是应该使用特定的格式和设置压缩video以获得最佳性能? 也许有一个完全不同的方法呢?

其实我尝试使用本文所述的GIF: https : //medium.com/swift-programming/ios-make-an-awesome-video-background-view-objective-c-swift-318e1d71d0a2

这个问题是:

  • 从video中创buildGIF需要花费大量的时间和精力
  • 我看到CPU使用情况没有明显下降
  • 这种方法支持多种屏幕尺寸是一种痛苦(至less在我尝试时 – Autolayout和Size Classes被启用 – 我无法让GIF在各种设备上正确缩放)
  • video质量很差

最好的方法是使用AVFoundation然后控制video图层本身

在头文件中声明@property (nonatomic, strong) AVPlayerLayer *playerLayer;

 - (void)viewDidLoad { [super viewDidLoad]; [self.view.layer addSublayer:self.playerLayer]; // loop movie [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(replayMovie:) name: AVPlayerItemDidPlayToEndTimeNotification object:nil]; } -(AVPlayerLayer*)playerLayer{ if(!_playerLayer){ // find movie file NSString *moviePath = [[NSBundle mainBundle] pathForResource:@"arenaVideo" ofType:@"mp4"]; NSURL *movieURL = [NSURL fileURLWithPath:moviePath]; _playerLayer = [AVPlayerLayer playerLayerWithPlayer:[[AVPlayer alloc]initWithURL:movieURL]]; _playerLayer.frame = CGRectMake(0,0,self.view.frame.size.width, self.view.frame.size.height); [_playerLayer.player play]; } return _playerLayer } -(void)replayMovie:(NSNotification *)notification { [self.playerLayer.player play]; } 

Swift 2.0

 lazy var playerLayer:AVPlayerLayer = { let player = AVPlayer(URL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("LaunchMovie", ofType: "mov")!)) player.muted = true player.allowsExternalPlayback = false player.appliesMediaSelectionCriteriaAutomatically = false var error:NSError? // This is needed so it would not cut off users audio (if listening to music etc. do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) } catch var error1 as NSError { error = error1 } catch { fatalError() } if error != nil { print(error) } var playerLayer = AVPlayerLayer(player: player) playerLayer.frame = self.view.frame playerLayer.videoGravity = "AVLayerVideoGravityResizeAspectFill" playerLayer.backgroundColor = UIColor.blackColor().CGColor player.play() NSNotificationCenter.defaultCenter().addObserver(self, selector:"playerDidReachEnd", name:AVPlayerItemDidPlayToEndTimeNotification, object:nil) return playerLayer }() override func viewDidLoad() { super.viewDidLoad() self.view.layer.addSublayer(self.playerLayer) } override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self) } // If orientation changes override func willAnimateRotationToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) { playerLayer.frame = self.view.frame } func playerDidReachEnd(){ self.playerLayer.player!.seekToTime(kCMTimeZero) self.playerLayer.player!.play() } 

testingiOS7 – iOS9

我意识到,这是一个旧的职位,但是因为我有一些经验,在我的iOS应用程序的CPU使用率下降,我会回应。

首先要看的是使用AVFoundationFramework

实施AVPlayer应该有助于降低CPU的性能

但最好的解决scheme是使用Brad Larson的GPUImage库,它利用了OpenGl,将大大减lessCPU的使用。 下载图书馆,并有一些如何使用的例子。 我build议使用GPUImageMovieWriter

我用一个AVAssetReader,GLKView和渲染通过CIImagepipe道。 在模拟器上播放没有过滤的video时,它会消耗大约80%的CPU。 在实际设备上,实时过滤(CIFilter)花费1x%。 它可以设置为循环和控制FPS。 我已经在Github上做了,并欢迎任何人有一个副本。 这将是一个不错的替代select,因为有些人不希望仅仅为了video背景视图而丢弃整个GPUImage。 拖放视图,它工作。 https://github.com/matthewlui/FSVideoView

我在iOS8 / 9 上find了GitHub上的这个代码

 - (void)viewDidLoad { [super viewDidLoad]; // Load the video from the app bundle. NSURL *videoURL = [[NSBundle mainBundle] URLForResource:@"video" withExtension:@"mov"]; // Create and configure the movie player. self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL]; self.moviePlayer.controlStyle = MPMovieControlStyleNone; self.moviePlayer.scalingMode = MPMovieScalingModeAspectFill; self.moviePlayer.view.frame = self.view.frame; [self.view insertSubview:self.moviePlayer.view atIndex:0]; [self.moviePlayer play]; // Loop video. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loopVideo) name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePlayer]; } - (void)loopVideo { [self.moviePlayer play]; } 

对于iOS9,我使用了Andrius的代码,并为循环添加了以下内容:

 -(void)replayBG:(NSNotification *)n { [playerLayer.player seekToTime:kCMTimeZero]; [playerLayer.player play]; }