有什么方法可以快速压缩视频?

时间:2019-06-06 06:01:28

标签: ios swift avassetwriter video-compression

我正在使用AVAssetWriter压缩视频,但是将大小为160的视频压缩为12 mb需要20到25秒。我想修复1600 kbps的比特率和自然的视频帧。有什么办法可以快速压缩?

 func compressFile(urlToCompress: URL, outputURL: URL, completion:@escaping (URL)->Void) {
            //video file to make the asset

            var audioFinished = false
            var videoFinished = false

            let asset = AVAsset(url: urlToCompress);

            //create asset reader
            do{
                assetReader = try AVAssetReader(asset: asset)
            } catch{
                assetReader = nil
            }

            guard let reader = assetReader else{
                fatalError("Could not initalize asset reader probably failed its try catch")
            }

            let videoTrack = asset.tracks(withMediaType: AVMediaType.video).first!
            let audioTrack = asset.tracks(withMediaType: AVMediaType.audio).first!

            let videoReaderSettings: [String:Any] =  [(kCVPixelBufferPixelFormatTypeKey as String?)!:kCVPixelFormatType_32ARGB ]

            // MARK: ADJUST BIT RATE OF VIDEO HERE

            let videoSettings:[String:Any] = [
                AVVideoCompressionPropertiesKey: [AVVideoAverageBitRateKey: self.bitrate] as Any,
                AVVideoCodecKey: AVVideoCodecType.h264,
                AVVideoHeightKey: videoTrack.naturalSize.height,//352,
                AVVideoWidthKey: videoTrack.naturalSize.width //640//
            ]


            let assetReaderVideoOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: videoReaderSettings)
            let assetReaderAudioOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: nil)


            if reader.canAdd(assetReaderVideoOutput){
                reader.add(assetReaderVideoOutput)
            }else{
                fatalError("Couldn't add video output reader")
            }

            if reader.canAdd(assetReaderAudioOutput){
                reader.add(assetReaderAudioOutput)
            }else{
                fatalError("Couldn't add audio output reader")
            }

            let audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: nil)
            let videoInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: videoSettings)
            videoInput.transform = videoTrack.preferredTransform
            //we need to add samples to the video input

            let videoInputQueue = DispatchQueue(label: "videoQueue")
            let audioInputQueue = DispatchQueue(label: "audioQueue")

            do{
                assetWriter = try AVAssetWriter(outputURL: outputURL, fileType: AVFileType.mov)
            }catch{
                assetWriter = nil
            }
            guard let writer = assetWriter else{
                fatalError("assetWriter was nil")
            }

            writer.shouldOptimizeForNetworkUse = true
            writer.add(videoInput)
            writer.add(audioInput)


            writer.startWriting()
            reader.startReading()
            writer.startSession(atSourceTime: CMTime.zero)


            let closeWriter:()->Void = {
                if (audioFinished && videoFinished){
                    self.assetWriter?.finishWriting(completionHandler: {

                        self.checkFileSize(sizeUrl: (self.assetWriter?.outputURL)!, message: "The file size of the compressed file is: ")

                        completion((self.assetWriter?.outputURL)!)

                    })

                    self.assetReader?.cancelReading()

                }
            }


            audioInput.requestMediaDataWhenReady(on: audioInputQueue) {
                while(audioInput.isReadyForMoreMediaData){
                    let sample = assetReaderAudioOutput.copyNextSampleBuffer()
                    if (sample != nil){
                        audioInput.append(sample!)
                    }else{
                        audioInput.markAsFinished()
                        DispatchQueue.main.async {
                            audioFinished = true
                            closeWriter()
                        }
                        break;
                    }
                }
            }

            videoInput.requestMediaDataWhenReady(on: videoInputQueue) {
                //request data here

                while(videoInput.isReadyForMoreMediaData){
                    let sample = assetReaderVideoOutput.copyNextSampleBuffer()
                    if (sample != nil){
                        videoInput.append(sample!)
                    }else{
                        videoInput.markAsFinished()
                        DispatchQueue.main.async {
                            videoFinished = true
                            closeWriter()
                        }
                        break;
                    }
                }
            }
        }

编辑:-使用上述方法,它会以不同的比特率而不是定义的比特率转换视频吗?

任何方向都会感激的。

预先感谢

1 个答案:

答案 0 :(得分:1)

这是一个不平凡的问题。对于如何更快地编码,没有“简单”的答案。如果您对此不熟悉,最好选择其他编解码器的比特率和编码速度更快的编解码器。您必须假设库正在完成它的工作。因此,您可以做一些事情:

  1. 使源文件变小-或分块
  2. 在具有更强大硬件的云服务上运行它
  3. 您可以选择其他编解码器和较低的比特率+宽度和高度。 (https://developer.apple.com/documentation/avfoundation/avvideocodectype
  4. 您可能会启动多个线程并以这种方式更快地编码,但我怀疑这样做会为您带来很多好处