AVPlayerを使って動画を再生する

Swiftで，AVPlayerを使って動画を再生する方法のメモです。動画を再生する方法は，他にもあります。
コードは[こちら](https://github.com/tky1117/MovieApp_iOS)

# 環境
Swift 5.0
Xcode 10.2

# 動画の再生
AVPlayerを使って動画を再生する流れは以下のようになります。

1. AVPlayerを用意
2. AVPlayerViewControllerを用意
3. AVPlayerViewControllerにAVPlayerを渡す。

まず，動画を再生するための関数を2つ用意しておきます。
`playMovieFromURL`：URLを受け取り，動画を再生する。
`playMovieFromPath`：パスを受け取り，動画を再生する。

```swift:ViewController.swift
func playMovieFromUrl(movieUrl: URL?) {
    if let movieUrl = movieUrl {
        let videoPlayer = AVPlayer(url: movieUrl)
        let playerController = AVPlayerViewController()
        playerController.player = videoPlayer
        self.present(playerController, animated: true, completion: {
            videoPlayer.play()
        })
    } else {
        print("cannot play")
    }
}

func playMovieFromPath(moviePath: String?) {
    if let moviePath = moviePath {
        self.playMovieFromUrl(movieUrl: URL(fileURLWithPath: moviePath))
    } else {
        print("no such file")
    }
}
```

動画を再生する例を3つ，以下に示します。自分は以下の3つの種類の動画の再生を混同していたために躓きました。

1. Bundle Resorcesにあるファイルの再生
2. リモートファイルの再生
3. ローカルファイルの再生

# 1. Bundle Resorcesの動画を再生

ログイン画面で流す動画のように，アプリ内にあらかじめ置いておく必要のある動画は，Bundle Resourcesに置いておきます。
具体的には，以下のようにBuild Phasesの中のCopy Bundle Resources内に再生したい動画（図中ではbundle.mp4）を追加します。

<img width="1139" alt="BundleResources.png" src="https://qiita-image-store.s3.amazonaws.com/0/297735/56db3acd-5835-5695-28e6-331a2213b5f3.png">


このリソースファイルの再生するには，ファイルのパスを`playMovieFromPath`に渡します。

```swift:ViewController.swift
let bundleDataName: String = "bundle"
let bundleDataType: String = "mp4"

@IBAction func playMovieFromBundleFile() {
    //MovieApp_iOS -> Build Phases -> Copy Bundle Resources 内にbundle.mp4を追加
    let moviePath: String? = Bundle.main.path(forResource: bundleDataName, ofType: bundleDataType)
    playMovieFromPath(moviePath: moviePath)
}
```


# 2. リモートファイルの再生

ダウンロードの必要がなければ，`playMovieFromUrl`に動画そのもののURLを渡すことで再生できます。

```swift:ViewController.swift
let remoteFileUrl: String = "https://d2qguwbxlx1sbt.cloudfront.net/TextInMotion-VideoSample-576p.mp4"

@IBAction func playMovieFromRemoteFile() {
    playMovieFromUrl(movieUrl: URL(string: remoteFileUrl))
}
```

# 3. ローカルファイルの再生

そもそも再生するためのファイルが無ければいけないので，適当なファイルをダウンロードしたいと思います。コードの`downloadFileUrl`をダウンロードしたい動画のURLに変更してください。
動画はDocumentsディレクトリにダウンロードします。この保存先は，用途に応じて変更してください。また，ダウンロードした動画のファイル名は`localDataNameWithExtension`の部分で指定します。

```swift:ViewController.swift
let downloadFileUrl: String = "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
let localDataNameWithExtension: String = "local.mov"

@IBAction func downloadMovieFromRemoteFile(){
    let task = URLSession.shared.dataTask(with: URL(string: downloadFileUrl)!) { (data, response, error) in
        if let data = data {
            print("succeeded in download")
            do {
                let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! + "/" + self.localDataNameWithExtension
                try data.write(to: URL(fileURLWithPath: path))              
            } catch let error {
                print(error)
            }
        } else {
            print("failed in download")
        }        
    }
    task.resume()
}
```

Bundle Resorcesの動画の再生と同様に，`playMovieFromPath`に，再生するファイルのパスを渡すことで動画を再生できます。

```swift:ViewController.swift
@IBAction func playMovieFromLocalFile() {
    let moviePath: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last! + "/" + localDataNameWithExtension
    playMovieFromUrl(movieUrl: URL(fileURLWithPath: moviePath))
}
```