美文网首页Swift基础
Swift基础--视频按帧分解成图片

Swift基础--视频按帧分解成图片

作者: 丿小七 | 来源:发表于2017-05-16 10:36 被阅读271次

    参考:iOS开发视频分解成图片(OC版)

     open func generateCGImagesAsynchronously(forTimes requestedTimes: [NSValue], completionHandler handler: @escaping AVFoundation.AVAssetImageGeneratorCompletionHandler)
    
    • 调用视频分解Function
    func slipImgsBtnClick() {
       imgArray.removeAll()
       
       //电脑桌面的一份mp4文件,时长3分20秒。。。path看情况自己定。。。。
       let tmpFileUrl = URL(fileURLWithPath: "/Users/tmy/Downloads/好好(你的名字).mp4")
       
       //调用视频分解func
       self.splitVideoFileUrlFps(splitFileUrl: tmpFileUrl, fps: 1, splitCompleteClosure: { [weak self](isSuccess, splitImgs) in
           if isSuccess {
               self?.imgArray = splitImgs as! [UIImage]
               
               //UI回主线程刷新
               DispatchQueue.main.async {[weak self] in
                   self?.tableView.reloadData()
               }
               print("图片总数目imgcount:\(String(describing: self?.imgArray.count))")
           }
       })
    }
    
    • 视频分解Function
    /// 视频分解成帧
    /// - parameter fileUrl                 : 视频地址
    /// - parameter fps                     : 自定义帧数 每秒内取的帧数
    /// - parameter splitCompleteClosure    : 回调
    func splitVideoFileUrlFps(splitFileUrl:URL, fps:Float, splitCompleteClosure:@escaping completeClosure) {
       
       // TODO: 判断fileUrl是否为空
       print("QQQQQQQQQQ ==> split: \(splitFileUrl)")
       
       var splitImages = [UIImage]()
       let optDict = NSDictionary(object: NSNumber(value: false), forKey: AVURLAssetPreferPreciseDurationAndTimingKey as NSCopying)
       let urlAsset = AVURLAsset(url: splitFileUrl, options: optDict as? [String : Any])
       
       let cmTime = urlAsset.duration
       let durationSeconds: Float64 = CMTimeGetSeconds(cmTime) //视频总秒数
       
       var times = [NSValue]()
       let totalFrames: Float64 = durationSeconds * Float64(fps) //获取视频的总帧数
       var timeFrame: CMTime
       
       for i in 0...Int(totalFrames) {
           timeFrame = CMTimeMake(Int64(i), Int32(fps)) //第i帧, 帧率
           let timeValue = NSValue(time: timeFrame)
           
           times.append(timeValue)
       }
       
       let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
       imgGenerator.requestedTimeToleranceBefore = kCMTimeZero //防止时间出现偏差
       imgGenerator.requestedTimeToleranceAfter = kCMTimeZero
       
       let timesCount = times.count
       
       //获取每一帧的图片
       imgGenerator.generateCGImagesAsynchronously(forTimes: times) { (requestedTime, image, actualTime, result, error) in
           
           //times有多少次body就循环多少次。。。。
           print("current-----\(requestedTime.value)   timesCount == \(timesCount)")
           print("timeScale-----\(requestedTime.timescale) requestedTime:\(requestedTime.value)")
           
           var isSuccess = false
           switch (result) {
           case AVAssetImageGeneratorResult.cancelled:
               print("cancelled------")
               
           case AVAssetImageGeneratorResult.failed:
               print("failed++++++")
               
           case AVAssetImageGeneratorResult.succeeded:
               let framImg = UIImage(cgImage: image!)
               splitImages.append(framImg)
               
               if (Int(requestedTime.value) == (timesCount-1)) { //最后一帧时 回调赋值
                   isSuccess = true
                   splitCompleteClosure(isSuccess, splitImages)
                   print("completed")
               }
           }
       }
    }
    

    屏幕快照 2017-05-16 10.34.14.png
    屏幕快照 2017-05-16 10.34.25.png
    • 使用
    //
    //  TMYImgTableViewController.swift
    //  TMYSegmentController
    //
    //  Created by TMY on 2017/5/15.
    //  Copyright © 2017年 TMY. All rights reserved.
    //
    
    import UIKit
    import AVFoundation
    
    class TMYImgTableViewController: UITableViewController {
    
        var imgArray = [UIImage]()
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.backgroundColor = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1)
            
            title = "图片展示"
            tableView.register(TMYImgCell.self, forCellReuseIdentifier: "imgCellIdentifier")
            tableView.tableFooterView = UIView()
            tableView.rowHeight = UITableViewAutomaticDimension
            tableView.estimatedRowHeight = UIScreen.main.bounds.size.height/3
            
            let rightBtn = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(slipImgsBtnClick))
            navigationItem.rightBarButtonItem = rightBtn
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        // MARK: - Table view data source
    
        override func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return imgArray.count
        }
        
        override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return UIScreen.main.bounds.size.height/3
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "imgCellIdentifier", for: indexPath) as!  TMYImgCell
            cell.imgView.image = imgArray[indexPath.row]
    
            return cell
        }
        
        func slipImgsBtnClick() {
            imgArray.removeAll()
            
            //电脑桌面的一份mp4文件,时长3分20秒。。。path看情况自己定。。。。
            let tmpFileUrl = URL(fileURLWithPath: "/Users/tmy/Downloads/好好(你的名字).mp4")
            
            //调用视频分解func
            self.splitVideoFileUrlFps(splitFileUrl: tmpFileUrl, fps: 1, splitCompleteClosure: { [weak self](isSuccess, splitImgs) in
                
                if isSuccess {
                    self?.imgArray = splitImgs as! [UIImage]
                    
                    //UI回主线程刷新
                    DispatchQueue.main.async {[weak self] in
                        self?.tableView.reloadData()
                    }
                    print("图片总数目imgcount:\(String(describing: self?.imgArray.count))")
                }
            })
        }
    }
    
    class TMYImgCell: UITableViewCell {
        
        let imgView = UIImageView()
        
        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            
             imgView.frame = CGRect(x: 10, y: 0, width: UIScreen.main.bounds.size.width - 20, height: UIScreen.main.bounds.size.height/3)
            imgView.contentMode = .scaleAspectFit
            addSubview(imgView)
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    extension TMYImgTableViewController {
        
        /// 视频分解成帧
        /// - parameter fileUrl                 : 视频地址
        /// - parameter fps                     : 自定义帧数 每秒内取的帧数
        /// - parameter splitCompleteClosure    : 回调
        func splitVideoFileUrlFps(splitFileUrl:URL, fps:Float, splitCompleteClosure:@escaping completeClosure) {
            
            // TODO: 判断fileUrl是否为空
            print("QQQQQQQQQQ ==> split: \(splitFileUrl)")
            
            var splitImages = [UIImage]()
            let optDict = NSDictionary(object: NSNumber(value: false), forKey: AVURLAssetPreferPreciseDurationAndTimingKey as NSCopying)
            let urlAsset = AVURLAsset(url: splitFileUrl, options: optDict as? [String : Any])
            
            let cmTime = urlAsset.duration
            let durationSeconds: Float64 = CMTimeGetSeconds(cmTime) //视频总秒数
            
            var times = [NSValue]()
            let totalFrames: Float64 = durationSeconds * Float64(fps) //获取视频的总帧数
            var timeFrame: CMTime
            
            for i in 0...Int(totalFrames) {
                timeFrame = CMTimeMake(Int64(i), Int32(fps)) //第i帧, 帧率
                let timeValue = NSValue(time: timeFrame)
                
                times.append(timeValue)
            }
            
            let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
            imgGenerator.requestedTimeToleranceBefore = kCMTimeZero //防止时间出现偏差
            imgGenerator.requestedTimeToleranceAfter = kCMTimeZero
            
            let timesCount = times.count
            
            //获取每一帧的图片
            imgGenerator.generateCGImagesAsynchronously(forTimes: times) { (requestedTime, image, actualTime, result, error) in
                
                //times有多少次body就循环多少次。。。。
                print("current-----\(requestedTime.value)   timesCount == \(timesCount)")
                print("timeScale-----\(requestedTime.timescale) requestedTime:\(requestedTime.value)")
                
                var isSuccess = false
                switch (result) {
                case AVAssetImageGeneratorResult.cancelled:
                    print("cancelled------")
                    
                case AVAssetImageGeneratorResult.failed:
                    print("failed++++++")
                    
                case AVAssetImageGeneratorResult.succeeded:
                    let framImg = UIImage(cgImage: image!)
                    splitImages.append(framImg)
                    
                    if (Int(requestedTime.value) == (timesCount-1)) { //最后一帧时 回调赋值
                        isSuccess = true
                        splitCompleteClosure(isSuccess, splitImages)
                        print("completed")
                    }
                }
            }
        }
    }
    

    Demo下载

    相关文章

      网友评论

        本文标题:Swift基础--视频按帧分解成图片

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