iOS畫中畫播放視頻

畫中畫功能iOS9就有了,以前只能在iPad上使用,iOS14開始在iPhone上也可以使用了,一直沒有這方面的需求也沒有具體的研究,不過畢竟是蘋果官方的東西,相信實(shí)現(xiàn)起來(lái)不會(huì)麻煩,有2種辦法來(lái)實(shí)現(xiàn)。前提都需要工程配置一定要對(duì)?。。?/p>

工程配置

配置BackgroundMode
//  開啟后臺(tái)播放權(quán)限
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];

1. 使用AVPlayerViewController

如果使用的是AVPlayerViewController,只要AVAudioSessionBackgroundMode配置對(duì)就默認(rèn)支持的,不用做其他任何操作。雖然很簡(jiǎn)單,但是相信很少人會(huì)直接用這個(gè)方式,幾乎所有的項(xiàng)目都會(huì)自定義播放器,而不是直接使用系統(tǒng)的這個(gè)全屏播放器。

2. 使用AVPictureInPictureController

使用AVPictureInPictureController承接自己寫的播放器的AVPlayerLayer即可實(shí)現(xiàn),先放出來(lái)一個(gè)官方鏈接??梢灾苯尤タ聪嚓P(guān)API。
在API中可以看到有一個(gè)根據(jù)AVPlayerLayer來(lái)初始化Controller的方法:

/*!
    @method     initWithPlayerLayer:
    @param      playerLayer
                The player layer from which to source the media content for the Picture in Picture controller.
    @abstract   Initialize the picture in picture controller with a player layer.
 */
- (nullable instancetype)initWithPlayerLayer:(AVPlayerLayer *)playerLayer;

我們就在ViewController中簡(jiǎn)單粗暴的來(lái)一個(gè)AVPlayer播放一個(gè)視頻嘗試一下,剛開始的思路是這樣的,先播放視頻,當(dāng)用戶將要退到后臺(tái)的時(shí)候,初始化AVPictureInPictureController并且啟動(dòng)畫中畫,后來(lái)實(shí)測(cè)發(fā)現(xiàn)這樣是行不通,初始化AVPictureInPictureController的動(dòng)作必須提前,然后在需要開啟或者停止畫中畫功能,下面的代碼是實(shí)現(xiàn)了在播放視頻的時(shí)候已經(jīng)初始化了AVPictureInPictureController,然后在應(yīng)用將要退到后臺(tái)的時(shí)候開啟畫中畫播放視頻,用戶回到前臺(tái)后停止畫中畫,AVPictureInPictureControllerDelegate中有一些相關(guān)的代理方法,全是可選實(shí)現(xiàn),基本上用不到,可以根據(jù)自己的需要進(jìn)行實(shí)現(xiàn):

#import <AVKit/AVKit.h>
@interface ViewController ()<AVPictureInPictureControllerDelegate>
@property(nonatomic,strong)AVPlayerItem *playItem;
@property(nonatomic,strong)AVPlayer *player;
@property(nonatomic,strong)AVPlayerLayer *playerLayer;
@property(nonatomic,strong)AVPictureInPictureController *pictureInPictureController;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
//    https://qiniu.hongwan.com.cn/hongwan/v/1982wi5b4690f4rqbd9kk.mp4  橫屏
//    https://qiniu.hongwan.com.cn/hongwan/v/990g76sj2wvedbs53vji.mp4   豎屏
    
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error:nil];

    NSString *urlStr  =@"https://qiniu.hongwan.com.cn/hongwan/v/990g76sj2wvedbs53vji.mp4";
    self.playItem = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:urlStr]];
    self.player = [[AVPlayer alloc] initWithPlayerItem:self.playItem];
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
     _playerLayer.frame = self.view.frame;
    _playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    [self.view.layer addSublayer:_playerLayer];
    [self.playItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willResignActive) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
//   監(jiān)聽實(shí)現(xiàn)循環(huán)播放
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(loopPlay:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];

    self.pictureInPictureController = [[AVPictureInPictureController alloc] initWithPlayerLayer:self.playerLayer];
    self.pictureInPictureController.delegate = self;
}
-(void)loopPlay:(NSNotification *)notification
{
    if (!notification.object) {
        return;
    }
    AVPlayerItem *item = (AVPlayerItem *)notification.object;
    __weak __typeof(&*self)weakSelf = self;
    [item seekToTime:kCMTimeZero completionHandler:^(BOOL finished) {
        if (finished) {
            [weakSelf.player play];
        }
    }];

}
-(void)willResignActive
{
    if ([AVPictureInPictureController isPictureInPictureSupported]) {
        if (self.pictureInPictureController.isPictureInPictureActive) {
            [self.pictureInPictureController stopPictureInPicture];
        } else {
            [self.pictureInPictureController startPictureInPicture];
        }
    }
}
-(void)didBecomeActive
{
    if ([AVPictureInPictureController isPictureInPictureSupported]) {
        if (self.pictureInPictureController.isPictureInPictureActive) {
            [self.pictureInPictureController stopPictureInPicture];
        }
    }
}
#pragma mark -------播放屬性監(jiān)聽--------
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"status"]) {
        switch (self.playItem.status) {
            case AVPlayerStatusReadyToPlay:
                if (!self.player.timeControlStatus || self.player.timeControlStatus != AVPlayerTimeControlStatusPaused) {
                    [self.player play];
                }
                break;
            default:
                break;
        }
    }
}

可能有的同學(xué)會(huì)用到一個(gè)很流行的視頻播放框架ZFPlayer,需要將實(shí)現(xiàn)ZFPlayerMediaPlayback協(xié)議的PlayerManager,將內(nèi)部的avLayer拋出來(lái),然后用這個(gè)layer來(lái)初始化AVPictureInPictureController即可。

以上就是項(xiàng)目中簡(jiǎn)單實(shí)現(xiàn)畫中畫播放視頻的完整流程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容