bilibili 直播 HTML5 播放器

B 站的直播的 HTML5 播放器

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

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

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

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

您需要先安装一个扩展,例如 篡改猴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('打开弹幕');
        }
    });
}