在国外视频网站都早已采用html5播放器的时候,绝大部分国内视频网站还在用flash,比如B站。Flash这货已经快被淘汰了,刚好DIYgod开发了一款H5弹幕播放器DPlayer,可以拿来对接B站。原理很简单,服务端获取B站弹幕数据,转换为适用于DPlayer的格式用于播放。
1.获取B站视频源
GitHub上找到一个B站第三方API,可以获取视频源等信息:
GET http://bilibili-service.daoapp.io/view/3580782 (其中3580782 为AV号),接口返回:
{
"allow_bp": 1,
"allow_download": 1,
"allow_feed": 0,
"author": "哔哩哔哩番剧",
"bangumi": {
"allow_download": "1",
"bangumi_id": "1033",
"season_id": "3271",
"title": "极速老师"
},
"coins": "5584",
"created": 1452804600,
"created_at": "2016-01-15 04:50",
"credit": "0",
"description": "#02 枫的时间 ",
"face": "http://i0.hdslb.com/user/9281/928123/myface.png",
"favorites": "4621",
"instant_server": "chat.bilibili.com",
"list": {
"0": {
"cid": 5710510,
"has_alias": false,
"page": 1,
"part": "",
"type": "vupload",
"vid": "vupload_5710510"
}
},
"mid": "928123",
"pages": 1,
"pic": "http://i0.hdslb.com/video/9a/9a886536a807d717fe9bfe9bd811ed5b.jpg",
"play": "979055",
"review": "4630",
"spid": null,
"src": "c",
"tag": "TV动画,洲崎绫,田中美海,冈本信彦,伊藤静,BILIBILI正版,黄老师,福山润,极速老师 第二季",
"tid": 33,
"title": "【1月】极速老师 第二季 02【独家正版】",
"typename": "连载动画",
"video_review": "46974"
}`</pre>
`list`即为该视频的分P,我们需要的是分P的CID,比如上面这个只分了1P,CID为5710510。
再GET第二个接口[http://bilibili-service.daoapp.io/video/3580782?quality=2](http://bilibili-service.daoapp.io/video/3580782?quality=2)
参数:
<pre>`quailty [int] 清晰度(1~2,根据视频有不同)
type [int] 0:flv,1:hdmp4,2:mp4
`</pre>
接口返回
<pre>`{
"accept": "mp4,hdmp4",
"backup": [
"http://cc.acgvideo.com/201601191329/77fcfd7934552b0e2cf974e84d7d92ba/b/81/3580782-1.mp4",
"http://ws.acgvideo.com/2/e8/3580782-1hd.mp4?wsTime=1453224424&wsSecret2=bdd28d4da66692521875ce8be36a2807&oi=2021932405&appkey=4ebafd7c4951b366&or=987503882"
],
"url": "http://ws.acgvideo.com/2/e8/3580782-1.mp4?wsTime=1453224424&wsSecret2=cc4ff05eabce23fb761d568caf3c85db&oi=2021932405&appkey=4ebafd7c4951b366&or=987503882"
}`</pre>
成功拿到视频源`http://ws.acgvideo.com/2/e8/3580782-1.mp4?wsTime=1453224424&wsSecret2=
cc4ff05eabce23fb761d568caf3c85db&oi=2021932405&appkey=4ebafd7c4951b366&or=987503882`
### 2.获取弹幕数据
B站弹幕数据接口:`comment.bilibili.com/[CID].xml`,我写了个简单的py脚本可以将其转换为DPlayer适用的格式。
接口为:`https://mm.aoaoao.me/?id=[CID]`
在DPlayer的Options中:
<pre>`var option = {
element: document.getElementById('player1'), // Optional, player element
autoplay: false, // Optional, autoplay video, not supported by mobile browsers
theme: '#FADFA3', // Optional, theme color, default: #b7daff
loop: true, // Optional, loop play music, default: true
video: { // Required, video info
url: '此处填写刚刚获取到的视频源URL', // Required, video url
pic: '封面图' // Optional, music picture
},
danmaku: { // Optional, showing danmaku
id: '此处填写视频CID', // Required, danmaku id, MUST BE UNIQUE, CAN NOT USE THESE IN YOUR NEW PLAYER: `https://dplayer.daoapp.io/list`
api: '此处填写转换服务端URL,你可以用我的:http://mm.aoaoao.me', // Required, danmaku api
token: 'tokendemo', // Optional, danmaku token for api
maximum: 1000 // Optional, maximum quantity of danmaku
}
}`</pre>
配置好后DPlayer可正常播放显示弹幕:
![QQ截图20160608132339](https://cdn.aoaoao.me/wp-content/uploads/2016/06/QQ截图20160608132339.png)
这里有一个Demo,调用了B站的一个视频:[http://aoaoao.me/api/demo/demo/](http://aoaoao.me/api/demo/demo/)
弹幕数据转换Python脚本:
<pre>`import requests
import sys
from flask import Flask,make_response
from flask import request
from xml.etree import ElementTree
reload(sys)
sys.setdefaultencoding('utf-8')
app = Flask(__name__)
node_info = list()
def get_node(node):
if node.attrib.has_key("p") > 0 :
node_list = [node.text,node.attrib['p']]
danmuinfo = node.attrib['p'].split(",")
node_info.append(node_list)
danmu_type = danmuinfo[1].replace("1","right")
danmu_type = danmu_type.replace("4","bottom")
danmu_type = danmu_type.replace("5","top")
danmu_text = str(node.text).replace('"',"")
danmu_text = danmu_text.replace("'","")
danmu_text = danmu_text.replace("\\","/")
return '{"_id":"'+danmuinfo[7]+'","author":"'+danmuinfo[6]+'","time":"'+danmuinfo[0]+'","text":"'+danmu_text+'","color":"#'+str(hex(int(danmuinfo[3])))[2:]+'","type":"'+danmu_type+'","player": ["bilibili469620"]},'
@app.route('/', methods=['POST', 'GET'])
def get_data():
r = requests.get('http://comment.bilibili.com/'+request.args.get('id',0)+'.xml')
root = ElementTree.fromstring(r.text)
lst_node = root.getiterator("d")
i = 1
data = ""
for node in lst_node:
data = data + get_node(node)
i = i + 1
finall_data='{"code": 1,"danmaku": ['+data[:-1]+']}'
response = make_response(finall_data,200)
response.headers['Access-Control-Allow-Origin'] = '*'
return response
if __name__ == '__main__':
app.run(host='0.0.0.0',threaded=True)