bilibili 直播 HTML5 播放器

B 站的直播的 HTML5 播放器

当前为 2017-02-21 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         bilibili 直播 HTML5 播放器
// @namespace    https://www.kindjeff.com/
// @version      2017.2.21
// @description  B 站的直播的 HTML5 播放器
// @author       kindJeff
// @match        http://live.bilibili.com/*
// @match        https://live.bilibili.com/*
// @require      https://cdn.bootcss.com/hls.js/0.6.21/hls.min.js
// @run-at       document-end
// ==/UserScript==

/***/
(function(t,i){typeof exports==="object"&&typeof module!=="undefined"?module.exports=i():typeof define==="function"&&define.amd?define(i):t.Danmaku=i()})(this,function(){"use strict";function t(){var t=9007199254740991;return[{range:0,time:-t,width:t,height:0},{range:t,time:t,width:0,height:0}]}var i={};function e(){i.ltr=t();i.rtl=t();i.top=t();i.bottom=t()}e();var s=function(t){var e=this;var s=this._hasMedia?this.media.currentTime:Date.now()/1e3;var n=this._hasMedia?this.media.playbackRate:1;function h(t,i){if(i.mode==="top"||i.mode==="bottom"){return s-t.time<e.duration}var h=e.width+t.width;var a=h*(s-t.time)*n/e.duration;if(t.width>a){return true}var r=e.duration+t.time-s;var o=e.duration*e.width/(e.width+i.width);return r>o}var a=i[t.mode];var r=0;var o=0;for(var d=1;d<a.length;d++){var u=a[d];var m=t.height;if(t.mode==="top"||t.mode==="bottom"){m+=u.height}if(u.range-u.height-a[r].range>=m){o=d;break}if(h(u,t)){r=d}}var l=a[r].range;var c={range:l+t.height,time:this._hasMedia?t.time:t._utc,width:t.width,height:t.height};a.splice(r+1,o-r-1,c);if(t.mode==="bottom"){return this.height-t.height-l%this.height}return l%(this.height-t.height)};var n=function(t){var i=document.createElement("div");if(t.html===true){i.innerHTML=t.text}else{i.textContent=t.text}i.style.cssText="position:absolute;";if(t.style){for(var e in t.style){i.style[e]=t.style[e]}}return i};var h=function(){var t=["oTransform","msTransform","mozTransform","webkitTransform","transform"];var i=document.createElement("div").style;for(var e=0;e<t.length;e++){if(t[e]in i){return t[e]}}return"transform"}();var a=function(){var t=Date.now()/1e3;var i=this._hasMedia?this.media.currentTime:t;var e=this._hasMedia?this.media.playbackRate:1;var a=null;var r=0;var o=0;for(o=0;o<this.runningList.length;o++){a=this.runningList[o];r=this._hasMedia?a.time:a._utc;if(i-r>this.duration){this.stage.removeChild(a.node);if(!this._hasMedia){a.node=null}this.runningList.splice(o,1)}}var d=[];var u=document.createDocumentFragment();while(this.position<this.comments.length){a=this.comments[this.position];r=this._hasMedia?a.time:a._utc;if(r>=i){break}a._utc=Date.now()/1e3;a.node=a.node||n(a);this.runningList.push(a);d.push(a);u.appendChild(a.node);++this.position}if(d.length){this.stage.appendChild(u)}for(o=0;o<d.length;o++){a=d[o];a.width=a.width||a.node.offsetWidth;a.height=a.height||a.node.offsetHeight}for(o=0;o<d.length;o++){a=d[o];a.y=s.call(this,a);if(a.mode==="top"||a.mode==="bottom"){a.x=this.width-a.width>>1;a.node.style[h]="translate("+a.x+"px,"+a.y+"px)"}}for(o=0;o<this.runningList.length;o++){a=this.runningList[o];if(a.mode==="top"||a.mode==="bottom"){continue}var m=this.width+a.width;var l=m*(t-a._utc)*e/this.duration;l|=0;if(a.mode==="ltr")a.x=l-a.width;if(a.mode==="rtl")a.x=this.width-l;a.node.style[h]="translate("+a.x+"px,"+a.y+"px)"}};var r=16;var o=16;function d(t){var i=window.getComputedStyle(t,null).getPropertyValue("font-size").match(/(.+)px/)[1]*1;if(t.tagName==="HTML"){o=i}else{r=i}}var u=Object.create(null);var m=function(t){if(u[t]){return u[t]}var i=12;var e=/^(\d+(?:\.\d+)?)(px|%|em|rem)(?:\s*\/\s*(\d+(?:\.\d+)?)(px|%|em|rem)?)?/;var s=t.match(e);if(s){var n=s[1]*1||10;var h=s[2];var a=s[3]*1||1.2;var d=s[4];if(h==="%")n*=r/100;if(h==="em")n*=r;if(h==="rem")n*=o;if(d==="px")i=a;if(d==="%")i=n*a/100;if(d==="em")i=n*a;if(d==="rem")i=o*a;if(d===undefined)i=n*a}u[t]=i;return i};var l=function(t){var i=document.createElement("canvas");var e=i.getContext("2d");var s=t.canvasStyle||{};s.font=s.font||"10px sans-serif";s.textBaseline=s.textBaseline||"bottom";var n=s.lineWidth*1;n=n>0&&n!==Infinity?Math.ceil(n):!!s.strokeStyle*1;e.font=s.font;t.width=t.width||Math.max(1,Math.ceil(e.measureText(t.text).width)+n*2);t.height=t.height||Math.ceil(m(s.font))+n*2;i.width=t.width;i.height=t.height;for(var h in s){e[h]=s[h]}var a=0;switch(s.textBaseline){case"top":case"hanging":a=n;break;case"middle":a=t.height>>1;break;default:a=t.height-n}if(s.strokeStyle){e.strokeText(t.text,n,a)}e.fillText(t.text,n,a);return i};var c=function(){this.stage.context.clearRect(0,0,this.width,this.height);var t=Date.now()/1e3;var i=this._hasMedia?this.media.currentTime:t;var e=this._hasMedia?this.media.playbackRate:1;var n=null;var h=0;var a=0;for(a=0;a<this.runningList.length;a++){n=this.runningList[a];h=this._hasMedia?n.time:n._utc;if(i-h>this.duration){n.canvas=null;this.runningList.splice(a,1)}}while(this.position<this.comments.length){n=this.comments[this.position];h=this._hasMedia?n.time:n._utc;if(h>=i){break}n._utc=Date.now()/1e3;n.canvas=l(n);n.y=s.call(this,n);if(n.mode==="top"||n.mode==="bottom"){n.x=this.width-n.width>>1}this.runningList.push(n);++this.position}for(a=0;a<this.runningList.length;a++){n=this.runningList[a];var r=this.width+n.width;var o=r*(t-n._utc)*e/this.duration;if(n.mode==="ltr")n.x=o-n.width+.5|0;if(n.mode==="rtl")n.x=this.width-o+.5|0;this.stage.context.drawImage(n.canvas,n.x,n.y)}};var f=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(t){return setTimeout(t,50/3)};var v=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||clearTimeout;var p=function(){if(!this.visible||!this.paused){return this}this.paused=false;if(this._hasMedia){for(var t=0;t<this.runningList.length;t++){var i=this.runningList[t];i._utc=Date.now()/1e3-(this.media.currentTime-i.time)}}var e=this;var s=this._useCanvas?c:a;function n(){s.call(e);e._requestID=f(n)}this._requestID=f(n);return this};var g=function(){if(!this.visible||this.paused){return this}this.paused=true;v(this._requestID);this._requestID=0;return this};var w=function(t,i,e){var s=0;var n=0;var h=t.length;while(n<h-1){s=n+h>>1;if(e>=t[s][i]){n=s}else{h=s}}if(t[n]&&e<t[n][i]){return n}return h};var _=function(){if(!this._hasMedia){return this}this.clear();e();var t=w(this.comments,"time",this.media.currentTime);this.position=Math.max(0,t-1);return this};var y=null;var x=null;var b=null;function M(){y=p.bind(this);x=g.bind(this);b=_.bind(this);this.media.addEventListener("play",y);this.media.addEventListener("pause",x);this.media.addEventListener("seeking",b)}function C(){this.media.removeEventListener("play",y);this.media.removeEventListener("pause",x);this.media.removeEventListener("seeking",b);y=null;x=null;b=null}var L=function(t){if(!/^(ltr|top|bottom)$/i.test(t)){return"rtl"}return t.toLowerCase()};var T=function(t){t.prototype.init=function(t){if(this._isInited){return this}if(!t||!t.container&&(!t.video||t.video&&!t.video.parentNode)){throw new Error("Danmaku requires container when initializing.")}this._hasInitContainer=!!t.container;this.container=t.container;this.visible=true;this.engine=(t.engine||"DOM").toLowerCase();this._useCanvas=this.engine==="canvas";this._requestID=0;this._speed=Math.max(0,t.speed)||144;this.duration=4;this.comments=JSON.parse(JSON.stringify(t.comments||[]));this.comments.sort(function(t,i){return t.time-i.time});for(var i=0;i<this.comments.length;i++){this.comments[i].mode=L(this.comments[i].mode)}this.runningList=[];this.position=0;this.paused=true;this.media=t.video||t.audio;this._hasMedia=!!this.media;this._hasVideo=!!t.video;if(this._hasVideo&&!this._hasInitContainer){var e=!this.media.paused;this.container=document.createElement("div");this.container.style.position=this.media.style.position;this.media.style.position="absolute";this.media.parentNode.insertBefore(this.container,this.media);this.container.appendChild(this.media);if(e&&this.media.paused){this.media.play()}}if(this._hasMedia){M.call(this)}if(this._useCanvas){this.stage=document.createElement("canvas");this.stage.context=this.stage.getContext("2d")}else{this.stage=document.createElement("div");this.stage.style.cssText="overflow:hidden;white-space:nowrap;transform:translateZ(0);"}this.stage.style.cssText+="position:relative;pointer-events:none;";this.resize();this.container.appendChild(this.stage);d(document.getElementsByTagName("html")[0]);d(this.container);if(!this._hasMedia||!this.media.paused){_.call(this);p.call(this)}this._isInited=true;return this}};var k=function(t){t.prototype.emit=function(t){if(!t||Object.prototype.toString.call(t)!=="[object Object]"){return this}var i=JSON.parse(JSON.stringify(t));i.text=(i.text||"").toString();i.mode=L(i.mode);i._utc=Date.now()/1e3;if(this._hasMedia){var e=0;if(i.time===undefined){i.time=this.media.currentTime;e=this.position}else{e=w(this.comments,"time",i.time)}this.comments.splice(e,0,i)}else{this.comments.push(i)}return this}};var D=function(t){t.prototype.clear=function(){if(this._useCanvas){this.stage.context.clearRect(0,0,this.width,this.height);for(var t=0;t<this.runningList.length;t++){this.runningList[t].canvas=null}}else{var i=this.stage.lastChild;while(i){this.stage.removeChild(i);i=this.stage.lastChild}}this.runningList=[];return this}};var I=function(t){t.prototype.destroy=function(){if(!this._isInited){return this}g.call(this);this.clear();if(this._hasMedia){C.call(this)}e();if(this._hasVideo&&!this._hasInitContainer){var t=!this.media.paused;this.media.style.position=this.container.style.position;this.container.parentNode.appendChild(this.media);this.container.parentNode.removeChild(this.container);if(t&&this.media.paused){this.media.play()}}for(var i in this){if(Object.prototype.hasOwnProperty.call(this,i)){this[i]=null}}return this}};var E=function(t){t.prototype.show=function(){if(this.visible){return this}this.visible=true;if(this._hasMedia&&this.media.paused){return this}_.call(this);p.call(this);return this}};var N=function(t){t.prototype.hide=function(){if(!this.visible){return this}g.call(this);this.clear();this.visible=false;return this}};var O=function(t){t.prototype.resize=function(){if(this._hasInitContainer){this.width=this.container.offsetWidth;this.height=this.container.offsetHeight}if(this._hasVideo&&(!this._hasInitContainer||!this.width||!this.height)){this.width=this.media.clientWidth;this.height=this.media.clientHeight}if(this._useCanvas){this.stage.width=this.width;this.stage.height=this.height}else{this.stage.style.width=this.width+"px";this.stage.style.height=this.height+"px"}this.duration=this.width/this._speed;return this}};var S=function(t){Object.defineProperty(t.prototype,"speed",{get:function(){return this._speed},set:function(t){if(typeof t!=="number"||isNaN(t)||!isFinite(t)||t<=0){return this._speed}this._speed=t;if(this.width){this.duration=this.width/t}return t}})};function q(t){this._isInited=false;t&&this.init(t)}T(q);k(q);D(q);I(q);E(q);N(q);O(q);S(q);return q});
/***/

