0

我正在使用AVAssetWriter压缩视频,但在 12 mb 中压缩大小为 160 的视频需要 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;
                    }
                }
            }
        }

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

任何方向都会不胜感激。

提前致谢

4

1 回答 1

1

这是一个不平凡的问题。如何更快地编码没有“简单”的答案。如果您对此不熟悉,最好选择另一种编解码器比特率和编码速度更快的编解码器。你必须假设图书馆正在做它的工作。所以,你可以做几件事:

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