前回に引き続き。Asset
を理解したら、次はComposition
の理解。
AVAsset
のサブクラスにはAVURLAsset
とAVComposition
の二つがある。
動画編集では必然的にComposition
を使うことになるので、まず基礎から。
CompositionとTrackとAsset
名称 | 説明 |
---|---|
Composition | 一つの映像作品 / プロジェクト |
Track | Compositionを構成する映像/音声トラック |
Asset | 各トラックの上にのせる素材 |
ここらへんは世の中の動画編集ソフトと基本的に同じ考え方なので、もしピンとこなかったらPremiere
辺りを使ってみて感覚をつかんでおくとわかりやすい。なお、ややこしいがComposition
もAsset
として扱えるので注意。
読み込んだAssetのトラックを調べてみる
AVAsset
のtracks
プロパティを見ると、そのAssetに含まれるトラックの情報を見れる。
let asset = AVURLAsset(url: url)
debugPrint(asset.tracks)
大抵の動画ファイルは、2トラック(映像トラック1 + 音声トラック1)から構成される。
[<AVAssetTrack: 0x600000018080, trackID = 1, mediaType = soun>, <AVAssetTrack: 0x6000000181e0, trackID = 2, mediaType = vide>]
tracks
の代わりに、tracks(withMediaType:)
を使うとタイプを限定したトラックのリストを取得できる。
debugPrint(asset.tracks(withMediaType: .video))
Compositionを作る
ファイルからAssetをロードする際にはAVURLAsset
を使ったが、ゼロからCompositionを作る場合はAVComposition
のサブクラスであるAVMutableComposition
を使う。
let composition = AVMutableComposition()
映像トラックを追加する
AVMutableComposition
生成直後はトラックがない空のコンポジションとなっているので、映像トラックを一つ追加する。
guard let videoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid) else {
debugPrint("Failed to add video track.")
return
}
addMutableTrack(withMediaType:, preferredTrackID:)
を呼ぶと、新しいトラックがCompositionに追加される。
- 今回は映像トラックなので
.video
を指定したが、.audio
を指定すると音声トラックが追加される。 -
preferredTrackID
に値を指定すると、任意のトラックIDをつけることができるが、特に指定する必要がない時はkCMPersistentTrackID_Invalid
を指定すると、自動的にユニークなIDをつけてくれる。(参考: https://developer.apple.com/documentation/avfoundation/avmutablecomposition/1387601-addmutabletrack)
映像トラックにAssetの映像を追加する
AVMutableCompositionTrack
には、insertTimeRange:ofTrack:atTime:error:
メソッドで他のAssetのトラックの内容を追加できる。
// 素材Assetの1個目のVideoトラックを使う
let srcVideoTrack = asset.tracks(withMediaType: .video)[0]
do {
// 0秒のタイミングに、映像全体を追加する
try videoTrack.insertTimeRange(srcVideoTrack.timeRange, of: srcVideoTrack, at: .zero)
} catch let error {
debugPrint(error)
}
大体メソッド名通りなので説明不要かもしれないが、
- TimeRange - 元素材トラックの方のどの範囲(0:30.000〜0:35.000 とか)を使うかをCMTimeRangeで指定する。今回は元素材トラック全体を指定した。
- ofTrack - 元素材トラックを指定
- atTime - 貼付ける先のトラックのどの位置に貼付けるか
例えば、元素材から最初の5秒間の映像(videoトラックのみ)をコピーしたい場合はこのように書ける。
let first5Seconds = CMTimeRange(start: .zero, end: CMTime(seconds: 5.0, preferredTimescale: srcVideoTrack.naturalTimeScale))
try videoTrack.insertTimeRange(first5Seconds, of: srcVideoTrack, at: .zero)
timescale
は特別な理由がなければ元素材に合わせておきたいので、元素材のnaturalTimeScaleを使用している。
CompositionをAVPlayerViewで再生する
作成したComposition(Asset)
は、AVPlayer
およびAVPlayerView
を使って画面で再生させることができる。
let player = AVPlayer(playerItem: AVPlayerItem(asset: composition))
playerView.player = player // playerViewはStoryboardに設置したAVPlayerView
ファイルに書き出してから内容を確認するのが面倒な場合や、プレビュー機能を作るときはこの仕組みも活用したい。
Compositionの書き出し
AVMutableComposition
はAVAsset
のサブクラスなので、AVAssetExportSessionを使ったファイルへの書き出しができる。
guard let session = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough) else {
debugPrint("Failed to prepare session")
return
}
session.outputURL = url
session.outputFileType = .mp4
session.exportAsynchronously {
switch session.status {
case .completed:
debugPrint("completed")
case .failed:
debugPrint("error: \(session.error!.localizedDescription)")
default:
break
}
}
- 利用可能な
PresetName
はAVAssetExportSession.allExportPresets()
で確認することができる。