使用AVAssetExportSession以全屏导出视频

11
我正在尝试为录制后的视频添加一些动画效果,然后导出视频。但在添加任何动画之前,我遇到了方向问题,视频方向从竖屏变成了横屏(未导出时为竖屏),这个问题已经解决了。现在我面临的问题是如何使它全屏,在 iPhone 6、7 Plus 上是全屏的,但在 iPad 上不是。
这是我的方法:
func export(_ url : URL) {
    let composition = AVMutableComposition()
    let asset = AVURLAsset(url: url, options: nil)

    let track =  asset.tracks(withMediaType : AVMediaTypeVideo)
    let videoTrack:AVAssetTrack = track[0] as AVAssetTrack
    let timerange = CMTimeRangeMake(kCMTimeZero, asset.duration)

    let compositionVideoTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())

    do {
        try compositionVideoTrack.insertTimeRange(timerange, of: videoTrack, at: kCMTimeZero)
    } catch {
        print(error)
    }

    let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())

    for audioTrack in asset.tracks(withMediaType: AVMediaTypeAudio) {
        do {
            try compositionAudioTrack.insertTimeRange(audioTrack.timeRange, of: audioTrack, at: kCMTimeZero)
        } catch {
            print(error)
        }

    }

    let size = self.view.bounds.size

    let videolayer = CALayer()
    videolayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)

    let parentlayer = CALayer()
    parentlayer.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    parentlayer.addSublayer(videolayer)

    let layercomposition = AVMutableVideoComposition()
    layercomposition.frameDuration = CMTimeMake(1, 30)
    layercomposition.renderSize = self.view.bounds.size
    layercomposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videolayer, in: parentlayer)

    let instruction = AVMutableVideoCompositionInstruction()

    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration)

    let videotrack = composition.tracks(withMediaType: AVMediaTypeVideo)[0] as AVAssetTrack
    let layerinstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videotrack)


    let ratio = size.height / videoTrack.naturalSize.width

    composition.naturalSize = videoTrack.naturalSize

    layerinstruction.setTransform(videoTrack.preferredTransform.scaledBy(x: 0.645 , y: ratio).translatedBy(x: self.view.bounds.height, y: 0), at: kCMTimeZero)

    instruction.layerInstructions = [layerinstruction]
    layercomposition.instructions = [instruction]

    let filePath = self.fileName()
    let movieUrl = URL(fileURLWithPath: filePath)

    guard let assetExport = AVAssetExportSession(asset: composition, presetName:AVAssetExportPresetHighestQuality) else {return}
    assetExport.videoComposition = layercomposition
    assetExport.outputFileType = AVFileTypeMPEG4
    assetExport.outputURL = movieUrl
    assetExport.exportAsynchronously(completionHandler: {
        switch assetExport.status {
        case .completed:
            print("success")
            let player = AVPlayer(url: movieUrl)
            let playerViewController = AVPlayerViewController()
            playerViewController.player = player
            self.present(playerViewController, animated: true) {
                playerViewController.player!.play()
            }
            break
        case .cancelled:
            print("cancelled")
            break
        case .exporting:
            print("exporting")
            break
        case .failed:
            print("failed: \(String(describing: assetExport.error))")
            break
        case .unknown:
            print("unknown")
            break
        case .waiting:
            print("waiting")
            break
        }
    })
}

1
你尝试过除了AVAssetExportPreset之外的其他预设吗? - Bluewings
1
我想这可能与您设置的 layercomposition.renderSize 有关,因为您将其设置为当前视图,因此如果您在手机上运行此操作,则输出视频大小会较小。您是否可以将renderSize设置为原始视频的大小? 这可能会解决问题。 - Chris
1
也许这个比例是通过高度/宽度计算的:让比例 = 尺寸.高度 / 视频轨道.自然尺寸.宽度 - xxtesaxx
@Bluewings 是的,我已经解决了问题,问题出在比例计算上。 - Mr.Ghamkhar
1个回答

1
我的问题得到解决的方法是更改比例因子和平移量。以下是代码:
    let size = self.view.bounds.size
    let trackTransform = videoTrack.preferredTransform
    let xScale = size.height / videoTrack.naturalSize.width
    let yScale = size.width / videoTrack.naturalSize.height


    let exportTransform = videoTrack.preferredTransform.translatedBy(x: trackTransform.ty * -1 , y: 0).scaledBy(x: xScale , y: yScale)

你把 exportTransform 插在哪里了? - Markinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接