要件

動画 sample.mp4 を最後まで再生した後、10秒の位置から最後までをループしたい。

検証1

AVPlayer で再生終了時にループポイントから再再生してみた。

var avPlayer:AVPlayer?
var playerItem: AVPlayerItem?

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    initialize()
}

override class func layerClass() -> AnyClass{
    return AVPlayerLayer.self
}

func initialize() {
    let path = NSBundle.mainBundle().pathForResource("sample", ofType: "mp4")
    let fileURL = NSURL(fileURLWithPath: path!)
    let asset = AVURLAsset(URL: fileURL, options: nil)

    playerItem = AVPlayerItem(asset: file)
    avPlayer = AVPlayer(playerItem: playerItem!)

    let videoLayer = layer as! AVPlayerLayer
    videoLayer.videoGravity =   AVLayerVideoGravityResizeAspect
    videoLayer.player = avPlayer

    NSNotificationCenter.defaultCenter().addObserver(
            self,
            selector: "restartVideoFromLoopPoint",
            name: AVPlayerItemDidPlayToEndTimeNotification,
            object: avPlayer?.currentItem)
}

func restartVideoFromLoopPoint()  {
    let seekTime : CMTime = CMTimeMake(10, 1)
    avPlayer?.seekToTime(seekTime)
    avPlayer?.play()
}

func play() {
    avPlayer?.play()
}

最後まで再生された後に一瞬止まってしまう。

検証2

AVMutableComposition を使うと10秒の位置から最後までのシームレスなループを作れたので、1つの動画を 最初から10秒10秒から最後のループ の動画に分割して AVQueuePlayer で繋いでみた。

var avPlayer:AVQueuePlayer?
var playerItems: [AVPlayerItem]?

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    initialize()
}

override class func layerClass() -> AnyClass{
    return AVPlayerLayer.self
}

func initialize() {
    let path = NSBundle.mainBundle().pathForResource("sample", ofType: "mp4")
    let fileURL = NSURL(fileURLWithPath: path!)
    let asset = AVURLAsset(URL: fileURL, options: nil)

    let oneTime = CMTimeRangeMake(CMTimeMake(0, 1), CMTimeMake(10, 1))
    let oneTimeComposition = AVMutableComposition()
    try! oneTimeComposition.insertTimeRange(oneTime, ofAsset: asset, atTime: oneTimeComposition.duration)
    let playItemA = AVPlayerItem(asset: oneTimeComposition)

    let loop = CMTimeRangeMake(CMTimeMake(10, 1), CMTimeMake(2, 1))
    let loopComposition = AVMutableComposition()
    for _ in 0...999 {
        try! loopComposition.insertTimeRange(loop, ofAsset: asset, atTime: loopComposition.duration)
    }

    let playItemB = AVPlayerItem(asset: loopComposition)
    playerItems = [playItemA, playItemB]
    avPlayer = AVQueuePlayer(items: playerItems!)

    let videoLayer = layer as! AVPlayerLayer
    videoLayer.videoGravity =   AVLayerVideoGravityResizeAspect
    videoLayer.player = avPlayer
}

func play() {
    avPlayer?.play()
}

不恰好なカタチになったけど、要件は満たした。
他にやり方があれば知りたい。

Next PostPrevious Post