LoginSignup
11
9

More than 3 years have passed since last update.

AVQueuePlayerをリピート再生させるときに詰まった話

Last updated at Posted at 2017-05-18

AVQueuePlayerとは

AVFoundationのAVPlayerを継承している。複数のAVPlayerItemを連続再生できるクラスです。

複数の動画を連続再生するときはAVQueuePlayerというクラスを使うといいらしい

let items = [AVPlayerItem(), AVPlayerItem(), AVPlayerItem()]
let queuePlayer = AVQueuePlayer(items: items)
queuePlayer.play()

ってやると配列の順番通りに動画が再生される

AVQueuePlayerでリピート再生を実現させる(間違ってる例)

僕は最後のAVPlayerItemが再生し終わったらseekを0にしてまた再生しとけばいいと思ってた

普通に
func setupObserver() {

  NotificationCenter.default.addObserver(self, selector: #selector(self.endPlaying), name: .AVPlayerItemDidPlayToEndTime, object: items.last)
}

func endPlaying() {
  queuePlayer.seek(to: kCMTimeZero)
  queuePlayer.play()
}

RxSwift使用
NotificationCenter.default.rx.notification(.AVPlayerItemDidPlayToEndTime, object: items.last).subscribe(onNext: { [weak self] _ in
  guard let `self` = self else { return }
  self.queuePlayer.seek(to: kCMTimeZero)
  self.queuePlayer.play()
}).disposed(by: disposeBag)

けどできませんでした、、、

できない理由はよくわからないんで知ってる人がいたら教えて欲しいです。

AVQueuePlayerでリピート再生を実現させる(できた)

正しいリピート再生のアプローチは

「1つめのAVPlayerItemが再生し終わる」
    ↓
「1つめのAVPlayerItemのseekを0にする」
    ↓
「次のAVPlayerItemを再生する」
    ↓
「1つめのAVPlayerItemをAVQueuePlayerのitemsの後ろにinsertする」
    ↓
「2つめのAVPlayerItemが再生し終わる」
    ↓
「2つめのAVPlayerItemのseekを0にする」
    ↓
以下同様
って方法だとリピートを実現することができた!

普通に
func setupObserver() {
  for item in items {
    NotificationCenter.default.addObserver(self, selector: #selector(self.endPlaying), name: .AVPlayerItemDidPlayToEndTime, object: item)
  }
}

func endPlaying(_ notification: Notification) {
  let item = notification.userInfo?["object"] as! AVPlayerItem
  // 再生し終わったらseekを0にして
  item.seek(to: kCMTimeZero)
  // 次を再生して
  queuePlayer.advanceToNextItem()
  // 後ろにinsert
  queuePlayer.insert(item, after: nil)
}

RxSwift使用
for item in items {
  NotificationCenter.default.rx.notification(.AVPlayerItemDidPlayToEndTime, object: item).subscribe(onNext: { [weak self] _ in
    guard let `self` = self else { return }
    // 再生し終わったらseekを0にして
    item.seek(to: kCMTimeZero)
    // 次を再生して
    self.player.advanceToNextItem()
    // 後ろにinsert
    self.player.insert(item, after: nil)
  }).disposed(by: disposeBag)
}

最後に

やー、はまりまくった。

RxSwiftじゃない方は文法間違いあっても知りません

11
9
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9