BeeReel/BeeReel/Lib/Player/BRPlayer.swift
2025-07-29 17:43:43 +08:00

201 lines
5.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// BRPlayer.swift
// BeeReel
//
// Created by 鸿 on 2025/6/24.
//
import UIKit
import SJBaseVideoPlayer
@objc protocol BRPlayerDelegate: NSObjectProtocol {
@objc optional func br_playerReadyToPlay(_ player: BRPlayer)
///
@objc optional func br_playerDurationDidChange(_ player: BRPlayer, duration: TimeInterval)
///
@objc optional func br_playerCurrentTimeDidChange(_ player: BRPlayer, time: TimeInterval)
///
@objc optional func br_playerDidPlayFinish(_ player: BRPlayer)
///
@objc optional func br_playerInBufferToPlay(_ player: BRPlayer)
///
@objc optional func br_playerBufferingCompleted(_ player: BRPlayer)
}
class BRPlayer: NSObject {
private(set) var isPlaying = false
private lazy var player: SJBaseVideoPlayer = {
let player = SJBaseVideoPlayer()
player.autoplayWhenSetNewAsset = false
player.resumePlaybackWhenAppDidEnterForeground = false
player.accurateSeeking = true
player.videoGravity = .resizeAspectFill
// player.disableVolumeSetting = true
player.rotationManager?.isDisabledAutorotation = true
player.controlLayerDataSource = self
player.resumePlaybackWhenPlayerHasFinishedSeeking = false
return player
}()
weak var delegate: BRPlayerDelegate?
weak var playerView: UIView? {
didSet {
playerView?.addSubview(player.view)
player.view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
}
private(set) weak var br_controlView: BRPlayerControlProtocol?;
var coverImageView: UIImageView? {
return self.player.presentView.placeholderImageView
}
var isLoop = false
///
var duration: TimeInterval {
return self.player.duration
}
var currentTime: TimeInterval {
return self.player.currentTime
}
var rate: Float {
get {
return self.player.rate
}
set {
self.player.rate = newValue
}
}
deinit {
brLog(message: "播放器销毁")
}
init(controlView: BRPlayerControlProtocol?) {
super.init()
self.br_controlView = controlView
setupPlayer()
}
func setPlayUrl(url: String) {
self.stop()
guard let url = URL(string: url) else { return }
guard let proxyUrl = BRPlayerCache.proxyURL(url: url) else { return }
let asset = SJVideoPlayerURLAsset(url: proxyUrl)
self.player.urlAsset = asset
}
func start() {
self.isPlaying = true
self.player.play()
}
func pause() {
self.isPlaying = false
self.player.pause()
}
///
// func pauseForUser() {
// self.isPlaying = false
// self.player.pauseForUser()
// }
func stop() {
self.isPlaying = false
self.player.stop()
}
func replay() {
player.replay()
}
func seek(toTime: TimeInterval) {
self.player.seek(toTime: toTime)
}
}
extension BRPlayer {
private func setupPlayer() {
//
self.player.gestureController.supportedGestureTypes = .singleTap
self.player.gestureController.singleTapHandler = { [weak self] _, _ in
guard let self = self else { return }
self.br_controlView?.singleTapEvent()
}
//
self.player.playbackObserver.playbackDidFinishExeBlock = { [weak self] player in
guard let self = self else { return }
if self.isLoop {
self.replay()
} else {
self.delegate?.br_playerDidPlayFinish?(self)
}
}
//
self.player.playbackObserver.playbackStatusDidChangeExeBlock = { [weak self] player in
guard let self = self else { return }
}
//
self.player.playbackObserver.timeControlStatusDidChangeExeBlock = { [weak self] player in
guard let self = self else { return }
if player.timeControlStatus == .waitingToPlay {//
self.delegate?.br_playerInBufferToPlay?(self)
brLog(message: "=======缓冲中 === \(player.reasonForWaitingToPlay ?? "")")
} else if player.timeControlStatus == .playing {
self.delegate?.br_playerBufferingCompleted?(self)
brLog(message: "=======缓冲完成")
}
}
self.player.playbackObserver.assetStatusDidChangeExeBlock = { [weak self] player in
guard let self = self else { return }
brLog(message: "assetStatus === \(player.assetStatus.rawValue)")
if player.assetStatus == .readyToPlay {
self.delegate?.br_playerReadyToPlay?(self)
}
}
//
self.player.playbackObserver.durationDidChangeExeBlock = { [weak self] player in
guard let self = self else { return }
self.delegate?.br_playerDurationDidChange?(self, duration: player.duration)
}
//
self.player.playbackObserver.currentTimeDidChangeExeBlock = { [weak self] player in
guard let self = self else { return }
self.delegate?.br_playerCurrentTimeDidChange?(self, time: player.currentTime)
}
}
}
//MARK: -------------- SJVideoPlayerControlLayerDataSource --------------
extension BRPlayer: SJVideoPlayerControlLayerDataSource {
func controlView() -> UIView! {
return self.br_controlView as? UIView
}
}