var room_id;

setTimeout(function(){
    //var xhr = new XMLHttpRequest();
    //xhr.onreadystatechange=function(){
    //    if (xhr.readyState==4 && xhr.status==200){
    //        eval(xhr.responseText);
            var link = $('#player_object').children('[name="flashvars"]').val();
            room_id = link.match(/cid=.*?&/)[0].slice(4,-1);
            get_url_and_replace_player(room_id);
            init_danmaku();
            set_danmu_control();
            click_list();
    //    }
    //};
    //xhr.open('GET', 'https://raw.githubusercontent.com/weizhenye/Danmaku/master/dist/danmaku.min.js');
    //xhr.send();
}, 2000);


function get_url_and_replace_player(room_id){
    var api_url = 'https://api.live.bilibili.com/api/playurl?platform=h5&cid=' + room_id;
    $.ajax({
        url: api_url,
        type: "GET",
        dataType: 'json',
        success: function(data){
            replace_player(data.data);

            if(window.df_danmu_ws!==undefined){
                window.i_close_it_myself = true;
                window.df_danmu_ws.close();
                window.df_danmu_ws = undefined;
            }
            var df_domain = 'broadcastlv.chat.bilibili.com';
            var df_portobj = {'ws':7170, 'wss':7172};
            window.df_danmu_ws = new DanmuSocket(parseInt(room_id), df_domain, df_portobj);
            window.df_danmu_ws.setListener(danmuListener);
        }
    });
}

