2016-12-24 84 views
0

我想調整我的ios應用程序中的視頻大小。我的代碼如下:ios - 視頻調整大小不尊重請求的大小

fileprivate func resize(url: URL, height: CGFloat, completion: @escaping ((URL) -> Void)) { 
    let video = AVAsset(url: url) 
    guard let track = video.tracks(withMediaType: AVMediaTypeVideo).first 
    else { return } 
    let size = track.naturalSize 

    // detect video rotation 
    let txf = track.preferredTransform 
    let videoAngle = atan2(txf.b, txf.a) 
    let isRotated = videoAngle == CGFloat(M_PI_2) || videoAngle == CGFloat(M_PI_2 * 3) 
    let videoW = isRotated ? size.height : size.width 
    let videoH = isRotated ? size.width : size.height 
    // get output width that keeps aspect ratio 
    let width = height/videoH * videoW 

    print("desired width \(width) height \(height)") 
    print("original width \(size.width) height \(size.height)") 

    // resize the video 
    let videoComposition = AVMutableVideoComposition() 
    videoComposition.renderSize = CGSize(width: width, height: height) 
    videoComposition.frameDuration = CMTimeMake(1, 30) 
    let instruction = AVMutableVideoCompositionInstruction() 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, video.duration) 
    videoComposition.instructions = [instruction] 
    let outputURL = Constants.cacheDirectory.appendingPathComponent(
    "\(String.random(ofLength: 10)).mp4") 

    guard let exporter = AVAssetExportSession(
    asset: video, 
    presetName: AVAssetExportPresetMediumQuality 
) else { return } 
    exporter.videoComposition = videoComposition 
    exporter.outputURL = outputURL 
    exporter.outputFileType = AVFileTypeQuickTimeMovie 

    exporter.exportAsynchronously(completionHandler: {() -> Void in 
    DispatchQueue.main.async { 
     let asset = AVAsset(url: outputURL) 
     let track = asset.tracks(withMediaType: AVMediaTypeVideo).first! 
     print("result size \(track.naturalSize)") 
     completion(outputURL) 
    } 
    }) 
} 

當我的影片,爲1280.0 x 720.0,並具有90度的旋轉打電話resize720高度,我得到的結果是320.0 x 568.0和我的日誌:

desired width 405.0 height 720.0 
original width 1280.0 height 720.0 
result size (320.0, 568.0) 

我甚至找不到這些數字來自哪裏的關係。唯一的問題是寬高比保持不變。

+0

您在使用iPhone 5或5S? –

+0

沒有iPhone 6.它有什麼關係? – Guig

+0

結果大小(320.0,568.0)此尺寸適用於iphone 5和5s –

回答

1

我最終採取了另一種方式,因爲視頻調整大小似乎要複雜得多,它應該在iOS上。 SDAVAssetExportSession在處理所有這些方面做得非常出色,如果你看一下code,那就有很多事情要做。

不管怎麼說,我最終的代碼如下所示:

import SDAVAssetExportSession 

fileprivate func resize(url: URL, height: CGFloat, completion: @escaping ((Error?) -> Void)) { 
    let video = AVAsset(url: url) 

    guard let track = video.tracks(withMediaType: AVMediaTypeVideo).first 
    else { return } 
    let size = track.naturalSize 

    let txf = track.preferredTransform 
    let videoAngle = atan2(txf.b, txf.a) 
    let isRotated = videoAngle == CGFloat(M_PI_2) || videoAngle == CGFloat(M_PI_2 * 3) 
    let videoW = isRotated ? size.height : size.width 
    let videoH = isRotated ? size.width : size.height 
    let width = height/videoH * videoW 

    let outputURL = Constants.cacheDirectory.appendingPathComponent(
    "\(String.random(ofLength: 10)).mp4") 

    if let encoder = SDAVAssetExportSession(asset: AVAsset(url: url)) { 
    encoder.outputFileType = AVFileTypeMPEG4 
    encoder.outputURL = outputURL 
    encoder.videoSettings = [ 
     AVVideoCodecKey: AVVideoCodecH264, 
     AVVideoWidthKey: width, 
     AVVideoHeightKey: height, 
     AVVideoCompressionPropertiesKey: [ 
     AVVideoAverageBitRateKey: 1000000, 
     AVVideoProfileLevelKey: AVVideoProfileLevelH264High40, 
     AVVideoMaxKeyFrameIntervalKey: 60, 
     ], 
    ] 

    encoder.exportAsynchronously(completionHandler: { 
     if encoder.status == AVAssetExportSessionStatus.completed { 
     DispatchQueue.main.async { 
      self.url = outputURL 
      let asset = AVAsset(url: outputURL) 
      let track = asset.tracks(withMediaType: AVMediaTypeVideo).first! 
      completion(nil) 
     } 
     } else if encoder.status == AVAssetExportSessionStatus.cancelled { 
     completion(nil) 
     } else { 
     completion(encoder.error) 
     } 
    }) 
    } 
}