|
@@ -0,0 +1,199 @@
|
|
|
+//
|
|
|
+// PublishCoverVideoView.swift
|
|
|
+// RainbowPlanet
|
|
|
+//
|
|
|
+// Created by 南鑫林 on 2019/11/12.
|
|
|
+// Copyright © 2019 RainbowPlanet. All rights reserved.
|
|
|
+//
|
|
|
+
|
|
|
+import UIKit
|
|
|
+
|
|
|
+class PublishCoverVideoView: UIView {
|
|
|
+
|
|
|
+ /// 合成导出路径
|
|
|
+ var outputPath : String?
|
|
|
+ /// 封面路径
|
|
|
+ var outCoverImagePath : String?
|
|
|
+ /// 总时长
|
|
|
+ var duration : Double? = 0
|
|
|
+ /// 展示的图片
|
|
|
+ var images = Array<UIImage>()
|
|
|
+
|
|
|
+ typealias SelectedImageClosure = (UIImage) -> Void
|
|
|
+ var selectedImageClosure : SelectedImageClosure?
|
|
|
+
|
|
|
+ override init(frame: CGRect) {
|
|
|
+ super.init(frame: frame)
|
|
|
+ }
|
|
|
+
|
|
|
+ init(outputPath : String?) {
|
|
|
+ self.init()
|
|
|
+ frame = CGRect(x: 14, y: kScreenHeight-89-kSafeTabBarHeight, width: kScreenWidth-28, height: 69)
|
|
|
+ self.outputPath = outputPath
|
|
|
+ setupViews()
|
|
|
+ setupData()
|
|
|
+ }
|
|
|
+
|
|
|
+ required init?(coder aDecoder: NSCoder) {
|
|
|
+ fatalError("init(coder:) has not been implemented")
|
|
|
+ }
|
|
|
+
|
|
|
+ func setupViews() {
|
|
|
+ addSubview(collectionView)
|
|
|
+ addSubview(view)
|
|
|
+ view.addSubview(progressView)
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ func setupData() {
|
|
|
+
|
|
|
+ let asset = AVURLAsset(url: URL(fileURLWithPath: outputPath ?? ""))
|
|
|
+ let videoTracks = asset.tracks(withMediaType: AVMediaType.video)
|
|
|
+ if videoTracks.count != 0 {
|
|
|
+ let track = videoTracks[0]
|
|
|
+ duration = CMTimeGetSeconds(CMTimeRangeGetEnd(track.timeRange))
|
|
|
+ }
|
|
|
+ getImages()
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private lazy var collectionView: UICollectionView = {
|
|
|
+ let collectionView = UICollectionView.init(frame: CGRect(x: 0, y: 0, width: kScreenWidth-28, height: 69), collectionViewLayout: collectionViewLayout)
|
|
|
+ collectionView.backgroundColor = .clear
|
|
|
+ collectionView.delegate = self;
|
|
|
+ collectionView.dataSource = self;
|
|
|
+ collectionView.showsVerticalScrollIndicator = false
|
|
|
+ collectionView.showsHorizontalScrollIndicator = false
|
|
|
+ collectionView.cornerRadius = 4
|
|
|
+ collectionView.masksToBounds = true
|
|
|
+ return collectionView
|
|
|
+ }()
|
|
|
+
|
|
|
+ private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
|
|
|
+ let collectionViewLayout = UICollectionViewFlowLayout.init()
|
|
|
+ collectionViewLayout.minimumLineSpacing = 0
|
|
|
+ collectionViewLayout.minimumInteritemSpacing = 0
|
|
|
+ collectionViewLayout.itemSize = CGSize(width:(kScreenWidth-28)/12, height: 69)
|
|
|
+ collectionViewLayout.scrollDirection = .horizontal
|
|
|
+ collectionViewLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
|
|
+ return collectionViewLayout
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var view: UIView = {
|
|
|
+ let view = UIView(frame: CGRect(x: 0, y: 0, width: kScreenWidth-28, height: 69))
|
|
|
+ view.backgroundColor = .clear
|
|
|
+ return view
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var progressView: UIView = {
|
|
|
+ let progressView = UIView(frame: CGRect(x: 0, y: 0, width: (kScreenWidth-28)/12, height: 69))
|
|
|
+ progressView.cornerRadius = 4
|
|
|
+ progressView.masksToBounds = true
|
|
|
+ progressView.layer.borderColor = kffffffColor.cgColor
|
|
|
+ progressView.layer.borderWidth = 2
|
|
|
+ return progressView
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var thumbnailImageGenerator: AVAssetImageGenerator = {
|
|
|
+ let thumbnailImageGenerator = AVAssetImageGenerator(asset: AVURLAsset(url: URL(fileURLWithPath: outputPath ?? "")))
|
|
|
+ thumbnailImageGenerator.appliesPreferredTrackTransform = true
|
|
|
+ thumbnailImageGenerator.requestedTimeToleranceBefore = CMTime.zero
|
|
|
+ thumbnailImageGenerator.requestedTimeToleranceAfter = CMTime.zero
|
|
|
+ thumbnailImageGenerator.maximumSize = CGSize(width: (kScreenWidth-28)/12, height: 69)
|
|
|
+ return thumbnailImageGenerator
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var imageGenerator: AVAssetImageGenerator = {
|
|
|
+ let imageGenerator = AVAssetImageGenerator(asset: AVURLAsset(url: URL(fileURLWithPath: outputPath ?? "")))
|
|
|
+ imageGenerator.appliesPreferredTrackTransform = true
|
|
|
+ imageGenerator.requestedTimeToleranceBefore = CMTime.zero
|
|
|
+ imageGenerator.requestedTimeToleranceAfter = CMTime.zero
|
|
|
+ return imageGenerator
|
|
|
+ }()
|
|
|
+
|
|
|
+
|
|
|
+ /// 获取图片
|
|
|
+ func getImages() {
|
|
|
+
|
|
|
+ var times = Array<NSValue>()
|
|
|
+ var startTime = CMTime.zero
|
|
|
+ let addTime = CMTimeMake(value: Int64(duration! * 1000/12), timescale: 1000)
|
|
|
+ let endTime = CMTimeMake(value: Int64(duration! * 1000), timescale: 1000);
|
|
|
+
|
|
|
+ while startTime < endTime {
|
|
|
+ times.append(NSValue(time: startTime))
|
|
|
+ startTime = CMTimeAdd(startTime, addTime)
|
|
|
+ }
|
|
|
+
|
|
|
+ thumbnailImageGenerator.generateCGImagesAsynchronously(forTimes: times) { [weak self] (requestedTime, cgImage, actualTime, result, error) in
|
|
|
+ if result == .succeeded {
|
|
|
+ let image = UIImage(cgImage: cgImage!)
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ self?.images.append(image)
|
|
|
+ self?.collectionView.reloadData()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+extension PublishCoverVideoView: UICollectionViewDelegateFlowLayout,UICollectionViewDataSource {
|
|
|
+ func numberOfSections(in collectionView: UICollectionView) -> Int {
|
|
|
+ return 1
|
|
|
+ }
|
|
|
+
|
|
|
+ func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
|
|
+ return images.count
|
|
|
+ }
|
|
|
+
|
|
|
+ func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
|
|
+ let cell = PublishCoverVideoCollectionViewCell.cellWith(collectionView: collectionView, indexPath: indexPath)
|
|
|
+ cell.image = images[indexPath.row]
|
|
|
+ return cell
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+extension PublishCoverVideoView {
|
|
|
+
|
|
|
+ override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
|
+ touch(touches: touches)
|
|
|
+ }
|
|
|
+
|
|
|
+ override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
|
+ touch(touches: touches)
|
|
|
+ }
|
|
|
+
|
|
|
+ override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
|
+ touch(touches: touches)
|
|
|
+ }
|
|
|
+
|
|
|
+ func touch(touches: Set<UITouch>) {
|
|
|
+ let touch = touches.first
|
|
|
+ let point = touch?.location(in: collectionView)
|
|
|
+ var percent = (point?.x ?? 0.0) / frame.width
|
|
|
+ if percent < 0 {
|
|
|
+ percent = 0
|
|
|
+ } else if percent > 1 {
|
|
|
+ percent = 1
|
|
|
+ }
|
|
|
+ progressView.center = CGPoint(x: frame.width * percent, y: frame.height/2)
|
|
|
+ let time = CMTimeMake(value: Int64(duration! * 1000 * Double(percent)), timescale: 1000);
|
|
|
+ DispatchQueue.global().async {
|
|
|
+ [weak self] in
|
|
|
+ guard let strongSelf = self else { return }
|
|
|
+ do {
|
|
|
+ let image = try strongSelf.imageGenerator.copyCGImage(at: time, actualTime: nil)
|
|
|
+ //旋转修正
|
|
|
+ let imageNew = UIImage.rotate(aImage: UIImage(cgImage: image))
|
|
|
+ if let selectedImageClosure = strongSelf.selectedImageClosure {
|
|
|
+ selectedImageClosure(imageNew)
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ NXLLog("错误")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|