iOS14 画中画调研

iOS14 画中画 调研

画中画(PictureInPicture)在iOS9就已经推出了,不过之前都只能在iPad使用,iPhone要使用画中画就得更新到iOS14才能使用。

苹果在iOS14中开放了手机端对画中画的支持,方便在app退出前台时仍然可以播放视频。 画中画的开启,本质上还是需要依赖系统播放器,同时UI、动画等都是系统原生提供的,因此自定义空间很小。

目前有三种方式实现画中画:

  • WKWebView自带
  • 如果对播放器要求不大的可以直接使用AVPlayerViewController,自身就提供画中画功能可直接使用,设置allowsPictureInPicturePlayback = YES即可展示出画中画按钮。
  • 自定义的播放器要开启画中画那就使用AVPictureInPictureController来包装,也是很简单易用,并且动画效果内部已经实现,只需要注意画中画按钮需要用户自己去实现,画中画图标系统已有相关APIpictureInPictureButtonStartImage

总共需要以下几步:

  • 开启后台模式,即Xcode中后台能力中的第一个勾选框

  • 创建AVPictureInPictureController(你一定要让用户通过操作(点击按钮等)来开始画中画显示。 不能直接在代码中直接startPictureInPicture ,这样的话你的APP上架审核会被拒绝,因为苹果本身是不希望用户自定义画中画的。)

  • [AVPictureInPictureController isPictureInPictureSupported]允许的情况下,设置AVAudioSession的category为AVAudioSessionCategoryPlayback

  • 可以播放遵守HLS协议的.m3u8的直播,因为AVPlayer 不支持 flv,只能播放 hls 的流。HLS是苹果主导的音视频传输协议,其主要的格式是一个索引文件(M3U8)+ ts分片的视频文件。

  • 如果业务使用系统播放器,那么这里一般不会有问题,因为播放器已经正确显示了。但是如果业务使用了自定义播放器,同时也希望具有画中画能力,那么通常会创建一个隐藏的系统播放器,作为画中画功能的承载。这时候就要注意保证用于渲染的view、layer正确地加入到了层级中

具体代码如下:

// init player
    NSURL *url = [NSURL URLWithString:@"https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8"];
    //使用playerItem初始化AVPlayer的目的是为了监听播放器的`status`状态
    self.playerItem = [AVPlayerItem playerItemWithURL:url];
    [self.playerItem addObserver:self
                 forKeyPath:@"status"
                    options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
                    context:nil];
    self.player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem ];
    
    // init player layer
    AVPlayerLayer * playerLayer = (AVPlayerLayer *)self.playerView.layer;
    playerLayer.player = self.player;
    
    // init pip controller
    self.pipController = [[AVPictureInPictureController alloc] initWithPlayerLayer:playerLayer];
    self.pipController.delegate = self;
    //监听'pictureInPicturePossible'是为了让自定义的画中画按钮是否显示/隐藏 或者 能否点击,因为有些时候即使设备支持,但是需要AVPlayer等到直播流可以播放的一个状态才可以为possible
    [self.pipController addObserver:self
                         forKeyPath:@"pictureInPicturePossible"
                            options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
                            context:nil];

   if ([AVPictureInPictureController isPictureInPictureSupported]) {
        NSLog(@"该设备支持画中画功能");
        //开启画中画后台声音权限
        NSError *error = nil;
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
        if (error) {
            NSLog(@"请求权限失败的原因为%@",error);
        }
    } else {
        NSLog(@"该设备不支持画中画功能");
    }
    
    //在点击画中画按钮的时候 开启画中画
     if (self.pipController.isPictureInPictureActive) {
        [self.pipController stopPictureInPicture];
    } else {
        [self.pipController startPictureInPicture];
    }
    
    //status状态一共三种 可以在不同的状态下设置不同的交互
    AVPlayerItemStatusReadyToPlay:
    AVPlayerItemStatusFailed:
    AVPlayerItemStatusUnknown:
    

注意点:
一、 AVPictureInPictureController的初始化通过将要展示视频的视图的view的 AVPlayerLayer来初始化。为了达到这种目的视频播放的视图的layer返回应该是AVPlayerLayer,重写+layerClass方法使得在创建的时候能返回一个不同的图层子类。UIView会在初始化的时候调用+layerClass方法,然后用它的返回类型来创建宿主图层。即需要在展示视频的view视图里有如下类方法

+ (Class)layerClass {
    return [AVPlayerLayer class];
}

二、 startPictureInPicture并不是立马触发,而是需要在视频可以开始播放时才允许打开。所以如果不加载一个本地加载的动画视频的话,界面上不会立马显示出画中画,给用户造成一种不灵敏的感觉。所以 先循环播放一个本地的 loading 视频来开启画中画,同时等待直播可以开始播放时,再将画中画的画面切换成真正的直播内容。

三、 因为AVPlayer只能播放本地视频或者HLS直播流,而AVPictureInPictureController的初始化需要用到AVPlayer。但公司目前的设备推流机制是直接客户端接受YUV数据并用OpenGL渲染,没有经过服务器取流,所以画中画暂时无法实现。

实现步骤:如果现在不支持,后续如果想实现的话,可以在点击画中画后去服务请求视频的HLS直播地址,和一些token的验证拼接,之后将其赋值给self.playLayer.player = [AVPlayer playerWithURL:[NSURL URLWithString:urlStr]];,之后就可以开启画中画了。否则就按失败处理。

//欢迎大家交流并指出错误,谢谢

官方文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容