はじめに
今回は Swift5で動画に字幕表示させたい
ということで、調査した内容をまとめた記事になります。
- AVPlayerで字幕表示させる
- そのときに躓いたこと
- 修正版ソースコード
AVPlayerで字幕表示させる
今回はこちらを参考にしました。
https://stackoverflow.com/questions/39589710/how-to-add-external-vtt-subtitle-file-to-avplayerviewcontroller-in-tvos
ソースコードに対して、自分なりにコメントしていましたmm
// 字幕と動画をまとめるパラメータ
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
大抵の動画ファイルは、映像トラックと音声トラックの2つに分裂していることを知りました。
映像トラックと音声トラックをセットするように改修しました。
完成ソースコード
下記のように修正したら、無事に音声が聞こえるようになりました
// 字幕と動画をまとめるパラメータ
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
}
映像トラックや音声トラックが複数ある場合は、気をつけてくださいね。
動画の構成に気がつかず、時間がかかってしまいました。
これが誰かの参考になれば、嬉しく思います。