开放平台视频投递流程的演进与思考
本期作者
周鑫
哔哩哔哩资深开发工程师
2020年加入B站,先后从事CRM平台、素材平台、开放平台和MCN平台的研发工作,专注于主站内容服务的业务落地。
简介
哔哩哔哩开放平台,是基于哔哩哔哩强大的内容社区生态,为媒体机构、有开发能力的up主、垂直行业企业、品牌服务商等,提供基础的服务能力、行业解决方案和个性化服务的平台,对于不同阶段的用户一起共建良性的内容生态。
开发者入驻开放平台的流程如下图所示,具体可参见官网指引:https://openhome.bilibili.com/doc/4/cbdcee3b-f57e-5c7b-cf27-83892fb811c4。
开放平台为开发者提供了丰富的业务能力支持,一个非常重要的业务场景就是视频稿件投递。
视频稿件投递
视频稿件投递包括视频文件上传、稿件提交两个主要环节。视频文件的上传包含了三个步骤:文件上传预处理,文件分片上传,文件分片合片。
外部应用请求接口时,需要传入access_token参数,这是通过授权环节获取的。将用户授权流程作为前置流程,确保了应用的操作限制在用户的授权范围内,保障了用户信息安全,符合了公司合规要求。具体授权流程见:https://openhome.bilibili.com/doc/4/eaf0e2b5-bde9-b9a0-9be1-019bb455701c。
上传预处理环节
外部应用请求上传预处理接口,传入如下参数:client_id(应用标识)、access_token(授权token)、name(文件全名称(含扩展名))、size(文件总大小(单位:字节))。client_id标识请求主体,用于识别该应用及其所属企业是否可用,请求的接口是否超过限额。access_token用于向鉴权服务进行鉴权,识别出用户mid,并判断是否超出了用户授权的操作权限范围。name标识文件类型,用于视频文件服务进行存储空间及参数预分配。
视频文件服务根据name生成32位的UUID字符串,拼接上相同的文件扩展名,生成filename。用该filename向稿件服务获取cid,作为内容的标识。
视频文件服务根据filename,按照upos:///的公式生成upos_uri,其中的bucket值为固定的ugcboss。
视频文件服务将upload_id、upos_uri、cid、filename返回给外部应用。
分片上传环节
外部应用请求分片上传接口,传入如下参数:client_id、access_token、upload_id、part_number(分片序号,从1开始)、upos_uri、分片二进制流(分片内容)。其中的upos_uri需要进行URLEncode处理后,作为参数使用(不少用户在这里会遇到两次URLEncode的问题)。
视频文件服务将分片文件放在在云存储的临时路径。
合片环节
外部应用请求分片合片接口,传入如下参数:client_id、access_token、upload_id、upos_uri、cid、profile(固定值“ugcupos/openplat”)。
视频文件服务对分片文件进行合片操作。
稿件提交环节
外部应用请求稿件提交接口,传入如下参数:client_id、access_token、视频文件信息、稿件信息。其中视频文件信息为cid和filename,均为预处理环节得到的结果。稿件信息包括:title(标题)、cover(封面地址)、tid(分区ID)、desc(视频描述)、tag(视频标签)等信息。
OpenAPI通过access_token鉴权,获取授权UP主的mid(即作者mid)。
OpenAPI请求稿件服务的稿件投递接口,传入作者mid、视频文件信息、稿件信息,调用成功后获得稿件ID,返回给外部应用。
思考
这一版本的交互特点是引入了灵活的鉴权服务,能够根据用户的授权信息,严格地限制外部应用的操作都被限定在用户授权的范围内,确保用户的信息安全。
根据用户的反馈,该版本最大的痛点就是交互上的参数过多,很多参数是内部多个服务之间的交互参数,增加了用户的理解成本和接入难度。
从平台本身的角度考虑,对外暴露的接口应该尽量都集中在OpenAPI服务里,尽量做到职责明确,以便于后续业务能力的扩展。
引入upload_token
在前面的介绍中我们可以看到,外部应用需要将预处理环节的结果存储起来,并在调用分片上传和合片接口时作为参数传入。这些信息本质上是平台内部信息,无需外部应用额外理解和记录的。因牵涉到多个内部服务间的交互,这里我们通过OpenAPI服务,来将这些内部信息进行记录,并映射成upload_token返回给外部应用,有效减少了接口交互的参数复杂度。
图中省略了视频文件服务对视频文件的具体处理环节,这部分与上一节一致。
上传预处理环节
外部应用请求上传预处理接口,传入如下参数:client_id、access_token、name,这些参数的含义及作用与前文所述一致,去除了没有实际生效的size参数。
鉴权服务根据client_id、access_token进行鉴权,并得到用户的mid信息。鉴权通过后,生成有效期较短的upload_token,将应用入参与upload_token生成映射,存入redis中,并将upload_token返回给OpenAPI。
OpenAPI服务,将upload_token作为参数,调用视频文件服务的内网接口。视频文件服务对upload_token鉴权后,获取所需的client_id、mid、name信息。然后进行初始化操作,对空间及参数进行预分配,并将这些结果返回给OpenAPI服务。
OpenAPI服务调用鉴权服务,将client_id、access_token、mid、upload_id、upos_uri、cid、filename、profile更新到upload_token的映射内容里,便于后续环节的使用。
分片上传环节
由于分片上传是流量接口,需要使用视频文件服务的网关能力来支持,外部应用的请求是直接打到视频文件服务上的。此时的入参为:upload_token、part_number、分片二进制流。
视频文件服务使用upload_token向鉴权服务进行鉴权,并获取对应的client_id、mid、upload_id、upos_uri信息,用于对分片文件进行存储。
合片环节
外部应用调用OpenAPI服务合片接口,传入upload_token参数。OpenAPI服务使用upload_token向鉴权服务进行鉴权。鉴权通过后,OpenAPI请求视频文件服务的内网接口,传入upload_token参数。
视频文件服务使用upload_token向鉴权服务进行鉴权,并获取对应的client_id、mid、upload_id、upos_uri、cid、profile信息,用于分片文件的合片处理过程。
稿件提交环节
外部应用调用OpenAPI的稿件提交接口,传入如下参数:client_id、access_token、upload_token、稿件信息。其中稿件信息包括:title(标题)、cover(封面地址)、tid(分区ID)、desc(视频描述)、tag(视频标签)等信息。
OpenAPI通过access_token鉴权获取授权UP主的mid(即作者mid),通过upload_token获取视频信息(主要有cid、filename)。
OpenAPI调用稿件服务的稿件投递接口,传入作者mid、视频信息、稿件信息,调用成功后获得稿件ID,返回给外部应用。
思考
这一版本通过引入上传令牌(upload_token),将各服务间交互用到的视频文件参数映射到鉴权服务里,降低了用户的理解成本、提高了用户的接入效率。
该版本解决了用户在文件上传和稿件投递环节的痛点问题,其他历史问题也就显露出来。外部应用在稿件提交完成后,往往无法及时感知到失败信息,因为视频文件的合片、转码是耗时操作。这种场景,我们需要能够及时告知用户失败信息。该问题目前已通过Webhooks方案予以解决。
有一些拥有优质创作者的小微平台,希望与B站共享内容生态,以较低的开发、运维、运营成本来对接开放平台,这些需要更近一步的能力支持。
提供JS SDK
前面提到的版本,都是针对服务端对接而制定的方案,access_token的数据安全风险较低。
但是在支持部分重要客户时,他们不希望承担视频文件上传带来的带宽负担,这时就需要从前端直接将视频文件上传到开放平台了。而这就需要支持WEB端与开放平台的直接交互,此时access_token就会有较大的暴露风险。而我们的upload_token方案里,upload_token的有效期较短,暴露在前端的数据安全风险较低。因此,我们基于upload_token方案,定制了JS SDK来支持客户的前端集成开发。
图中省略了开放平台的内部处理逻辑以及稿件提交环节,这部分与上一节一致。
上传预处理环节
步骤1,用户通过三方WEB端选择本地文件。点击上传按钮,通过步骤2调用三方服务端,并传入name信息。
步骤3则是三方服务端调用开放平台的文件上传预处理接口,并在步骤4里获取到upload_token。
三方服务端通过步骤5,将upload_token返回给三方WEB端,用于后续流程的交互。
分片上传环节
步骤6,三方WEB端调用JS SDK能力,并填入参数。
JS SDK通过步骤7进行本地视频文件的切片操作。然后循环执行步骤8,将分片全部上传至开放平台。此时,三方WEB端可通过JS SDK获取上传进度信息。
合片环节
JS SDK执行到步骤10,判断分片都以上传完毕,通过步骤11调用开放平台的合片接口,触发合片流程。
步骤12通知合片完成之后,JS SDK通知三方WEB文件上传流程已执行完毕。
思考
这一版本通过JS SDK的方案来支持专项用户快速、低成本地接入开放平台,实践了一些定制化的方案,为后续通用能力的沉淀积累经验。
该版本也存在一些待改进的地方,因涉及到客户端跨域请求,需要有域名白名单的处理,这部分还需要人为介入。
改进带来的收益
通过这一系列的技术改进,通过对用户反馈信息进行分析发现,用户在视频文件上传环节的问题反馈明显减少。之前常见的参数问题,如upos_uri和profile被url_encode了多次等高频问题已不再出现。根据埋点数据分析得知,从企业首次申请资质,到首次投稿成功,平均耗时缩短了62.67%。
后续演进的思考
开放平台当前主要通过公共邮箱、工单系统、日志采集、接口埋点上报的方式,来获取用户接入的情况,寻找不断演进的方向。
公共邮箱和工单系统,主要是用于客户主动进行咨询和反馈,开放平台客户支持团队进行回复。根据这些信息及其后续跟进沟通,可以较为明确底收集到客户的真实诉求,并逐步形成Q&A文档。
日志采集主要用于错误日志告警场景,针对用户在接口调用时常见的错误进行整理,有针对性地优化对外接口文档,引导用户正确接入。
接口埋点上报,则针对接口调用情况进行上报并存储在hive中,在数据平台和BI平台进行多维度的数据分析,产出报表以供决策。
更多体验欢迎访问开放平台官网地址:https://openhome.bilibili.com/