function replace_player(m3u8_url){
    var w = $('#js-player-decorator').width();
    var h = $('#js-player-decorator').height();

    remove_player();

    var player = document.createElement('video');
    player.id = 'h5_player';
    player.style.width = '100%';
    player.style.height = '100%';
    player.style.position = 'absolute';
    player.setAttribute('controls', 'controls');
    document.getElementById('js-player-decorator').appendChild(player);

    if(Hls.isSupported()) {
        var video = document.getElementById('h5_player');
        var hls = new Hls();
        hls.loadSource(m3u8_url);
        hls.attachMedia(video);
        hls.on(Hls.Events.MANIFEST_PARSED,function() {
          video.play();
        });
    }
}

function remove_player(){
    var flash_player = document.getElementById('player_object');
    if(flash_player!==null)
        flash_player.remove();

    var html5_player = document.getElementById('h5_player');
    if(html5_player!==null)
        html5_player.remove();
}

function click_list(){
    if(window.location.pathname==='/'){
        $($('[role="list"]')[0]).children().on('click', function(){
            var room_id = $(this).attr('data-cid');
            get_url_and_replace_player(room_id);
        });
    }
}


/* danmaku */
const rawHeaderLen = 16;
const packetOffset = 0;
const headerOffset = 4;
const verOffset = 6;
const opOffset = 8;
const seqOffset = 12;
var pako = window.pako;
var textDecoder = getDecoder(true);
var textEncoder = getEncoder();
var heartbeatInterval;

