AVFoundation 获取视频帧图片以及相关信息

AVFoundation框架是iOS平台多媒体的主要框架之一,它囊括了四个方面的内容:

  • 音视频播放以及编辑
  • 利用麦克风和摄像头进行数据采集,录制成音频或视频
  • 音频处理
  • 将文字转换成音频

本篇主要想记录一下音视频获取信息以及学习一下关于Asset的相关知识。

基本信息获取

从工程中读取视频文件内容:
官方提供了两个种读取的方法分别是有添加参数的和直接添加
直接读取:

let   path = Bundle.main.path(forResource: "IMG_2735", ofType: "mp4")
let url = URL.init(fileURLWithPath: path)
let mainAsset = AVAsset(url: url)

通过添加参数来读取,添加参数时,需要知道以下参数的意义:

  • AVURLAssetPreferPreciseDurationAndTimingKey
    当前是否支持精确的持续时间以及随机访问任何时间点内容
  • AVURLAssetReferenceRestrictionsKey
    是否支持涉及外部引用资源解析,因为存在某些媒体文件是引用了外部的资源的,如果这里限制了,那就会导致这类文件不能正确读取资源
  • AVURLAssetHTTPCookiesKey
    包含一个HTTP cookies的资源访问请求,在默认的情况下,AVURLAsset只有一个缓存的Cookies,这个选项可以帮助你直接使用当前Cookies来进行访问资源,以提速访问
let   path = Bundle.main.path(forResource: "IMG_2735", ofType: "mp4")
let url = URL.init(fileURLWithPath: path)
let options = [AVURLAssetAllowsCellularAccessKey:false,AVURLAssetPreferPreciseDurationAndTimingKey:true]
let mainAsset = AVURLAsset.init(url: url, options: options)

可以读取的基础信息如下:

        let d = CMTimeGetSeconds(mainAsset.duration)
        let p = mainAsset.providesPreciseDurationAndTiming
        print("时长:\(d),可用时间准确性:\(p) \(mainAsset.duration.timescale)")
        
        let formatter = DateFormatter.init()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let cc = mainAsset.creationDate
        let createDate = formatter.string(from: cc?.dateValue ?? Date.init())
        print("创建时间:\(createDate)")
       
        let rate = mainAsset.preferredRate //速率
        print("rate:\(rate)")
        
        let volume = mainAsset.preferredVolume //音量
        print("volume:\(volume)")
        
        let canPlay = mainAsset.isPlayable //是否支持播放
        print("isPlayable:\(canPlay)")
        
        let export = mainAsset.isExportable //是否支持导出
        print("exportable:\(export)")
        
        let reabable = mainAsset.isReadable //是否可读取内容
        print("readable:\(reabable)")
        
        let composable = mainAsset.isComposable //是否可合成
        print("composable:\(composable)")
        
        let hasProtect = mainAsset.hasProtectedContent //是否受保护
        print("hasProtect:\(hasProtect)")
        
        let compatible = mainAsset.isCompatibleWithSavedPhotosAlbum//是否可以写入相册
        print("是否可以写入相册:\(compatible)")

AVAsset里面包含了一个或多个AVAssetTrack可以通过下面几个方法来获取对应的音视频轨道:

    /**
      @property     tracks
      @abstract     获取所有的音视频轨道
    */
    open var tracks: [AVAssetTrack] { get }

    
    /**
      @method       trackWithTrackID:
      @abstract     根据trackID来获取对应的音视频轨道.
      @param        trackID
      @result       返回一个或者零个音视频轨道
    */
    open func track(withTrackID trackID: CMPersistentTrackID) -> AVAssetTrack?

    
    /**
      @method       tracksWithMediaType:
      @abstract 根据media type来获取对应的音/视频轨道组
      @param        mediaType
                     参考 AVMediaFormat.h 类
      @result       音/视频轨道组
    */
    open func tracks(withMediaType mediaType: AVMediaType) -> [AVAssetTrack]

    
    /**
      @method       tracksWithMediaCharacteristic:
      @abstract       根据特殊的描述符来获取对应的音/视频轨道组.
      @param        mediaCharacteristic
                    参考 AVMediaFormat.h 类
      @result       音/视频轨道组
    */
    open func tracks(withMediaCharacteristic mediaCharacteristic: AVMediaCharacteristic) -> [AVAssetTrack]

另外也可以遍历AVAssetTrack的一些基本参数:

    for track in mainAsset.tracks {
         print("trackID:\(track.trackID)")
         print("mediaType:\(track.mediaType.rawValue)")
         print("nominalFrameRate:\(track.nominalFrameRate)")
         print("minFrameDuration:\(track.minFrameDuration.seconds)")
         print("formatDescription:\(track.formatDescriptions)")
    }

获取某一时刻的视频帧

这里可以分为两部分,一个是根据某个间隔获取视频的每一个时刻的视频帧,这里用到了一次获取多个视频帧的方法:

       let imgc = mainAsset.tracks(withMediaType: .video).count
        var track:AVAssetTrack!
        if imgc == 1 {
            track = mainAsset.tracks(withMediaType: .video).first
        }
        let gem = AVAssetImageGenerator.init(asset: mainAsset)
        //缩略图的宽高
        gem.maximumSize = CGSize.init(width: 128, height: 72)
        gem.apertureMode = AVAssetImageGenerator.ApertureMode.cleanAperture
        var array:[NSValue]! = []
        let d = mainAsset.duration.seconds
        let all = d * Double(track.nominalFrameRate)
        
        let numberGet = Int(d*5)//每秒里面取5帧
        let scan = Int(all)/numberGet //取帧间隔
        for item in 0..

另一个则是相对简单的,直接通过请求某个时间点的时刻来获取对应视频帧信息的帧信息内容:
这里我实现了一个slider,通过这个slider的value值变化来取对应的视频帧

///这里是slider change 的内容
  @objc func changeAction(){
        print("slider.value:\(slider.value)")
       
        let imgc = mainAsset.tracks(withMediaType: .video).count
        var track:AVAssetTrack!
        if imgc == 1 {
            track = mainAsset.tracks(withMediaType: .video).first
        }
        let v = slider.value * Float(mainAsset.duration.seconds) * track.nominalFrameRate
        let t = CMTime.init(value: CMTimeValue(v), timescale: CMTimeScale(track.nominalFrameRate))
        imageGen.cancelAllCGImageGeneration()
        guard let img = try?self.imageGen.copyCGImage(at: t, actualTime: nil) else {
            return
        }
        print("get a img by asset")
        self.thumbImageView.image = UIImage.init(cgImage: img)
}

在获取帧信息的时候,频繁出现的一个东西:CMTime时间值,这里解释一下高浩浩浩浩浩浩

后面或有更多AVFoundation的相关知识记录在此,欢迎关注。

你可能感兴趣的:(AVFoundation 获取视频帧图片以及相关信息)