我正在使用AVKit向用户显示视频。
当用户选择视频时,将使用AVKit的标准播放器呈现该视频。这使它全屏显示。
如果用户选择将其设置为"画中画",则用户可以继续使用应用程序的其余部分。
这意味着用户可以选择另一个视频进行播放,该视频确实与上一个视频同时播放(全屏(,该视频在画中画中仍然可见。
当选择第二个视频时,我想关闭第一个(PiP(视频,但是,在启动第二个视频之前,我尝试"关闭"前一个视频,但它不起作用。
我认为这是因为它显示为画中画,所以 AVPlayerViewController 不再代表它......
有没有办法简单地做到这一点?
播放视频时(不起作用(尝试终止第一个视频,如果第二个视频正在尝试播放:
func play(FileName filename: String, FileType type: String)
{
if self.isVideoPlaying == YES
{
self.playerController!.dismiss(animated: YES, completion: { self.isVideoPlaying = NO ; self.play(FileName: filename, FileType: type) })
return
}
self.isVideoPlaying = YES
let path = Bundle.main.path(forResource: filename, ofType: type)
let url = NSURL(fileURLWithPath: path!)
let player = AVPlayer(url: url as URL)
...
好的,这是我解决它的方法:
-
具有在播放视频时设置的类属性"isAlreadyPlaying: Bool"...然而
-
在"播放"视频并向AVPlayerViewController呈现(新(视频的方法中,请在开头进行以下检查:
if self.isAlreadyPlaying == YES
{
killVideoPlayer()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5, execute: { self.play(FileName: filename, FileType: type) })
return
}
... Here you put the normal play / present code
在"killVideoPlayer(("方法中,将属性"isAlreadyPlaying"设置为NO/false。
即
(仅供那些还不知道的人(,这是 kill 函数:
private func killVideoPlayer()
{
self.isAlreadyPlaying = NO
self.playerController?.player?.pause()
self.playerController?.player = nil
let audioSession = AVAudioSession.sharedInstance()
do
{
try audioSession.setActive(false, options: .notifyOthersOnDeactivation)
try audioSession.setCategory(.soloAmbient)
}
catch
{
print("Audio session failed")
}
self.playerController?.dismiss(animated: YES, completion:
{
self.playerController = nil
})
}
SwiftUI 和 UIViewControllerRepresentable
我的问题是,我想在播放新视频时关闭播放的最后一个画中画视频。 我使用 Combine 和AVPlayerViewControllerDelegate的函数解决了它。
协调器跟踪当前播放的视频的 PIP 状态,并将该 AVPlayerViewController 存储在管理器单例中,以防视频处于 PIP 中。播放新视频后,已存储的AVPlayerViewController将被关闭。
struct PlayerView: UIViewControllerRepresentable {
private let playerViewController: AVPlayerViewController = {
AVPlayerViewController()
}()
public func makeCoordinator() -> Coordinator {
Coordinator()
}
func makeUIViewController(context: Context) -> AVPlayerViewController {
playerViewController.delegate = context.coordinator
context.coordinator.playerController = playerViewController
return playerViewController
}
func updateUIViewController(_ playerController: AVPlayerViewController, context: Context) { }
class Coordinator: NSObject, AVPlayerViewControllerDelegate {
weak var playerController: AVPlayerViewController? {
didSet {
playerController?.delegate = self
}
}
private var cancellables: Set<AnyCancellable> = Set<AnyCancellable>()
private var videoisPlayedInPip = PassthroughSubject<Bool, Never>()
private var pictureInPictureManager: VideoPlayerPictureInPictureManager = .shared
init() {
super.init()
handlePictureInPictureChanges()
}
private func handlePictureInPictureChanges() {
//Dismiss video played in PIP when a new video is played
self.pictureInPictureManager.closeLastPipPlayer()
// Update new video played in PIP
videoisPlayedInPip.sink { [weak self] isInPip in
guard let self else { return }
if isInPip {
self.pictureInPictureManager.updateLastPiPAVPlayerVC(self.playerController)
} else {
self.pictureInPictureManager.updateLastPiPAVPlayerVC(nil)
}
}
.store(in: &cancellables)
}
func playerViewControllerWillStartPictureInPicture(_ playerViewController: AVPlayerViewController) {
videoisPlayedInPip.send(true)
}
func playerViewControllerWillStopPictureInPicture(_ playerViewController: AVPlayerViewController) {
videoisPlayedInPip.send(false)
}
}
}
class VideoPlayerPictureInPictureManager {
public static let shared = VideoPlayerPictureInPictureManager()
private(set) var lastPiPAVPlayerVC: AVPlayerViewController?
//Dismiss video played in PIP
public func closeLastPipPlayer() {
lastPiPAVPlayerVC?.dismiss(animated: false)
lastPiPAVPlayerVC?.player?.pause()
lastPiPAVPlayerVC?.player = nil
DispatchQueue.main.async { [weak self] in
self?.lastPiPAVPlayerVC?.dismiss(animated: true, completion: {
self?.updateLastPiPAVPlayerVC(nil)
})
}
}
//Update new video played in PIP
public func updateLastPiPAVPlayerVC(_ vc: AVPlayerViewController?) {
self.lastPiPAVPlayerVC = vc
}
}