Objective-C
Xcode
Swift
SwiftDay 20

SwiftでVideo Player

More than 3 years have passed since last update.

Swift Advent Calenderの20日(土)担当の山口です。

よろしくお願いします。

今この時点で19日の18時を回っているという不味い状態ですが頑張ります。

普段業務でiOSのStatic Libraryを2つほど作っているので、「SwiftでStatic Library!」とかっていう記事にしたかったのですが、Swiftでは出来なさそうなので泣く泣くVideoPlayerにしました。


再生方法

iOSではVideoの再生は2種類あります。

- AVPlayer

- MPMoviePlayerController

今回は前者のAVPlayerで実装します。

以下のシミュレーターのキャプチャです。

スクリーンショット 2014-12-20 5.09.23.png


準備

Appleが公開している動画再生のsampleを少し参考にしました。

必要なFrameWorkはAVFoundationです。

import AVFoundation

登場Class

- AVPlayerLayer

- AVURLAsset

- AVPlayerItem

- AVPlayer

を使います。


実装


■ AVPlayerLayer

まずAVPlayerLayer用のUIViewの子クラスを作ります

import UIKit

import AVFoundation

class AVPlayerView: UIView {

// AVPlayerのgetterとsetter
var player: AVPlayer {
get {
let layer: AVPlayerLayer = self.layer as AVPlayerLayer
return layer.player
}
set(newValue) {
let layer: AVPlayerLayer = self.layer as AVPlayerLayer
layer.player = newValue
}
}
// layerClassのoverride
override class func layerClass() -> AnyClass {
return AVPlayerLayer.self
}

func setVideoFillMode(mode: NSString) {
let layer: AVPlayerLayer = self.layer as AVPlayerLayer
layer.videoGravity = mode
}
}


■ Assetの読み込み

次に下記を使って実際playerを作っていきます

- AVURLAsset

- AVPlayerItem

- AVPlayer

AVPlayerItemがファイルを読み込んだかどうかを見るためにKVOをセットします。


一つ注意なのが、KVOのキーは"status"でないと動きません。


var playerView: AVPlayerView!

var playerItem: AVPlayerItem!
var assets: AVURLAsset!
var player: AVPlayer!

// ...

// ローカルのsample.mp4ファイルを読み込みます
let URLString: NSString = NSBundle.mainBundle().pathForResource("sample", ofType: "mp4")!
let URL: NSURL = NSURL.fileURLWithPath(URLString)!

self.assets = AVURLAsset.assetWithURL(URL) as AVURLAsset
self.playerItem = AVPlayerItem(asset: self.assets)

// PlayerのStatusを監視するためにKVOをセットします
self.playerItem.addObserver(self, forKeyPath: "status", options: .New | .Initial, context: nil)
self.player = AVPlayer.playerWithPlayerItem(self.playerItem) as AVPlayer


■ KVO監視、再生

次にKVOの監視部分です。

.ReadyToPlayに入り、AVPlayerLayerにplayerをセットすれば、いつでも再生が可能です。

self.player.play()self.player.pause()で動画の再生や停止ができます。

ここでシークバーのsetupをするなどすれば、純正のPlayerと同じぐらいのものが作れます。

override func observeValueForKeyPath(keyPath: String,

ofObject object: AnyObject,
change: [NSObject : AnyObject],
context: UnsafeMutablePointer<Void>) {

if keyPath == "status" {
let status : AVPlayerItemStatus = self.playerItem.status as AVPlayerItemStatus

if status == .ReadyToPlay {
// 再生準備完了
NSLog("ReadyToPlay")
// playerのセット
self.playerView.player = self.player
self.playerView.setVideoFillMode(AVLayerVideoGravityResizeAspectFill)
}
else if status == .Failed {
NSLog("Failed")
}
else if status == .Unknown {
NSLog("Unknown")
}
}
else {
super.observeValueForKeyPath(keyPath,
ofObject: object,
change: change,
context: context)
}
}

時間がなかったのでシークバーの説明などは出来ませんでしたが、これで動画の再生まではいけると思います。

MPMoviePlayerControllerだと細かいPlayerのUIとかはイジれないので、AVPlayerで動画再生はできるようになったほうが良い気がしました。


参考