使用 AVAssetExportSession 全屏导出视频
Posted
技术标签:
【中文标题】使用 AVAssetExportSession 全屏导出视频【英文标题】:Exporting Video in full screen with AVAssetExportSession 【发布时间】:2017-05-09 15:07:16 【问题描述】:我正在尝试为视频制作一些动画(录制后),然后将其导出。 但在任何动画之前,我遇到了方向变成横向的问题(没有导出它是纵向),但没有解决,但现在我无法让它全屏显示。在 iphone 6,7 加上它的全屏在 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
)
【问题讨论】:
你试过AVAssetExportPreset
以外的其他预设吗?
我认为这与您的layercomposition.renderSize
有关,您将其设置为当前视图,因此如果您在手机上运行此操作,iPad 上的输出视频会更小。你可以将renderSize设置为原始视频的大小吗?这可能会奏效。
也许这个比率是通过高度/宽度计算的:让 ratio = size.height / videoTrack.naturalSize.width
@Bluewings 是的,我的问题在于规模的计算
【参考方案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 ?以上是关于使用 AVAssetExportSession 全屏导出视频的主要内容,如果未能解决你的问题,请参考以下文章
使用 AVAssetExportSession 导出 MP3
AVAssetExportSession - 如何从视频持续时间中修剪毫秒