在国外视频网站都早已采用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&amp;wsSecret2=bdd28d4da66692521875ce8be36a2807&amp;oi=2021932405&amp;appkey=4ebafd7c4951b366&amp;or=987503882"
    ],
    "url": "http://ws.acgvideo.com/2/e8/3580782-1.mp4?wsTime=1453224424&amp;wsSecret2=cc4ff05eabce23fb761d568caf3c85db&amp;oi=2021932405&amp;appkey=4ebafd7c4951b366&amp;or=987503882"
}`</pre>
成功拿到视频源`http://ws.acgvideo.com/2/e8/3580782-1.mp4?wsTime=1453224424&amp;wsSecret2=
cc4ff05eabce23fb761d568caf3c85db&amp;oi=2021932405&amp;appkey=4ebafd7c4951b366&amp;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") &gt; 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)