Есть ли способ быстро сжать видео? - PullRequest
0 голосов
/ 06 июня 2019

Я использую AVAssetWriter для сжатия видео, но сжатие видео размером 160 в 12 МБ заняло от 20 до 25 секунд.Я хочу исправить битрейт 1600 кбит / с и естественный кадр видео.Есть ли способ быстро сжать?

 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 Ответ

1 голос
/ 06 июня 2019

Это нетривиальная проблема.Не существует «простого» ответа на вопрос, как кодировать быстрее.Если вы не знакомы с этим, вам лучше выбрать другие скорости кодеков и кодеки, которые кодируют быстрее.Вы должны предположить, что библиотека делает свою работу.Итак, есть несколько вещей, которые вы можете сделать:

  1. Уменьшить исходный файл - или разбить его на части
  2. Запустить его в облачной службе с более мощным оборудованием
  3. Вы можете выбрать другой кодек и меньший набор битрейта + ширина и высота.(https://developer.apple.com/documentation/avfoundation/avvideocodectype)
  4. Вы можете потенциально раскручивать несколько потоков и быстрее кодировать таким образом, но я сомневаюсь, что это принесет вам большую пользу
...