MicroCommunityWeb/public/js/jessibuca/renderer.js
2021-09-30 18:33:44 +08:00

1664 lines
72 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

!(function () {
/**
* @param opt
* container: DOM 容器
* contextOptions
* videoBuffer
* forceNoGL
* isNotMute
* decoder
* @constructor
*/
function Jessibuca(opt) {
this._opt = opt;
if (typeof opt.container === "string") {
this._opt.container = document.getElementById(opt.container);
}
if (!this._opt.container) {
throw new Error('Jessibuca need container option');
return;
}
this._canvasElement = document.createElement("canvas");
this._canvasElement.style.position = "absolute";
this._canvasElement.style.top = 0;
this._canvasElement.style.left = 0;
this._opt.container.appendChild(this._canvasElement);
this._container = this._opt.container;
this._container.style.overflow = "hidden";
this._containerOldPostion = {
position: this._container.style.position,
top: this._container.style.top,
left: this._container.style.left,
width: this._container.style.width,
height: this._container.style.height
}
if (this._containerOldPostion.position != "absolute") {
this._container.style.position = "relative"
}
this._opt.videoBuffer = opt.videoBuffer || 0;
this._opt.text = opt.text || '';
//
this._opt.isResize = opt.isResize === false ? opt.isResize : true;
this._opt.isFullResize = opt.isFullResize === true ? opt.isFullResize : false;
this._opt.isDebug = opt.debug === true;
this._opt.timeout = typeof opt.timeout === 'number' ? opt.timeout : 30;
this._opt.supportDblclickFullscreen = opt.supportDblclickFullscreen === true;
this._opt.showBandwidth = opt.showBandwidth === true;
this._opt.operateBtns = Object.assign({
fullscreen: false,
screenshot: false,
play: false,
audio: false
}, opt.operateBtns || {});
this._opt.keepScreenOn = opt.keepScreenOn === true;
if (!opt.forceNoGL) this._initContextGL();
this._audioContext = new (window.AudioContext || window.webkitAudioContext)();
this._audioEnabled(true);
if (!opt.isNotMute) this._audioEnabled(false);
if (this._contextGL) {
this._initProgram();
this._initBuffers();
this._initTextures();
}
this._onresize = () => this.resize();
this._onfullscreenchange = () => this._fullscreenchange();
window.addEventListener("resize", this._onresize);
document.addEventListener('fullscreenchange', this._onfullscreenchange);
this._decoderWorker = new Worker(opt.decoder || 'ff.js')
var _this = this;
this._hasLoaded = false;
this._stats = {
buf: 0,
fps: 0,
abps: '',
vbps: '',
ts: ''
};
if (this._opt.supportDblclickFullscreen) {
this._canvasElement.addEventListener('dblclick', function () {
_this.fullscreen = !_this.fullscreen;
}, false);
}
this.onPlay = noop;
this.onPause = noop;
this.onRecord = noop;
this.onFullscreen = noop;
this.onMute = noop;
this.onLoad = noop;
this.onLog = noop;
this.onError = noop;
this.onTimeUpdate = noop;
this.onInitSize = noop;
this._onMessage();
this._initDom();
this._initStatus();
this._initEventListener();
this._hideBtns();
//
this._initWakeLock();
this._enableWakeLock();
};
function noop() {
}
Jessibuca.prototype._initDom = function () {
var playBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAARVJREFUSMe9laEOglAUhs+5k9lJFpsJ5QWMJoNGbEY0mEy+gr6GNo0a3SiQCegMRILzGdw4hl+Cd27KxPuXb2zA/91z2YXoGRERkX4fvN3A2QxUiv4dFM3n8jZRBLbbVfd+ubJuF4xjiCyXkksueb1uSKCIZYGLBTEx8ekEoV7PkICeVgs8HiGyXoO2bUigCDM4HoPnM7bI8wwJ6Gk0sEXbLSay30Oo2TQkoGcwgFCSQMhxDAvoETEscDiQkJC4LjMz8+XyZ4HrFYWjEQqHQ1asWGWZfmdFAsVINxuw00HhbvfpydpvxWkKTqdYaRCUfUPJCdzv4Gr1uqfli0tOIAzByUT/iCrL6+84y3Bw+D6ui5Ou+jwA8FnIO++FACgAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDEtMDhUMTY6NDI6NTMrMDg6MDCKP7wnAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAw+2IEmwAAAEl0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vaG9tZS9hZG1pbi9pY29uLWZvbnQvdG1wL2ljb25fZ2Y3MDBzN2IzZncvYm9mYW5nLnN2Z8fICi0AAAAASUVORK5CYII=';
var pauseBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAHVJREFUSMftkCESwCAMBEOnCtdXVMKHeC7oInkEeQJXkRoEZWraipxZc8lsQqQZBACAlIS1oqGhhTCdu3oyxyyMcdRf79c5J7SWDBky+z4173rbJvR+VF/e/qwKqIAKqMBDgZyFzAQCoZTpxq7HLDyOrw/9b07l3z4dDnI2IAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wMS0wOFQxNjo0Mjo1MyswODowMIo/vCcAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDEtMDhUMTY6NDI6NTMrMDg6MDD7YgSbAAAASnRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9ob21lL2FkbWluL2ljb24tZm9udC90bXAvaWNvbl9nZjcwMHM3YjNmdy96YW50aW5nLnN2ZxqNZJkAAAAASUVORK5CYII=';
var screenshotBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAaxJREFUSMfNlLFOAkEQhmevAZMjR6OGRBJKsFBzdkYNpYSaWkopIOFRCBWh1ieA+ALGRgutjK0HzV2H5SX7W/zsmY3cnTEhcZovOzcz9+/s7Ir8d4OGht7fBwAgjvEri2OTl1ffSf0xAMBxRIkS1e3Se3+vcszEMe/6OqmT/aN2m1wsNu/o5YVsNHI7BgA4PCRfXzfXCwKy1RLbcXZG9nrkzc12jvT8nPU/PtatOThgAx8fuS4WyZ0de2e+T87n5OcnuVqRsxl5cpImQDnKUc7DA1fVqpimZCu+vCSjiNH9PlmpJNTQ0INBErfeafZRAakC6FWKfH9nwU7H/l6rGdqCOx3y7c3U+aOARsMMp+1vNskwTLjulB23XJL1epqA9OshIiKeJxAIoug7UyA4OuLi6Ynr52deu+NjOy4MSc9Ln8rMDpTLybBpaOjdXbJUIqdTm8a/t2fn/RSQewR24HicTLmGhnbdzcPquvYtGY3+PIR24UKBUXd35v6Sk4lN47+9NXm/FBAEedfGTjw9JYdDm76fm6+hoS8ujGAxT6L9Im7bTKeurvIEb92+AES1b6x283XSAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAwij+8JwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0wMS0wOFQxNjo0Mjo1MyswODowMPtiBJsAAABJdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL2hvbWUvYWRtaW4vaWNvbi1mb250L3RtcC9pY29uX2dmNzAwczdiM2Z3L2NhbWVyYS5zdmeyubWEAAAAAElFTkSuQmCC';
var fullscreenBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAALZJREFUSMftVbsORUAQVSj8DomChvh3lU5CoSVCQq2RObeYu8XG3deVoHCak81kds7Oaz3vxRcAAMwztOg6vX9d6/3XFQQC+b7iAoFhYE7Tvx9EIFAcy/ftO3MQGAQkCfM4MmeZWyajiLnvmYuCeduMAuSzvRBVYNluFHCssSgFp7Sq9ALKkjnPf9ubRtkDL27HNT3QtsY9cAjsNAVheHIKBOwD2wpxFHDbJpwmaHH2L1iWx+2BDy8RbXXtqbRBAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAwij+8JwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0wMS0wOFQxNjo0Mjo1MyswODowMPtiBJsAAABTdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL2hvbWUvYWRtaW4vaWNvbi1mb250L3RtcC9pY29uX2dmNzAwczdiM2Z3L3F1YW5waW5nenVpZGFodWEuc3ZnTBoI7AAAAABJRU5ErkJggg==';
var minScreenBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAYJJREFUSMfdVbGKwkAQnQn+geAfWBixUTsVgp3YGKxSWflVNmIjARULwc5KO40ipNHWRgs/wGLniucKa+Jd5ODuuGle5u3szGRmd5bor4iIiMhuB3Sc+HXXBdp2/Lpta7v4dccRJUrUdhtNQIkSVa3C8HwG1uumg34f2OnEB+h0tF1Sv5b+YIsttpZLEhKSdhvscPi8IXFF74GJiYnHY7Cex8zMvFgkbInjmJnv98kqoO30vmhLtaRMB60WtEbDNDudgMUiKiQSzfjOMzFxoQAyCPSfw7/nQZ/PUYnpNGV6OR6BmYzJbzYIoBQCzGaRBDQvJCTdLnTLolg5HN5t6f8V1h/oUT4PrVKJWBotmEzQw+vV3J9Ow851P2/BaoX9Yfh0BrJZYKlk8uUyHOpDeLuBHwzMBJtN2PV6IPUhXK9Nf5cLMAxfluanrmGkRBggtRo03wfq66P/6CsJAnOg+f6rgfZI4BGYiYlHIx048eR6krcnq34kkj1GuVz8+jceo9+SD5A8yGh8CTq7AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAwij+8JwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0wMS0wOFQxNjo0Mjo1MyswODowMPtiBJsAAABNdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL2hvbWUvYWRtaW4vaWNvbi1mb250L3RtcC9pY29uX2dmNzAwczdiM2Z3L3p1aXhpYW9odWEuc3ZnoCFr0AAAAABJRU5ErkJggg==';
var quietBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAR9JREFUSMfVlD0LglAYhe9VkwgNihpsjbYQf4JTS7+iuaGxpcGfJjS0NFRLk2NDi6MogafhJGRIX9yEzvJwrx/nvPd9VYh/F3LkyBuN2g3J1QoAgCQhPe/Hxq5Lo+0WlfJ9dYYAgGaTDAIyy/BUnwcwWJlhcLnZkN2ugIBAuy2kkEL2ep8F73S4kjfFcfn6cMj9KLodrWVBiXyf75tMyOOR+4MBOZ8XLXzorboA5UpnM/J0Ivd7+vX7xX2asqGpVKtFXi5sqWmypXefrfIWAACmU/JwKCoun8hu9zA0uk6u13wgirg+n7+bAcsibbt6SB3n9TQXPxwAwHJJpum7M6BcDDQa0SgMaw9QPkJNIxcLMo4ZcDz+eYDqQFLWbqxKV57EtW1WtMbmAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAwij+8JwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0wMS0wOFQxNjo0Mjo1MyswODowMPtiBJsAAABKdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL2hvbWUvYWRtaW4vaWNvbi1mb250L3RtcC9pY29uX2dmNzAwczdiM2Z3L2ppbmd5aW4uc3ZnIlMYaQAAAABJRU5ErkJggg==';
var playAudioBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAU5JREFUSMftkzGKwlAURf9PULBQwULSCKK1bZAgNuoaFFyAC3AdZg0uQCwshWzAShEEO7Gy0soUCu9Occ3An5nMGCfdzGsO7+Xy3/03iVL/lbAAACiVIBCI77O37Vi9QCDZbEqLm03ycEBUAoHk818v7nYpul5Jz4tf8HBKYa1mcjwmbzd8rG8NFIsU7ffk8UjmcjE3XK+RtB4G2PT75GbDeblMttumfjSKMRCGLxsQCKTReE9KIJDJxDw/SmKxiOZWWh+ntrSlre2WXRAorbTSrZapip7X66kbMKtQUFBQCENznsmQ93vqBhh5r8fO85jAcsnIrcce1yV3uxgD8zl5uZgU+dGBVlrp6GbTKRPwffaDAek45Gz2/M0AAJ0OeTol+w0rFYrOZ3K1MhNJEjEAwHF4cBA8Z8B1zcXV6msv+JMR2yaHQ1LrXx/8Z+sNRxsWcwZeb6UAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDEtMDhUMTY6NDI6NTMrMDg6MDCKP7wnAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAw+2IEmwAAAEt0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vaG9tZS9hZG1pbi9pY29uLWZvbnQvdG1wL2ljb25fZ2Y3MDBzN2IzZncvc2hlbmd5aW4uc3ZnFog1MQAAAABJRU5ErkJggg==';
var recordBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAPRJREFUSMflVDEOwjAQO0e8gr2sZYVunREbD6ISfAgmkBjpC/hBEQ+AtTWD6QAI0gBlqRfLp+TiXC5n1nXgMUCS5HBoNBqj6IOMMFwuEpsNAABl6d3HihWrOJaBsuRPkGW+c929HAxuYefb6L+R0ZgkMrJYiItCnCT1sl5Y1jwXj0bNniJNJWqujfX7LyrwJh8AYDxWgulU0dPp20IFlxoODm61kpE4VnS9/puBXyPYgH7LbKY3PhwUnUw+NdC4CdW9+71UgyZspwIBB9No3O0klktxUahyx+Pz+lYG0Xzu84lXRqTqwRQAGAzns8R223gUdxZXGcAK5Hp0ClIAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDEtMDhUMTY6NDI6NTMrMDg6MDCKP7wnAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTAxLTA4VDE2OjQyOjUzKzA4OjAw+2IEmwAAAE50RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vaG9tZS9hZG1pbi9pY29uLWZvbnQvdG1wL2ljb25fZ2Y3MDBzN2IzZncvbHV6aGlzaGlwaW4uc3Zn5Zd7GQAAAABJRU5ErkJggg==';
var recordingBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAAahJREFUSMdjYBjpgBFd4NZK+f+soQYG//T+yzFuUFUl2cApjEWM/758UZvysPDn3127GBkZGBgY/v4l6ICb9xTWsRbp6/9f9W8N44Jz5xgCGI4wfGFiIttrR/5n/3/U3KyR8rj8t0RdHS5lcAv+//yXzzhZTY1ii2FAmsGZocna+maD3GnWY62tNzbJBbDOffLkxie5eJYwa2uYMhaigzb2/zyGguPH/y9mTGKYYGlJUIMiYxDjHCen/4oMDAxznJzg4k8Z/jP+l5LCCAFCQP30Y5dfXVZWDI7/zzIs8PNjNGJ4/7/r+XNKA4rkoNZ4/lj0V9TmzUxJv0J+F+jrM3YyvPq/acsWujmA2oBkB9y4LifLxhoa+teAzYFtwtWr/8sZxBj9fHxo7oCbprJ72MqOHWNgZGBkYFy1isGGoZahTFSU0hAgOhcQnfph4P7/df9T9u1jPMn4nyHmxIn/bAzLGe7GxTHsZyj+f+zpUwYGBmmG6bQsiMr+L/v/rqlJY9Njm9889fW4lGEUxXCHwAomUgH3vxBG8c+f1WWf9P98sns3oaJ4FAAAbtWqHTT84QYAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDEtMDhUMTY6MzU6MjMrMDg6MDBLHbvEAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTAxLTA4VDE2OjM1OjIzKzA4OjAwOkADeAAAAE50RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vaG9tZS9hZG1pbi9pY29uLWZvbnQvdG1wL2ljb25fcTM1YTFhNHBtY2MvbHV6aGlzaGlwaW4uc3Zn6xlv1QAAAABJRU5ErkJggg==';
var gifBase64 = 'data:image/gif;base64,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';
var playBigBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwEAYAAAAHkiXEAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAASAAAAEgARslrPgAAByBJREFUeNrlXFlIVV0U3vsaaINmZoX0YAR6y8oGMkKLoMESSjBoUJEoIogoIggigoryIQoKGqi3Roh6TKGBIkNEe6hMgzTNKLPSUlMrNdvrf/juurlP5zpc7znb+r+X755pn7W+Pe+9zpVimIEUKVKJiUIKKWRqKs5OmwZOTBQkSFBUFK5HR+tPt7WBOzpwX3U1jquqwGVleK6iQkoppSQy7a8xEBERLVwIPnsWXF9PrqCxEXzxInjpUrDH47YO0h2hw8JwtG4deN8+8OzZA0vl7Vt/iZZCCtnUhPPt7fp9o0fjvpgYHHu9uD8+Hsdsh52hggTV1uLg2DHwpUvSIz3S093ttE4hB5qSxYuRAc+f910im5vBFy6As7LALORQ7RgzBullZIBPngQ3NPRt1+vXeH7NGtN69u8oERFFRIDPnQMrZe8YZ0huLhwMDzdjb1gYC4zj4uKAeaFIkbpxAwfWvse48FOngp89s7eeS1p2Nlg63vQF7Y8iRWrlSthZXR2wZhAR0dy55gwlIqI5c8AfPtgbeuUKHIqKMi3soP3z1UzwiRP2NbqtDbxsmXuGacK3tOgG/fwJ3rbNtIDO+J2ZiQzp6ND97uzE+RUrHDaAmxprif/+HQasXm1aKKcBPxcsADc1/VEjFClS8+eH7oXcuSpSpJ480V/Y0wPOyjItjNtgofWmiPHuHa7Hxg79RUT0e1Rjxb/X1ASnDw9vf/3S9bl1K/iEFSlSixbZdz7Xr5t2fLgBuuTn2xfUjRsHmVBYGNg6gWpo+FtHNU4DuowYAZ3Ky+11GzOm/4SIiGjDBvuczM52zAHua4iI6OpVcGEheO1a8PCdP/j9CNRyKFKk9u4doBDWCRXXBOcE0GekgVBUhPuSk00LPTAdCwp0+3n0GBER4AFenbQiJ8cdg7dvpwGB5xunT4PHjTMtuL0/qan29q9fH+AB62jnyxe31moGlwFWNDbCzq1bcez+snLffr14odtrMzrCBet6/Pnz7hoabAZY8fgxT5iGRwbs36/b19kJHjnS49+BEkIIMXmy/vjt26YdCA4pKdgHKC2Fo5cvh2xiFBTu3NGPw8Ox/5CW5tG3/hi8VffokRmDQwUeNOTlwc/KSmRIbq67djx9Cm5p+W2akEKmpfnaSt5zZdTXY8+0udmQcg5h0iQwD3MfPgRPn+7UG6GjUjiqrNSver0eVIWEBP85EiSIN7H/dSxZAuY1roMHHRt02OqamOhrgnoN46SQQn76ZFoad8Hj8kOH4D/PZJOSQvYKW11jYnxNkHWK3NFhWhKz8HrB9+7xaCU06fYKIiBBgiIjfRlgHTf/j+NlNMTFgceOHXJSJEgQ9wXCVyOk9AlvLfEDWDT6X+DAAXSiHz8OOSkppJCRkfrJ9vYR+NHaql8wNV42jVevUFJ37kQ8kHX8PlRMmOD/SYIEtbZ69IAkvsATs38dP36ADx8GJyc7IzyD+xbhqxE1Nb4a8PKlfiE+HsOxyEgYZI1A+9tRUADetQtNTF2dU29CJ84Twhkz9KtVVb4+oKxMvxAWxjM101KFBvX1qNmbNkHwNWucFl4HT/QmTvSfIkGCSks9HC2MsxxzyTekp5uWLjh0dYHz88FeL2ry5ctm7LHq2NMD7rXUg6rC0cKM9+/BfQS1hghDXg1VpEjdvasvLpqHf3VWs/P+/QA3Lltm75jz8T7BZQAvn9tscJgWXpEiNWuWvd2bNwcQwONbnq6p0R8oLnYnA7Zs6Vvw7m7Yd/z4gDe5DQH2Xrum29/SwoObfh7cts1egFWrnDU4Lg785g2Ytx4LC2H4zJmmhe3XD5+dsJsD1xhHjgwwgfBwPFBXpydQXe3uFqXzfU9o7ZUSXFRkX/IHMcENGKXgixY27fBwA8TZudO+5dixY4gJ37xpyQVfvEtmpmnHTQMFMiUFevBeL6OkZMg1GQlER4P5wwTGt29g65bmvw/4HShanD+5mjIlxC+cNw/cKxqYw7RDHZY9TOEXXpEiVVurC8+jtJUrnTNAkSK1fDle2NWlG9DeDs7IMC2UM35zU2Mt8Urhel6eywalp+vCMzhM++hRDlo1LeCg/dNGNdy5Wtt4LvEuCv+HodqHCu/e2Y8Cyss5aNW0sAPzh8fx1uEkgyMGHWxqgjM8NhYGWoNSraMnvm6+89aXDHjmap1AMUpKcD9/+D2MAYNzcsD9fRDNsZMcwsedfehiPJFeUhJ4925wWVnfdvFHiDt2gEM/MXT+rwp47UMKKeT27Ti7Zw+YA6UCgbdKKyr8cTVSSCEbG3Ge/5yDwWtD48fjfv6rAl7C6LUeb4uvX8FnzuD5U6ewjP35s9M6uQaUJP4Qgz8E4SbJ2sk5BV5jevAAvHmzqS9/hs0XJxBi1CgOWtVjVnlHKSEB16Oj/wgoE0L8LsFcM169AldV8Q4UjouKULKtNch9/AdsEf6XQYgIsAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wMS0xMlQxMTo1NjowNSswODowMGcMj/QAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDEtMTJUMTE6NTY6MDUrMDg6MDAWUTdIAAAASXRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9ob21lL2FkbWluL2ljb24tZm9udC90bXAvaWNvbl9wZHMzeWYxNGczYi9ib2Zhbmcuc3Zn11us5wAAAABJRU5ErkJggg==';
function _setStyle(dom, cssObj) {
Object.keys(cssObj).forEach(function (key) {
dom.style[key] = cssObj[key];
})
}
var doms = {};
var fragment = document.createDocumentFragment();
var btnWrap = document.createElement('div');
var control1 = document.createElement('div');
var control2 = document.createElement('div');
var textDom = document.createElement('div');
var speedDom = document.createElement('div');
var playDom = document.createElement('div');
var playBigDom = document.createElement('div');
var pauseDom = document.createElement('div');
var screenshotsDom = document.createElement('div');
var fullscreenDom = document.createElement('div');
var minScreenDom = document.createElement('div');
var loadingDom = document.createElement('div');
var loadingTextDom = document.createElement('div');
var quietAudioDom = document.createElement('div');
var playAudioDom = document.createElement('div');
var recordDom = document.createElement('div');
var recordingDom = document.createElement('div');
var bgDom = document.createElement('div');
loadingTextDom.innerText = this._opt.loadingText || '';
textDom.innerText = this._opt.text || '';
speedDom.innerText = '';
playDom.title = '播放';
pauseDom.title = '暂停';
screenshotsDom.title = '截屏';
fullscreenDom.title = '全屏';
minScreenDom.title = '退出全屏';
quietAudioDom.title = '静音';
playAudioDom.title = '取消静音';
recordDom.title = '录制';
recordingDom.title = '取消录制';
var wrapStyle = {
height: '38px',
zIndex: 11,
position: 'absolute',
left: 0,
bottom: 0,
width: '100%',
background: 'rgba(0,0,0)'
};
var bgStyle = {
position: 'absolute',
width: '100%',
height: '100%',
};
if (this._opt.background) {
bgStyle = Object.assign({}, bgStyle, {
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundSize: '100%',
backgroundImage: "url('" + this._opt.background + "')"
})
}
//
var loadingStyle = {
position: 'absolute',
width: '100%',
height: '100%',
textAlign: 'center',
color: "#fff",
display: 'none',
backgroundImage: "url('" + gifBase64 + "')",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundSize: "40px 40px",
};
var playBigStyle = {
position: 'absolute',
width: '100%',
height: '100%',
display: 'none',
background: 'rgba(0,0,0,0.4)',
backgroundImage: "url('" + playBigBase64 + "')",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundSize: "48px 48px",
cursor: "pointer"
};
var loadingTextStyle = {
position: 'absolute',
width: "100%",
top: '60%',
textAlign: 'center',
}
var controlStyle = {
position: 'absolute',
top: 0,
height: '100%',
display: 'flex',
alignItems: 'center',
};
var styleObj = {
display: 'none',
position: 'relative',
fontSize: '13px',
color: '#fff',
lineHeight: '20px',
marginLeft: '5px',
marginRight: '5px',
userSelect: 'none'
};
var styleObj2 = {
display: 'none',
position: 'relative',
width: '16px',
height: '16px',
marginLeft: '8px',
marginRight: '8px',
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundSize: '100%',
cursor: 'pointer',
};
_setStyle(bgDom, bgStyle);
_setStyle(btnWrap, wrapStyle);
_setStyle(loadingDom, loadingStyle);
_setStyle(playBigDom, playBigStyle);
_setStyle(loadingTextDom, loadingTextStyle);
_setStyle(control1, Object.assign({}, controlStyle, {
left: 0
}));
_setStyle(control2, Object.assign({}, controlStyle, {
right: 0
}));
_setStyle(textDom, styleObj);
_setStyle(speedDom, styleObj);
_setStyle(playDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + playBase64 + "')",
}));
_setStyle(pauseDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + pauseBase64 + "')"
}));
_setStyle(screenshotsDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + screenshotBase64 + "')"
}));
_setStyle(fullscreenDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + fullscreenBase64 + "')"
}));
_setStyle(minScreenDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + minScreenBase64 + "')"
}));
_setStyle(quietAudioDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + quietBase64 + "')"
}));
_setStyle(playAudioDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + playAudioBase64 + "')"
}));
_setStyle(recordDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + recordBase64 + "')"
}));
_setStyle(recordingDom, Object.assign({}, styleObj2, {
backgroundImage: "url('" + recordingBase64 + "')"
}));
loadingDom.appendChild(loadingTextDom);
if (this._opt.text) {
control1.appendChild(textDom);
doms.textDom = textDom;
}
if (this._opt.showBandwidth) {
control1.appendChild(speedDom);
doms.speedDom = speedDom;
}
// record
//control2.appendChild(recordingDom);
//control2.appendChild(recordDom);
// screenshots
if (this._opt.operateBtns.screenshot) {
control2.appendChild(screenshotsDom);
doms.screenshotsDom = screenshotsDom;
}
// play stop
if (this._opt.operateBtns.play) {
control2.appendChild(playDom);
control2.appendChild(pauseDom);
doms.playDom = playDom;
doms.pauseDom = pauseDom;
}
// audio
if (this._opt.operateBtns.audio) {
control2.appendChild(playAudioDom);
control2.appendChild(quietAudioDom);
doms.playAudioDom = playAudioDom;
doms.quietAudioDom = quietAudioDom;
}
// fullscreen
if (this._opt.operateBtns.fullscreen) {
control2.appendChild(fullscreenDom);
control2.appendChild(minScreenDom);
doms.fullscreenDom = fullscreenDom;
doms.minScreenDom = minScreenDom;
}
btnWrap.appendChild(control1);
btnWrap.appendChild(control2);
fragment.appendChild(bgDom);
doms.bgDom = bgDom;
fragment.appendChild(loadingDom);
doms.loadingDom = loadingDom;
if (this._showControl()) {
fragment.appendChild(btnWrap);
}
if (this._opt.operateBtns.play) {
fragment.appendChild(playBigDom);
doms.playBigDom = playBigDom;
}
this._container.appendChild(fragment);
this._doms = doms;
};
Jessibuca.prototype._initWakeLock = function () {
this._wakeLock = null;
var _this = this;
var handleWakeLock = () => {
if (this._wakeLock !== null && "visible" === document.visibilityState) {
_this._enableWakeLock();
}
};
document.addEventListener('visibilitychange', handleWakeLock);
document.addEventListener('fullscreenchange', handleWakeLock);
};
Jessibuca.prototype._enableWakeLock = function () {
if (this._opt.keepScreenOn) {
if ("wakeLock" in navigator) {
var _this = this;
navigator.wakeLock.request("screen").then((lock) => {
_this._wakeLock = lock;
_this._wakeLock.addEventListener('release', function () {
});
})
}
}
};
Jessibuca.prototype._initGainNode = function () {
var gainNode = this._audioContext.createGain();
var _this = this;
var source;
if (!navigator.mediaDevices.getUserMedia) {
console.log('getUserMedia not supported on your browser!');
return;
}
navigator.mediaDevices.getUserMedia(
// constraints - only audio needed for this app
{
audio: true
},
// Success callback
function (stream) {
source = _this._audioContext.createMediaStreamSource(stream);
source.connect(gainNode);
gainNode.connect(_this._audioContext.destination);
_this._gainNode = gainNode;
},
// Error callback
function (err) {
console.log('The following gUM error occurred: ' + err);
}
);
};
Jessibuca.prototype._showControl = function () {
var result = false;
var hasBtnShow = false;
Object.keys(this._opt.operateBtns).forEach((key) => {
if (this._opt.operateBtns[key]) {
hasBtnShow = true;
}
});
if (this._opt.showBandwidth || this._opt.text || hasBtnShow) {
result = true;
}
return result;
};
Jessibuca.prototype._onMessage = function () {
var _this = this;
this._decoderWorker.onmessage = function (event) {
var msg = event.data;
switch (msg.cmd) {
case "init":
_this._opt.isDebug && console.log("decoder worker init")
_this.setBufferTime(_this._opt.videoBuffer);
if (!_this._hasLoaded) {
_this._opt.isDebug && console.log("has loaded");
_this._hasLoaded = true;
_this.onLoad();
_this._trigger('load');
}
break
case "initSize":
_this._canvasElement.width = msg.w;
_this._canvasElement.height = msg.h;
_this.onInitSize();
_this.resize();
_this._trigger('videoInfo', {w: msg.w, h: msg.h});
if (_this.isWebGL()) {
} else {
_this._initRGB(msg.w, msg.h)
}
break
case "render":
if (_this._contextGL) {
_this._drawNextOutputPictureGL(msg.output);
} else {
_this._drawNextOutputPictureRGBA(msg.buffer);
}
if (_this.loading) {
_this.loading = false;
_this.playing = true;
_this._opt.isDebug && console.log("clear check loading timeout");
_this._clearCheckLoading();
}
_this._trigger('timeUpdate', msg.ts);
_this.onTimeUpdate(msg.ts);
_this._updateStats({bps: msg.bps, ts: msg.ts});
_this._checkHeart();
break
case "initAudio":
_this._initAudioPlay(msg.frameCount, msg.samplerate, msg.channels)
_this._trigger('audioInfo', {
numOfChannels: msg.channels, // 声频通道
length: msg.frameCount, // 帧数
sampleRate: msg.samplerate // 采样率
});
break
case "playAudio":
_this._playAudio(msg.buffer)
break
case "print":
_this.onLog(msg.text)
this._trigger('log', msg.text);
_this._opt.isDebug && console.log(msg.text);
break
case "printErr":
_this.onLog(msg.text);
this._trigger('log', msg.text);
_this.onError(msg.text);
this._trigger('error', msg.text);
_this._opt.isDebug && console.error(msg.text);
break;
case "initAudioPlanar":
_this._initAudioPlanar(msg);
_this._trigger('audioInfo', {
numOfChannels: msg.channels, // 声频通道
length: undefined, // 帧数
sampleRate: msg.samplerate // 采样率
});
break;
default:
_this._opt.isDebug && console.log(msg);
_this[msg.cmd](msg)
}
};
};
Jessibuca.prototype._initEventListener = function () {
var _this = this;
this._doms.playDom && this._doms.playDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.play();
}, false);
this._doms.playBigDom && this._doms.playBigDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.play();
}, false);
this._doms.pauseDom && this._doms.pauseDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.pause();
}, false);
// screenshots
this._doms.screenshotsDom && this._doms.screenshotsDom.addEventListener('click', function (e) {
e.stopPropagation();
var filename = _this._opt.text + '' + _now();
_this._screenshot(filename);
}, false);
//
this._doms.fullscreenDom && this._doms.fullscreenDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.fullscreen = true;
}, false);
//
this._doms.minScreenDom && this._doms.minScreenDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.fullscreen = false;
}, false);
//
this._doms.recordDom && this._doms.recordDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.recording = true;
}, false);
//
this._doms.recordingDom && this._doms.recordingDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.recording = false;
}, false);
this._doms.quietAudioDom && this._doms.quietAudioDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.cancelMute();
}, false);
this._doms.playAudioDom && this._doms.playAudioDom.addEventListener('click', function (e) {
e.stopPropagation();
_this.mute();
}, false);
};
/**
* set debug
* @param flag
*/
Jessibuca.prototype.setDebug = function (flag) {
this._opt.isDebug = !!flag;
};
/**
* mute
*/
Jessibuca.prototype.mute = function () {
this._audioEnabled(false);
this.quieting = true;
};
/**
* cancel mute
*/
Jessibuca.prototype.cancelMute = function () {
this._audioEnabled(true);
this.quieting = false;
};
/**
* 设置旋转角度
*/
Jessibuca.prototype.setRotate = function (deg) {
};
Jessibuca.prototype._initStatus = function () {
this._loading = true;
this.loading = true;
this._recording = false;
this.recording = false;
this._playing = false;
this.playing = false;
this._quieting = this._opt.isNotMute ? false : true;
this.quieting = this._opt.isNotMute ? false : true;
this._fullscreen = false;
this.fullscreen = false;
}
Jessibuca.prototype._initBtns = function () {
// show
_domToggle(this._doms.pauseDom, true);
_domToggle(this._doms.screenshotsDom, true);
_domToggle(this._doms.fullscreenDom, true);
_domToggle(this._doms.quietAudioDom, true);
_domToggle(this._doms.textDom, true);
_domToggle(this._doms.speedDom, true);
_domToggle(this._doms.recordDom, true);
// hide
_domToggle(this._doms.loadingDom, false);
_domToggle(this._doms.playDom, false);
_domToggle(this._doms.playBigDom, false);
_domToggle(this._doms.bgDom, false);
};
Jessibuca.prototype._hideBtns = function () {
var _this = this;
Object.keys(this._doms).forEach(function (dom) {
if (dom !== 'bgDom') {
_domToggle(_this._doms[dom], false);
}
})
};
function _checkFull() {
var isFull = document.fullscreenElement || window.webkitFullscreenElement || document.msFullscreenElement;
if (isFull === undefined) isFull = false;
return !!isFull;
}
Jessibuca.prototype._updateStats = function (options) {
options = options || {};
if (!this._startBpsTime) {
this._startBpsTime = _now();
}
var _nowTime = _now();
var timestamp = _nowTime - this._startBpsTime;
if (timestamp < 1 * 1000) {
this._bps += (options.bps || 0);
this._stats.fps += 1;
this._stats.vbps += parseInt((options.bps || 0));
return;
}
this._stats.ts = options.ts;
this._doms.speedDom && (this._doms.speedDom.innerText = _bpsSize(this._bps));
this._trigger('bps', this._bps);
this._trigger('stats', this._stats);
this._trigger('performance', _fpsStatus(this._stats.fps));
this._bps = 0;
this._stats.fps = 0;
this._stats.vbps = 0;
this._startBpsTime = _nowTime;
};
Jessibuca.prototype._checkHeart = function () {
if (this._checkHeartTimeout) {
clearTimeout(this._checkHeartTimeout);
this._checkHeartTimeout = null;
}
var _this = this;
this._checkHeartTimeout = setTimeout(function () {
_this._opt.isDebug && console.log('check heart timeout');
_this._trigger('timeout');
_this.recording = false;
_this.playing = false;
_this._close();
}, this._opt.timeout * 1000);
};
Jessibuca.prototype._checkLoading = function () {
if (this._checkLoadingTimeout) {
clearTimeout(this._checkLoadingTimeout);
this._checkLoadingTimeout = null;
}
var _this = this;
this._checkLoadingTimeout = setTimeout(function () {
_this._opt.isDebug && console.log('check loading timeout');
_this._trigger('timeout');
_this.playing = false;
_this._close();
_domToggle(_this._doms.loadingDom, false);
}, this._opt.timeout * 1000);
};
Jessibuca.prototype._clearCheckLoading = function () {
if (this._checkLoadingTimeout) {
clearTimeout(this._checkLoadingTimeout);
this._checkLoadingTimeout = null;
}
};
Jessibuca.prototype._initCheckVariable = function () {
this._startBpsTime = '';
this._bps = 0;
if (this._checkHeartTimeout) {
clearTimeout(this._checkHeartTimeout);
this._checkHeartTimeout = null;
}
}
//
Jessibuca.prototype._initAudioPlanar = function (msg) {
var channels = msg.channels
var samplerate = msg.samplerate
var context = this._audioContext;
var isPlaying = false;
var audioBuffers = [];
if (!context) return false;
var _this = this
this._playAudio = function (buffer) {
var frameCount = buffer[0][0].length
var audioBuffer = context.createBuffer(channels, frameCount * buffer.length, samplerate);
var copyToCtxBuffer = function (fromBuffer) {
for (var channel = 0; channel < channels; channel++) {
var nowBuffering = audioBuffer.getChannelData(channel);
for (var j = 0; j < buffer.length; j++) {
for (var i = 0; i < frameCount; i++) {
nowBuffering[i + j * frameCount] = fromBuffer[j][channel][i]
}
//postMessage({ cmd: "setBufferA", buffer: fromBuffer[j] }, '*', fromBuffer[j].map(x => x.buffer))
}
}
}
var playNextBuffer = function () {
isPlaying = false;
//console.log("~", audioBuffers.length)
if (audioBuffers.length) {
playAudio(audioBuffers.shift());
}
//if (audioBuffers.length > 1) audioBuffers.shift();
};
var playAudio = function (fromBuffer) {
if (!fromBuffer) return
if (isPlaying) {
audioBuffers.push(fromBuffer);
//console.log(audioBuffers.length)
return;
}
isPlaying = true;
copyToCtxBuffer(fromBuffer);
var source = context.createBufferSource();
source.buffer = audioBuffer;
source.connect(context.destination);
// source.onended = playNextBuffer;
source.start();
};
_this._playAudio = playAudio
_this.audioInterval = setInterval(playNextBuffer, audioBuffer.duration * 1000);
playAudio(buffer)
};
}
function _unlock(context) {
context.resume();
var source = context.createBufferSource();
source.buffer = context.createBuffer(1, 1, 22050);
source.connect(context.destination);
if (source.noteOn)
source.noteOn(0);
else
source.start(0);
}
function _domToggle(dom, toggle) {
if (dom) {
dom.style.display = toggle ? 'block' : "none";
}
}
function _dataURLToFile(dataURL) {
const arr = dataURL.split(",");
const bstr = atob(arr[1]);
const type = arr[0].replace("data:", "").replace(";base64", "")
let n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], 'file', {type});
}
function _downloadImg(content, fileName) {
const aLink = document.createElement("a");
aLink.download = fileName;
aLink.href = URL.createObjectURL(content);
aLink.click();
URL.revokeObjectURL(content);
}
function _bpsSize(value) {
if (null == value || value === '') {
return "0 KB/S";
}
var srcsize = parseFloat(value);
var size = srcsize / 1024;
size = size.toFixed(2);
return size + 'KB/S';
}
function _fpsStatus(fps) {
var result = 0;
if (fps >= 24) {
result = 2;
} else if (fps >= 15) {
result = 1;
}
return result;
}
/**
* set audio
* @param flag
*/
Jessibuca.prototype._audioEnabled = function (flag) {
if (flag) {
_unlock(this._audioContext)
this._audioEnabled = function (flag) {
if (flag) {
// 恢复
this._audioContext.resume();
} else {
// 暂停
this._audioContext.suspend();
}
}
} else {
this._audioContext.suspend();
}
}
Jessibuca.prototype._playAudio = function (data) {
var context = this._audioContext;
var isPlaying = false;
var isDecoding = false;
if (!context) return false;
var audioBuffers = [];
var decodeQueue = []
var _this = this
var playNextBuffer = function (e) {
if (audioBuffers.length) {
playBuffer(audioBuffers.shift())
}
};
var playBuffer = function (buffer) {
isPlaying = true;
var audioBufferSouceNode = context.createBufferSource();
audioBufferSouceNode.buffer = buffer;
audioBufferSouceNode.connect(context.destination);
// audioBufferSouceNode.onended = playNextBuffer;
audioBufferSouceNode.start();
if (!_this.audioInterval) {
_this.audioInterval = setInterval(playNextBuffer, buffer.duration * 1000 - 1);
}
}
var decodeAudio = function () {
if (decodeQueue.length) {
context.decodeAudioData(decodeQueue.shift(), tryPlay, decodeAudio);
} else {
isDecoding = false
}
}
var tryPlay = function (buffer) {
decodeAudio()
if (isPlaying) {
audioBuffers.push(buffer);
} else {
playBuffer(buffer)
}
}
var playAudio = function (data) {
decodeQueue.push(...data)
if (!isDecoding) {
isDecoding = true
decodeAudio()
}
}
this._playAudio = playAudio
playAudio(data)
}
Jessibuca.prototype._initAudioPlay = function (frameCount, samplerate, channels) {
var context = this._audioContext;
var isPlaying = false;
var audioBuffers = [];
if (!context) return false;
var _this = this
var resampled = samplerate < 22050;
if (resampled) {
_this._opt.isDebug && console.log("resampled!")
}
var audioBuffer = resampled ? context.createBuffer(channels, frameCount << 1, samplerate << 1) : context.createBuffer(channels, frameCount, samplerate);
var playNextBuffer = function () {
isPlaying = false;
//console.log("~", audioBuffers.length)
if (audioBuffers.length) {
playAudio(audioBuffers.shift());
}
};
var copyToCtxBuffer = channels > 1 ? function (fromBuffer) {
for (var channel = 0; channel < channels; channel++) {
var nowBuffering = audioBuffer.getChannelData(channel);
if (resampled) {
for (var i = 0; i < frameCount; i++) {
nowBuffering[i * 2] = nowBuffering[i * 2 + 1] = fromBuffer[i * (channel + 1)] / 32768;
}
} else
for (var i = 0; i < frameCount; i++) {
nowBuffering[i] = fromBuffer[i * (channel + 1)] / 32768;
}
}
} : function (fromBuffer) {
var nowBuffering = audioBuffer.getChannelData(0);
for (var i = 0; i < nowBuffering.length; i++) {
nowBuffering[i] = fromBuffer[i] / 32768;
}
};
var playAudio = function (fromBuffer) {
if (isPlaying) {
audioBuffers.push(fromBuffer);
return;
}
isPlaying = true;
copyToCtxBuffer(fromBuffer);
var source = context.createBufferSource();
source.buffer = audioBuffer;
source.connect(context.destination);
if (!_this.audioInterval) {
_this.audioInterval = setInterval(playNextBuffer, audioBuffer.duration * 1000);
}
source.start();
};
this._playAudio = playAudio;
}
/**
* Returns true if the canvas supports WebGL
*/
Jessibuca.prototype.isWebGL = function () {
return !!this._contextGL;
};
/**
* set timeout
* @param time
*/
Jessibuca.prototype.setTimeout = function (time) {
if (typeof time === 'number') {
this._opt.timeout = Number(time);
}
};
/**
* @desc 视频缩放模式, 当视频分辨率比例与canvas显示区域比例不同时,缩放效果不同:
0 视频画面完全填充canvas区域,画面会被拉伸
1 视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边(默认)
2 视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全
* @param type
*
*/
Jessibuca.prototype.setScaleMode = function (type) {
if (type === 0) {
this._opt.isFullResize = false;
this._opt.isResize = false;
} else if (type === 1) {
this._opt.isFullResize = false;
this._opt.isResize = true;
} else if (type === 2) {
this._opt.isFullResize = true;
}
this.resize();
};
/**
* Create the GL context from the canvas element
*/
Jessibuca.prototype._initContextGL = function () {
var canvas = this._canvasElement;
var gl = null;
var validContextNames = ["webgl", "experimental-webgl", "moz-webgl", "webkit-3d"];
var nameIndex = 0;
while (!gl && nameIndex < validContextNames.length) {
var contextName = validContextNames[nameIndex];
try {
var contextOptions = {preserveDrawingBuffer: true};
if (this._opt.contextOptions) {
contextOptions = Object.assign(contextOptions, this._opt.contextOptions);
}
gl = canvas.getContext(contextName, contextOptions);
} catch (e) {
gl = null;
}
if (!gl || typeof gl.getParameter !== "function") {
gl = null;
}
++nameIndex;
}
;
this._contextGL = gl;
};
/**
* Initialize GL shader program
*/
Jessibuca.prototype._initProgram = function () {
var gl = this._contextGL;
var vertexShaderScript = [
'attribute vec4 vertexPos;',
'attribute vec4 texturePos;',
'varying vec2 textureCoord;',
'void main()',
'{',
'gl_Position = vertexPos;',
'textureCoord = texturePos.xy;',
'}'
].join('\n');
var fragmentShaderScript = [
'precision highp float;',
'varying highp vec2 textureCoord;',
'uniform sampler2D ySampler;',
'uniform sampler2D uSampler;',
'uniform sampler2D vSampler;',
'const mat4 YUV2RGB = mat4',
'(',
'1.1643828125, 0, 1.59602734375, -.87078515625,',
'1.1643828125, -.39176171875, -.81296875, .52959375,',
'1.1643828125, 2.017234375, 0, -1.081390625,',
'0, 0, 0, 1',
');',
'void main(void) {',
'highp float y = texture2D(ySampler, textureCoord).r;',
'highp float u = texture2D(uSampler, textureCoord).r;',
'highp float v = texture2D(vSampler, textureCoord).r;',
'gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;',
'}'
].join('\n');
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderScript);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
this._opt.isDebug && console.log('Vertex shader failed to compile: ' + gl.getShaderInfoLog(vertexShader));
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderScript);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
this._opt.isDebug && console.log('Fragment shader failed to compile: ' + gl.getShaderInfoLog(fragmentShader));
}
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
this._opt.isDebug && console.log('Program failed to compile: ' + gl.getProgramInfoLog(program));
}
gl.useProgram(program);
this._shaderProgram = program;
};
/**
* Initialize vertex buffers and attach to shader program
*/
Jessibuca.prototype._initBuffers = function () {
var gl = this._contextGL;
var program = this._shaderProgram;
var vertexPosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]), gl.STATIC_DRAW);
var vertexPosRef = gl.getAttribLocation(program, 'vertexPos');
gl.enableVertexAttribArray(vertexPosRef);
gl.vertexAttribPointer(vertexPosRef, 2, gl.FLOAT, false, 0, 0);
var texturePosBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 1, 0, 1]), gl.STATIC_DRAW);
var texturePosRef = gl.getAttribLocation(program, 'texturePos');
gl.enableVertexAttribArray(texturePosRef);
gl.vertexAttribPointer(texturePosRef, 2, gl.FLOAT, false, 0, 0);
this._texturePosBuffer = texturePosBuffer;
};
/**
* Initialize GL textures and attach to shader program
*/
Jessibuca.prototype._initTextures = function () {
var gl = this._contextGL;
var program = this._shaderProgram;
var yTextureRef = this._initTexture();
var ySamplerRef = gl.getUniformLocation(program, 'ySampler');
gl.uniform1i(ySamplerRef, 0);
this._yTextureRef = yTextureRef;
var uTextureRef = this._initTexture();
var uSamplerRef = gl.getUniformLocation(program, 'uSampler');
gl.uniform1i(uSamplerRef, 1);
this._uTextureRef = uTextureRef;
var vTextureRef = this._initTexture();
var vSamplerRef = gl.getUniformLocation(program, 'vSampler');
gl.uniform1i(vSamplerRef, 2);
this._vTextureRef = vTextureRef;
};
/**
* Create and configure a single texture
*/
Jessibuca.prototype._initTexture = function () {
var gl = this._contextGL;
var textureRef = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, textureRef);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.bindTexture(gl.TEXTURE_2D, null);
return textureRef;
};
/**
* Draw picture data to the canvas.
* If this object is using WebGL, the data must be an I420 formatted ArrayBuffer,
* Otherwise, data must be an RGBA formatted ArrayBuffer.
*/
Jessibuca.prototype._drawNextOutputPicture = function (data) {
if (this._contextGL) {
this._drawNextOutputPictureGL(data);
} else {
this._drawNextOutputPictureRGBA(data);
}
};
/**
* Draw the next output picture using WebGL
*/
Jessibuca.prototype._drawNextOutputPictureGL = function (data) {
var gl = this._contextGL;
var texturePosBuffer = this._texturePosBuffer;
var yTextureRef = this._yTextureRef;
var uTextureRef = this._uTextureRef;
var vTextureRef = this._vTextureRef;
var croppingParams = this.croppingParams
var width = this._canvasElement.width
var height = this._canvasElement.height
if (croppingParams) {
gl.viewport(0, 0, croppingParams.width, croppingParams.height);
var tTop = croppingParams.top / height;
var tLeft = croppingParams.left / width;
var tBottom = croppingParams.height / height;
var tRight = croppingParams.width / width;
var texturePosValues = new Float32Array([tRight, tTop, tLeft, tTop, tRight, tBottom, tLeft, tBottom]);
gl.bindBuffer(gl.ARRAY_BUFFER, texturePosBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texturePosValues, gl.DYNAMIC_DRAW);
} else {
gl.viewport(0, 0, this._canvasElement.width, this._canvasElement.height);
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, yTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data[0]);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, uTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width / 2, height / 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data[1]);
gl.activeTexture(gl.TEXTURE2);
gl.bindTexture(gl.TEXTURE_2D, vTextureRef);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width / 2, height / 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data[2]);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
};
/**
* Draw next output picture using ARGB data on a 2d canvas.
*/
Jessibuca.prototype._drawNextOutputPictureRGBA = function (data) {
this.imageData.data.set(data);
var croppingParams = this.croppingParams
if (!croppingParams) {
this.ctx2d.putImageData(this.imageData, 0, 0);
} else {
this.ctx2d.putImageData(this.imageData, -croppingParams.left, -croppingParams.top, 0, 0, croppingParams.width, croppingParams.height);
}
};
Jessibuca.prototype.ctx2d = null;
Jessibuca.prototype.imageData = null;
Jessibuca.prototype._initRGB = function (width, height) {
this.ctx2d = this._canvasElement.getContext('2d');
this.imageData = this.ctx2d.getImageData(0, 0, width, height);
this.clear = function () {
this.ctx2d.clearRect(0, 0, width, height)
};
};
Jessibuca.prototype.pause = function () {
this._close();
if (this.loading) {
_domToggle(this._doms.loadingDom, false);
}
this.recording = false;
this.playing = false;
};
Jessibuca.prototype._close = function () {
if (this.audioInterval) {
clearInterval(this.audioInterval)
}
delete this._playAudio
this._decoderWorker.postMessage({cmd: "close"})
if (this._wakeLock) {
this._wakeLock.release();
this._wakeLock = null;
}
// this._contextGL.clear(this._contextGL.COLOR_BUFFER_BIT);
this._initCheckVariable();
}
/**
* destroy
* @desc delete worker,
*/
Jessibuca.prototype.destroy = function () {
// destroy
this._decoderWorker.terminate()
window.removeEventListener("resize", this._onresize);
window.removeEventListener('fullscreenchange', this._onfullscreenchange);
this._initCheckVariable();
this._clearCheckLoading();
this._off();
this._hasLoaded = false;
// remove dom
while (this._container.firstChild) {
this._container.removeChild(this._container.firstChild);
}
if (this._wakeLock) {
this._wakeLock.release();
}
}
/**
* 清理画布为黑色背景
* 用于canvas重用进行多个流切换播放时将上一个画面清理
* 避免后一个视频播放之前出现前一个视频最后一个画面
*/
Jessibuca.prototype.clearView = function () {
this._contextGL.clear(this._contextGL.COLOR_BUFFER_BIT);
};
/**
* play
* @param url
*/
Jessibuca.prototype.play = function (url) {
if (!this.playUrl && !url) {
return;
}
var needDelay = false;
if (url) {
if (this.playUrl) {
this._close();
needDelay = true;
this._contextGL.clear(this._contextGL.COLOR_BUFFER_BIT);
}
this.loading = true;
_domToggle(this._doms.bgDom, false);
this._checkLoading();
this.playUrl = url;
} else if (this.playUrl) {
// retry
if (this.loading) {
this._hideBtns();
_domToggle(this._doms.fullscreenDom, true);
_domToggle(this._doms.pauseDom, true);
_domToggle(this._doms.loadingDom, true);
this._checkLoading();
} else {
this.playing = true;
}
}
this._initCheckVariable();
if (needDelay) {
var _this = this;
setTimeout(function () {
_this._decoderWorker.postMessage({cmd: "play", url: _this.playUrl, isWebGL: _this.isWebGL()})
}, 300);
} else {
this._decoderWorker.postMessage({cmd: "play", url: this.playUrl, isWebGL: this.isWebGL()})
}
};
/**
* has loaded
* @returns {boolean}
*/
Jessibuca.prototype.hasLoaded = function () {
return this._hasLoaded;
};
Object.defineProperty(Jessibuca.prototype, "fullscreen", {
set(value) {
if (value) {
if (!_checkFull()) {
this._container.requestFullscreen();
}
_domToggle(this._doms.minScreenDom, true);
_domToggle(this._doms.fullscreenDom, false);
} else {
if (_checkFull()) {
document.exitFullscreen();
}
_domToggle(this._doms.minScreenDom, false);
_domToggle(this._doms.fullscreenDom, true);
}
if (this._fullscreen !== value) {
this.onFullscreen(value);
this._trigger('fullscreen', value);
}
this._fullscreen = value;
},
get() {
return this._fullscreen;
}
});
Object.defineProperty(Jessibuca.prototype, 'playing', {
set(value) {
if (value) {
_domToggle(this._doms.playBigDom, false);
_domToggle(this._doms.playDom, false);
_domToggle(this._doms.pauseDom, true);
_domToggle(this._doms.screenshotsDom, true);
_domToggle(this._doms.recordDom, true);
if (this._quieting) {
_domToggle(this._doms.quietAudioDom, true);
_domToggle(this._doms.playAudioDom, false);
} else {
_domToggle(this._doms.quietAudioDom, false);
_domToggle(this._doms.playAudioDom, true);
}
} else {
this._doms.speedDom && (this._doms.speedDom.innerText = '');
if (this.playUrl) {
_domToggle(this._doms.playDom, true);
_domToggle(this._doms.playBigDom, true);
_domToggle(this._doms.pauseDom, false);
}
// 在停止状态下录像,截屏,音量是非激活,只有播放,最大化时可点击
_domToggle(this._doms.recordDom, false);
_domToggle(this._doms.recordingDom, false);
_domToggle(this._doms.screenshotsDom, false);
_domToggle(this._doms.quietAudioDom, false);
_domToggle(this._doms.playAudioDom, false);
}
if (this._playing !== value) {
if (value) {
this.onPlay();
this._trigger('play');
} else {
this.onPause();
this._trigger('pause');
}
}
this._playing = value;
},
get() {
return this._playing;
}
});
Object.defineProperty(Jessibuca.prototype, 'recording', {
set(value) {
if (value) {
_domToggle(this._doms.recordDom, false);
_domToggle(this._doms.recordingDom, true);
} else {
_domToggle(this._doms.recordDom, true);
_domToggle(this._doms.recordingDom, false);
}
if (this._recording !== value) {
this.onRecord(value);
this._trigger('record', value);
this._recording = value;
}
},
get() {
return this._recording;
}
});
Object.defineProperty(Jessibuca.prototype, 'quieting', {
set(value) {
if (value) {
_domToggle(this._doms.quietAudioDom, true);
_domToggle(this._doms.playAudioDom, false);
} else {
_domToggle(this._doms.quietAudioDom, false);
_domToggle(this._doms.playAudioDom, true);
}
if (this._quieting !== value) {
this.onMute(value);
this._trigger('mute', value);
}
this._quieting = value;
},
get() {
return this._quieting;
}
});
Object.defineProperty(Jessibuca.prototype, 'loading', {
set(value) {
if (value) {
this._hideBtns();
_domToggle(this._doms.fullscreenDom, true);
_domToggle(this._doms.pauseDom, true);
_domToggle(this._doms.loadingDom, true);
} else {
this._initBtns();
}
this._loading = value;
},
get() {
return this._loading;
}
});
/**
* resize
*/
Jessibuca.prototype.resize = function () {
var width = this._container.clientWidth;
var height = this._container.clientHeight;
if (this._showControl()) {
height -= 38;
}
var resizeWidth = this._canvasElement.width;
var resizeHeight = this._canvasElement.height;
var wScale = width / resizeWidth;
var hScale = height / resizeHeight;
var scale = wScale > hScale ? hScale : wScale;
if (!this._opt.isResize) {
if (wScale !== hScale) {
scale = wScale + ',' + hScale;
}
}
//
if (this._opt.isFullResize) {
scale = wScale > hScale ? wScale : hScale;
}
this._opt.isDebug && console.log('wScale', wScale, 'hScale', hScale, 'scale', scale);
this._canvasElement.style.transform = "scale(" + scale + ")"
this._canvasElement.style.left = ((width - resizeWidth) / 2) + "px"
this._canvasElement.style.top = ((height - resizeHeight) / 2) + "px"
}
Jessibuca.prototype._fullscreenchange = function () {
this.fullscreen = _checkFull();
}
/**
* change buffer
* @param buffer
*/
Jessibuca.prototype.changeBuffer = function (buffer) {
this._stats.buf = Number(buffer) * 1000;
this._decoderWorker.postMessage({cmd: "setVideoBuffer", time: Number(buffer)});
};
/**
* 设置最大缓冲时长,单位秒,播放器会自动消除延迟。
* @param buffer
*/
Jessibuca.prototype.setBufferTime = function (buffer) {
this.changeBuffer(buffer);
};
/**
* 设置音量大小取值0.0 — 1.0
* 当为0.0时,完全无声
* 当为1.0时,最大音量,默认值
* @param volume
*/
Jessibuca.prototype.setVolume = function (volume) {
if (this._gainNode) {
this._gainNode.gain.setValueAtTime(volume, this._audioContext.currentTime);
}
};
/**
* 开启屏幕常亮, 在play前调用
* 在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮
* H5目前在chrome\edge 84, android chrome 84及以上有原生亮屏API, 需要是https页面
* 其余平台为模拟实现,此时为兼容实现,并不保证所有浏览器都支持
*/
Jessibuca.prototype.setKeepScreenOn = function () {
this._opt.keepScreenOn = true;
};
/**
* set fullscreen
* @param flag
*/
Jessibuca.prototype.setFullscreen = function (flag) {
var fullscreen = !!flag;
if (this.fullscreen !== fullscreen) {
this.fullscreen = fullscreen;
}
};
function _now() {
return new Date().getTime();
}
Jessibuca.prototype._screenshot = function (filename, format, quality) {
filename = filename || _now();
var formatType = {
png: 'image/png',
jpeg: 'image/jpeg',
webp: 'image/webp'
};
var encoderOptions = 0.92;
if (typeof quality !== 'undefined') {
encoderOptions = Number(quality);
}
var dataURL = this._canvasElement.toDataURL(formatType[format] || formatType.png, encoderOptions);
_downloadImg(_dataURLToFile(dataURL), filename);
}
/**
* 截图,调用后弹出下载框保存截图
* @param filename 保存的文件名 默认时间戳
* @param format 截图的格式可选png或jpeg或者webp
* @param quality 可选参数当格式是jpeg或者webp时压缩质量取值0.0 ~ 1.0
*/
Jessibuca.prototype.screenshot = function (filename, format, quality) {
this._screenshot(filename, format, quality);
};
var eventSplitter = /\s+/;
// Execute callbacks
function _callEach(list, args, context) {
if (list) {
for (var i = 0, len = list.length; i < len; i += 1) {
list[i].apply(context, args);
}
}
}
/**
*
* @param events
* @param callback
* @returns {Jessibuca}
*/
Jessibuca.prototype.on = function (events, callback) {
var cache, event, list;
if (!callback) return this;
cache = this.__events || (this.__events = {});
events = events.split(eventSplitter);
while (event = events.shift()) {
list = cache[event] || (cache[event] = []);
list.push(callback);
}
return this;
};
/**
*
* @param events
* @param callback
* @returns {Jessibuca}
* @private
*/
Jessibuca.prototype._off = function () {
var cache;
if (!(cache = this.__events)) return this;
delete this.__events;
return this;
};
/**
*
* @param events
* @returns {Jessibuca}
* @private
*/
Jessibuca.prototype._trigger = function (events) {
var cache, event, all, list, i, len, rest = [], args;
if (!(cache = this.__events)) return this;
events = events.split(eventSplitter);
// Fill up `rest` with the callback arguments. Since we're only copying
// the tail of `arguments`, a loop is much faster than Array#slice.
for (i = 1, len = arguments.length; i < len; i++) {
rest[i - 1] = arguments[i];
}
// For each event, walk through the list of callbacks twice, first to
// trigger the event, then to trigger any `"all"` callbacks.
while (event = events.shift()) {
if (list = cache[event]) list = list.slice();
// Execute event callbacks.
_callEach(list, rest, this);
}
return this;
}
if (typeof define === 'function') {
define(function () {
return Jessibuca;
});
} else if (typeof exports !== 'undefined') {
module.exports = Jessibuca;
} else {
window.Jessibuca = Jessibuca;
}
})();