Skip to content

Instantly share code, notes, and snippets.

@lisp-ceo
Created July 17, 2017 06:02
Show Gist options
  • Save lisp-ceo/848a78e69b9cd2202dfef9b843d2bd4b to your computer and use it in GitHub Desktop.
Save lisp-ceo/848a78e69b9cd2202dfef9b843d2bd4b to your computer and use it in GitHub Desktop.
Swift function to compress and multiple video and audio to H264
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