AVPlayerで字幕表示する方法(字幕ファイル.vtt)&AVMutableCompositionの使い方

## はじめに
今回は `Swift５で動画に字幕表示させたい` ということで、調査した内容をまとめた記事になります。

1. AVPlayerで字幕表示させる
2. そのときに躓いたこと
3. 修正版ソースコード

## AVPlayerで字幕表示させる
今回はこちらを参考にしました。
https://stackoverflow.com/questions/39589710/how-to-add-external-vtt-subtitle-file-to-avplayerviewcontroller-in-tvos

ソースコードに対して、自分なりにコメントしていましたmm

```video.swift

// 字幕と動画をまとめるパラメータ
let videoPlusSubtitles = AVMutableComposition()

// 動画情報
let localVideoAsset = AVURLAsset(url: URL(string: "https://aa/bb/test.mp4") ?? URL(string:"")!)
// 動画追加
let videoTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)

do{

　　guard localVideoAsset.tracks.count > 0 else{
             // error msg
                return
            }
　　　　　　　//表示Rangeを決定する
            try? videoTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset.duration),
                                             of: localVideoAsset.tracks(withMediaType: .video)[0],
                                             at: CMTime.zero)
}

// 字幕情報
let subtitleURL = URL(fileURLWithPath: model.data?[self.selected].subtitlePath ?? "")
            //字幕ファイル今回はvttファイル
            let subtitleAsset = AVURLAsset(url: "https://aa/bb/test.vtt")
// 字幕追加
            let subtitleTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .text, preferredTrackID: kCMPersistentTrackID_Invalid)
            do{
                guard subtitleAsset.tracks.count > 0 else{
                    //error msg
                    return
                }
//表示Rangeを決定する
                try? subtitleTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset.duration),
                                                    of: subtitleAsset.tracks(withMediaType: .text)[0],
                                                    at: CMTime.zero)
            }
// playerにセットする
        let playerViewController = AVPlayerViewController()
        let player = AVPlayer(playerItem: AVPlayerItem(asset: videoPlusSubtitles))
        playerViewController?.player = player

 
    }
```

字幕を表示することに成功しました。
やったー！！

## そのときに躓いたこと
しかし再生したときに、音声が流れないことに気がつきました。
なんで音声が流れないかというと、「// 動画情報」で映像トラックしかセットしていなかったからです。
それは下記のQiitaを見て、理解しました。
https://qiita.com/croquette0212/items/8912053e616e575a4d4a

大抵の動画ファイルは、映像トラックと音声トラックの２つに分裂していることを知りました。
映像トラックと音声トラックをセットするように改修しました。

## 完成ソースコード
下記のように修正したら、無事に音声が聞こえるようになりました

```video.swift
// 字幕と動画をまとめるパラメータ
let videoPlusSubtitles = AVMutableComposition()

// 動画情報
let localVideoAsset = AVURLAsset(url: URL(string: "https://aa/bb/test.mp4") ?? URL(string:"")!)
// 動画追加
let videoTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
// 音声トラック追加（前回忘れていたのも）
let audioTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        do{
            guard localVideoAsset.tracks(withMediaType: .video).count > 0 else {
                return
            }

            try? videoTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset.duration),
                                             of: localVideoAsset.tracks(withMediaType: .video)[0],
                                             at: CMTime.zero)
            
            // 音声トラック追加（前回忘れていたのも）
            guard localVideoAsset.tracks(withMediaType: .audio).count > 0 else {
                return
            }
            try? audioTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset.duration),
                                             of: localVideoAsset.tracks(withMediaType: .audio)[0],
                                             at: CMTime.zero)

            
        }

// 字幕情報
let subtitleURL = URL(fileURLWithPath: model.data?[self.selected].subtitlePath ?? "")
            //字幕ファイル今回はvttファイル
            let subtitleAsset = AVURLAsset(url: "https://aa/bb/test.vtt")
// 字幕追加
            let subtitleTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .text, preferredTrackID: kCMPersistentTrackID_Invalid)
            do{
                guard subtitleAsset.tracks.count > 0 else{
                    //error msg
                    return
                }
//表示Rangeを決定する
                try? subtitleTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset.duration),
                                                    of: subtitleAsset.tracks(withMediaType: .text)[0],
                                                    at: CMTime.zero)
            }
// playerにセットする
        let playerViewController = AVPlayerViewController()
        let player = AVPlayer(playerItem: AVPlayerItem(asset: videoPlusSubtitles))
        playerViewController?.player = player

 
    }
```

映像トラックや音声トラックが複数ある場合は、気をつけてくださいね。
動画の構成に気がつかず、時間がかかってしまいました。
これが誰かの参考になれば、嬉しく思います。