2015-12-10 7 views
10

Я записал видео с Фронтальная камера и выход отражается ...Как перевернуть видео с помощью AVFoundation

Я попытался с помощью AVMutablecompositionlayerinstructions и переворачивать видео, но не повезло.

Поиск в Google и поиск переполнения стека были бесплодными, поэтому, я уверен, простой, прямой пример того, как это сделать, - это то, что принесет пользу многим.

+0

Если вы используете AVCaptureConnection для записи, я бы исправить проблему там, устанавливая видео Ориентация с помощью 'setVideoOrientation' – Lefteris

ответ

13

Theres никаких указаний на то, что вы используете для записи видео, больной не берут на себя AVCaptureSession + AVCaptureVideoDataOutput

lazy var videoFileOutput: AVCaptureVideoDataOutput = AVCaptureVideoDataOutput() 
let v = videoFileOutput.connectionWithMediaType(AVMediaTypeVideo) 
v.videoOrientation = .Portrait 
v.videoMirrored = true 
7

Вы можете использовать -[AVMutableVideoCompositionLayerInstruction setTransform:atTime:]

CGAffineTransform transform = CGAffineTransformMakeTranslation(self.config.videoSize, 0); 
transform = CGAffineTransformScale(transform, -1.0, 1.0); 
[videoCompositionLayerInstruction setTransform:transform atTime:videoTime]; 

// then append video tracks 
// [compositionTrack insertTimeRange:timeRange ofTrack:track atTime:atTime error:&error]; 

// apply instructions 
videoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration); 
videoCompositionInstruction.layerInstructions = @[videoCompositionLayerInstruction]; 

videoComposition = [AVMutableVideoComposition videoComposition]; 
videoComposition.renderSize = CGSizeMake(self.config.videoSize, self.config.videoSize); 
videoComposition.frameDuration = CMTimeMake(1, self.config.videoFrameRate); 
videoComposition.instructions = @[videoCompositionInstruction]; 

https://github.com/ElfSundae/AVDemo/tree/ef2ca437d0d8dcb3dd41c5a272c8754a29d8a936/AVSimpleEditoriOS

Экспорт состав:

AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:composition presetName:presetName]; 
exportSession.outputFileType = AVFileTypeMPEG4; 
exportSession.outputURL = outputURL; 
exportSession.shouldOptimizeForNetworkUse = YES; 
// videoComposition contains transform instructions for video tracks 
exportSession.videoComposition = videoComposition; 
// audioMix contains background music for audio tracks 
exportSession.audioMix = audioMix; 

[exportSession exportAsynchronouslyWithCompletionHandler:^{ 
    AVAssetExportSessionStatus status = exportSession.status; 
    if (status != AVAssetExportSessionStatusCompleted) { 
     // exportSession.error 
    } else { 
     // exportSession.outputURL 
    } 
}]; 
+0

Спасибо за ваш пример - и как бы вы экспортировали эту композицию в видео? – PinkFloydRocks

+0

@PinkFloydRocks Я использую AVAssetExportSession, ответ был обновлен. –

+0

CGAffineTransformMakeTranslation (self.config.videoSize, 0); , Для этого требуется значение CGFloat, а не значение CGSize. Не знаю, как вы получили этот код для работы и опубликовать его здесь. –

0

После вы получите ваш выход преобразования видео

func mirrorVideo(inputURL: URL, completion: @escaping (_ outputURL : URL?) ->()) 
{ 
    let videoAsset: AVAsset = AVAsset(url: inputURL) 
    let clipVideoTrack = videoAsset.tracks(withMediaType: AVMediaType.video).first! as AVAssetTrack 

    let composition = AVMutableComposition() 
    composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID()) 

    let videoComposition = AVMutableVideoComposition() 
    videoComposition.renderSize = CGSize(width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.width) 
    videoComposition.frameDuration = CMTimeMake(1, 30) 

    let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack) 

    let instruction = AVMutableVideoCompositionInstruction() 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30)) 
    var transform:CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0) 
    transform = transform.translatedBy(x: -clipVideoTrack.naturalSize.width, y: 0.0) 
    transform = transform.rotated(by: CGFloat(Double.pi/2)) 
    transform = transform.translatedBy(x: 0.0, y: -clipVideoTrack.naturalSize.width) 

    transformer.setTransform(transform, at: kCMTimeZero) 

    instruction.layerInstructions = [transformer] 
    videoComposition.instructions = [instruction] 

    // Export 

    let exportSession = AVAssetExportSession(asset: videoAsset, presetName: AVAssetExportPreset640x480)! 
    let fileName = UniqueIDGenerator.generate().appending(".mp4") 
    let filePath = documentsURL.appendingPathComponent(fileName) 
    let croppedOutputFileUrl = filePath 
    exportSession.outputURL = croppedOutputFileUrl 
    exportSession.outputFileType = AVFileType.mp4 
    exportSession.videoComposition = videoComposition 
    exportSession.exportAsynchronously { 
     if exportSession.status == .completed { 
      DispatchQueue.main.async(execute: { 
       completion(croppedOutputFileUrl) 
      }) 
      return 
     } else if exportSession.status == .failed { 
      print("Export failed - \(String(describing: exportSession.error))") 
     } 

     completion(nil) 
     return 
    } 
}