function getDecoder (isUseful) {
    if(window['TextDecoder'] && isUseful) {
        return new window['TextDecoder']();
    } else {
        return {
            decode: (buf) => {
                return decodeURIComponent(window.escape(String.fromCharCode.apply(null, new Uint8Array(buf))));
            }
        }
    }
}

function getEncoder () {
    if(window['TextEncoder']) {
        return new window['TextEncoder']();
    } else {
        return {
            encode: (str) => {
                let buf = new ArrayBuffer(str.length);
                let bufView = new Uint8Array(buf);
                for (let i = 0, strlen = str.length; i < strlen; i++) {
                    bufView[i] = str.charCodeAt(i);
                }
                return bufView;
            }
        }
    }
}

function mergeArrayBuffer(ab1, ab2) {
    var u81 = new Uint8Array(ab1),
        u82 = new Uint8Array(ab2),
        res = new Uint8Array(ab1.byteLength + ab2.byteLength);
    res.set(u81, 0);
    res.set(u82, ab1.byteLength);
    return res.buffer;
}

class DanmuSocket {

    constructor (roomid,domain,portobj) {
        const ws = window.location.protocol.indexOf('https') > -1 ? 'wss' : 'ws';
        const port = portobj[ws];
        this.connection = new WebSocket(ws + "://"+ domain +":"+ port +"/sub");
        this.connection.binaryType = 'arraybuffer';
        this.connection.onopen = this.firstConnection.bind(this);
        this.connection.onmessage = onMessage.bind(this);
        this.connection.onclose = onClose.bind(this);
        this.connection.onerror = onError.bind(this);
        this.roomid = roomid
    }

