直播中BarrageRenderer弹幕的显示(二)—— 工程实践

版本记录

版本号 时间
V1.0 2017.07.23

前言

在我们做直播等视频类app的时候,总是有显示和发送弹幕的要求,弹幕可以方便用户进行沟通和互动,增加了娱乐性,增强app等客户端的用户粘度,下面我们就说一下弹幕显示方面的问题和相关框架BarrageRenderer。
1. 直播中BarrageRenderer弹幕的显示(一)—— 框架介绍
这一篇就结合工程实现说明该框架的使用。

BarrageRenderer文件

下面看一下这个头文件。

#import <Foundation/Foundation.h>

#import "BarrageHeader.h"

@class BarrageDescriptor;
@class BarrageRenderer;

@protocol BarrageRendererDelegate <NSObject>

@optional

/// 通过外部渠道获取当前时间,用于内部时间系统; 当依附的视频具有快进快退功能时,必须实现这个函数,并返回时间轴上的当前时刻,即已经播放的时间.
- (NSTimeInterval)timeForBarrageRenderer:(BarrageRenderer *)renderer;

@end

/// 弹幕渲染器
@interface BarrageRenderer : NSObject

#pragma mark - life cycle

#pragma mark - control

/// 启动弹幕, 内部时钟从0开始;
/// 若是stop之后的start,则start函数内部会清空records;
/// 视频开始的时候需要同时运行此方法.
- (void)start;

/// 暂停, 已经渲染上去的保持不变, 此时发送弹幕无效, 内部时钟暂停;
/// 视频暂停的时候需要同时运行此方法.
- (void)pause;

/// 停止弹幕渲染, 会清空所有; 再发弹幕就无效了; 一切都会停止;
/// 此方法在不再需要弹幕的时候必须调用,否则可能造成内存泄露.
- (void)stop;

/// 接收弹幕消息, 如果尚未start, 则调用无效.
- (void)receive:(BarrageDescriptor *)descriptor;

#pragma mark - config

/// 画布的边距
@property(nonatomic,assign)UIEdgeInsets canvasMargin;

/// 画布是否拦截事件
@property(nonatomic,assign)BOOL masked;

/// 调整弹幕整体速度, 需要>0, 否则会被抛弃.
@property(nonatomic,assign)CGFloat speed;

/// 如果时光倒流, 弹幕能不能重新显示. 若设置为YES, 则当执行后退8s->5s时,会显示6s时刻上的弹幕.
@property(nonatomic,assign)BOOL redisplay;

/// 获取外部时间的代理,若需将弹幕固定到时间点上,则需设置此代理
@property(nonatomic,weak)id<BarrageRendererDelegate> delegate;

#pragma mark - output

/// 返回给外部的view
@property(nonatomic,weak)UIView * view;

/// 获取当前屏幕弹幕数量,spriteName表示弹幕类名,如果传入nil,则计算屏幕显示出的所有弹幕数量.
- (NSInteger)spritesNumberWithName:(NSString *)spriteName;

/// 逻辑时间,露出参考.
@property(nonatomic,assign,readonly)NSTimeInterval time;

#pragma mark - z-index

/// 是否开启z-index功能,开启之后,性能会稍有降低,绘图会按照z_index进行,值越大,越靠上;默认关闭.
@property(nonatomic,assign)BOOL zIndex;

#pragma mark - record

/// 如需要记录,需要在运行start之后立即运行此函数,内部会通过时间差计算delay;
/// 记录弹幕,可能会序列化到本地; 默认为NO.
@property(nonatomic,assign)BOOL recording;

/// 加载已经存在的弹幕,如果已经start, 会立刻被调用receive; 否则, 会等到start的时候再调用receive.
- (void)load:(NSArray *)descriptors;

/// 弹幕记录数组.
- (NSArray *)records;

@end


工程实现

下面看一下我建立工程的代码。

1. JJBarrageModel.h
#import <Foundation/Foundation.h>

@interface JJBarrageModel : NSObject

