Уменьшите частоту кадров видео, чтобы получить ощущение GIF в Swift.

Я пытался снизить частоту кадров видео до 10 или 15 кадров в секунду. Есть некоторые вопросы, связанные с OBJC, возникшие 4/5 лет назад. В быстром ничего не нашел..

Вот над чем я работаю на Playground:

import Cocoa
import AVKit


var assetWriter:AVAssetWriter?
var assetReader:AVAssetReader?
let bitrate:NSNumber = NSNumber(value:8000000)

func compressFile(urlToCompress: URL, outputURL: URL, completion:@escaping (URL)->Void){

    var videoFinished = false

    let asset = AVAsset(url: urlToCompress);

    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 videoReaderSettings: [String:Any] =  [(kCVPixelBufferPixelFormatTypeKey as String?)!:kCVPixelFormatType_32ARGB ]

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

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

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

    let videoInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: videoSettings)
    videoInput.transform = videoTrack.preferredTransform

    let videoInputQueue = DispatchQueue(label: "videoQueue")

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

    writer.shouldOptimizeForNetworkUse = true
    writer.add(videoInput)


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


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

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

            })

            assetReader?.cancelReading()

        }
    }

    videoInput.requestMediaDataWhenReady(on: videoInputQueue) {
        while(videoInput.isReadyForMoreMediaData){
            let sample = assetReaderVideoOutput.copyNextSampleBuffer()

            if (sample != nil){
                videoInput.append(sample!)
            }else{
                videoInput.markAsFinished()

                DispatchQueue.main.async {
                    videoFinished = true
                    closeWriter()
                }
                break;
            }
        }

    }


}

func checkFileSize(sizeUrl: URL, message:String){
    let data = NSData(contentsOf: sizeUrl)!
    print(message, (Double(data.length) / 1048576.0), " mb")
}


compressFile(urlToCompress: URL(fileURLWithPath: "/Users/koraybirand/Desktop/video.mp4"), outputURL: URL(fileURLWithPath: "/Users/koraybirand/Desktop/video5.mp4")) { (URL) in

}

person Koray Birand    schedule 24.05.2019    source источник


Ответы (2)


Попробуйте добавить AVVideoAverageNonDroppableFrameRateKey в настройках видео

person Francesco Mattiussi    schedule 24.05.2019
comment
уже пробовал. CMSampleBufferCreateCopyWithNewTiming - это решение, но не удалось - person Koray Birand; 25.05.2019
comment
вы получаете: Словарь настроек вывода содержит один или несколько недопустимых ключей: AverageNonDroppableFrameRate - person Koray Birand; 25.05.2019

Только что использовал NextLevelSessionExporter... Утверждается, что он предназначен только для IOS, но работает и на Mac Os X... Просто измените:

internal func createVideoComposition()
.......
videoComposition.frameDuration = CMTimeMake(value: 1, timescale: Int32(frameRate))

замените frameRate на желаемое значение

person Koray Birand    schedule 26.05.2019