    firstConnection () {
        console.log("Danmu WebSocket Server Connected.");
        console.log("Handshaking...");
        var token = JSON.stringify({
            'uid': 0,
            'roomid': this.roomid
        });
        var headerBuf = new ArrayBuffer(rawHeaderLen);
        var headerView = new DataView(headerBuf, 0);
        var bodyBuf = textEncoder.encode(token);
        headerView.setInt32(packetOffset, rawHeaderLen + bodyBuf.byteLength);
        headerView.setInt16(headerOffset, rawHeaderLen);
        headerView.setInt16(verOffset, 1);
        headerView.setInt32(opOffset, 7);
        headerView.setInt32(seqOffset, 1);
        this.connection.send(mergeArrayBuffer(headerBuf, bodyBuf));
    }

    heartBeat () {
        var headerBuf = new ArrayBuffer(rawHeaderLen);
        var headerView = new DataView(headerBuf, 0);
        headerView.setInt32(packetOffset, rawHeaderLen);
        headerView.setInt16(headerOffset, rawHeaderLen);
        headerView.setInt16(verOffset, 1);
        headerView.setInt32(opOffset, 2);
        headerView.setInt32(seqOffset, 1);
        this.connection.send(headerBuf);
    }

    closeHeartBeat () {
        clearInterval(this.heartBeating);
    }

    send (data) {
        this.connection.send(data);
    }

    close () {
        this.connection.close();
    }

    setListener (listener) {
        this._listener = listener;
    }

}

function onMessage (evt) {
    var data = evt.data;
    var dataView = new DataView(data, 0);
    var packetLen = dataView.getInt32(packetOffset);
    var headerLen = dataView.getInt16(headerOffset);
    var ver = dataView.getInt16(verOffset);
    var op = dataView.getInt32(opOffset);
    var seq = dataView.getInt32(seqOffset);

    switch(op) {
        case 8:
            this.heartBeat();
            heartbeatInterval = setInterval(this.heartBeat.bind(this), 30 * 1000);
        break;
        case 3:
            // console.log("online: " + dataView.getInt32(16));
            if (this._listener) this._listener('online', dataView.getInt32(16));
        break;
        case 5:
            var packetView = dataView;
            var msg = data;
            var msgBody;
            for (var offset=0; offset<msg.byteLength; offset+=packetLen) {
                packetLen = packetView.getInt32(offset);
                headerLen = packetView.getInt16(offset+headerOffset);
                msgBody = textDecoder.decode(msg.slice(offset+headerLen, offset+packetLen));
                if (!msgBody) {
                    textDecoder = getDecoder(false);
                    msgBody = textDecoder.decode(msg.slice(offset+headerLen, offset+packetLen));
                }
                if (this._listener) this._listener('msg', msgBody);
            }
        break;
    }
}

function onClose () {
    if (heartbeatInterval) clearInterval(heartbeatInterval);
    if(! i_close_it_myself){
        var delay = Math.floor(Math.random() * (6 - 3) + 3);
        setTimeout(this.firstConnection.bind(this), delay * 1000);
        console.log(delay);
    }
    i_close_it_myself = false;
}

function onError () {
    console.log("Client Error.");
}


/*******************/
function change_online(online) {
    $('span.v-bottom').text(online + ' 人');
}

