💻作者 : SoEasy 📅时间 : 2024年4月5日 🪢个人公众号 : SoEasy同学
一、弹幕原理与开发
1.1 简介
在使用TVBox观看剧集时,可以通过弹幕开关打开,弹幕会随着视频的播放而滚动。如图:
本文带你了解TVBox的FongMi版,是如何开发接口源的时候带上弹幕效果的。
1.2 弹幕原理
影视(FongMi)壳是支持播放时带弹幕的,需要在开发接口源时,向壳子提供弹幕接口,弹幕接口和解析后的播放直链(.m3u8)接口同步返回。
以java开发的接口源为例:
在接口源的playContent方法中,通常最终只返回url和header,例如:
return Result.get().url(realUrl).header(getHeader()).string();
其返回结构如下:
{
“url”: "https://xxx.com/xxx.m3u8",
"header": {xxx}
}
若要加弹幕接口,需要写成:
return Result.get().url(realUrl).danmaku(danmuUrl).header(getHeader()).string();
其返回接口如下:
{
“url”: "https://xxx.com/xxx.m3u8",
"danmaku": "http://xxx.com/danmuxxx",
"header": {xxx}
}
这里的key为danmaku,是FongMi壳子支持的弹幕url的key。值danmuUrl必须是一个在线地址,不是直接返回弹幕文件。
因此弹幕接口,需要有服务器进行托管(相当于T4接口弹幕),当然,你也可以通过爬虫jar包中,启动本地代理,通过本地服务提供弹幕接口。
1.2 弹幕接口规范
FongMi壳对弹幕接口有一定规范,具体如下:
接口响应码:200
接口响应头:Content-Type: application/xml
接口响应结果:
<?xml
version="1.0" encoding="UTF-8"?>
<i>
<chatserver>chat.bilibili.com</chatserver>
<chatid>52175602</chatid>
<mission>0</mission>
<maxlimit>1000</maxlimit>
<state>0</state>
<real_name>0</real_name>
<source>k-v</source>
<d p="1,5,24,16777215">有 6515 条弹幕列队来袭~做好准备吧!</d>
<d p="0,1,24,16777215">这是我的第一条弹幕</d>
<d p="0,1,24,16777215">这是我的第一条弹幕</d>
</i>
其中的字段解释如下:
- chatserver 和 chatid 分别表示对话的服务和id,壳子不做要求,自己标记即可
- mission 和 maxlimit 可按照示例指定
- state real_name 均为0即可
- source 固定k-v格式
d标签就是真正的弹幕数据,格式如下:
1)d标签的内容即弹幕内容
2)p属性有四个值,分别表示:
- 弹幕随视频出现的时间(单位秒)
- 弹幕的出现方式,1表示从右向左滚动,5表示固定在顶部居中
- 弹幕的字体大小,表示24px
- 弹幕的颜色,例如#FFFFFF是黑色,将16进制的FFFFFF转成10静止的结果
1.3 弹幕源
弹幕源就是弹幕网站的数据,有一些网站会自建弹幕源(例如玩偶),也有一些会采集爱优腾官方的弹幕。
推荐使用圣城影视的弹幕源接口,其接口规则如下:
https://dmku.thefilehosting.com/?ac=dm&url=https://www.iqiyi.com/v_22wkjrcd5fc.html
格式为: https://dmku.thefilehosting.com/?ac=dm&url= 参数url为视频的官网播放页面地址(爱奇艺),例如:https://www.iqiyi.com/v_22wkjrcd5fc.html
案例是仙剑四第一季的播放页面,弹幕源接口返回的数据为json格式,结果如下:
{
"code": 23,
"name": "94ae89d19150ee41ee2e P",
"danum": 13121,
"danmuku": [
[
1,
"top",
"#FFFFFF",
"",
"有 13121 条弹幕列队来袭~做好准备吧!"
],
[
"6",
"top",
"#fb7299",
"",
"请不要相信视频中任何广告,有任何问题到留言进行反馈!"
],
[
1,
"right",
"#FFFFFF",
"",
"鞠宝出场 黄金万两",
"",
"",
"24px"
]
]
}
danmuku对应的值为弹幕数据,格式为:
- 第1个表示类型1-滚动,6-固定
- 第2个“top”或"right",表示方向,在顶部或者从右向左
- 第3个表示字体颜色
- 第5个为弹幕内容
- 第8个为弹幕字体大小
1.4 弹幕接口
通过以上步骤大概能够开发出一个在FongMi壳播放的弹幕demo。你只需要部署一个服务,提供一个在线的弹幕接口,通过入参(例如剧名、集数、分类等)去调用圣城的弹幕库的数据,将json格式的数据转换成FongMi壳需要的xml格式,弹幕接口url地址提供给接口源开发的playContent方法里的danmaku字段即可。壳子会去调用弹幕url获取弹幕数据。
二、本地代理
2.1 本地代理原理
上面的步骤需要服务器托管弹幕接口,一般开发接口源时并没有服务器可托管,因此,可以利用FongMi壳提供的本地代理接口实现弹幕接口托管。
本地代理的本质是:FongMi壳在软件启动时,会提供一个本地http服务,默认ip为127.0.0.1,端口9978。默认提供了如推送url,设置地址等功能。但是你可以通过开发jar包时,提供一个proxy的类来拓展本地接口的功能。
你可以在FongMi的爬虫仓库获取到proxy.java代码。提供了一下方法:
public static Object[] proxy(Map<String, String> params) throws Exception {
switch (params.get("do")) {
case "ck":
return new Object[]{200, "text/plain; charset=utf-8", new ByteArrayInputStream("ok".getBytes("UTF-8"))};
case "ali":
return Ali.proxy(params);
case "bili":
return Bili.proxy(params);
case "webdav":
return WebDAV.vod(params);
default:
return null;
}
}
使用FongMi的爬虫仓库打包后,你可以通过设备的ip,访问上面的ck即测试接口:check
接口url如下:
http://127.0.0.1:9978/proxy?do=ck
将ip替换成设备的ip进行测试时,会返回字符串ok。参数params可以在url后面加上&xxx=xxx提供。
2.2 本地代理开发弹幕接口
基于以上原理,你可以拓展开发出一个本地弹幕接口,用于将圣城弹幕源数据转成壳子需要的xml格式,再将本地弹幕接口作为壳子需要的弹幕接口提供出去即可。
改造逻辑如下:
- 拓展proxy里的方法,添加一个case,
case "danmu":
return Danmu.proxy(params);
- 在Danmu.java文件里,提供proxy静态方法(demo)
public static Object[] proxy(Map<String, String> params) {
// 弹幕库 https://dmku.thefilehosting.com/?ac=dm&url=https://www.iqiyi.com/v_28zgfdyu0ns.html
Object[] result = new Object[3];
result[0] = 200;
result[1] = "application/xml";
String test = "<?xml\n" +
"version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<i>\n" +
" <chatserver>chat.bilibili.com</chatserver>\n" +
" <chatid>52175602</chatid>\n" +
" <mission>0</mission>\n" +
" <maxlimit>1000</maxlimit>\n" +
" <state>0</state>\n" +
" <real_name>0</real_name>\n" +
" <source>k-v</source>\n" +
" <d p=\"1,5,24,16777215\">有 无数 条弹幕列队来袭~做好准备吧!</d>\n" +
" <d p=\"0,1,24,16777215\">SoEasy的弹幕测试0</d>\n" +
" <d p=\"1,1,24,16777215\">SoEasy的弹幕测试1</d>\n" +
" <d p=\"3,1,24,16777215\">SoEasy的弹幕测试3</d>\n" +
" <d p=\"6,1,24,16777215\">SoEasy的弹幕测试6</d>\n" +
" <d p=\"9,1,24,16777215\">SoEasy的弹幕测试9</d>\n" +
" <d p=\"15,1,24,16777215\">SoEasy的弹幕测试15</d>\n" +
"</i>";
result[2] = new ByteArrayInputStream(test.getBytes());
return result;
}
- 在你开发的接口源里,playcontent方法改造成:
{
// xxxx
String danmuUrl = Proxy.getUrl() + "?do=danmu"; //getUrl()的结果就是 127.0.0.1:9978
return Result.get().url(realUrl).danmaku(danmuUrl).header(getHeader()).string();
}
ps:
注意本地代理接口proxy的写法:
public static Object[] proxy(Map<String, String> params)
入参接受一个map,可以传递剧名、集数等参数
返回值是一个对象数据。开发时参照案例开发即可。规则如下:
- 第一个对象,返回响应码
- 第二个对象,返回响应头Content-Type的值
- 第三个对象,返回响应内容的字节数组输入流
2.3 抓包测试
以ok的线路中南瓜弹幕为例,播放时抓包,可以看到弹幕接口:
以ok的线路进行弹幕测试: url: 192.168.1.6:9978/proxy?do=danmu&type_name=悬疑,谍战,国产,电视剧&vod_year=&vod_name=追击者&ep_name=1
以本地demo案例测试效果如下: