6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CollectionViewを使って動画キャプチャーを作ってみる(1)

Posted at

collectionViewSample.gif

とりあえず動くものを作ってみる。動画を10分割してキャプチャー一覧を表示。選択されたところから再生します。

UICollectionViewは基本的にはUITbaleViewを使うのと同じような仕組みで動く。

    //1
    override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }
    
    //2
    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    
    //3
    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    //cellの設定
    }

最低上記3つの関数を実装すれば良い(と思う)
セルに関してはUITableViewのセルのようにフォーマットが用意されてるわけではなさそうなので、毎回UICollectionViewCellのサブクラスを用意するっぽいです。

class CustomCell : UICollectionViewCell {
    

    @IBOutlet weak var imageView: UIImageView!

    @IBOutlet weak var timeLabel: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        //fatalError("init(coder:) has not been implemented")
    }
    
    override func awakeFromNib() {
        
        let backgroundView = UIView(frame: frame)
        backgroundView.backgroundColor = UIColor.whiteColor()
        self.backgroundView = backgroundView
        
        let selectedBGView = UIView(frame: frame)
        selectedBGView.backgroundColor = UIColor.redColor()
        self.selectedBackgroundView = selectedBGView
    }
    
}

awakeFromNib内でセレクトされた時にCellの背景色を変えるロジックを入れてます。この場合、選択されたら赤くなる。他にも方法はあるみたいです。

動画を扱うプログラミングはなかなか奥が深いのですが、まず
AVFoundation
AssetsLibrary
上記2つのライブラリをプロジェクトに追加。
動画はiPhoneで撮った動画をプロジェクトに追加。
後はそれを読み込み、再生時間を10分割した時のキャプチャー画像とその時の読み込み時間を配列に保存。

import UIKit
import AVFoundation
import AssetsLibrary

class ViewController: UICollectionViewController {
    
    struct Capture {
        var picture : CGImageRef
        var time : Float64
    }
    
    var generator : AVAssetImageGenerator!
    var captureAry : [Capture]!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        
        if let path = NSBundle.mainBundle().URLForResource("IMG_0727", withExtension: "mp4") {
            do {
                let avAsset = AVURLAsset(URL: path, options: nil)
                
                // assetから画像をキャプチャーする為のジュネレーターを生成.
                generator = AVAssetImageGenerator(asset: avAsset)
                
                let runningTime = Int64(CMTimeGetSeconds(avAsset.duration))
                
                let time : CMTime = CMTimeMake(runningTime, 10)
                var capturedTime : CMTime = kCMTimeZero
                
                captureAry = []
                
                for _ in 0...9 {
                    let capturedImage : CGImageRef! = try! generator.copyCGImageAtTime(capturedTime, actualTime: nil)
                    
                    let capture = Capture(picture: capturedImage, time: CMTimeGetSeconds(capturedTime))
                    captureAry.append(capture)
                    
                    capturedTime = CMTimeAdd(capturedTime, time)
                }
            }
        }
    }

セルを選択された際はstroyBoardでsegueを使う場合は以下のとおり

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        NSLog("segue")
        
        let index : NSIndexPath = (self.collectionView?.indexPathForCell(sender as! UICollectionViewCell))!
        
        let capture = captureAry[index.row]
        let value : UInt64 = UInt64(capture.time*100)
        
        
        NSUserDefaults.standardUserDefaults().setObject(NSNumber(unsignedLongLong: value), forKey: "time")
        NSUserDefaults.standardUserDefaults().synchronize()
    }

後はセルを選択された際に呼び出すDetailViewを作ればOK


import Foundation
import AVKit
import AVFoundation

class PlayerViewController: AVPlayerViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let item : Int64 = Int64(NSUserDefaults.standardUserDefaults().objectForKey("time") as! Int)
        
        //let time = item * Int64(1)
        
        let seektime =  CMTimeMake(item, 100)
        NSLog("%f", CMTimeGetSeconds(seektime))
        
        
        if let url = NSBundle.mainBundle().URLForResource("IMG_0727", withExtension: "mp4") {
            do {
                player = AVPlayer(URL: url)
                player?.seekToTime(seektime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
            }
        } else {
            fatalError("error")
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func viewDidAppear(animated: Bool) {
        player?.play()
    }
}

これでとりあえず動くものが出来ます。これをより汎用的に作り直すのは次回。

参考

UICollectionViewを実装する[swift&xcode6]
UICollectionViewの使い方だけでなく、選択されたデータの遷移方法としてNSUserDefaultsを使っているのも参考にさせて頂きました。

005 動画から静止画を取り出す
キャプター画像を作るやり方はこのページを参照

AVFoundation プログラミングガイド
選択されたセルの背景色を変えるとか・・・それ以外にも少しずつ。

6
8
0

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
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?