मैं एक छवि और एक वीडियो को गठबंधन करने का प्रयास कर रहा हूं। मैंने उन्हें संयोजित और निर्यात किया है, हालांकि यह घुमावदार साइड तरीकों से घिरा हुआ है।AVFoundation निर्यात अभिविन्यास गलत
थोक कोड पेस्ट के लिए खेद है। मैंने 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)")
तो यहां तक कि हमारे फ्रेम आकार शेष विधि के लिए गलत हैं। अब जब हम ओवरले छवि परत को जाने और बनाने का प्रयास करते हैं तो फ्रेम सही नहीं है:
let aLayer = CALayer()
aLayer.contents = UIImage(named: "OverlayTestImageOverlay")?.CGImage
aLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
aLayer.opacity = 1
यहां मेरी पूरी विधि है।
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)
})
}
})
}
यह है कि मैं क्या निर्यात हो रही है:
मैं वीडियो बारी बारी से करने के लिए इन दोनों तरीकों जोड़ने का प्रयास:
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)
}
अद्यतन मेरी 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)
में जोड़ना
कौन मुझे इस उत्पादन देता है:
तो मैं करीब हो रही है लेकिन मुझे लगता है कि क्योंकि ट्रैक मूल रूप से गलत तरीके से लोड किया जा रहा है, मैं वहाँ समस्या को हल करने की जरूरत है लग रहा है। इसके अलावा, मुझे नहीं पता कि अब विशाल ब्लैक बॉक्स क्यों है। मैं शायद सोचा था कि यह लोड वीडियो संपत्ति यहाँ की सीमा से ले रही है मेरी छवि परत की वजह से था:
aLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height)
हालांकि कुछ छोटे चौड़ाई/ऊंचाई है कि बदलते एक फर्क नहीं है। मैं तो काला वर्ग से छुटकारा पाने के लिए एक फसल आरईसी जोड़ने के बारे में सोचा था, लेकिन है कि या तो काम नहीं किया :(
इन दोनों तरीकों का इस्तेमाल नहीं की Allens सुझाव के बाद:
class func videoCompositionInstructionForTrack(track: AVCompositionTrack, asset: AVAsset) -> AVMutableVideoCompositionLayerInstruction
class func orientationFromTransform(transform: CGAffineTransform) -> (orientation: UIImageOrientation, isPortrait: Bool)
लेकिन अद्यतन करने अपने मूल विधि इस तरह देखने के लिए:
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
हम वास्तव में समाप्त होने वाला है लेकिन समस्या अब संपादन के लिए renderSize
लगता है।अगर मैं परिदृश्य आकार के अलावा और कुछ के लिए इसे बदल मैं इस मिल:
यहाँ इस लिंक से आपको मदद कर सकता है http://stackoverflow.com/questions/10034337/how-to- निर्यात-वीडियो-एसेट-थ्रू-एवासेटेटपोर्टेशन-इन-पोर्ट्रेट-मोड –
मैंने यह भी कोशिश की है :(हालांकि मैं सुझाव की सराहना करता हूं। – random
क्या आप इसे गठबंधन में बदलने की कोशिश कर सकते हैं ImageVid() विधि --- compositionVideoTrack.preferredTransform = CGAffineTransformMakeRotation (M_PI_2); –