最近闲的无聊开始看番,然后B站的番要大会员,网上看视频又没有弹幕,于是就想着把B站弹幕加载到别的视频上,于是研究就开始了。。。
获取cid#
查了很多资料,有很多可以获取cid的方法,但是都没办法用php写出来,我一度裂开了啊。然后不小心点到查看源代码,发现所有的cid都写在了里面。。。
算了,不多做解释了,贴个代码吧。
获取方法:?url=番剧分享地址(不能是b.tv开头的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<? php
header("Content-type:application/json");
function get($url) {
$ua = "Mozilla/5.0 (Windows NT 6.3; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36 Edg/81.0.416.62";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_USERAGENT, $ua);
curl_setopt($curl, CURLOPT_ENCODING, "gzip"); //这里是关键,曾一度乱码,一直以为是编码的问题,让我又裂了好久
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
$url = str_replace('m.bilibili.com', 'www.bilibili.com', $_GET['url']);
$result = get($url);
preg_match("/window\.__INITIAL_STATE__=\{(.*?)\};/", $result, $matches);
$preJson = str_replace("window.__INITIAL_STATE__=", "", $matches[0]);
$preJson = str_replace(";", "", $preJson);
$dataArray = json_decode($preJson, true);
$epList = $dataArray['epList'];
for ($i = 0; $i < count($epList); $i++) {
$return[] = [
'cid' => $epList[$i]['cid'],
'name' => $epList[$i]['titleFormat'].$epList[$i]['longTitle'].$epList[$i]['badge'],
'cover' => "https:".$epList[$i]['cover'],
'comment' => "https://comment.bilibili.com/".$epList[$i]['cid'].
".xml"
];
//cover和comment完全是闲了么事加的
}
echo json_encode($return, JSON_UNESCAPED_UNICODE);
?>
|
转换弹幕格式#
总体内容#
梅开二度,我又裂了啊,Dplayer不支持xml的格式,还必须自己转换。在网上查到一个,没有用,又不知道他在写什么玩意,只好自己动手了。
参考了一下Dplayer 的示例视频的弹幕,我开始了研究
获取方法: ?cid={cid}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<? php
header("Content-type:application/json");
function get($url) {
$ua = "Mozilla/5.0 (Windows NT 6.3; ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36 Edg/81.0.416.62";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_USERAGENT, $ua);
curl_setopt($curl, CURLOPT_ENCODING, "gzip");
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
function xmlToJson($xmlContent) {
//通过正则获取弹幕参数
$query = "/<d.*?p=\"(.*?)\".*?>(.*?)<\/d>/";
preg_match_all($query, $xmlContent, $matches);
$result['code'] = 0;
for ($i = 0; $i < count($matches[1]); $i++) {
$p = explode(",", $matches[1][$i]);
if ($p[1] == "4") {
$p[1] = "2";
}
elseif($p[1] == '5') {
$p[1] = '1';
}
elseif($p[1] == '1') {
$p[1] = '0';
}
$result['data'][] = [
round($p[0], 3),
intval($p[1]),
intval($p[3]),
$p[6],
$matches[2][$i]
];
}
return $result;
}
$xmlContent = get("https://comment.bilibili.com/".$_GET['cid'].
".xml");
$result = xmlToJson($xmlContent);
echo json_encode($result, JSON_UNESCAPED_UNICODE);
?>
|
写完这一段,发现参数完全对上了,却加载不了,我又裂了啊,最后猜是JS对数据类型要求比较严格,于是做出了尝试,最终解决了。。。
弹幕位置的转化#
写完之后,发现弹幕位置对不上。。。
参考资料:https://www.bilibili.com/read/mobile/6189156
经过尝试发现Dplayer的弹幕位置参数如下
Dplayer的使用#
基本使用#
使用前需要引入js文件
1
|
<script src="https://jsd.imbai.cn/pics/npm/dplayer/dist/DPlayer.min.js">
|
1
2
3
4
5
6
7
8
9
10
|
const dp = new DPlayer({
container: document.getElementById('player'),//通过id获取位置
preload: 'none',
video: {
url: url
},
danmaku: {
addition: [comment]
}
});
|
出现的一些问题和解决办法#
问题一: 部分格式文件播放不了
建议一次性引用下面这些JS文件
1
2
3
4
5
6
7
8
|
<script src="https://jsd.imbai.cn/pics/npm/flv.js/dist/flv.min.js">
</script>
<script src="https://jsd.imbai.cn/pics/npm/hls.js/dist/hls.min.js">
</script>
<script src="https://jsd.imbai.cn/pics/npm/dashjs/dist/dash.all.min.js">
</script>
<script src="https://jsd.imbai.cn/pics/webtorrent/latest/webtorrent.min.js">
</script>
|
这里我也裂开了,当时大晚上能用第二天早上就不能用了,当场蒙了,然后dp的api也用不了,就很懵,于是改成了下面这样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
function reload() {
var num = Math.random() * 100;
var player = "<div id=\"player" + num + "\"></div>";
$("#play").empty();
$("#play").append(player);
var url = $("#videourl").val();
var danmu = $("#danmuurl").val();
load(url, danmu, num);
}
function load(url, comment, num) {
const dp = new DPlayer({
container: document.getElementById('player' + num),
preload: 'none',
video: {
url: url
},
danmaku: {
addition: [comment]
}
});
}
|
就是加了一个随机div,每次构建不同的dplayer
问题三:弹幕字体修改
这里。。。。发现手机不能用font-family的我蒙了
还好在Github上找到了解决办法:fonts.css
引用css
1
|
<link rel="stylesheet" href="https://jsd.imbai.cn/pics/npm/fonts.css@2.0.0/dist/fonts.css">
|
Github地址:https://github.com/zenozeng/fonts.css
最后的最后放上结果的Github地址,随手弄了一个UI
https://github.com/3401797899/bilibili-danmu
好累啊,去休息了。。。