@property (nonatomic, copy) NSString *videoTime;
@property (nonatomic, copy) NSString *barrageType;
@property (nonatomic, copy) NSString *fontSize;
@property (nonatomic, copy) NSString *barrageColor;
@property (nonatomic, copy) NSString *timestamp;
@property (nonatomic, copy) NSString *barragePoolId;
@property (nonatomic, copy) NSString *userHash;
@property (nonatomic, copy) NSString *barrageID;
@property (nonatomic, copy) NSString *message;
@property (nonatomic, assign) NSTimeInterval delay;

@end

2. JJBarrageRendererVC.h

#import <UIKit/UIKit.h>

@interface JJBarrageRendererVC : UIViewController

@end


3. JJBarrageRendererVC.m

#import "JJBarrageRendererVC.h"
#import "BarrageRenderer.h"
#import "JJBarrageModel.h"

@interface JJBarrageRendererVC () <BarrageRendererDelegate>

@property (nonatomic, strong) BarrageRenderer *renderer;
@property (nonatomic, assign) NSTimeInterval predictedTime;
@property (nonatomic, strong) NSDate *startDate;

@end

@implementation JJBarrageRendererVC

#pragma mark - Override Base Function

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor darkGrayColor];
    
    [self setupUI];
    
    //初始化弹幕
    [self initBarrageRenderer];
}

#pragma mark - Object Private Function

- (void)setupUI
{
    UIButton *sendButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [sendButton setTitle:@"发送弹幕" forState:UIControlStateNormal];
    sendButton.layer.borderColor = [UIColor yellowColor].CGColor;
    [sendButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    sendButton.frame = CGRectMake((self.view.center.x - 50), (self.view.center.y - 10), 100, 20);
    [sendButton addTarget:self action:@selector(buttonDidClick) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:sendButton];
}

//弹幕初始化

- (void)initBarrageRenderer
{
    self.renderer = [[BarrageRenderer alloc]init];
    self.renderer.view.userInteractionEnabled = NO;
    self.renderer.masked = NO;
    self.renderer.delegate = self;
    self.renderer.redisplay = YES;
    self.renderer.canvasMargin = UIEdgeInsetsMake(30, 0, 30, 0);
    self.predictedTime = 0.0f;
    [self start];
    [self.view addSubview:self.renderer.view];
}

//开始发送弹幕

- (void)start
{
    self.startDate = [NSDate date];
    [self.renderer start];
}

//发送弹幕

- (void)sendBarrageWithModel:(JJBarrageModel *)model
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.renderer receive:[self walkImageTextSpriteDescriptorAWithData:model]];
    });
}

//加载弹幕描述符

- (BarrageDescriptor *)walkImageTextSpriteDescriptorAWithData:(JJBarrageModel *)model
{
    BarrageDescriptor * descriptor = [[BarrageDescriptor alloc] init];
    descriptor.spriteName = NSStringFromClass([BarrageWalkTextSprite class]);
    descriptor.params[@"direction"] = @(BarrageWalkDirectionR2L);
    descriptor.params[@"trackNumber"] = @5;
    descriptor.params[@"text"] = model.message?:@"";
    descriptor.params[@"textColor"] = [UIColor whiteColor];
    descriptor.params[@"shadowColor"] = [UIColor darkGrayColor];
    descriptor.params[@"speed"] = @(0.5 * model.message.length + 100);
    return descriptor;
}

#pragma mark - Action && Notification

- (void)buttonDidClick
{
    JJBarrageModel *model = [[JJBarrageModel alloc] init];
    model.message = @"我是个弹幕,弹幕,弹幕啊!";
    model.barrageColor = @"ffb412";
    model.fontSize = [NSString stringWithFormat:@"%f", 16.0f];
    model.delay = 0;
    
    [self sendBarrageWithModel:model];
}

#pragma mark - BarrageRendererDelegate

- (NSTimeInterval)timeForBarrageRenderer:(BarrageRenderer *)renderer
{
    NSTimeInterval interval = [[NSDate date]timeIntervalSinceDate:self.startDate];
    interval += self.predictedTime;
    return interval;
}

@end


功能效果

下面我们就看一下功能效果。

功能效果1
功能效果2

后记

未完,待续~~~

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

推荐阅读更多精彩内容