iOS 12+ ReplayKit 系统录屏(三) 丢帧压缩

视频录制后需要上传,但是录制视频要想压缩,有几个可以压缩的点:比特率、帧率、分辨率
比特率:单位像素所占的比特值
帧率:单位时间内的视频帧数
分辨率:图片所占的像素点的一个度量 w * h

这里我们在最低的比特率和分辨率的情况下(不改变清晰度),降低帧率也能压缩视频大小,只是视频卡顿了点

自定义丢帧:

下面一个刻度6个视频帧 ,1s(1000ms)假设有30帧 ’-‘代表一帧,’|‘代表刻度
目的:丢帧处理后1s(1000ms) 5帧
每个视频帧都有在视频中特定的位置,如果其后的视频帧丢失,就会拿当前展示的视频帧代替展示,知道有新的视频帧来替换,所以丢帧也就是适当的时间内取合适的帧,如下5个刻度代表1s,一共有30帧,要想丢帧至5帧/s,就要丢掉25帧,为了视频卡顿程度最低,我们间隔取帧的时间间隔不能太长,最好越均匀约好,结果:每一刻度内同一位置取帧,例如都取刻度内第一帧

|------|------|------|------|------|

|------|------|------|------|------|

但是录屏视频帧并不都是稳定的:例如当前iPhone6s及其以下设备所装iOS系统会针对性能进行优化:性能占用越高,录屏帧越低,例如:①录屏时高频操作手机,视频帧率就会降低;②录屏界面无变化时帧率会降低;
只有无操作或者低频操作的或者界面有变化的录屏帧率才越稳定,经测试iPhone6s的帧率变化范围大约为3帧/s ~ 30帧/s,普通操作的帧率在22帧/s 附近波动
只有iPhone7及其以上视频帧率稳定在30帧/s附近小幅波动
所以丢帧就行为就变成了不是绝对的稳定了,能够适配所有iPhone7及其以上手机的录屏视频丢帧后稳定在5帧/s,iPhone7以下只能在正常操作下在3~4帧/s
为了稳定帧率,我的处理就是取每一刻度的第一帧,不管此刻度有几帧,如果是均匀的,那丢帧后也是均匀的,如果不均匀,丢帧后就相对均匀

代码:


    var appenedAgoSampleBuffer:CMSampleBuffer?//已经拼里面的前一帧
    var lastSameBuffer:CMSampleBuffer?
    var firstTime:Double = 0.0
 override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {
        switch sampleBufferType {
        case RPSampleBufferType.video:
            if assetWriter.status == AVAssetWriter.Status.failed || assetWriter.status == AVAssetWriter.Status.completed || assetWriter.status == AVAssetWriter.Status.cancelled {
                print("assetWrite状态:\(assetWriter.status)")
                return
            }
            if assetWriter.status == AVAssetWriter.Status.unknown {
                //num = 0
                assetWriter.startWriting()
                assetWriter.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sampleBuffer))
                print("AVAssetWriter.Status.unknown")
            }
            if assetWriter.status == AVAssetWriter.Status.writing {
                if videoInput.isReadyForMoreMediaData
                {
                    print("AVAssetWriter.Status.writing")
                    let position:CMTime = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer) ;
                    print("====================\(CMTimeGetSeconds(position))")
                    var canAppend = false
                    if lastSameBuffer == nil {//第一帧
                        canAppend = true
                        let firstPosition:CMTime = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer);//第一帧的时间戳
                        firstTime = CMTimeGetSeconds(firstPosition)*1000//第一帧的时间
                        appenedAgoSampleBuffer = sampleBuffer
                    }else{
                        let appenedAgoPosition:CMTime = CMSampleBufferGetOutputPresentationTimeStamp(appenedAgoSampleBuffer!);//前一帧时间戳
                        let time = CMTimeGetSeconds(position)*1000 - firstTime//当前帧和第一帧的时间差
                        let appenedAgoTime = CMTimeGetSeconds(appenedAgoPosition)*1000 - firstTime//前一帧的时间
                        if (Int(time)/200) > (Int(appenedAgoTime)/200) {
                            canAppend = true
                            appenedAgoSampleBuffer = sampleBuffer
                        }
                    }
                    if  canAppend {
                        let success:Bool = videoInput.append(sampleBuffer)
                        lastSameBuffer = sampleBuffer
                        if !success {
                            print("AVAssetWriter.Status.faild")
                            self.stopRecording()
                        }
                        print("appended")
                    }

                }
            }
            break
        case RPSampleBufferType.audioApp:
            // Handle audio sample buffer for app audio
            break
        case RPSampleBufferType.audioMic:
            // Handle audio sample buffer for mic audio
            break
        @unknown default:
            // Handle other sample buffer types
            fatalError("Unknown type of sample buffer")
        }
       
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值