thelearner
thelearner

Reputation: 1136

Reducing the size of a video exported with AVAssetExportSession - iOS Swift

I'm currently exporting a video in the following way:

   let exporter = AVAssetExportSession.init(asset: mixComposition, presetName: AVAssetExportPreset1280x720)
   exporter?.outputURL = outputPath
   exporter?.outputFileType = AVFileType.mp4
   exporter?.shouldOptimizeForNetworkUse = true
   exporter?.videoComposition = mainCompositionInst

A 15s video consumes about 20MB in data. Comparing this to Snapchat's 2MB videos, this number seems totally unacceptable.

I already reduced the quality of the export- and capture session (1280x720).

The video is filmed on a custom camera. UIImagePickerController is not used.

AVAssetExportSession is used with default settings.

Is there any way I can reduce the size of my videos? Thanks a lot!

EDIT 1: I tried to use this library: https://cocoapods.org/pods/NextLevelSessionExporter

Unfortunately, this creates sizing problems and removes my audio:

// Creating exporter
    let exporter = NextLevelSessionExporter(withAsset: mixComposition)
    exporter.outputURL = outputPath
    exporter.outputFileType = AVFileType.mp4
    exporter.videoComposition = mainCompositionInst

    let compressionDict: [String: Any] = [
        AVVideoAverageBitRateKey: NSNumber(integerLiteral: 2500000),
        AVVideoProfileLevelKey: AVVideoProfileLevelH264BaselineAutoLevel as String,
        ]

        exporter.videoOutputConfiguration = [
            AVVideoCodecKey: AVVideoCodecType.h264,
            AVVideoWidthKey: NSNumber(integerLiteral: 1280),
            AVVideoHeightKey: NSNumber(integerLiteral: 720),
            AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
            AVVideoCompressionPropertiesKey: compressionDict
        ]

        exporter.audioOutputConfiguration = [
            AVFormatIDKey: kAudioFormatMPEG4AAC,
            AVEncoderBitRateKey: NSNumber(integerLiteral: 128000),
            AVNumberOfChannelsKey: NSNumber(integerLiteral: 2),
            AVSampleRateKey: NSNumber(value: Float(44100))
        ]

enter image description here

Upvotes: 4

Views: 6456

Answers (4)

JunHyeon Kim
JunHyeon Kim

Reputation: 59

If you set the fileLengthLimit value, the video bitrate value of the file generated by the exportSession changes. That's exactly what I wanted. If you want to set the video bitrate value of the AVExportSession, calculate and set the fileLengthLimit value of the AVExportSession.

Like this:

exportSession.fileLengthLimit = Int64(Double(preferredBitrate / 8) * video duration)

Thanks Lalit Kumar.

Upvotes: 1

Kousuke Ariga
Kousuke Ariga

Reputation: 801

Lalit Kumar's answer works perfectly. On top of his solution, I wrote an AVAsset extension so that I can easily set the bit rate, as opposed to the file size. The equation in the preferredBitrate method is my original. You could have a hard coded table instead.

extension AVAsset {
    private var preferredBitRate: Float {
        //          720p   1080p
        //  30fps:   5.0    11.3
        //  60fps:   7.5    16.9
        // 120fps:  11.3    25.3
        // 240fps:  16.9    38.0 (Mbps)
        guard let videoTrack = self.tracks(withMediaType: .video).first else {
            return .zero
        }
        let size = Float(min(videoTrack.naturalSize.width, videoTrack.naturalSize.height))
        let frameRate = videoTrack.nominalFrameRate
        return pow(1.5, log2(frameRate / 30)) * pow(size / 720, 2) * 5
    }

    private var preferredFileLength: Int64 {
        // 1 Mbit := 125000 bytes
        return Int64(self.duration.seconds * Double(self.preferredBitRate)) * 125000
    }
}

Upvotes: 2

Kumar
Kumar

Reputation: 1942

cracked this finally.

Use exportSession.fileLengthLimit = 1048576 * 10 //10 MB

10MB is hard coded number. Use according to your required bitrate.

fileLengthLimit /* Indicates the file length that the output of the session should not exceed. Depending on the content of the source asset, it is possible for the output to slightly exceed the file length limit. The length of the output file should be tested if you require that a strict limit be observed before making use of the output. See also maxDuration and timeRange. */

Upvotes: 7

Andy Jazz
Andy Jazz

Reputation: 58093

To reduce file size try these properties for setting up HEVC codec (use cocoa pod NextLevelSessionExporter):

let compressionDict: [String: Any] = [
AVVideoAverageBitRateKey: NSNumber(integerLiteral: 2500000), //lower it if you wish
AVVideoProfileLevelKey: AVVideoProfileLevelH264BaselineAutoLevel as String,
]
exporter.videoOutputConfiguration = [
    AVVideoCodecKey : AVVideoCodecType.hevc,
    AVVideoWidthKey : NSNumber(integerLiteral: 1280),
    AVVideoHeightKey: NSNumber(integerLiteral: 720),
    AVVideoScalingModeKey: AVVideoScalingModeResizeAspectFill,
    AVVideoCompressionPropertiesKey: compressionDict
]

You need to upgrade to macOS High Sierra and iOS 11 in order to use HEVC video codec. But if you can't use HEVC for some reason, use regular H.264 with lower bitrate.

AVVideoCodecKey : AVVideoCodecType.h264:

enter image description here

Also, look at this SO post about video bitrate in iOS.

Upvotes: 9

Related Questions