Created
July 17, 2017 06:02
-
-
Save lisp-ceo/848a78e69b9cd2202dfef9b843d2bd4b to your computer and use it in GitHub Desktop.
Swift function to compress and multiple video and audio to H264
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static func compressVideo(inputURL: URL, outputURL: URL) -> Promise<URL> { | |
let videoAsset = AVURLAsset(url: inputURL, options: nil) | |
return Promise<URL> { fulfill, reject in | |
guard let videoTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo).first else { | |
reject(AVServiceError.noDataFound) | |
return | |
} | |
guard let audioTrack = videoAsset.tracks(withMediaType: AVMediaTypeAudio).first else { | |
reject(AVServiceError.noDataFound) | |
return | |
} | |
do { | |
let videoSize: CGSize = videoTrack.naturalSize | |
// Video Writer | |
let compressionSettings: [String: Any] = [ | |
AVVideoCodecKey: AVVideoCodecH264, | |
AVVideoCompressionPropertiesKey: [AVVideoAverageBitRateKey: 2500000], | |
AVVideoWidthKey: min(1920.0, videoSize.width), | |
AVVideoHeightKey: min(1080.0, videoSize.height) | |
] | |
let videoWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: compressionSettings) | |
videoWriterInput.expectsMediaDataInRealTime = true | |
videoWriterInput.transform = videoTrack.preferredTransform | |
let videoWriter = try AVAssetWriter(outputURL: outputURL, fileType: AVFileTypeQuickTimeMovie) | |
videoWriter.add(videoWriterInput) | |
// Video Reader | |
let videoReaderSettings: [String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: NSNumber(value: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)] | |
let videoReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: videoReaderSettings) | |
let videoReader = try AVAssetReader(asset: videoAsset) | |
videoReader.add(videoReaderOutput) | |
// Audio Writer | |
let audioWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeAudio, outputSettings: nil) | |
audioWriterInput.expectsMediaDataInRealTime = false | |
videoWriter.add(audioWriterInput) | |
// Audio Reader | |
let audioReaderOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: nil) | |
let audioReader = try AVAssetReader(asset: videoAsset) | |
audioReader.add(audioReaderOutput) | |
videoWriter.startWriting() | |
videoReader.startReading() | |
videoWriter.startSession(atSourceTime: kCMTimeZero) | |
// Start Writing From Video Reader | |
let processingQueue = DispatchQueue(label: "video_compression_queue") | |
videoWriterInput.requestMediaDataWhenReady(on: processingQueue, using: { | |
while(videoWriterInput.isReadyForMoreMediaData) { | |
if videoReader.status == .reading, let sampleBuffer = videoReaderOutput.copyNextSampleBuffer() { | |
videoWriterInput.append(sampleBuffer) | |
} else { | |
videoWriterInput.markAsFinished() | |
if(videoReader.status == .completed) { | |
// Start Writing From Audio Reader | |
audioReader.startReading() | |
videoWriter.startSession(atSourceTime: kCMTimeZero) | |
let audio_queue = DispatchQueue(label: "audio_compression_queue") | |
audioWriterInput.requestMediaDataWhenReady(on: audio_queue, using: { | |
while(audioWriterInput.isReadyForMoreMediaData) { | |
if audioReader.status == .reading, let sampleBuffer = audioReaderOutput.copyNextSampleBuffer() { | |
audioWriterInput.append(sampleBuffer) | |
} else { | |
audioWriterInput.markAsFinished() | |
if audioReader.status == .completed { | |
videoWriter.finishWriting(completionHandler: { | |
fulfill(outputURL) | |
}) | |
} | |
} | |
} | |
}) | |
} | |
} | |
} | |
}) | |
} catch { | |
reject(error) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment