Skip to content

Latest commit

 

History

History
133 lines (80 loc) · 10.1 KB

DOC.md

File metadata and controls

133 lines (80 loc) · 10.1 KB

代码说明

整个小程序端分为4个部分

  • app.js 负责处理和微信相关的逻辑,用户登录,群组记录,用户状态查询
  • pages/list 列表页,展示当前正在直播的用户
  • pages/publish 推流页,主播在该页下推流。提供一些基本的推流选项
  • pages/play 播放页, 观众观看直播的页面

App.js

这一部分比较复杂,功能是处理微信的数据并存到自己的数据表中。涉及到不少后端部分的代码,请对照后端部分代码 关于微信登录流程,可以先看看微信的官方文档熟悉下流程, 这里

存储用户信息

代码里大多都是请求各种微信和自己后台的接口,整个登录工作流程如下:

  • 用户打开,调用wx.login来获取code, code是包含了用户session数据的一个token,但是出于安全考虑,获取session需要后台手动请求微信接口
  • 服务端(该项目server下的代码)后台收到code后请求微信获取session存储在后台,用于以后和微信通信。微信返回session的同时,还会带上该用户的OpenID, OpenId是对一个小程序来说用户的唯一ID。
  • 通过上一步拿到的唯一用户ID OpenId,我们可以把它作为主键,建立自己的用户表了。微信不会开放除了当前访问者以外的用户信息给我们,所以为了实现列表页,我们需要自己维护一个用户表。这一块的逻辑具体见后端代码。
  • 这里我们需要自己生成一个session(3rd session)来作为小程序端和服务端的认证信息,当然后台再维护一个session表就复杂,这里Demo使用了JWT的方案(JSON WEB TOKEN)
  • 使用微信返回的session作为密钥,内部用户表的id作为数据, 签发JWT返回给小程序端。(之后小程序的每个请求都需要附上这个JWT作为认证信息)
  • wx.login获取code成功后,我们就可以调用wx.getUserInfo来获取当前用户的具体信息了(昵称,头像等等)
  • 拿到用户的具体信息后,就把这个信息同步给我们的服务端,让后端我们自己的用户表也储存这些数据。因为现在的请求都会附上JWT,JWT服务端decode后可以获取用户id,以此来定位用户实现更新。

通过上述步骤, 我们就可以让每一个访问过该小程序的人的详细信息都存入我们的用户表里了。这样就方便我们实现后面列表页的功能(因为需要列出用户列表) 在调用wx.login之前,可以先调用wx.checkSession来判断当前用户的session有没有过期,减少后端获取session的过程

其实上面的过程中,我们并没有正在用到微信的session数据(只是用来加密自己JWT),但是因为sessionopenid是一并返回的,就放在一起说了
下面这个流程,就需要session来实现

存储群组信息

微信的各种应用总是要考虑群组的情况,直播这种社交类应用就不用多说。群内直播、群员动态这种功能就需要我们后台除了储存用户表, 还需要存储一个群组表(如无需要可以跳过此段)
当然,微信是不会给我们直接提供获取当前群成员这种接口的,所以存储群组表的方法就是:
当一用户从某个群打开小程序的分享卡片时,我们就把这个用户加入这个群组表中。同样的道理,当用户分享小程序到某个群的时候,我们就也可以做这件事。
这里主要讨论第一种情况,下面说下详细的流程:

  • 用户打开成功调用wx.login之后,判断用户是否携带了shareTicket这个参数,见此
  • 如果携带这个参数,表示用户是从某个群组的分享卡片中进入的小程序,我们调用wx.getShareInfo传入这个参数就可以获取用户的分享信息了
  • 获取分享信息成功后,微信不会直接返回明文数据给我们(安全考虑,防止网络中间人获取敏感信息), 我们得到了encryptedData, 和iv 2个数据,将这2个参数发给我们服务端端进行解密
  • 这里就需要用上刚刚的session数据了,session为密钥,iv为cbc初始向量,encryptData为输入调用AES-CBC就可以解密数据了,见此
  • 后台拿到了分享的解密数据后,就能获取groupID,该id是对于一个小程序来说的群组唯一ID,通过这个id我们建立群组表,将当前请求的用户加入用户表

至此我们存储了所有访问用户的详细和相关的群组信息,可以进入我们下面的开发流程了

Pages/publish 推流页

我们还是按照先推流再播放的顺序来介绍,这样整个流程比较清晰。

