ran*_*dom 9 camera orientation ios avassetexportsession swift
我正在尝试将图像和视频结合起来.我将它们组合并输出但是它是旋转的侧面方式.
很抱歉批量代码粘贴.我已经看到了关于应用变换的答案,compositionVideoTrack.preferredTransform但是什么也没做.添加AVMutableVideoCompositionInstruction也没有做任何事情.
我觉得这个区域是事情开始出错的地方.这儿这儿:
// I feel like this loading here is the problem
let videoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
// because it makes our parentLayer and videoLayer sizes wrong
let videoSize = videoTrack.naturalSize
// this is returning 1920x1080, so it is rotating the video
print("\(videoSize.width) , \(videoSize.height)")
Run Code Online (Sandbox Code Playgroud)
所以在这里我们的帧大小对于该方法的其余部分是错误的.现在,当我们尝试去创建叠加图像层时,框架不正确:
let aLayer = CALayer()
aLayer.contents = UIImage(named: "OverlayTestImageOverlay")?.CGImage
aLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
aLayer.opacity = 1
Run Code Online (Sandbox Code Playgroud)
这是我完整的方法.
func combineImageVid() {
let path = NSBundle.mainBundle().pathForResource("SampleMovie", ofType:"MOV")
let fileURL = NSURL(fileURLWithPath: path!)
let videoAsset = AVURLAsset(URL: fileURL)
let mixComposition = AVMutableComposition()
let compositionVideoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
var clipVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)
do {
try compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), ofTrack: clipVideoTrack[0], atTime: kCMTimeZero)
}
catch _ {
print("failed to insertTimeRange")
}
compositionVideoTrack.preferredTransform = videoAsset.preferredTransform
// I feel like this loading here is the problem
let videoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
// because it makes our parentLayer and videoLayer sizes wrong
let videoSize = videoTrack.naturalSize
// this is returning 1920x1080, so it is rotating the video
print("\(videoSize.width) , \(videoSize.height)")
let aLayer = CALayer()
aLayer.contents = UIImage(named: "OverlayTestImageOverlay")?.CGImage
aLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
aLayer.opacity = 1
let parentLayer = CALayer()
let videoLayer = CALayer()
parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(aLayer)
let videoComp = AVMutableVideoComposition()
videoComp.renderSize = videoSize
videoComp.frameDuration = CMTimeMake(1, 30)
videoComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)
let mixVideoTrack = mixComposition.tracksWithMediaType(AVMediaTypeVideo)[0]
mixVideoTrack.preferredTransform = CGAffineTransformMakeRotation(CGFloat(M_PI * 90.0 / 180))
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: mixVideoTrack)
instruction.layerInstructions = [layerInstruction]
videoComp.instructions = [instruction]
// create new file to receive data
let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docsDir: AnyObject = dirPaths[0]
let movieFilePath = docsDir.stringByAppendingPathComponent("result.mov")
let movieDestinationUrl = NSURL(fileURLWithPath: movieFilePath)
do {
try NSFileManager.defaultManager().removeItemAtPath(movieFilePath)
}
catch _ {}
// use AVAssetExportSession to export video
let assetExport = AVAssetExportSession(asset: mixComposition, presetName:AVAssetExportPresetHighestQuality)
assetExport?.videoComposition = videoComp
assetExport!.outputFileType = AVFileTypeQuickTimeMovie
assetExport!.outputURL = movieDestinationUrl
assetExport!.exportAsynchronouslyWithCompletionHandler({
switch assetExport!.status{
case AVAssetExportSessionStatus.Failed:
print("failed \(assetExport!.error)")
case AVAssetExportSessionStatus.Cancelled:
print("cancelled \(assetExport!.error)")
default:
print("Movie complete")
// play video
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
print(movieDestinationUrl)
})
}
})
}
Run Code Online (Sandbox Code Playgroud)
我尝试添加这两种方法来旋转视频:
class func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction {
let instruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
let assetTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
let transform = assetTrack.preferredTransform
let assetInfo = orientationFromTransform(transform)
var scaleToFitRatio = UIScreen.mainScreen().bounds.width / assetTrack.naturalSize.width
if assetInfo.isPortrait {
scaleToFitRatio = UIScreen.mainScreen().bounds.width / assetTrack.naturalSize.height
let scaleFactor = CGAffineTransformMakeScale(scaleToFitRatio, scaleToFitRatio)
instruction.setTransform(CGAffineTransformConcat(assetTrack.preferredTransform, scaleFactor),
atTime: kCMTimeZero)
} else {
let scaleFactor = CGAffineTransformMakeScale(scaleToFitRatio, scaleToFitRatio)
var concat = CGAffineTransformConcat(CGAffineTransformConcat(assetTrack.preferredTransform, scaleFactor), CGAffineTransformMakeTranslation(0, UIScreen.mainScreen().bounds.width / 2))
if assetInfo.orientation == .Down {
let fixUpsideDown = CGAffineTransformMakeRotation(CGFloat(M_PI))
let windowBounds = UIScreen.mainScreen().bounds
let yFix = assetTrack.naturalSize.height + windowBounds.height
let centerFix = CGAffineTransformMakeTranslation(assetTrack.naturalSize.width, yFix)
concat = CGAffineTransformConcat(CGAffineTransformConcat(fixUpsideDown, centerFix), scaleFactor)
}
instruction.setTransform(concat, atTime: kCMTimeZero)
}
return instruction
}
class func orientationFromTransform(transform: CGAffineTransform) -> (orientation: UIImageOrientation, isPortrait: Bool) {
var assetOrientation = UIImageOrientation.Up
var isPortrait = false
if transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0 {
assetOrientation = .Right
isPortrait = true
} else if transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0 {
assetOrientation = .Left
isPortrait = true
} else if transform.a == 1.0 && transform.b == 0 && transform.c == 0 && transform.d == 1.0 {
assetOrientation = .Up
} else if transform.a == -1.0 && transform.b == 0 && transform.c == 0 && transform.d == -1.0 {
assetOrientation = .Down
}
return (assetOrientation, isPortrait)
}
Run Code Online (Sandbox Code Playgroud)
更新我的combineImageVid()方法添加此内容
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)
let mixVideoTrack = mixComposition.tracksWithMediaType(AVMediaTypeVideo)[0]
//let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: mixVideoTrack)
//layerInstruction.setTransform(videoAsset.preferredTransform, atTime: kCMTimeZero)
let layerInstruction = videoCompositionInstructionForTrack(compositionVideoTrack, asset: videoAsset)
Run Code Online (Sandbox Code Playgroud)
这给了我这个输出:
所以我越来越近,但是我觉得因为赛道原本是以错误的方式装载的,所以我需要解决那里的问题.另外,我不知道为什么现在有巨大的黑匣子.我想也许是因为我的图像层在这里占用了加载的视频资产的界限:
aLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
Run Code Online (Sandbox Code Playgroud)
然而,将其改为一些小宽度/高度并没有什么区别.然后我考虑添加一个作物rec以摆脱黑色方块,但这也不起作用:(
根据Allens建议不使用这两种方法:
class func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction
class func orientationFromTransform(transform: CGAffineTransform) -> (orientation: UIImageOrientation, isPortrait: Bool)
Run Code Online (Sandbox Code Playgroud)
但更新我的原始方法看起来像这样:
videoLayer.frame = CGRectMake(0, 0, videoSize.height, videoSize.width) //notice the switched width and height
...
videoComp.renderSize = CGSizeMake(videoSize.height,videoSize.width) //this make the final video in portrait
...
layerInstruction.setTransform(videoTrack.preferredTransform, atTime: kCMTimeZero) //important piece of information let composition know you want to rotate the original video in output
Run Code Online (Sandbox Code Playgroud)
我们已经非常接近,但现在问题似乎是编辑renderSize.如果我将其更改为横向尺寸以外的任何其他尺寸,我会得到:
All*_*len 16
这是Apple的定位文件:
https://developer.apple.com/library/ios/qa/qa1744/_index.html
如果你的原始视频是在iOS模式下拍摄的,它的自然尺寸仍然是风景,但它带有mov文件中的旋转元数据.要旋转视频,您需要使用以下代码更改第1段代码:
videoLayer.frame = CGRectMake(0, 0, videoSize.height, videoSize.width) //notice the switched width and height
...
videoComp.renderSize = CGSizeMake(videoSize.height,videoSize.width) //this make the final video in portrait
...
layerInstruction.setTransform(videoTrack.preferredTransform, atTime: kCMTimeZero) //important piece of information let composition know you want to rotate the original video in output
Run Code Online (Sandbox Code Playgroud)
是的,你真的很亲密!
| 归档时间: |
|
| 查看次数: |
2791 次 |
| 最近记录: |