美文网首页iOS控件
iOS视频播放:预览播放视频前面N秒的设计

iOS视频播放:预览播放视频前面N秒的设计

作者: 双鱼子曰1987 | 来源:发表于2020-11-04 09:16 被阅读0次

一、需求

  • 1、视频播放列表中,对于曝光的视频,需要播放视频前面N秒;
  • 2、如果同时曝光多个视频,则视频循环播放视频。如A、B、C三个视频同时都在屏幕内,那么依照曝光的先后顺序播放A-B-C;
  • 3、视频的显示格式有两种:一个Cell显示一个视频;一个Cell显示两个视频。
  • 4、只有当上一个cell的视频全部播放完成后,才会播放下一个Cell的视频。

二、设计

2.1、设计要求

  • 使用系统AVPlayer、AVPlayerLayer、AVPlayerItem来播放视频。
  • 多个视频,同时只有一个Player存在。
  • Cell的曝光控制逻辑。
  • 使用数据驱动渲染Cell(DataItem唯一,Cell复用)。
  • 通用组件设计标准,多个页面可以简单集成使用。

2.2、类图

短视频预览控制~.png

2.3、设计说明

  • 采用数据驱动框架RETableViewManager,具体的搜索GitHub。
  • RETBL_ViewController 信息流列表,持有DataItemList,将其交给RETableViewManager渲染出cell;每个DataItem对应列表每一条数据,且唯一,但Cell复用,根据DataItem渲染页面。RETBL_ViewController 持有VideoPlayerController,功能如下。
@interface RETBL_ViewController : NSObject
@property (nonatomic, strong) VideoPlayerController *videoPlayerManager;
@property (nonatomic, strong) RETableViewManager *tblViewManager;

// 曝光的时候
[self.videoPlayerManager addVideoIntoList:item];

// cell 消失
[self.videoPlayerManager removeVideoFromList:item];
@end
  • ShortVideoPlayerViewDelegate 协议接口,VideoPlayerController 可以通过 id< ShortVideoPlayerViewDelegate> obj(本例是DataItem) 向外部获取VideoUrlVideoContainerView(AVPlayerLayer的播放容器View)。
@protocol VideoPlayerPreviewDelegate <NSObject>
@optional
- (NSArray<NSString *> *)videoUrlList;
- (NSArray<UIView *> *)videoContainerViewList;
@end
  • 代理模式,CellDataItem 实现 ShortVideoPlayerViewDelegate接口,并且DataItem 有代理属性cDelegate 指向Cell。这样设计之后,针对信息流每一个Cell中,DataItem提供VideoUrl;又通过DataItem的代理向Cell获取VideoContainerView
@interface VideosPreviewTableCell : RETableCell < ShortVideoPlayerViewDelegate >
@end
@implementation VideosPreviewTableCell
#pragma mark - ZTHVideoPlayerPreviewDelegate
- (NSArray<UIView *> *)videoContainerViewList {
    return viewList; // 一个cell可能有多个视频view
}
@end

@interface VideosPreviewTableCellItem : RETableCellItem < ShortVideoPlayerViewDelegate >
@property (nonatomic, weak) id< ShortVideoPlayerViewDelegate > cDelegate;
@end
@implementation VideosPreviewTableCellItem
#pragma mark - ZTHVideoPlayerPreviewDelegate
- (NSArray<NSString *> *)videoUrlList {
    return urlList;
}

- (NSArray<UIView *> *)videoContainerViewList {
    if (self.cDelegate && [self.cDelegate respondsToSelector:@selector(videoContainerViewList)]) {
        return [self.cDelegate videoContainerViewList];
    }
    
    return nil;
}
@end
  • VideoPlayerController
    用来管理哪些DataItem需要播放,当cell曝光%50以上,则加入播放队列;当Cell不可见从播放队列中移除。
@interface VideoPlayerController ()
/// 由于Player的ContentView,可能被复用的,如在Cell中使用。但是每个Id
@property (nonatomic, strong) NSMutableArray<id< ShortVideoPlayerViewDelegate >> *videoItemList;
@property (nonatomic, strong) ShortVideoPlayerCenter *currentPlayerCenter;
@property (nonatomic, strong) GCDTimer *timer;
@end

@implementation VideoPlayerController
// timer回调函数,播放videoItemList的控制
- (void)videoPlayControlLoopHandler {
  ...
}
@end

同时,内部设计一个定时器1s,定时器函数videoPlayControlLoopHandler主要代码是,检查VideoPlayer播放器状态是否可以加载下一个DataItem,可以则加载下一个,播放其对应视频。

采用定时器的原因在于,将列表DataITem播放与否 和 视频播放逻辑剥离,彼此互不影响。类似RunLoop循环机制,将需要播放的DataItem放入队列中,内部定时循环是否启动播放。而不是来一个就马上播放一个,消失一个立即暂停,当列表快速滚动的时候,会频繁让播放器在播放和暂停不断切换,会影响性能。

当然,后续的优化中,可以加入列表的ScrollRate,当滚动太快的时候,暂停播放逻辑提高性能。也可以考虑加入displaylink,当有空余能力的时候,才启动播放逻辑。

  • ShortVideoPlayerCenter 专门负责每个DataItem对应视频的播放。
    播放某个DataItem的时候,通过id< ShortVideoPlayerViewDelegate > obj(本例即DataItem自身),获取videoUrlList 和 viewList,保存在ShortVideoPlayerUnit实例中。
    VideoPlayer播放时候,取出videoUrl 和 对应的containerView(将PlayerLayer添加上去);播放N秒后,播放当前DataItem的下一个视频。如果全部播放结束,改变播放器状态允许加载下一个。
@interface ShortVideoPlayerCenter ()
/// 由于Player的ContentView,可能被复用的,如在Cell中使用。但是每个Id
@property (nonatomic, strong) EasyVideoPlayer *videoPlayer;
@property (nonatomic, strong) ShortVideoPlayerUnit *playerUnit;
@end

@implementation ShortVideoPlayerCenter
// timer回调函数,播放videoItemList的控制
- (void)videoPlayControlLoopHandler {
  ...
}
@end
  • ShortVideoPlayerUnit 存储DataItem 对应的 videoUrlListviewList;原则上一个url对应一个view。
    ShortVideoPlayerUnit 的设计主要考虑的是,播放逻辑中的可变和不可变剥离。VideoPlayerPlayerLayer 和 播放逻辑控制,是不变的部分;但播放数据是经常异动,且urlview都不同,因此封装起来,好管理这部分数据的创建和销毁。
@interface ShortVideoPlayerUnit : NSObject
@property (nonatomic, strong) NSArray<NSString *> *videoUrlList;
@property (nonatomic, strong) NSArray<UIView *> *videoViewList;
@end

三、总结

  • 通用性能力,需要“视频预览”能力的列表,只需要让数据源和Cell实现ShortVideoPlayerViewDelegate,提供对应url和view,然后交给VideoPlayerController进行管理即可,然后在Cell曝光和消失的时候添加和移除数据源即可。
  • 由于考虑到NSTimer强引用性,需要手动是否timer否则会导致循环引用。因此这边使用GCDTimer
  • 使用Timer左右loop动力驱动,可以根据具体的需求切换为DisplayLink,然后加入scrollRate滚动速率等因此,进一步提高性能。

其他

  • 上面类的命名已经非项目命名,叫法不甚合适,本篇旨在说明设计意图。

相关文章

网友评论

    本文标题:iOS视频播放:预览播放视频前面N秒的设计

    本文链接:https://www.haomeiwen.com/subject/hukivktx.html