diff --git a/WOKA.xcodeproj/project.pbxproj b/WOKA.xcodeproj/project.pbxproj index 955a7e2..7642746 100644 --- a/WOKA.xcodeproj/project.pbxproj +++ b/WOKA.xcodeproj/project.pbxproj @@ -233,6 +233,7 @@ 9C834ED72C1C1F9200B29A9C /* Exo2-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8332BDBC3EF00E4CA14 /* Exo2-Regular.ttf */; }; 9C834ED82C1C1F9200B29A9C /* Exo2-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9C56E8312BDBC3EF00E4CA14 /* Exo2-Thin.ttf */; }; 9C834EDC2C1C26CD00B29A9C /* HtmlText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C834EDB2C1C26CD00B29A9C /* HtmlText.swift */; }; + 9C8446872C40FC6E003E3E53 /* AVPlayerTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C8446862C40FC6E003E3E53 /* AVPlayerTesting.swift */; }; 9C8C4FAE2C1315410017DD3B /* WebViewVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C8C4FAD2C1315410017DD3B /* WebViewVC.swift */; }; 9C8C4FB02C1328060017DD3B /* Disclaimer.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 9C8C4FAF2C1328060017DD3B /* Disclaimer.rtf */; }; 9C9BEEC72BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */; }; @@ -505,6 +506,7 @@ 9C834EC52C1C1D9500B29A9C /* BlogDetailsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDetailsVC.swift; sourceTree = ""; }; 9C834ED92C1C20EC00B29A9C /* WOKA.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WOKA.entitlements; sourceTree = ""; }; 9C834EDB2C1C26CD00B29A9C /* HtmlText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HtmlText.swift; sourceTree = ""; }; + 9C8446862C40FC6E003E3E53 /* AVPlayerTesting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVPlayerTesting.swift; sourceTree = ""; }; 9C8C4FAD2C1315410017DD3B /* WebViewVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewVC.swift; sourceTree = ""; }; 9C8C4FAF2C1328060017DD3B /* Disclaimer.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Disclaimer.rtf; sourceTree = ""; }; 9C9BEEC62BEE1BBF004ECC2F /* CollectionViewCenteredFlowLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewCenteredFlowLayout.swift; sourceTree = ""; }; @@ -1391,6 +1393,7 @@ 52F4E8652C3D123B00778FBC /* JWKaraokePlayerVC.swift */, 525FC61C2C3D3DC30049145D /* AVAssetMods.swift */, 525FC65C2C3D57D80049145D /* TestingKaraokeVC.swift */, + 9C8446862C40FC6E003E3E53 /* AVPlayerTesting.swift */, ); path = Controller; sourceTree = ""; @@ -1764,6 +1767,7 @@ 52BC3BF02C1701F8002FACA6 /* BlogDM.swift in Sources */, 525954192BE8CC3400191286 /* ConstantString.swift in Sources */, 52D774EB2BDFC0BF001D87DE /* OTPVC.swift in Sources */, + 9C8446872C40FC6E003E3E53 /* AVPlayerTesting.swift in Sources */, 52AF71F42C36C40B00BC5972 /* GamesWebViewVC.swift in Sources */, 9C007F202C255DF200F798C2 /* SeasonEpisodeListingDM.swift in Sources */, 52D2F3D82C24043D009E52FF /* ShimmerEffectView.swift in Sources */, diff --git a/WOKA/Karaoke/Controller/AVPlayerTesting.swift b/WOKA/Karaoke/Controller/AVPlayerTesting.swift new file mode 100644 index 0000000..13d8aa3 --- /dev/null +++ b/WOKA/Karaoke/Controller/AVPlayerTesting.swift @@ -0,0 +1,22 @@ +// +// AVPlayerTesting.swift +// WOKA +// +// Created by Bilal on 12/07/2024. +// + +import UIKit +import AVKit + +class AVPlayerTesting: AVPlayerViewController { + + override func viewDidLoad() { + super.viewDidLoad() + let videoURL = URL(string: "https://content.jwplatform.com/videos/699dmCGz-Ysj2G4DQ.mp4")! + let player = AVPlayer(url: videoURL) + self.player = player + player.play() + // Do any additional setup after loading the view. + } + +} diff --git a/WOKA/Karaoke/Controller/JWKaraokePlayerVC.swift b/WOKA/Karaoke/Controller/JWKaraokePlayerVC.swift index e198a63..6fddab7 100644 --- a/WOKA/Karaoke/Controller/JWKaraokePlayerVC.swift +++ b/WOKA/Karaoke/Controller/JWKaraokePlayerVC.swift @@ -12,56 +12,65 @@ import AVFoundation class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate { - @IBOutlet weak var outerStack: UIStackView! @IBOutlet weak var backButton: UIButton! @IBOutlet weak var startRecordBtn: LocalisedElementsButton! @IBOutlet weak var playBtn: LocalisedElementsButton! @IBOutlet weak var downloadRecordingBtn: LocalisedElementsButton! + @IBOutlet weak var karaokeStack: UIStackView! + @IBOutlet weak var karaokeLoading: UIActivityIndicatorView! + @IBOutlet weak var startStopRecordingStack: UIStackView! + @IBOutlet weak var outerStack : UIStackView! var config: JWPlayerConfiguration! var dismissTapped: (() -> Void)? - var videoIndex : Int? - var documentAudioUrl : URL? + + var audioURLFromMP4 : URL? var recordedAudioURL: URL? var audioRecorder: AVAudioRecorder? + var videoTitle : String? + var videoUrl : String? + + var mixedAudioURL: URL? var isRecording = false - var playerAV : AVAudioPlayer? + var isPlaying = false - var mixedAudioURL: URL? { - didSet{ - do{ - let sPlayer = try AVAudioPlayer(contentsOf: self.mixedAudioURL!) - self.playerAV = sPlayer - self.playerAV?.prepareToPlay() -// self.playerAV?.play() - }catch{ - - } - } - } + var startTime : TimeInterval? + var endTime : TimeInterval? + + var audioPlayer = AVPlayer() override func viewDidLoad() { super.viewDidLoad() - player.configurePlayer(with: config) - self.delegate = self - //Disable Picture in Picture playerView.allowsPictureInPicturePlayback = false playerView.captionStyle = .none self.view.bringSubviewToFront(outerStack) self.view.bringSubviewToFront(backButton) - setupRecorder() + setupKaraoke() } - func setupRecorder(){ + // MARK: - AudioRecording + + func setupAudio() { +// FileManager.default.clearTmpDirectory() + let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory(.playAndRecord, mode: .default,options: .defaultToSpeaker) try audioSession.setActive(true) +// // URL of the downloaded M4A file +// guard let audioURL = Bundle.main.url(forResource: "Sample_audio", withExtension: "m4a") else { +// print("Audio file not found.") +// return +// } + + // Initialize AVAudioPlayer with the downloaded M4A file +// player = try AVAudioPlayer(contentsOf: audioURLFromMP4!) +// player?.prepareToPlay() // Define settings for the audio recorder let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! @@ -83,63 +92,148 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate } func startRecording() { - guard let player = player, let audioRecorder = audioRecorder else { return } - player.play() + startTime = self.player.time.position.round(to: 1) + self.interfaceBehavior = .hidden + guard let audioRecorder = audioRecorder else { return } audioRecorder.record() + } func stopRecording() { - guard let player = player, let audioRecorder = audioRecorder else { return } - player.pause() // Pause playback instead of stopping it + endTime = self.player.time.position.round(to: 1) + self.interfaceBehavior = .normal + guard let audioRecorder = audioRecorder else { return } audioRecorder.stop() - + self.player.pause() // Mix the recorded audio with the downloaded M4A file - mixAudio() + guard let startTime , let endTime else{return} + mixAudio(start: startTime, stop: endTime) } - func mixAudio() { + + func mixAudio(start : TimeInterval, stop : TimeInterval) { + let totalTime = stop - start guard let recordedAudioURL = recordedAudioURL else { return } -// guard let playerURL = Bundle.main.url(forResource: "Sample_audio", withExtension: "m4a") else { return } - guard let playerURL = documentAudioUrl else{return} + guard let playerURL = audioURLFromMP4 else { return } + Utilities.startProgressHUD(msg: "Mixing Audio") let composition = AVMutableComposition() + let compositionDuration = CMTime(seconds: totalTime, preferredTimescale: 1) - // Add the recorded audio + // Add the recorded audio from 0 to 10 seconds let recordedAudioAsset = AVURLAsset(url: recordedAudioURL) let recordedAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) + do { - try recordedAudioTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: recordedAudioAsset.duration), of: recordedAudioAsset.tracks(withMediaType: .audio)[0], at: CMTime.zero) + try recordedAudioTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: compositionDuration), of: recordedAudioAsset.tracks(withMediaType: .audio)[0], at: CMTime.zero) } catch { + Utilities.dismissProgressHUD() print("Error adding recorded audio track: \(error.localizedDescription)") } - // Add the downloaded M4A file + // Add the downloaded M4A file from 10 to 20 seconds let playerAsset = AVURLAsset(url: playerURL) let playerTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) do { - try playerTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: playerAsset.duration), of: playerAsset.tracks(withMediaType: .audio)[0], at: CMTime.zero) + try playerTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime(seconds: start, preferredTimescale: 1), duration: compositionDuration), of: playerAsset.tracks(withMediaType: .audio)[0], at: CMTime.zero) } catch { + Utilities.dismissProgressHUD() print("Error adding player audio track: \(error.localizedDescription)") } + // Example usage: + + // Export the mixed audio let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! - mixedAudioURL = documentsDirectory.appendingPathComponent("mixedAudio.m4a") + let filePath = documentsDirectory.appendingPathComponent("mixedAudio.m4a") + deleteFileIfExist(at: filePath) + + mixedAudioURL = filePath +// mixedAudioURL = documentsDirectory.appendingPathComponent("mixedAudio.m4a") + guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) else { return } exportSession.outputURL = mixedAudioURL exportSession.outputFileType = .m4a + exportSession.exportAsynchronously { if exportSession.status == .completed { print("Mixing audio completed.") + Utilities.dismissProgressHUD() + DispatchQueue.main.async { + self.playBtn.isEnabled = true + } + - self.saveToFilesApp() - // Play the mixed audio if needed } else if exportSession.status == .failed { - print("Mixing audio failed.") + print("Mixing audio failed.", exportSession.error?.localizedDescription) } } } + func deleteFileIfExist(at url: URL) { + let fileManager = FileManager.default + + do { + // Check if the file exists + if fileManager.fileExists(atPath: url.path) { + // Attempt to delete the file + try fileManager.removeItem(at: url) + print("File deleted successfully.") + } else { + print("File does not exist at path: \(url.path)") + } + } catch { + print("Error deleting file: \(error.localizedDescription)") + } + } + + + +// func mixAudio() { +// guard let recordedAudioURL = recordedAudioURL else { return } +// guard let playerURL = audioURLFromMP4 else{return} +// let composition = AVMutableComposition() +// +// // Add the recorded audio +// let recordedAudioAsset = AVURLAsset(url: recordedAudioURL) +// let recordedAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) +// do { +// try recordedAudioTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: recordedAudioAsset.duration), of: recordedAudioAsset.tracks(withMediaType: .audio)[0], at: CMTime.zero) +// } catch { +// print("Error adding recorded audio track: \(error.localizedDescription)") +// } +// +// // Add the downloaded M4A file +// let playerAsset = AVURLAsset(url: playerURL) +// let playerTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) +// +// do { +// try playerTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: playerAsset.duration), of: playerAsset.tracks(withMediaType: .audio)[0], at: CMTime.zero) +// } catch { +// print("Error adding player audio track: \(error.localizedDescription)") +// } +// +// // Export the mixed audio +// let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! +// mixedAudioURL = documentsDirectory.appendingPathComponent("mixedAudio.m4a") +// guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) else { return } +// exportSession.outputURL = mixedAudioURL +// exportSession.outputFileType = .m4a +// exportSession.exportAsynchronously { +// if exportSession.status == .completed { +// print("Mixing audio completed.") +// +// self.saveToFilesApp() +// // Play the mixed audio if needed +// +// +// } else if exportSession.status == .failed { +// print("Mixing audio failed.") +// } +// } +// } + func saveToFilesApp() { guard let mixedAudioURL = mixedAudioURL else { return } DispatchQueue.main.async { @@ -149,6 +243,40 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate } } + func setupKaraoke(){ + guard let videoUrl else{return} + let avURL = URL(string: videoUrl)! + let asset = AVAsset(url: avURL) + hideShowKaraoke(isLoading: true) + let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(videoTitle?.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) + self.audioURLFromMP4 = url + self.setupAudio() + } + } + } + + func hideShowKaraoke(isLoading : Bool){ + DispatchQueue.main.async { [weak self] in + guard let self else{return} + if isLoading{ + karaokeLoading.startAnimating() + karaokeStack.isHidden = false + startStopRecordingStack.isHidden = true + }else{ + karaokeLoading.stopAnimating() + karaokeLoading.hidesWhenStopped = true + karaokeStack.isHidden = true + startStopRecordingStack.isHidden = false + } + } + } + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // self.navigationController?.isNavigationBarHidden = true @@ -160,20 +288,13 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate } @IBAction func startRecordingBtnTapped(_ sender: LocalisedElementsButton) { -// if sender.titleLabel?.text?.lowercased() == "start recording"{ -// guard let audioRecorder else { return } -// startRecordBtn.setTitle("Stop Recording", for: .normal) -// audioRecorder.record() -// }else{ -// guard let audioRecorder else { return } -// startRecordBtn.setTitle("Stop Recording", for: .normal) -// audioRecorder.record() -// } - + self.playBtn.isEnabled = false if isRecording { stopRecording() + self.interfaceBehavior = .normal sender.setTitle("Start Recording", for: .normal) } else { + self.interfaceBehavior = .hidden startRecording() sender.setTitle("Stop Recording", for: .normal) } @@ -181,12 +302,57 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate } @IBAction func playBtnTapped(_ sender: LocalisedElementsButton) { - playerAV?.play() + if !isPlaying { + playMixedAudio() + self.interfaceBehavior = .normal + self.interfaceBehavior = .hidden + sender.setTitle("Pause", for: .normal) + } else { + self.interfaceBehavior = .normal + sender.setTitle("Play", for: .normal) + } + + isPlaying.toggle() + + self.player.pause() + print("Play") + } + func playMixedAudio() { + guard let mixedAudioURL = mixedAudioURL else { return } + + do { + + let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + + let destinationURL = documentsDirectoryURL.appendingPathComponent("xyze.m4a") + + do { + + try FileManager.default.copyItem(at: mixedAudioURL, to: destinationURL) + + } catch + let error as NSError { print(error.localizedDescription)} + + let playerKAraoke = AVPlayer(url: destinationURL) + playerKAraoke.volume = 1.0 + playerKAraoke.play() + +// // Configure the audio session +// let audioSession = AVAudioSession.sharedInstance() +// try audioSession.setCategory(.playAndRecord, mode: .default, options: [.defaultToSpeaker]) +// try audioSession.setActive(true) +// +// let audioPlayer = try AVAudioPlayer(contentsOf: mixedAudioURL) +// audioPlayer.volume = 1.0 +// audioPlayer.play() + } catch { + print("Error playing mixed audio: \(error.localizedDescription)") + } } - @IBAction func downloadRecording(_ sender: LocalisedElementsButton) { print("DownloadRecording") + self.saveToFilesApp() } @IBAction func backBtnTapped(_ sender: UIButton) { self.player.stop() @@ -259,8 +425,29 @@ class JWKaraokePlayerVC: JWPlayerViewController, JWPlayerViewControllerDelegate } extension JWKaraokePlayerVC: UIDocumentPickerDelegate { + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { - // Handle document picking completion if needed + deleteTemporaryFile() + +// guard let selectedURL = urls.first else { return } +// do { +// try FileManager.default.moveItem(at: fileURL, to: selectedURL) +// } catch { +// print("Error saving file to Files app: \(error)") +// } + } + // Method to delete the temporary file + func deleteTemporaryFile() { + let tempFileURL = audioURLFromMP4! + do { + try FileManager.default.removeItem(at: tempFileURL) + print("Temporary file deleted successfully.") + } catch { + print("Error deleting temporary file: \(error.localizedDescription)") + } + } + func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { + print("Document picker was cancelled") } } // MARK: - Full Screen Handling @@ -350,3 +537,96 @@ extension JWKaraokePlayerVC { print("Item ", item) } } + + +//OLD Code +//private var audioEngine: AVAudioEngine! +// private var audioFile: AVAudioFile! +// private var audioPlayerNode: AVAudioPlayerNode! +// private var recordedAudioFile: AVAudioFile! +//private var recordingURL: URL! +// +//private func setupAudioEngine() { +// audioEngine = AVAudioEngine() +// audioPlayerNode = AVAudioPlayerNode() +// +// audioEngine.attach(audioPlayerNode) +// let format = audioEngine.mainMixerNode.outputFormat(forBus: 0) +// audioEngine.connect(audioPlayerNode, to: audioEngine.mainMixerNode, format: format) +//} +// +//private func startRecording() { +// let format = audioEngine.mainMixerNode.outputFormat(forBus: 0) +// let outputFileURL = FileManager.default.temporaryDirectory.appendingPathComponent("savedRecordedAudio.m4a") +// recordingURL = outputFileURL +// +// do { +// recordedAudioFile = try AVAudioFile(forWriting: outputFileURL, settings: format.settings) +// } catch { +// print("Error creating audio file for recording: \(error)") +// return +// } +// +// audioEngine.mainMixerNode.installTap(onBus: 0, bufferSize: 1024, format: format) { (buffer, time) in +// do { +// try self.recordedAudioFile?.write(from: buffer) +// } catch { +// print("Error writing audio buffer: \(error)") +// } +// } +// +// do { +// try audioEngine.start() +// } catch { +// print("Error starting audio engine: \(error)") +// return +// } +// +// audioPlayerNode.play() +//} +// +//private func stopRecording() { +// audioEngine.mainMixerNode.removeTap(onBus: 0) +// audioPlayerNode.stop() +// audioEngine.stop() +// guard let mixedAudioURL = recordingURL else { return } +// playAudio(at: mixedAudioURL) +//// presentDocumentPicker() +// } +// +//private func playAudio(at url: URL) { +// do { +// let audioPlayer = try AVAudioPlayer(contentsOf: url) +// audioPlayer.play() +// } catch { +// print("Error playing audio: \(error)") +// } +//} +// +//private func getDocumentsDirectory() -> URL { +// return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] +//} +// +//private func presentDocumentPicker() { +// guard let mixedAudioURL = recordingURL else { return } +// DispatchQueue.main.async { +// let documentPicker = UIDocumentPickerViewController(url: mixedAudioURL, in: .exportToService) +// documentPicker.delegate = self +// self.present(documentPicker, animated: true, completion: nil) +// } +//} +// +//private func saveRecordingToFile() { +// let fileManager = FileManager.default +// let documentsURL = getDocumentsDirectory().appendingPathComponent("savedRecordedAudio.m4a") +// +// do { +// if fileManager.fileExists(atPath: documentsURL.path) { +// try fileManager.removeItem(at: documentsURL) +// } +// try fileManager.moveItem(at: recordingURL, to: documentsURL) +// print("Recording saved to: \(documentsURL)") +// } catch { +// print("Error saving recording: \(error)") +// } +//} diff --git a/WOKA/Karaoke/Controller/KaraokeDetailsVC.swift b/WOKA/Karaoke/Controller/KaraokeDetailsVC.swift index ef031dc..a6229d3 100644 --- a/WOKA/Karaoke/Controller/KaraokeDetailsVC.swift +++ b/WOKA/Karaoke/Controller/KaraokeDetailsVC.swift @@ -161,9 +161,10 @@ class KaraokeDetailsVC: UIViewController { @IBAction func playNowBtnTapped(_ sender: LocalisedElementsButton) { // let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) -// let vcPush = sb.instantiateViewController(withIdentifier: "TestingKaraokeVC") as! TestingKaraokeVC +// let vcPush = sb.instantiateViewController(withIdentifier: "AVPlayerTesting") as! AVPlayerTesting // self.present(vcPush, animated: true) // return + var itemBuild = JwPlayerItemCreate(url: "") if AuthFunc.shareInstance.getDefaultLanguage() == .english{ @@ -181,16 +182,56 @@ class KaraokeDetailsVC: UIViewController { DispatchQueue.main.async { [weak self] in guard let self else{return} Utilities.startProgressHUD() + FileManager.default.clearTmpDirectory() let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) - let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.aVPlayerVC) as! AVPlayerVC - vc.videoURL = itemBuild.url - vc.titleVideo = itemBuild.titles - vc.modalPresentationStyle = .fullScreen - self.present(vc, animated: true) + let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.jwKaraokePlayerVC) as! JWKaraokePlayerVC + do { + + // Create a JWPlayerItem + let item = try JWPlayerItemBuilder() + .file(URL(string: itemBuild.url)!) + .posterImage(URL(string: itemBuild.poster ?? "")!) + .title(itemBuild.titles ?? "Karaoke") + .build() + + // Create a JWPlayerConfiguration + let config = try JWPlayerConfigurationBuilder() + .playlist(items: [item]) + .autostart(true) + .build() + + vc.config = config + vc.videoTitle = itemBuild.titles + vc.videoUrl = itemBuild.url + + vc.modalPresentationStyle = .overFullScreen + vc.modalTransitionStyle = .crossDissolve +// vc.documentAudioUrl = url + Utilities.dismissProgressHUD() + // Present the PlayerVC + self.present(vc, animated: true) + } catch { + print("Error creating JWPlayer configuration: \(error)") + Utilities.dismissProgressHUD() + } + // Dismiss the progress HUD after the view controller presentation Utilities.dismissProgressHUD() } +// DispatchQueue.main.async { [weak self] in +// guard let self else{return} +// Utilities.startProgressHUD() +// let sb = UIStoryboard(name: K.StoryBoard.Karaoke, bundle: nil) +// let vc = sb.instantiateViewController(withIdentifier: K.StoryBoardID.Karaoke.aVPlayerVC) as! AVPlayerVC +// vc.videoURL = itemBuild.url +// vc.titleVideo = itemBuild.titles +// vc.modalPresentationStyle = .fullScreen +// self.present(vc, animated: true) +// // Dismiss the progress HUD after the view controller presentation +// Utilities.dismissProgressHUD() +// +// } } diff --git a/WOKA/Karaoke/Karaoke.storyboard b/WOKA/Karaoke/Karaoke.storyboard index e4c89ef..dd80233 100644 --- a/WOKA/Karaoke/Karaoke.storyboard +++ b/WOKA/Karaoke/Karaoke.storyboard @@ -21,6 +21,14 @@ + + + + + + + + @@ -602,7 +610,7 @@ - + @@ -825,7 +833,7 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + - + - - + + + - - - - - + + + + + + +