美文网首页
swift 视频合并高质量小体积压缩

swift 视频合并高质量小体积压缩

作者: 秋叶红90 | 来源:发表于2020-07-09 10:14 被阅读0次
//
//  WMVideoExporter.swift
//  WMVideo
//
//  Created by wumeng on 2019/11/25.
//  Copyright © 2019 wumeng. All rights reserved.
//

import AVKit

class WMVideoExporter: NSObject {
    
    var composition: AVMutableComposition?
    var videoComposition: AVMutableVideoComposition?
    var outputUrl: String?
    
    override init() {
        super.init()
    }
    
    func exportVideo(completeHandler: @escaping (String) -> ()) {
        guard let videoComposition = videoComposition,
            let composition = composition,
            let outputUrl = outputUrl else { return }
        
        let videoSize = videoComposition.renderSize
        
        guard let assetReader = try? AVAssetReader.init(asset: composition),
            let assetWriter = try? AVAssetWriter.init(outputURL: URL.init(fileURLWithPath: outputUrl), fileType: .mov)else { return }
        let pixelNumber = 1000000
//        let pixelNumber = 3 * videoSize.height * videoSize.width
        let compressionProperties = [
            AVVideoProfileLevelKey: AVVideoProfileLevelH264MainAutoLevel,
            AVVideoAllowFrameReorderingKey: false,
            AVVideoExpectedSourceFrameRateKey: 30,
            AVVideoMaxKeyFrameIntervalKey: 30,
            AVVideoAverageBitRateKey: pixelNumber
            ] as [String : Any]
        let outputSettings = [
            AVVideoCodecKey: AVVideoCodecType.h264,
            AVVideoWidthKey: videoSize.width,
            AVVideoHeightKey: videoSize.height ,
            AVVideoCompressionPropertiesKey: compressionProperties
            ] as [String : Any]
        
        let assetWriterVideoInput = AVAssetWriterInput.init(mediaType: .video, outputSettings: outputSettings)
        assetWriterVideoInput.expectsMediaDataInRealTime = true
        if assetWriter.canAdd(assetWriterVideoInput) {
            assetWriter.add(assetWriterVideoInput)
        }
        
        let audioOutputSettings = [
            AVFormatIDKey: kAudioFormatMPEG4AAC,
            AVEncoderBitRatePerChannelKey: 28000,
            AVSampleRateKey: 22050,
            AVNumberOfChannelsKey: 1]
        
        let assetWriterAudioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioOutputSettings)
        assetWriterAudioInput.expectsMediaDataInRealTime = true
        if assetWriter.canAdd(assetWriterAudioInput) {
            assetWriter.add(assetWriterAudioInput)
        }
        let readerVideoOutput = AVAssetReaderVideoCompositionOutput.init(videoTracks: composition.tracks(withMediaType: .video), videoSettings: nil)
        readerVideoOutput.videoComposition = videoComposition
        readerVideoOutput.alwaysCopiesSampleData = false
        if assetReader.canAdd(readerVideoOutput) {
            assetReader.add(readerVideoOutput)
        }
        
        let readerAudioOutput = AVAssetReaderAudioMixOutput.init(audioTracks: composition.tracks(withMediaType: .audio), audioSettings: nil)
        readerAudioOutput.alwaysCopiesSampleData = false
        if assetReader.canAdd(readerAudioOutput) {
            assetReader.add(readerAudioOutput)
        }
        
        assetReader.startReading()
        assetWriter.startWriting()
        assetWriter.startSession(atSourceTime: CMTime.zero)
        
        var videoComplete = false
        var audioComplete = false
        
        let finishBlock = {
            assetWriter.finishWriting {
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3, execute: {
                    completeHandler(outputUrl)
                })
            }
        }
        
        assetWriterVideoInput.requestMediaDataWhenReady(on: DispatchQueue(label: "videoOutQueue")) {
            while (assetWriterVideoInput.isReadyForMoreMediaData && assetReader.status == .reading) {
                guard let sampleBuffer = readerVideoOutput.copyNextSampleBuffer() else {
                    assetWriterVideoInput.markAsFinished()
                    videoComplete = true
                    if audioComplete {
                        finishBlock()
                    }
                    return
                }
                assetWriterVideoInput.append(sampleBuffer)
            }
        }
        
        assetWriterAudioInput.requestMediaDataWhenReady(on: DispatchQueue(label: "voiceOutQueue")) {
            while (assetWriterAudioInput.isReadyForMoreMediaData && assetReader.status == .reading) {
                guard let sampleBuffer = readerAudioOutput.copyNextSampleBuffer() else {
                    assetWriterAudioInput.markAsFinished()
                    audioComplete = true
                    if videoComplete {
                        finishBlock()
                    }
                    return
                }
                assetWriterAudioInput.append(sampleBuffer)
            }
        }
    }
    
}


相关文章

网友评论

      本文标题:swift 视频合并高质量小体积压缩

      本文链接:https://www.haomeiwen.com/subject/syrjcktx.html