2015-09-02 3 views
6

Ich verwende AVMutableComposition und AVAssetExportSession, um ein Video zu schneiden. Zufällig, und ich meine zufällig (ich kann nicht konsequent reproduzieren) Benutzer Videos haben ein paar schwarze Rahmen am Anfang des getrimmten Videos. Das Audio ist nicht betroffen. Ich kann 100% bestätigen, dass die zu beschneidenden Videos nichts damit zu tun haben, da dies für eine Vielzahl von Videos aus verschiedenen Quellen geschieht.AVMutableComposition Video Schwarz beim Start

Jeder Einblick, warum diese Videos am Anfang mit schwarzen Rahmen exportiert werden, wäre sehr willkommen. Vielen Dank!

Einiger entsprechender Code (sorry für die Länge):

// AVURLAssetPreferPreciseDurationAndTimingKey added in attempt to solve issue 
let videoAsset = AVURLAsset(URL: url, options: [AVURLAssetPreferPreciseDurationAndTimingKey: true]) 
var mixComposition = AVMutableComposition() 

let compositionVideoTrack = mixComposition.addMutableTrackWithMediaType(
    AVMediaTypeVideo, 
    preferredTrackID: Int32(kCMPersistentTrackID_Invalid) 
) 
let clipVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] as! AVAssetTrack 
let videoSize = clipVideoTrack.naturalSize 
// startTime and duration are NSTimeInterval types 
let start = startTime == 0 ? kCMTimeZero : CMTimeMakeWithSeconds(startTime, videoAsset.duration.timescale) 
var dur = CMTimeMakeWithSeconds(duration, videoAsset.duration.timescale) 
if dur.value >= videoAsset.duration.value { 

    dur = videoAsset.duration 

} 
compositionVideoTrack.insertTimeRange(
    CMTimeRange(start: start, duration: dur), 
    ofTrack:clipVideoTrack, 
    atTime: kCMTimeZero, 
    error:nil 
) 

compositionVideoTrack.preferredTransform = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0].preferredTransform 

let compositionAudioTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) 
let clipAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack 
compositionAudioTrack.insertTimeRange(
    CMTimeRange(start: start, duration: dur), 
    ofTrack: clipAudioTrack, 
    atTime: kCMTimeZero, 
    error: nil 
) 

let parentLayer = CALayer() 
parentLayer.backgroundColor = UIColor.blackColor().CGColor 
let videoLayer = CALayer() 
videoLayer.backgroundColor = UIColor.blackColor().CGColor 
var parentFrame = CGRect(
    x: 0, 
    y: 0, 
    width: videoSize.width, 
    height: videoSize.height 
) 
if parentFrame.width % 2 > 0 { 
    parentFrame.size.width = parentFrame.size.width - 1 
} 
// Fix crop frame height 
if parentFrame.size.height % 2 > 0 { 
    parentFrame.size.height = parentFrame.size.height - 1 
} 
parentLayer.frame = parentFrame 
videoLayer.frame = CGRect(
    x: 0, 
    y: 0, 
    width: videoSize.width, 
    height: videoSize.height 
) 
parentLayer.addSublayer(videoLayer) 

let videoComp = AVMutableVideoComposition() 
videoComp.renderSize = parentLayer.frame.size 
videoComp.frameDuration = CMTimeMake(1, Int32(clipVideoTrack.nominalFrameRate)) 
videoComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer) 

let instruction = AVMutableVideoCompositionInstruction() 
instruction.timeRange = CMTimeRange(start: kCMTimeZero, duration: mixComposition.duration) 
let videoTrack = mixComposition.tracksWithMediaType(AVMediaTypeVideo)[0] as! AVAssetTrack 
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack) 

layerInstruction.setTransform(CGAffineTransformMakeScale(parentLayer.frame.size.width/videoSize.width, parentLayer.frame.size.height/videoSize.height), atTime: kCMTimeZero) 
instruction.layerInstructions = [layerInstruction] 
videoComp.instructions = [instruction] 

// Export 
let exportSession = AVAssetExportSession(
    asset: mixComposition, 
    presetName: AVAssetExportPresetHighestQuality 
) 
exportSession.videoComposition = videoComp 
let renderFileName = "video.mp4" 
let renderURL = NSURL(fileURLWithPath: NSTemporaryDirectory().stringByAppendingPathComponent(renderFileName)) 
exportSession.outputURL = renderURL 
exportSession.outputFileType = AVFileTypeQuickTimeMovie 
exportSession.exportAsynchronouslyWithCompletionHandler { ... } 
+0

Haben Sie eine Lösung gefunden? –

Antwort

0

Die für uns zu dieser Lösung war nicht zu versuchen, das Video in der gleichen Operation zu beschneiden und zu trimmen. Ich habe immer noch keine Antwort darauf, warum das passiert ist, aber wir konnten es lösen, indem wir zuerst das Video für die Zeit trimmten, und dann, nachdem wir das Video mit der richtigen Dauer hatten, die Crop-Operation darauf ausführte.

Leider glaube ich, dies ist nur ein Fehler im Framework, aber zumindest in unserem Fall waren wir in der Lage, es zu lösen, indem wir weniger in jeder Operation und nur Stringing-Operationen zusammen tun.