function emit_danmu(data) {
    if(data.cmd==='DANMU_MSG'){
        var msg = data.info[1];
        window.df_danmaku.emit({
            text: msg,
            canvasStyle: {
                font: data.info[0][2]+'px sans-serif',
                textAlign: 'start',
                textBaseline: 'bottom',
                direction: 'inherit',
                fillStyle: '#fff',
                strokeStyle: '#000',
                lineWidth: 1.2,
                shadowBlur: 0,
                shadowColor: '#000',
                shadowOffsetX: 0,
                shadowOffsetY: 0,
                filter: 'none',
                globalAlpha: 1.0
            }
        })
    }else if(data.cmd==='WELCOME'){

    }else if(data.cmd==='SEND_GIFT'){

    }
}

function append_danmu(data) {
    if(data.cmd==='DANMU_MSG'){
        var u_name = data.info[2][1];
        var uid = data.info[2][0];
        var lv = data.info[4][0];
        var rank = data.info[4][3]; if(typeof(rank)=='string'&&rank.indexOf('>')!==-1) {rank.replace('>', '&gt;')}
        var msg = data.info[1];
        // console.log(u_name,uid,lv,rank,msg);
        var comment_div = '<div class="msg-item-ctnr"><div class="chat-msg " data-uname="'+u_name+'" data-uid="'+uid+'"><div class="user-level-icon lv-'+lv+'"> UL '+lv+' <div class="user-level-info"><p>用户等级:'+lv+'</p><p><a href="http://live.bilibili.com/rank" target="_blank">排名:'+rank+'</a></p></div></div><span class="user-name color">'+u_name+' : </span><span class="msg-content">'+msg+'</span></div></div>';
        $(comment_div).appendTo('#chat-msg-list');
        if($('#chat-msg-list').children().length>100)
            $('#chat-msg-list').children(':first').remove();
        $("#chat-msg-list").scrollTop($("#chat-msg-list")[0].scrollHeight);
    }
}

function danmuListener(content_type, content){
    if(content_type==='online'){
        if(window.dom_changed===undefined){
            $('#h5_player').prev().appendTo('#js-player-decorator');
            window.dom_changed = true;
        }
        change_online(content);
    }else if(content_type==='msg'){
        var content_obj = JSON.parse(content);
        emit_danmu(content_obj);
        append_danmu(content_obj);
    }
}

function init_danmaku() {
    window.df_danmaku = new Danmaku();
    df_danmaku.init({
        container: $('#js-player-decorator')[0],
        video: $("#h5_player")[0],
        engine:'canvas'
    });
    $('canvas')[0].style.position = 'absolute';

    // send danmu
    function send_danmu(){
        var msg = $("#df-danmu-textbox").val();
        var xhr = new XMLHttpRequest();
        // xhr.setRequestHeader('X-Cookie', document.cookie);
        xhr.open('POST', 'http://live.bilibili.com/msg/send');
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send($.param({
            color: 16777215,
            fontsize: 25,
            mode: 1,
            msg: msg,
            rnd: Math.floor(Date.now() / 1000),
            roomid: room_id
        }));
    }
    $("#danmu-textbox").off('keypress');
    $("#danmu-textbox").off('keyup');
    $("#danmu-textbox").off('keydown');
    $("#danmu-send-btn").off('click');

    $("#danmu-textbox")[0].id = 'df-danmu-textbox';
    $("#danmu-send-btn")[0].id = 'df-danmu-send-btn';
    $("#df-danmu-textbox").on('keyup', function (e) {
        if(e.keyCode == 13){
            send_danmu();
            $("#df-danmu-textbox").val('');
            e.preventDefault();
            return false;
        }
        return true;
    });
    $("#df-danmu-send-btn").on('click', function (e) {
        e.preventDefault();
        send_danmu();
        $("#df-danmu-textbox").val('');
    });
}

function set_danmu_control(){
    if(location.pathname==='/'){
        return;
    }

    var control_btn = $("<button>关闭弹幕</button>");
    control_btn.css('border-radius', '5px');
    control_btn.css('font-size', '12px');
    control_btn.height('21px');
    $('.room-info.tag-ctnr.v-top').children().remove();
    control_btn.appendTo('.room-info.tag-ctnr.v-top');
    control_btn.on('click', function () {
        if(control_btn.text()=='打开弹幕'){
            control_btn.text('关闭弹幕');
            $('canvas')[0].style.display = 'block';
        }else{
            $('canvas')[0].style.display = 'none';
            control_btn.text('打开弹幕');
        }
    });
}