iOS---视频播放、剪切、暂停--Swift

import UIKit

importAVFoundation

importMediaPlayer

importFoundation

classTVViewController:BaseViewController,UIScrollViewDelegate{

    varpayerTV:AVPlayer?

    varplayToEndTimeBool:Bool?

    varplayAtem:AVPlayerItem?

    varloadProgressView:UIView?

    varplayerLayer:AVPlayerLayer?

    varurl:NSURL?

    vartempPath:NSString?

    vareditScrollView:UIScrollView?

    vartimeMutArr:NSMutableArray?

    varshearPlayBool:Bool?

    varshearAfterPlayBool:Bool?

    overridefuncviewDidLoad() {

        super.viewDidLoad()

        self.initInterface()

        self.initTV()

        self.aVAssetImageGenerator()

    }

    //获取视频帧图像

    funcaVAssetImageGenerator() ->Void{

        /*

         AVAssetImageGenerator 提供独立于回放的资产的缩略图或预览图像的对象。

         */

        self.editScrollView=UIScrollView.init(frame:CGRect.init(origin:CGPoint.init(x:0, y:300), size:CGSize.init(width:UIScreen.main.bounds.size.width, height:80)))

        self.view.addSubview(self.editScrollView!)

        self.editScrollView?.delegate = self

        //读取解析视频帧

        //初始化AVURLAsset对象

        letasset:AVURLAsset=AVURLAsset.init(url:self.url!asURL)

        //获取总视频的长度 = 总帧数 / 每秒的帧数

          letsumTime:Float=Float(integerLiteral: (asset.duration.value) /Int64(asset.duration.timescale))

        //创建AVAssetImageGenerator对象

        let generator : AVAssetImageGenerator = AVAssetImageGenerator.init(asset: asset)

        generator.maximumSize = CGSize.init(width: UIScreen.main.bounds.width, height: 80)

        generator.appliesPreferredTrackTransform = true

        generator.requestedTimeToleranceBefore = CMTime.zero

        generator.requestedTimeToleranceAfter = CMTime.zero

        self.timeMutArr = NSMutableArray.init()

        foriin0..

            let time:CMTime = CMTimeMake(value: Int64(i*NSInteger(asset.duration.timescale)), timescale: Int32(asset.duration.timescale))

            letvalue:NSValue=NSValue.init(time: time)

            self.timeMutArr?.add(value)

        }

       varcount:NSInteger=0

        generator.generateCGImagesAsynchronously(forTimes:self.timeMutArr!as! [NSValue]) { (requestedTime, img, actualTime, result, error)in

            if result == AVAssetImageGenerator.Result.succeeded{

                print(count)

                DispatchQueue.main.sync {

                    letthumImgView:UIImageView=UIImageView.init()

                    thumImgView.image=UIImage.init(cgImage: img!)

                    self.editScrollView?.addSubview(thumImgView)

                    thumImgView.frame=CGRect.init(origin:CGPoint.init(x:50+ count*50, y:0), size:CGSize.init(width:50, height:70))

                    self.editScrollView?.contentSize=CGSize.init(width:100+count*50, height:0)

                    count = count +1

                }

            }

            if result == AVAssetImageGenerator.Result.failed{

                print(error!.localizedDescription)

            }

            if result == AVAssetImageGenerator.Result.cancelled{

                print("cancelled")

            }

        }

        self.editScrollView?.contentOffset=CGPoint.init(x:50, y:0)

    }

    funcscrollViewDidEndDecelerating(_scrollView:UIScrollView) {

        print(scrollView.contentOffset.x)

    }

    //界面初始化

    funcinitInterface() ->Void{

        self.view.backgroundColor = UIColor.white

        self.title="视屏的播放与截取"

    }

    //视频的初始化

    funcinitTV() ->Void{

      shearAfterPlayBool = false

        self.url=NSURL.init(fileURLWithPath:Bundle.main.path(forResource:"tv", ofType:"mp4")!)

        shearPlayBool = false

        self.addPlayer(url:self.url!)

        self.addBut()

    }

    //添加播放器

    funcaddPlayer(url:NSURL) ->Void{

     playToEndTimeBool = false

     NotificationCenter.default.addObserver(self, selector:  #selector(PlayToEndTime), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)

        if(!(shearPlayBool!)) {

            self.url=NSURL.init(fileURLWithPath:Bundle.main.path(forResource:"tv", ofType:"mp4")!)

        }

        self.playAtem=AVPlayerItem.init(url:self.url!asURL)

        self.payerTV=AVPlayer.init(playerItem:self.playAtem)

        //创建播放器

        self.playerLayer=AVPlayerLayer.init(player:self.payerTV)

        self.playerLayer?.frame=CGRect.init(origin:CGPoint.init(x:0, y:160), size:CGSize.init(width:UIScreen.main.bounds.size.width, height:140))

        self.payerTV?.seek(to:CMTimeMake(value:0, timescale:1000))//设置播放位置  1000位帧率

        self.view.layer.addSublayer(self.playerLayer!)

        /*volume--表示当前播放器的音频音量;0.0表示“关闭所有音频”,1.0表示“以当前项的最大音量播放”。

         iOS注意:不要使用此属性实现用于媒体播放的音量滑块。为此,使用MPVolumeView,它在外观上是可定制的,并提供用户期望的标准媒体播放行为。

         这个属性在iOS中最有用的是控制AVPlayer相对于其他音频输出的音量,而不是最终用户的音量控制。*/

        self.payerTV?.volume=0.5;

        let progressView:UIProgressView = UIProgressView.init(progressViewStyle: UIProgressView.Style.default)

        progressView.frame=CGRect.init(origin:CGPoint.init(x:0, y:150), size:CGSize.init(width:UIScreen.main.bounds.size.width, height:20))

        self.view.addSubview(progressView)

        if(self.loadProgressView!=nil) {

            self.loadProgressView=UIView.init(frame:CGRect.init(origin:CGPoint.init(x:0, y:145), size:CGSize.init(width:10, height:10)))

            self.view.addSubview(self.loadProgressView!)

            self.loadProgressView?.backgroundColor = UIColor.yellow

        }else{

             self.loadProgressView?.frame=CGRect.init(origin:CGPoint.init(x:0, y:145), size:CGSize.init(width:10, height:10))

        }

        //监听视频播放进度

        self.payerTV?.addPeriodicTimeObserver(forInterval:CMTimeMakeWithSeconds(1, preferredTimescale:Int32(NSEC_PER_SEC)), queue:nil, using: { (time)in

             //进度 当前时间/总时间

            let progress:Float = Float(CMTimeGetSeconds(self.payerTV!.currentItem!.currentTime()) / CMTimeGetSeconds(self.payerTV!.currentItem!.duration))

            progressView.progress= progress

            if(progress ==1){

                self.loadProgressView?.frame=CGRect.init(origin:CGPoint.init(x:Int(Float(progress*(Float.init(UIScreen.main.bounds.size.width))-10.0)), y:145), size:CGSize.init(width:10, height:10))

            }else{

                 self.loadProgressView?.frame=CGRect.init(origin:CGPoint.init(x:Int(Float(progress*(Float.init(UIScreen.main.bounds.size.width))-0.0)), y:145), size:CGSize.init(width:10, height:10))

            }

        })

         //在进度条上面--添加手势--可以拖动控制播放的位置

        letpan:UIPanGestureRecognizer=UIPanGestureRecognizer.init(target:self, action:#selector(playpanGestureRecognizer(gestureRecognizer:)))

        self.loadProgressView?.addGestureRecognizer(pan)

    }

    //控制按钮

    funcaddBut() ->Void{

        let playBut:UIButton = UIButton.init(type: UIButton.ButtonType.custom)

        self.view.addSubview(playBut)

        playBut.frame=CGRect.init(origin:CGPoint.init(x:20, y:104), size:CGSize.init(width:80, height:30))

        playBut.setTitle("播放", for: UIControl.State.normal)

        playBut.setTitleColor(UIColor.black, for: UIControl.State.normal)

        playBut.addTarget(self, action:#selector(play), for:UIControl.Event.touchUpInside)

        let shearPlayBut:UIButton = UIButton.init(type: UIButton.ButtonType.custom)

        self.view.addSubview(shearPlayBut)

        shearPlayBut.frame=CGRect.init(origin:CGPoint.init(x:20, y:64), size:CGSize.init(width:80, height:30))

        shearPlayBut.setTitle("剪切播放", for:UIControl.State.normal)

        shearPlayBut.setTitleColor(UIColor.black, for: UIControl.State.normal)

        shearPlayBut.addTarget(self, action:#selector(shearPlay), for:UIControl.Event.touchUpInside)

        let suspendedBut:UIButton = UIButton.init(type: UIButton.ButtonType.custom)

        self.view.addSubview(suspendedBut)

        suspendedBut.frame=CGRect.init(origin:CGPoint.init(x:120, y:104), size:CGSize.init(width:80, height:30))

        suspendedBut.setTitle("暂停", for:UIControl.State.normal)

        suspendedBut.setTitleColor(UIColor.black, for: UIControl.State.normal)

        suspendedBut.addTarget(self, action:#selector(suspended), for:UIControl.Event.touchUpInside)

        let retBut:UIButton = UIButton.init(type: UIButton.ButtonType.custom)

        self.view.addSubview(retBut)

        retBut.frame=CGRect.init(origin:CGPoint.init(x:220, y:104), size:CGSize.init(width:80, height:30))

        retBut.setTitle("重播", for: UIControl.State.normal)

        retBut.setTitleColor(UIColor.black, for: UIControl.State.normal)

        retBut.addTarget(self, action:#selector(ret), for:UIControl.Event.touchUpInside)

        let shearBut:UIButton = UIButton.init(type: UIButton.ButtonType.custom)

        self.view.addSubview(shearBut)

        shearBut.frame=CGRect.init(origin:CGPoint.init(x:220, y:64), size:CGSize.init(width:80, height:30))

        shearBut.setTitle("剪切", for: UIControl.State.normal)

        shearBut.setTitleColor(UIColor.black, for: UIControl.State.normal)

        shearBut.addTarget(self, action:#selector(shear), for:UIControl.Event.touchUpInside)

    }

    //播放

    @objcfuncplay() ->Void{

        if playToEndTimeBool! {

            playToEndTimeBool = false

            self.payerTV?.seek(to:CMTimeMake(value:0, timescale:1000))

        }

      shearPlayBool = false

      self.payerTV?.play()

    }

    //暂停

    @objcfuncsuspended() ->Void{

        self.payerTV?.pause()

    }

    //重播

    @objcfuncret() ->Void{

        self.payerTV?.seek(to:CMTimeMake(value:0, timescale:1000))

        self.payerTV?.play()

    }

    //剪切

    @objcfuncshear() ->Void{

        self.suspended()

        shearAfterPlayBool = true

        self.tempPath = NSTemporaryDirectory() + "tmpMov.mp4" as NSString

        self.deleteTempFile()//视频裁剪的时候要清理一下之前的视屏

        letasset:AVAsset=AVAsset.init(url:self.url!asURL)

        let exportSession:AVAssetExportSession = AVAssetExportSession.init(asset: asset, presetName: AVAssetExportPresetPassthrough)!

        letfurl:NSURL=NSURL.fileURL(withPath:self.tempPath!asString)asNSURL

        exportSession.outputURL= furlasURL

        exportSession.outputFileType = AVFileType.mp4

        let endTime:NSInteger = NSInteger(CMTimeGetSeconds(self.payerTV!.currentItem!.duration));//希望剪切的---结束时间点

         let startTime:NSInteger = NSInteger(CMTimeGetSeconds(self.payerTV!.currentItem!.currentTime())) //希望剪切的---开始时间点

        /*

         CMTime CMTimeMakeWithSeconds(

         Float64 seconds,          //第几秒的截图,是当前视频播放到的帧数的具体时间

         int32_t preferredTimeScale //首选的时间尺度 "每秒的帧数" );

         */

        letstart:CMTime=CMTimeMakeWithSeconds(Float64(startTime), preferredTimescale:Int32(1*NSEC_PER_SEC) )

        letduration:CMTime=CMTimeMakeWithSeconds(Float64(endTime - startTime), preferredTimescale:Int32(1*NSEC_PER_SEC))

        /*

         其中start表示时间的起点,duratin表示时间范围的持续时间。*/

        letrange:CMTimeRange=CMTimeRangeMake(start: start, duration: duration)

        /*

       timeRange--  指定要从源导出的时间范围。导出会话的默认时间范围是kCMTimeZero..kCMTimePositiveInfinity,这意味着将导出资产的完整持续时间*/

        exportSession.timeRange= range

        exportSession.exportAsynchronously{

            switchexportSession.status{

            case.unknown:

                print("unknown")

                break

            case.waiting:

                 print("waiting")

                break

            case.exporting:

                 print("exporting")

                break

            case.completed:

                print("completed")

                letmovieUrl:NSURL=NSURL.fileURL(withPath:self.tempPath!asString)asNSURL

                UISaveVideoAtPathToSavedPhotosAlbum(movieUrl.relativePath!, self, Selector(("video:didFinishSavingWithError:contextInfo:")), nil)

                break

            case.failed:

                print(exportSession.error!.localizedDescription)

                break

            case.cancelled:

                 print("cancelled")

                break

            }

        }

    }

    funcvideo(videoPath:String, didFinishSavingWithError error:NSError, contextInfo info:AnyObject) {

    }

    //剪切播放

    @objcfuncshearPlay() ->Void{

        if shearAfterPlayBool! {

            shearPlayBool=true

            //播放剪切之后的视屏

            self.url=NSURL.init(fileURLWithPath:self.tempPath!asString)

           self.addPlayer(url:self.url!)

            self.payerTV?.play()

        }

    }

    //播放结束

    @objcfuncPlayToEndTime() ->Void{

         playToEndTimeBool = true;//播放结束

    }

    //拖动手势

    @objcfuncplaypanGestureRecognizer(gestureRecognizer:UIPanGestureRecognizer) ->Void{

        //获取手势的位置

        letposition:CGPoint= gestureRecognizer.translation(in:self.loadProgressView!)

        //通过stransform 进行平移交换

        self.loadProgressView!.transform=CGAffineTransform.init(translationX: position.x, y: position.y)

         //将增量置为零

        gestureRecognizer.setTranslation(CGPoint.zero, in:self.loadProgressView)

        let progress:CGFloat = self.loadProgressView!.frame.origin.x / UIScreen.main.bounds.size.width

        self.payerTV?.seek(to: CMTimeMakeWithSeconds(CMTimeGetSeconds(self.payerTV!.currentItem!.duration)*(Double.init(progress)), preferredTimescale: 1000))

        self.payerTV?.play()

    }

    funcdeleteTempFile() ->Void{

        leturl:NSURL=NSURL.init(fileURLWithPath:self.tempPath!asString)

        let fm: FileManager = FileManager.default

        letexist:Bool= fm.fileExists(atPath: url.path!asString)

        ifexist {

            do{

                tryfm.removeItem(at: urlasURL)

            }catch{

            }

        }else{

        }

    }

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容