上篇文章完成了直播的简单业务,我们可以慢慢将这个直播进行完善, 例如 附近直播
直播礼物
直播回放
, 当然实际业务要比我说的复杂,博主这里提供一个思路
现在社交附近的人都是基本功能, 所以我们的直播也不例外, 本身附近的人功能就不复杂, 只不过是选择哪种方式来做合适罢了。要做这个附近的人,首先要收集用户的经纬度存放到数据库,也就是我们的数据表会变成这样
参数名 | 说明 |
---|---|
id | 自增主建 |
user_id | 用户ID |
live_url | 播放地址 |
obs_url | 推流地址 |
avatar | 直播封面 |
title | 直播标题 |
status | 直播状态 是否在播 |
lat | 纬度 |
lng | 经度 |
city | 给用户看的位置信息 |
获得了经纬度后,我们就可以通过技术手段获取附近的用户,按照位置信息、 热度等排序展示给用浏览了
常见附近的人处理方式有:
mysql
实现附近的人也分2种方案
这种就需要计算,消耗大一点,但是数据量小直径忽略,业务最大,开发效率最大
这里给出一点代码,大家可以看看
// 6371是计算公式的公里 英里是3959
$distanceRaw = <<<SQL
(
6371*acos(
cos(radians(%s))
*cos(radians(lat))
*cos(radians(lng)-radians(%s))
+sin(radians(%s))
*sin(radians(lat))
)
) AS distance
SQL;
$data = LiveRoomModel::query()
->where(['status' => 1])
->having('distance', '<=', $km)
->forPage(
$data['page'], $data['size']
)
->orderBy('distance')->get(
[
'id',
'title',
'room_avatar',
'city',
'status',
DB::raw(
sprintf(
$distanceRaw, $data['lat'], $data['lng'], $data['lat']
)
)
]
)->toArray();
还有另一种方式, 设置 geometry
地理空间类型字段, 可以利用 mysql
的空间函数 ST_Distance_Sphere
进行计算得出距离, 以米为单位
GeoHash
减少计算GeoHash
算法将二维的经纬度数据映射到一维的整数,这样所有的元素都将挂载到一条线上,距离靠近的二维坐标映射到一维后的点之间距离会很接近。当我们想要计算附近的人时,首先将目标位置映射到这条线上,然后在这条一维的线上获取附近的点就ok了。
我们使用对经纬度进行 geohash
算法计算得出hash
值, 存入数据库使用like
查询, 查出附近的人进行二次计算得出距离即可
Redis
中处理这些地理位置坐标点的思想是:
Redis
中经纬度使用52位的整数进行编码,放进zset
中,zset
的value
元素是key
,score
是GeoHash
的52位整数值。在使用Redis
进行Geo
查询时,其内部对应的操作其实只是zset(skiplist)
的操作。通过zset
的score
进行排序就可以得到坐标附近的其它元素,通过将score
还原成坐标值就可以得到元素的原始坐标
二维平面坐标点
一维整数编码值
zset(score为编码值)
zrangebyscore(获取score相近的元素)
通过score(整数编码值)反解坐标点
附近点的地理位置坐标
使用 redis geo
指令就可以实现了, 使用时务必再次想起,它只是一个普通的zset
结构。
georadiusbymember
查询指定元素附近的其它元素geodist
计算两个元素之间的距离在一个地图应用中,车的数据、餐馆的数据、人的数据可能会有百万千万条,如果使用 Redis
的 Geo
数据结构,它们将全部放在一个 zset
集合中。在 Redis
的集群环境中,集合可能会从一个节点迁移到另一个节点,如果单个 key
的数据过大,会对集群的迁移工作造成较大的影响,在集群环境中单个 key
对应的数据量不宜超过 1M
,否则会导致集群迁移出现卡顿现象,影响线上服务的正常运行。
所以,这里建议 Geo
的数据使用单独的 Redis
实例部署,不使用集群环境。
如果数据量过亿甚至更大,就需要对 Geo
数据进行拆分,按国家拆分、按省拆分,按市拆分,在人口特大城市甚至可以按区拆分。这样就可以显著降低单个 zset
集合的大小。(注意:zset
集合大小,进行合适地切分)
这个效率比较高,也是应用比较多,我们也介绍一下
es
也有地理位置相关的数据类型, 例如: geo_point
geo_shapes
那这两种有一定区别, 我们做一个简单的附近的人采用 geo_point
即可, geo_shapes 纯粹是用来过滤的
用于计算距离、排序、打分以及聚合, 有时候距离并不是影响排序的唯一因素, 可能和热度, 好评也相关, 所以打分也是一个很重要的功能, 如果大家的排序多样化 可以选择 es
geo_point
和geo_shape
的最大区别是: geo_point
表示一个点;geo_shape
则表示有多个点连成线组成的形状。 学过数学的肯定很容易理解。
他的主要作用就是: 判断查询的形状与索引的形状的关系
geo_point
类型的就满足不了我们的需求了Geo-shapes
不能用于计算距离、排序、打分以及聚合。
MongoDB
也可以利用2d
索引, 本质上还是geohash
,附近的人只是一种基础功能, 做的时候考虑是否需要引入新技术, 新增成本是否能够接受? 我们不需要盲目使用各种各样的技术,根据业务挑选最合适的,就算技术最新又怎样,解决不了业务,导致项目延期,你这次采用的技术毫无价值
这个基本是必不可少的一项了, 做起来也不困难, 博主完整说一下, 这里包含一些前后端的交互
在开发APP
的过程中,需要在APP
中实现设计同学的UE
效果动画,一般都是通过代码实现的,当对于较复杂的动画时,例如直播中刷礼物时的动画,这时利用代码实现会比较复杂。而且Android
和iOS
两端不好统一效果,如果用gif
图片来实现的话,在图片大小和动画帧数之间很难权衡。而且会导致内存吃紧。为了解决这样的问题,介绍两款实现复杂动画的开源库:Lottie
和SVGA
。
地址: https://github.com/airbnb/lottie-ios
爱彼迎
的好东西, 别说, 他们APP
效果很不错, JS
代码风格也是业内标杆, 我以前严格要求项目组按照这种风格编码.
但是这个对平台有限制,iOS 8.0
以上,Android API 14
以上。交互动画不可行,主要是播放类型动画。开发成本也比较低, 设计师导出json后,开发同学只需引用文件即可。
地址: http://svga.io/
动画设计师专注动画设计,通过工具输出 svga
动画文件,提供给开发工程师在集成 svga player
之后直接使用。方便,跨平台好, 我们公司选择的就是这个, 我们还有一个微信小程序, 当时小程序
对Lottie
支持不太好,并且公司前端技术也比较倾向于这个
然后我们说一下后端, 如果按照数据驱动开发的方式的话, 我们需要将礼物相关表建立一下, 例如: 礼物表、礼物类别、直播间礼物打赏日志、其他用户消费日志等等
这里我说一下礼物表, 基本字段
参数名 | 说明 |
---|---|
id | 自增主建 |
title | 礼物名称 |
image | 礼物图片 |
svga | SVGA的URL |
price | 礼物价值的虚拟币 |
is_animation | 1特效 0 为特效 |
time | 特效持续时间 s为单位 |
sort | 礼物排序 |
礼物如果需要抽点的, 做一个系统配置。看到这,我相信大家应该都有一个大概了, 怎么做心里应该有点数了, 还有一个没说到的就是, 礼物发送之后是需要让所有人看到的, 这样我们就需要做消息广播了, 这个可以使用 IM
实现, 后面再说
因为直播是在线看的, 用户又不一定每次都有时间在某个点去看, 所以回放也变成了一个必不可少的功能。开通云点播,在云直播的功能配置里面有录制配置,每次直播完后的视频会保存到云点播里面 那这个视频是需要和用户绑定的, 所以腾讯这边提供了回调给我们,当直播断流时会回调我们的接口,将本次录播的文件等信息传递给我们,我们进行保存。 那么还可以利用点播做一个类似抖音的东西, 我们可以让用户上传视频到云点播、直播视频保存在云点播,做一个视频列表,向下滑动来观看,只要将视频和用户关联起来就可以了。可以做的很多,就不一一介绍了
这个也比较简单,看看文档就行,所以不做过多的介绍,就到这了,下一篇继续介绍直播聊天室的实现