美文网首页
Metal导出视频压缩大小方案

Metal导出视频压缩大小方案

作者: 王方帅 | 来源:发表于2021-07-20 16:26 被阅读0次
    1. 实际测试发现,默认视频导出的情况下自定义分辨率时码率较高,但很多分辨率根本不需要设置那么高的码率即可满足需求,设置码率太高会导致导出视频过大,浪费了磁盘空间。
    2. 现有两种方案设置视频导出的码率,经测试发现,原导出19MB的视频,用方案二导出时仅占用4.6MB,且肉眼看不出明显区别。

    方案一:
    采用AVAssetReader和AVAssetWriter边读视频边写本地的方式,支持修改视频码率。
    https://www.jianshu.com/p/4f69c22c6dce
    对应的swift版本我已经翻译出来了,见
    https://github.com/wangfangshuai/SDAVAssetExportSession中的SDAVAssetExportSession.swift文件。

    方案二:
    写一个根据码率及不同分辨率适配计算一个文件大小,设置到AVAssetExportSession对象的fileLimit中。

    /**
     autoQuality: 自动根据分辨率计算合适的码率。
     customQuality:
     0-1之间的值,自定义质量,值越高码率越大。
     值为0时是autoQuality的0.5,值为1时是autoQuality的1.5,值为0.5时等于autoQuality
     */
    public enum CompressRate {
        case auto
        case custom(rate: CGFloat)
    }
    
    /**
     videoQuality: 视频品质
     size: 视频分辨率
     duration: 视频时长,单位(秒)
     */
    public func videoFileLimit(compressRate: CompressRate, size: CGSize, duration: Double) -> Int64 {
        
        //设置基于720p的码率大小
        let default720CodeRate: CGFloat = 3072000
        
        //基于720p的每像素码率适配到不同的分辨率中,需要拿到default720CodeRatePerPixel和useCodeRatePerPixel
        let default720CodeRatePerPixel: CGFloat = 3.333333333
        let codeRatePerPixels = [
            (424 * 240, 5.660377358),
            (640 * 360, 3.888888889),
            (768 * 432, 3.279320988),
            (848 * 480, 3.773584906),
            (1024 * 576, 3.689236111),
            (1280 * 720, 3.333333333),
            (1920 * 1080, 3.641975309),
        ]
        var useCodeRatePerPixel: CGFloat = 3.641975309
        for index in 0 ... codeRatePerPixels.count - 2 {
            let (pixel, codeRatePerPixel) = codeRatePerPixels[index]
            let (pixel2, _) = codeRatePerPixels[index + 1]
            
            //当前尺寸到下一个尺寸之间大小的0.3也适配到当前尺寸所属的数组值中。
            if size.width * size.height <= CGFloat(CGFloat(pixel2 - pixel) * 0.3 + CGFloat(pixel)) {
                useCodeRatePerPixel = CGFloat(codeRatePerPixel)
                break
            }
        }
        
        //每像素文件大小 = 3100000时的每像素文件大小 * 新码率 / 3100000
        var bytesPerPixel = (CGFloat(0.446279674546814) * default720CodeRate / CGFloat(3100000))
        
        //拿到不同分辨率对应的每像素文件大小
        bytesPerPixel = bytesPerPixel * useCodeRatePerPixel / default720CodeRatePerPixel
        
        //适配Rate得到压缩适配的每像素文件大小
        var compressFitBytes = CGFloat()
        switch compressRate {
        case .custom(var rate):
            let minBytes = bytesPerPixel * 0.5
            let maxBytes = bytesPerPixel * 2.5
            if rate < 0 { rate = 0 }
            if rate > 1 { rate = 1 }
            compressFitBytes = rate * (maxBytes - minBytes) + minBytes
        case .auto:
            compressFitBytes = bytesPerPixel
        }
        let fileLimit = Int64(compressFitBytes * size.width * size.height * CGFloat(duration))
        return fileLimit
    }
    

    相关文章

      网友评论

          本文标题:Metal导出视频压缩大小方案

          本文链接:https://www.haomeiwen.com/subject/wpkrmltx.html