ソースビデオがあり、ソースビデオの各フレームの領域を取得して、そこから新しいビデオを生成したいと考えています。たとえば、解像度A
x B
、コンテンツ サイズX
x Y
、出力解像度C
xのビデオがある場合、元のビデオの各フレームの最初のxピクセルをコンテンツとする解像度xD
のビデオを作成します。C
D
X
Y
これを実現するためにAVAssetReader
、ソース ビデオの読み取りには を使用しAVAssetWriter
、新しいビデオの書き込みには を使用しています。ソース ビデオの領域X
xだけを抽出するために、アセット リーダーの出力としてオブジェクトを使用しています。セットアップ コードは次のようなものです。Y
AVAssetReaderVideoCompositionOutput
let output = AVAssetReaderVideoCompositionOutput(...)
output.videoComposition = AVMutableVideoComposition(
asset: asset,
videoTrack: videoTrack,
contentRect: contentRect,
renderSize: renderSize
)
次に、ビデオ コンテンツをトリミングするためのロジックは、次のカスタム初期化子で発生します。
extension AVMutableVideoComposition {
convenience init(asset: AVAsset, videoTrack: AVAssetTrack, contentRect: CGRect, renderSize: CGSize) {
// Compute transform for rendering the video content at `contentRect` with a size equal to `renderSize`.
let trackFrame = CGRect(origin: .zero, size: videoTrack.naturalSize)
let transformedFrame = trackFrame.applying(videoTrack.preferredTransform)
let moveToOriginTransform = CGAffineTransform(translationX: -transformedFrame.minX, y: -transformedFrame.minY)
let moveToContentRectTransform = CGAffineTransform(translationX: -contentRect.minX, y: -contentRect.minY)
let scaleTransform = CGAffineTransform(scaleX: renderSize.width / contentRect.width, y: renderSize.height / contentRect.height)
let transform = videoTrack.preferredTransform.concatenating(moveToOriginTransform).concatenating(moveToContentRectTransform).concatenating(scaleTransform)
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
layerInstruction.setTransform(transform, at: .zero)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(start: .zero, duration: asset.duration)
instruction.layerInstructions = [layerInstruction]
self.init(propertiesOf: asset)
instructions = [instruction]
self.renderSize = renderSize
}
}
このコードは、コンテンツのサイズなど、場合によっては正常に機能します(origin = (x = 0, y = 0), size = (width = 1416, height = 1920))
。ただし、幅を 1417 に変更すると機能せず、次のエラー メッセージが表示されます。
Error Domain=AVFoundationErrorDomain Code=-11858 "Source frame unsupported format" UserInfo={NSUnderlyingError=0x283e689c0 {Error Domain=NSOSStatusErrorDomain Code=-12502 "(null)"}, NSLocalizedFailureReason=ビデオを合成できませんでした., NSDebugDescription=ソース フレームサポートされていない形式、NSLocalizedDescription=操作停止}
これは、エラーが発生したテスト ビデオを含むサンプル プロジェクトへのリンクです。幅1416、1421、1422、1423、1429で機能し、1416と1429の間の他のすべての幅値で失敗するため、これがランダムに見える場合があります。ここで何が問題で、どうすれば問題を解決できますか?
なぜこのアプローチを使用するのですか?
を使用するAVAssetReaderVideoCompositionOutput
代わりに を使用してAVAssetReaderTrackOutput
手動でクロッピングを行う理由は、前者を使用するとアプリのメモリ フットプリントを削減できるためです。サイズ。これは、同時に複数のビデオを処理している場合に関係します。