iOS14 picture-in-picture realizes the whole process plus various pits

1. Realization

Achieving picture-in-picture is very simple, just take one, two or three steps.

1. Prepare for picture-in-picture
#import <AVKit/AVKit.h>

@property (nonatomic, strong) AVPictureInPictureController *pipVC;
@property (nonatomic, strong) AVPlayerLayer *playerLayer;
@property (nonatomic, strong) AVPlayer *player;
复制代码
2. Configuration
- (void)startPip {
    self.player = [AVPlayer playerWithURL:[NSURL URLWithString:self.liveVideo.hdlurl]];
    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
    self.playerLayer.frame = CGRectMake(100, 80, 100, 200);
    [self.player play];
    [self.view.layer addSublayer:self.playerLayer];
    //1.判断是否支持画中画功能
    if ([AVPictureInPictureController isPictureInPictureSupported]) {
        //2.开启权限
        @try {
            NSError *error = nil;
            [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeMoviePlayback options:AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers error:&error];
            // 为什么注释掉这里?你会发现有时 AVAudioSession 会有开启失败的情况。故用上面的方法
            [[AVAudioSession sharedInstance] setCategory:AVAudioSessionOrientationBack error:&error];
            [[AVAudioSession sharedInstance] setActive:YES error:&error];
        } @catch (NSException *exception) {
            NSLog(@"AVAudioSession发生错误");
        }
        self.pipVC = [[AVPictureInPictureController alloc] initWithPlayerLayer:self.playerLayer];
        self.pipVC.delegate = self;
    }
}
复制代码
3. Start/Close
- (void)openOrClose {
    if (self.pipVC.isPictureInPictureActive) {
        [self.pipVC stopPictureInPicture];
    } else {
        [self.pipVC startPictureInPicture];
    }
}

//各种代理
// 即将开启画中画
- (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
    NSLog(@"");
}
// 已经开启画中画
- (void)pictureInPictureControllerDidStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
    NSLog(@"");
}
// 开启画中画失败
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController failedToStartPictureInPictureWithError:(NSError *)error {
    NSLog(@"%@", error);
}
// 即将关闭画中画
- (void)pictureInPictureControllerWillStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
    NSLog(@"");
}
// 已经关闭画中画
- (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {
    NSLog(@"");
}
// 关闭画中画且恢复播放界面
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler {
    NSLog(@"");
}
复制代码

Second, pay attention to points and pits

  • After the AVPlayerLayer frame is set, the size of the picture-in-picture can be adjusted

  • The bottom layer of the picture-in-picture is AVPlayer. Some people say that only video can be played. In fact, it is wrong. It can play the live broadcast of .m3u8 (currently a certain audio has this logic)

    • So there is a problem, if the player in the APP uses URLs of other protocols, how to switch? The player provided for the SDK in the general APP.
    • In the live broadcast, if the APP and the picture-in-picture use URLs with different protocols, it will not have much impact, because the picture is always real-time, there is no synchronization problem, only the UI needs to be dealt with excessively.
  • The picture-in-picture is AVPictureInPictureController. If you want to display it globally in the APP, you need to let the singleton hold the

  • Debugging on the real machine! The emulator is playable

  • When the app is killed, the picture-in-picture disappears immediately

Guess you like

Origin juejin.im/post/7078530834906480653