首页 > 解决方案 > 如何裁剪由 AVCaptureMovieFileOutput 录制的视频?

问题描述

我制作了 CustomCamera,它将视频录制到全屏(通过将 AVCaptureVideoPreviewLayer 的 videoGravity 设置为 resizeAspectFill)并使用 AVCaptureMovieFileOutput 保存录制。录制效果很好,但是当我将录制的视频保存到图库时,它没有全屏播放。它的顶部和底部都有黑条。因此,在录制时,由于 resizeAspectFill,它会以全屏显示,但在导出视频后,会在没有任何转换的情况下导出视频,因此它会按照录制的比例播放(我猜)。我试图使视频导出全屏的代码如下,但它不起作用。

func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
if let err = error as NSError?, err.code != -11810 { //-11810 = recording stopped when timelimit reached
    print("Error recording movie: \(err)")
} else {
    let videoAsset: AVAsset = AVAsset( url: outputFileURL )
    guard let clipVideoTrack = videoAsset.tracks( withMediaType: AVMediaType.video ).first as AVAssetTrack? else {
        
        return
    }
    
    let videoComposition = AVMutableVideoComposition(propertiesOf: videoAsset)

    let instruction = AVMutableVideoCompositionInstruction()
    instruction.timeRange = clipVideoTrack.timeRange
    
     let transformer = AVMutableVideoCompositionLayerInstruction( assetTrack: clipVideoTrack)
    transformer.setTransform(videoPreviewLayer.affineTransform(), at: .zero) // This is the transform value of AVCaptureVideoPreviewLayer
    print("clipVideoTrack size: \(clipVideoTrack.naturalSize)")
    
    instruction.layerInstructions = [transformer]
    videoComposition.instructions = [instruction]
    
    let outputPath = "\(NSTemporaryDirectory())\(UUID().uuidString).mov"
    let croppedOutputFileUrl = URL(fileURLWithPath: outputPath)
    
    let exporter = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPresetHighestQuality)!
    exporter.videoComposition = videoComposition
    exporter.outputURL = croppedOutputFileUrl
    exporter.outputFileType = .mov
    exporter.shouldOptimizeForNetworkUse = true
    exporter.canPerformMultiplePassesOverSourceMediaData = true
    
    exporter.exportAsynchronously( completionHandler: { () -> Void in
        if let error = exporter.error {
            print("Error in exporting: \(error)")
        }
        if exporter.status == .completed {
            print("exported successfully")
        }
        DispatchQueue.main.async(execute: {
            if let url = exporter.outputURL {
                print("exported file url: \(url)")
            } else {
            }
            
        })
    })
}
}

标签: swiftvideo-processingavassetexportsessionavcapturemoviefileoutput

解决方案


录制的视频尺寸取决于您的会话sessionPreset

captureSession.sessionPreset = AVCaptureSession.Preset.vga640x480 // and many others 

它与选择播放视频的当前方面无关


推荐阅读