架构上,我们使用的是七牛云的直播云服务,也就是说我们推流会直接推到七牛的直播云服务器上。我们只要指定流id,直播云就会帮我们创建这条流。通过这个流id,我们就可以拿到我们的推流地址(推流地址首先需要用户自行在直播云界面绑定域名),将我们的流媒体数据推送到远端服务器上。

原则上,流id的选取应该是和用户id一一对应的。当然根据不同需求流id的生成逻辑也可以有所不同,比如在流id里加上GroupID来实现群内直播,实现同一用户推送不同的流到不同的群里等等。

本Demo采用的流id生成逻辑很简单,直接使用用户的OpenID作为流ID。(出于安全考虑,可以尝试给OpenIDhash或者加密后再作为流id)

这样梳理下来,我们整个推流页的主要流程就是:

  • 等待用户登录回调,获取用户信息
  • 通过用户信息去请求后端,获取相应协议的推流地址(Demo中为RTMP)
  • 调用LivePushContext开始推流

详细说明

我们推流的根本是微信提供的live-pusher组件以及控制它的LivePushContext对象(这部分详细见微信文档

css/html 相关

需要注意的是 live-pusher是默认顶层组件,也就是说其他组件都会无视zindex被它盖住,除了<cover-view><cover-image>。所以如果想实现控件需要使用这2个组件。

截止到我使用的1.9.2基础库版本,这2个组件在ios下的css表现很差,很多属性的表现方式很诡异,在android下情况稍微好一点但是也会有一些css上不去的情况。基本表现为无法设置透明度,无法设置动画,图片有概率无法显示等等。

主流程

  • live-pusher的一些想要控制的参数和Page里的data绑定,如: 推流地址、清晰度、前后摄像头等等
  • 当用户登录成功时向服务端发送请求获取当前用户的推流地址(服务端会根据用户的七牛云密钥计算一个有时效的推流token)
  • 调用setData设定推流地址,在回调里调用LivePushContext的start方法开始推流(注意这里必须要在setData的回调中调用,具体见微信的setData说明)
  • 绑定一些控件的handle

通过这些流程,用户接入推流页面后,就会自动开始采集摄像头数据并推流到七牛直播云了。

Pages/list 列表页

其他用户想要观看主播的直播,首先肯定需要列表页这样一个入口。列表页展示当前正在推流的用户列表,因为之前用户数据都已经入库,所以实现起来就比较简单了。

直播云为我们提供了批量查询流状态的api,后端通过这个方法,筛选出正在推流的用户,把流信息merge到一起返回给小程序端。

列表页再根据这些信息渲染直播列表就可以了,然后绑定一个handle,当用户点击列表项的时候,跳转到播放页面,并在跳转地址的query信息中带上点击的用户的OpenId

如果想要实现群内直播,列表页筛选的时候就需要加上GroupID作为query之一

Pages/play 播放页

通过上面的流程我们可以知道,用户进入播放页的时候,会把他想要观看的主播用户信息带在query上。

我们通过这个信息再去请求服务端同样就可以得到这个主播的播放地址,将这个返回的播放地址填入微信提供的live-player组件就可以在线观看直播了

所以播放页的整个流程和publish页类似,都是获取用户信息,请求后端获取地址,setData后开始播放

几个注意的点

  • live-player同样也是顶层组件,而且在测试过程中发现live-player甚至连微信的showToast showLoading都会遮挡。
  • 自动全屏这个功能经过测试在某些机型可能会失败

直播鉴黄

对于一个直播应用来说,如果想上线开放给大众,那么色情传播就是个不得不重视的问题。这里Demo使用了七牛直播云的直播鉴黄服务。

开启后,如果有任何一个流发现有色情数据,直播鉴黄服务就会向我们配置的一个hook地址发送一个请求,请求附上这个流的相关信息以及相关的色情数据信息。

开发者可以基于这些参数自行定制处理逻辑,在Demo中,采用了直接禁播该流的做法。参见

其他可以实现的Feature

直播云为我们提供了很多便捷的功能点,还有一些Demo没有列举的点

直播封面

通过在直播云界面配置直播封面的域名地址,我们就可以通过一个流id(用户数据)来生成一个直播封面(基于推流的截帧)。

这个封面可以用于微信分享图片,列表页展示等等。

录制点播

直播云支持录制主播的推流数据生成点播的播放地址,开发者可以轻松实现点播某个主播的历史直播。