248 lines
10 KiB
Swift
248 lines
10 KiB
Swift
////
|
|
//// AVPlayerVM.swift
|
|
//// WOKA
|
|
////
|
|
//// Created by Bilal on 05/07/2024.
|
|
////
|
|
//
|
|
//import UIKit
|
|
//import AVKit
|
|
//
|
|
//class AVPlayerVM{
|
|
//
|
|
// weak var vc : AVPlayerVC!
|
|
//
|
|
// var player : AVPlayer? = nil
|
|
// var isThumbSeek : Bool = false
|
|
// var timer : Timer?
|
|
// var isFinished = false{
|
|
// didSet{
|
|
// if isFinished{
|
|
// timer?.invalidate()
|
|
// timer = nil
|
|
// vc.reloadBtn.isHidden = false
|
|
// vc.stackCtrView.isHidden = true
|
|
// vc.tintView.isHidden = false
|
|
// vc.sliderStack.isHidden = true
|
|
// }else{
|
|
// vc.reloadBtn.isHidden = true
|
|
// vc.stackCtrView.isHidden = false
|
|
// vc.sliderStack.isHidden = false
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// private var playerLayer : AVPlayerLayer? = nil
|
|
// private var timeObserver : Any? = nil
|
|
//
|
|
// func initView(){
|
|
// vc.seekSlider.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
|
|
//
|
|
// self.vc.videoTitle.text = vc.titleVideo
|
|
// setupKaraoke()
|
|
//
|
|
// }
|
|
//
|
|
// @objc func videoDidFinish() {
|
|
// self.isFinished = true
|
|
//
|
|
// }
|
|
//
|
|
// func setupKaraoke(){
|
|
// guard let url = vc.videoURL else{return}
|
|
// hideShowKaraoke(isLoading: true)
|
|
// let avURL = URL(string: url)!
|
|
// let asset = AVAsset(url: avURL)
|
|
//
|
|
// let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(vc.titleVideo?.trimmingCharacters(in: .whitespaces) ?? "extractedAudio").m4a")
|
|
// FileManager.default.clearTmpDirectory()
|
|
// asset.writeAudioTrackToURL(outputURL) { [weak self] isDone, error,url in
|
|
// guard let self else{return}
|
|
// print(isDone, error , url)
|
|
// if error == nil{
|
|
// hideShowKaraoke(isLoading: false)
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// func hideShowKaraoke(isLoading : Bool){
|
|
// DispatchQueue.main.async { [weak self] in
|
|
// guard let self else{return}
|
|
// if isLoading{
|
|
// vc.karaokeLoading.startAnimating()
|
|
// vc.karaokeStack.isHidden = false
|
|
// vc.playPauseRecordStack.isHidden = true
|
|
// }else{
|
|
// vc.karaokeLoading.stopAnimating()
|
|
// vc.karaokeLoading.hidesWhenStopped = true
|
|
// vc.karaokeStack.isHidden = true
|
|
// vc.playPauseRecordStack.isHidden = false
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// // MARK: - Setup Video Player
|
|
//
|
|
// func setVideoPlayer() {
|
|
// guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
|
|
//
|
|
// if self.player == nil {
|
|
//
|
|
// // Create a subview for the video player
|
|
// let playerView = UIView(frame: vc.viewControll.bounds)
|
|
// playerView.backgroundColor = .clear // Make sure the background is clear
|
|
// vc.viewControll.addSubview(playerView)
|
|
// vc.viewControll.sendSubviewToBack(playerView) // Ensure the player view is below other UI elements
|
|
//
|
|
// // Initialize the player
|
|
// let playerItem = AVPlayerItem(url: url)
|
|
// player = AVPlayer(playerItem: playerItem)
|
|
//
|
|
// // Add observer for AVPlayerItemFailedToPlayToEndTimeNotification
|
|
// NotificationCenter.default.addObserver(self,
|
|
// selector: #selector(playerItemFailedToPlayToEndTime(_:)),
|
|
// name: .AVPlayerItemFailedToPlayToEndTime,
|
|
// object: playerItem)
|
|
//
|
|
// // Add observer for AVPlayerItem's status
|
|
// playerItem.addObserver(self.vc,
|
|
// forKeyPath: "status",
|
|
// options: [.new, .initial],
|
|
// context: nil)
|
|
//
|
|
// // Set up the player layer
|
|
// playerLayer = AVPlayerLayer(player: player)
|
|
// playerLayer?.videoGravity = .resizeAspectFill
|
|
// playerLayer?.frame = playerView.bounds
|
|
//
|
|
// if let playerLayer = playerLayer {
|
|
// playerView.layer.addSublayer(playerLayer)
|
|
// }
|
|
//
|
|
// // Add observer for play/pause
|
|
// player?.addObserver(self.vc, forKeyPath: "rate", options: [.new, .initial], context: nil)
|
|
//
|
|
// // Add observer for buffering
|
|
// playerItem.addObserver(self.vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
|
|
// playerItem.addObserver(self.vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
|
|
//
|
|
// // Add observer for video finished playing
|
|
// NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
|
// self.setObserverToPlayer()
|
|
// startTimer()
|
|
// player?.play()
|
|
// }
|
|
// }
|
|
//
|
|
// func reloadVideo() {
|
|
// guard let videoURL = vc.videoURL, let url = URL(string: videoURL) else { return }
|
|
//
|
|
// // Remove existing observers
|
|
// NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
|
|
// player?.currentItem?.removeObserver(vc, forKeyPath: "status")
|
|
// player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackBufferEmpty")
|
|
// player?.currentItem?.removeObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp")
|
|
//
|
|
// // Create a new player item
|
|
// let playerItem = AVPlayerItem(url: url)
|
|
// player?.replaceCurrentItem(with: playerItem)
|
|
//
|
|
// // Add observers again
|
|
// NotificationCenter.default.addObserver(self, selector: #selector(videoDidFinish), name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
|
// playerItem.addObserver(vc, forKeyPath: "status", options: [.new, .initial], context: nil)
|
|
// playerItem.addObserver(vc, forKeyPath: "isPlaybackBufferEmpty", options: [.new, .initial], context: nil)
|
|
// playerItem.addObserver(vc, forKeyPath: "isPlaybackLikelyToKeepUp", options: [.new, .initial], context: nil)
|
|
//
|
|
// player?.play()
|
|
// }
|
|
//
|
|
// func setObserverToPlayer() {
|
|
// let interval = CMTime(seconds: 0.3, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
|
|
// timeObserver = player?.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main, using: { elapsed in
|
|
// self.updatePlayerTime()
|
|
// })
|
|
// }
|
|
//
|
|
//
|
|
// // Handle notification
|
|
// @objc func playerItemFailedToPlayToEndTime(_ notification: Notification) {
|
|
// if let error = notification.userInfo?[AVPlayerItemFailedToPlayToEndTimeErrorKey] as? Error {
|
|
// print("Error: \(error.localizedDescription)")
|
|
// handlePlayerError(error)
|
|
// }
|
|
// }
|
|
//
|
|
// func handlePlayerError(_ error: Error) {
|
|
// // Update the UI or show an alert to the user
|
|
// Utilities.alertWithBtnCompletion(title: "Error", msgBody: error.localizedDescription, okBtnStr: "Retry?", vc: vc.self) { [weak self] isDone in
|
|
// guard let self else{return}
|
|
// player?.play()
|
|
// }
|
|
// }
|
|
//
|
|
// // MARK: - ShowHideControls
|
|
// func startTimer(){
|
|
// timer = Timer.scheduledTimer(withTimeInterval: 4.5, repeats: false) { _ in
|
|
// self.showHideControls()
|
|
// }
|
|
// }
|
|
//
|
|
// func showHideControls(){
|
|
// if isFinished{
|
|
// vc.stackCtrView.isHidden = true
|
|
// vc.reloadBtn.isHidden.toggle()
|
|
// vc.sliderStack.isHidden = true
|
|
// }else{
|
|
// vc.reloadBtn.isHidden = true
|
|
// vc.stackCtrView.isHidden.toggle()
|
|
// vc.sliderStack.isHidden.toggle()
|
|
// }
|
|
//
|
|
// vc.tintView.isHidden.toggle()
|
|
//
|
|
// if !vc.stackCtrView.isHidden{
|
|
// startTimer()
|
|
// }
|
|
// }
|
|
//
|
|
// // MARK: - Update the player time Label with Slider
|
|
//
|
|
// private func updatePlayerTime() {
|
|
// guard let currentTime = self.player?.currentTime() else { return }
|
|
// guard let duration = self.player?.currentItem?.duration else { return }
|
|
//
|
|
// let currentTimeInSecond = CMTimeGetSeconds(currentTime)
|
|
// let durationTimeInSecond = CMTimeGetSeconds(duration)
|
|
//
|
|
// if self.isThumbSeek == false {
|
|
// self.vc.seekSlider.value = Float(currentTimeInSecond/durationTimeInSecond)
|
|
// }
|
|
//
|
|
// let value = Float64(self.vc.seekSlider.value) * CMTimeGetSeconds(duration)
|
|
//
|
|
// var hours = value / 3600
|
|
// var mins = (value / 60).truncatingRemainder(dividingBy: 60)
|
|
// var secs = value.truncatingRemainder(dividingBy: 60)
|
|
// var timeformatter = NumberFormatter()
|
|
// timeformatter.minimumIntegerDigits = 2
|
|
// timeformatter.minimumFractionDigits = 0
|
|
// timeformatter.roundingMode = .down
|
|
// guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
|
|
// return
|
|
// }
|
|
// self.vc.lbCurrentTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
|
|
//
|
|
// hours = durationTimeInSecond / 3600
|
|
// mins = (durationTimeInSecond / 60).truncatingRemainder(dividingBy: 60)
|
|
// secs = durationTimeInSecond.truncatingRemainder(dividingBy: 60)
|
|
// timeformatter = NumberFormatter()
|
|
// timeformatter.minimumIntegerDigits = 2
|
|
// timeformatter.minimumFractionDigits = 0
|
|
// timeformatter.roundingMode = .down
|
|
// guard let hoursStr = timeformatter.string(from: NSNumber(value: hours)), let minsStr = timeformatter.string(from: NSNumber(value: mins)), let secsStr = timeformatter.string(from: NSNumber(value: secs)) else {
|
|
// return
|
|
// }
|
|
// self.vc.lbTotalTime.text = "\(hoursStr):\(minsStr):\(secsStr)"
|
|
// }
|
|
//}
|