web-dev-qa-db-ja.com

iOSの背景としてのビデオの最も効果的な方法

おそらく、iOSアプリの最新のトレンドの1つに気づいたかもしれません。それは、主にログイン画面または「初回起動」画面で、ビデオを背景として使用することです。昨日、非常に単純なテストプロジェクト(ビューコントローラーが1つのみ)でこれを模倣しようとしましたが、パフォーマンスを除いて結果に満足しています。 iOSシミュレーター(シミュレートされたiPhone 6)で試してみると、CPU使用率70-110の間で変動します%。これは、単純なログイン画面には非常に不合理に思えます。

これは実際の動作のように見えます: http://oi57.tinypic.com/nqqntv.jpg

問題は次のとおりです:これを達成するためのよりCPU効率の高い方法はありますか? Vine、Spotify、Instagramなどのアプリはどのようにこれを行っていますか?

あなたが答える前に;私が使用した方法は、MPMoviePlayerControllerを使用して再生されたフルHDビデオでした。

- (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];
}

もちろん、ビデオのエッジをトリミングして、解像度が1920x1080ではなく700x1080の線に沿ったものになるようにすることもできますが、それによってパフォーマンスに大きな違いが生じたでしょうか。または、最適なパフォーマンスを実現するために、特定の形式と設定でビデオを圧縮する必要がありますか?たぶん、これにはまったく別のアプローチがありますか?

実際、この記事で説明されているようにGIFを使用してみました: https://medium.com/Swift-programming/ios-make-an-awesome-video-background-view-objective-c-Swift-318e1d71d0a2 ==

それに関する問題は次のとおりです。

  • ビデオからGIFを作成するには、多くの時間と労力がかかります
  • 試してみたところ、CPU使用率の大幅な低下は見られませんでした
  • 複数の画面サイズをサポートすることは、このアプローチでは全体的な苦痛です(少なくとも、自動レイアウトとサイズクラスを有効にして試したときは、デバイス間でGIFを正しくスケーリングできませんでした)
  • ビデオの品質が悪い
18
Axel K

最良の方法は、AVFoundationを使用してから、ビデオレイヤー自体を制御することです。

ヘッダーファイルで@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()

}

IOS7でテスト済み-iOS9

これは古い投稿だと思いますが、iOSアプリのCPU使用率を下げた経験があるので、返信します。

最初に見る場所は使用です AVFoundationFramework

AVPlayer を実装すると、CPUが少しダウンするのに役立つはずです

しかし、最善の解決策は、OpenGlを利用してCPU使用率を大幅に削減するBrad Larsonの GPUImage ライブラリを使用することです。ライブラリをダウンロードすると、使用方法の例があります。 GPUImageMovieWriterの使用をお勧めします

2
bolnad

私は見つけました GitHubのこのコード iOS8/9で私のために働いた

- (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];
}
1
Kevin Jantzer

AVAssetReader、GLKViewを使用してこれを行い、CIImageパイプラインを介してレンダリングします。シミュレーターでフィルター処理されていないビデオを再生すると、約80%のCPUを消費します。実際のデバイスでは、リアルタイムフィルタリング(CIFilter)で1x%のコストがかかります。 FPSをループして制御するように設定することもできます。私はGithubで作成しましたので、どなたでもコピーをお持ちいただけます。ビデオの背景ビューだけのためにGPUImage全体をドロップしたくない人にとっては良い代替選択肢になります。ビューをドラッグアンドドロップすると機能します。 https://github.com/matthewlui/FSVideoView

1
MatthewLuiHK

IOS9の場合、Andriusのコードを使用し、ループに次を追加しました。

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