

やりたいことは

iOSで  
AVPlayerで動画を再生し  
最後まで再生されたら  
リピートフラグの変数を見て  
必要があれば再度頭から再生する  
というだけです。

ですが、数百回に1回くらいのかなりまれな確率で  
画面的には最後まで再生された所で止まり  
しかし動画の尺の秒数後にまた動き出す  
ということが起きます。  
それは動画の秒数きっかりです。

何故動画の秒数きっかりと判断したか、という点ですが  
複数台のipadを横において同じ動画を再生する同じコードを走らせており  
ぴったり同時に再生開始し  
iPad1では例えば3秒の動画の再生を繰り返しており  
iPad2でも同様に揃って動いているが、その問題が起きた時は  
iPad2だけ3秒間動画の最後のフレームで止まり、次のループの時にはiPad1とピッタリ同時にまた頭から再生しはじめたため  
止まっていた時間は動画の尺の分であると判断できます。

動画ファイルはネット上のものではなく、カメラロールに入っているものです。

これは確率は低いものの何度か現象を見ており再現はしています。

コードの一部は以下です。特別なことはしていない認識です・・・。

[code]

    // 再生時にViewControllerから動画URLを渡して呼んでいる
    - (void)setPlayerWithURL:(NSURL *)url
    {
        self.player = [[AVPlayer alloc]initWithURL:url];
        [(AVPlayerLayer*)self.playerView.layer setPlayer:self.player];
    
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(playerItemDidReachEnd:)
                                                     name:AVPlayerItemDidPlayToEndTimeNotification
                                                   object:[self.player currentItem]];
    }
    
    // 再生完了時
    - (void)playerItemDidReachEnd:(NSNotification *)notification
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"notification recieve");
            if (self.isRepeat)
            {
                NSLog(@"notification replay");
                [self.player seekToTime:kCMTimeZero];
                [self.player play];
            }
        });
    }
    
[/code]

見た目上は1回分再生が止まっているものの、次のループには動き出すので、描画が止まっているだけで内部的には動いていると思っていますが

色々調べたものの、そのような現象や対策を発見できませんでした。

環境としては  
iPad Air 2 Wi-Fiモデル 16GB MGLW2J/A  
OS8.4  
です。

ただし過去にもOSのバージョンが古い時にも起きておりこのバージョンのみの現象でないです。  
そして端末もiPad限定ではなくiPhoneでも起きています。

対策などご存知の方おられましたらご教授いただけますとありがたいです。


CC BY-SA 3.0
2015-09-22T00:10:27.053
16837
2022-07-23T15:04:55.537
10373
question
ios
AVPlayer.playが描画されないことがあります


原因の可能性としては、seekToTimeと、playの処理が同時に実行されることで、発生しているのでは？と推測しています。

以下の関数を利用するのは、いかがでしょうか？

[code]

    - (void)seekToTime:(CMTime)time
     completionHandler:(void (^)(BOOL finished))completionHandler
    
[/code]

シークし終わった後に、明示的に再生を実行する手順です。  
以下が、変更案です。

[code]

    // 再生完了時
    - (void)playerItemDidReachEnd:(NSNotification *)notification
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"notification recieve");
            if (self.isRepeat)
            {
                NSLog(@"notification seekToHead");
                [self.player seekToTime:kCMTimeZero
                      completionHandler:^(BOOL finished) {
                           if(finished){
                               NSLog(@"notification replay");
                               [self.player play];
                           }
                      }];
    
            }
        });
    }
    
[/code]


CC BY-SA 3.0
2015-09-22T06:06:25.853
16839
2015-09-22T06:06:25.853
3766
16837
answer


再生しているのは、httpで取得したm3u8の動画でしょうか？  
m3u8は複数のファイルから成り立っていますので、通信状況などでどれかが取得できないとき、  
AVPlayerは復帰するまでしばらく待機するはずです。

再生が停止するということですが、playerのrateは0になっていますか？  
0でなければ内部的には再生できていると思います。  
あとは、statusはどうなっていますか？  
KVO使って、rateとstatusを監視し適切にハンドリングしたほうがいいと思います。

また、エラーは出てないでしょうか？

[code]

     NSError * error = self.player.currentItem.error;
    
     if (error == nil) {
       AVPlayerItemErrorLog * log = [session.player.currentItem errorLog];
       AVPlayerItemErrorLogEvent *event = [log events][0];
       NSLog(@"エラー %@", log);
       NSLog(@"エラー URI %@", [event URI]);
       NSLog(@"エラー errorStatusCode %ld", (long)[event errorStatusCode]);
       NSLog(@"エラー errorDomain %@", [event errorDomain]);
       NSLog(@"エラー errorComment %@", [event errorComment]);          
     }else{            
       NSLog(@"エラー %@", error);
     }
    
[/code]


CC BY-SA 4.0
2018-08-20T01:30:57.337
47638
2018-08-20T02:04:25.053
2018-08-20T02:04:25.053
3060
29782
16837
answer