MillmanY / MMPlayerView

Custom AVPlayerLayer on view and transition player with good effect like youtube and facebook
MIT License
730 stars 118 forks source link

MMPlayerView

paypal

CI Status Version License Platform

Demo-Swift

List / Shrink / Transition / Landscape

list shrink transition landscape

MMPlayerLayer

ex. use when change player view frequently like tableView / collectionView
import MMPlayerView
mmPlayerLayer.playView = cell.imgView
mmPlayerLayer.getStatusBlock { [weak self] (status) in

}
self.mmPlayerLayer.set(url: DemoSource.shared.demoData[indexPath.row].play_Url)
self.mmPlayerLayer.resume()

Transition

##PresentedViewController
1. Set transition config
    required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
        self.mmPlayerTransition.present.pass { (config) in
            // setting
            .....
        }
    }
2. Set MMPLayerToProtocol on PresentedViewController
3. Set MMPlayerPrsentFromProtocol on PresentingViewController

Landscape

1.Set MMPlayerLayer
   // roation screen to landscape can change player to fullscreen
   mmplayerLayer.fullScreenWhenLandscape = true

2. Set from code
   mmplayerLayer.setOrientation(.landsacpeLeft)

3. Observer
  mmPlayerLayer.getOrientationChange { (status) in
        print("Player OrientationChange \(status)")
  }

Cover View

landscape

## add cover item view on player
play.replace(cover: CoverA.instantiateFromNib())

Progress

// Custom your progress view and it will add on player center
// view need to implement ProgressProtocol, and add progress in this view, when start/stop control what need to do
.custom(view: <#T##MMProgressProtocol#>)
 public protocol MMProgressProtocol {
     func start()
     func stop()
 }

Cache

playerLayer.cacheType = .memory(count: 10)
public enum MMPlayerCacheType {
    case none
    case memory(count: Int) // set this to cache seek time in memory and if cache out of count will remove first you    
    stored
}

Layer Protocol

// detect if touch in videoRect
// if touch out of videoRect will not trigger show/hide cover view event
public protocol MMPlayerLayerProtocol: class {

func touchInVideoRect(contain: 

) // 
}

Downloader

        var downloadObservation: MMPlayerObservation?

        downloadObservation = MMPlayerDownloader.shared.observe(downloadURL: downloadURL) { [weak self] (status) in
            switch status {
            case .cancelled:
                print("Canceld")
            case .completed:
                DispatchQueue.main.async {
                    self?.downloadBtn.setTitle("Delete", for: .normal)
                    self?.downloadBtn.isHidden = false
                    self?.progress.isHidden = true
                }
            case .downloading(let value):
                self?.downloadBtn.isHidden = true
                self?.progress.isHidden = false
                self?.progress.progress = value
                print("Exporting \(value) \(downloadURL)")
            case .failed(let err):
                DispatchQueue.main.async {
                    self?.downloadBtn.setTitle("Download", for: .normal)
                }

                self?.downloadBtn.isHidden = false
                self?.progress.isHidden = true
                print("Download Failed \(err)")
            case .none:
                DispatchQueue.main.async {
                    self?.downloadBtn.setTitle("Download", for: .normal)
                }
                self?.downloadBtn.isHidden = false
                self?.progress.isHidden = true
            case .exist:
                DispatchQueue.main.async {
                    self?.downloadBtn.setTitle("Delete", for: .normal)
                }
                self?.downloadBtn.isHidden = false
                self?.progress.isHidden = true
            }

Delete

        if let info = MMPlayerDownloader.shared.localFileFrom(url: downloadURL)  {
            MMPlayerDownloader.shared.deleteVideo(info)
        }

Subtitle

     let subTitleStr = Bundle.main.path(forResource: "test", ofType: "srt")!
         if let str = try? String.init(contentsOfFile: subTitleStr) {
             self.mmPlayerLayer.subtitleSetting.subtitleType = .srt(info: str)
             self.mmPlayerLayer.subtitleSetting.defaultTextColor = .red
             self.mmPlayerLayer.subtitleSetting.defaultFont = UIFont.boldSystemFont(ofSize: 20)
         }
     }

Shrink

    // Return a view which you want back
    self.mmPlayerLayer.shrinkView(onVC: self, isHiddenVC: false) { [weak self] () -> UIView? in
        guard let self = self, let path = self.findCurrentPath() else {return nil}
        let cell = self.findCurrentCell(path: path) as! PlayerCell
        self.mmPlayerLayer.set(url: cell.data!.play_Url)
        self.mmPlayerLayer.resume()
        return cell.imgView
    }
    // Check player is shrink or not
    self.mmPlayerL.isShrink

Demo-SwiftUI

Control

let control = MMPlayerControl()
//Play
control.set(url: self.videoList[idx].play_Url)
control.resume()
//InValidate
control.invalidate()
//Observation parameter
@Published
public var orientation: PlayerOrientation = .protrait
@Published
public var timeInfo = TimeInfo()
@Published
public var isMuted = false
@Published
public var isBackgroundPause = true
@Published
@Published
public var repeatWhenEnd: Bool = false
@Published
public var isLoading: Bool = false
public var cacheType: PlayerCacheType = .none
@Published
public private(set) var isCoverShow = false
@Published
public var autoHideCoverType = CoverAutoHideType.disable
public var coverAnimationInterval = 0.3
@Published
public var error: MMPlayerViewUIError?

Init View

let player = MMPlayerViewUI(control: self.control, cover: CoverAUI())

Download

view.modifier(MMPlayerDownloaderModifier(url: obj.play_Url!, status: $downloadStatus))

Transition Player

//func playerTransition<Content: View>(view: Content, from: CGRect?) -> AnyTransition
if showDetailIdx != nil {
    DetailView(obj: self.playListViewModel.videoList[showDetailIdx!], showDetailIdx: $showDetailIdx)
       .edgesIgnoringSafeArea(.all)
       .transition(.playerTransition(view: MMPlayerViewUI(control: control) ,from: fromFrame))
        .zIndex(1)
}
// Trigger transition
withAnimation { 
      self.fromFrame = obj.frame
      self.showDetailIdx = offset
}

Requirements

iOS 12.0+
Swift 5.0+

Installation

MMPlayerView is available through CocoaPods. To install it, simply add the following line to your Podfile:

Swift 5 
pod 'MMPlayerView'

Author

millmanyang@gmail.com

License

MMPlayerView is available under the MIT license. See the LICENSE file for more info.