Jessibuca是一款开源的纯H5直播流播放器,通过Emscripten将音视频解码库编译成Js(ams.js/wasm)运行于浏览器之中。兼容几乎所有浏览器,可以运行在PC、手机、微信中,无需额外安装插件。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1715 lines
73 KiB

!(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: ''
};
this._audioPlayBuffers = [];
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._initGainNode();
//
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,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';
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 && 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.loading) {
_this.loading = false;
_this.playing = true;
_this._opt.isDebug && console.log("clear check loading timeout");
_this._clearCheckLoading();
}
if (_this.playing) {
if (_this.isWebGL()) {
_this._drawNextOutputPictureGL(msg.output);
} else {
_this._drawNextOutputPictureRGBA(msg.buffer);
}
}
_this._trigger('timeUpdate', msg.ts);
_this.onTimeUpdate(msg.ts);
_this._updateStats({bps: msg.bps, ts: msg.ts});
_this._checkHeart();
break
case "initAudio":
_this._opt.isDebug && console.log('initAudio');
_this._initAudioPlay(msg.frameCount, msg.samplerate, msg.channels)
_this._trigger('audioInfo', {
numOfChannels: msg.channels, // 声频通道
length: msg.frameCount, // 帧数
sampleRate: msg.samplerate // 采样率
});
break
case "playAudio":
if (_this.playing && !_this.quieting) {
_this._opt.isDebug && console.log('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._opt.isDebug && console.log('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._audioPlayBuffers = [];
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._audioPlaying = 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._limitAudioPlayBufferSize = function () {
if (this._audioPlayBuffers.length > 2) {
this._audioPlayBuffers.shift();
}
};
//
Jessibuca.prototype._initAudioPlanar = function (msg) {
var channels = msg.channels
var samplerate = msg.samplerate
var context = this._audioContext;
this._audioPlaying = false;
this._audioPlayBuffers = [];
if (!context) return false;
var _this = this
this._playAudio = function (buffer) {
_this._isDebug() && console.log('_initAudioPlanar-_playAudio');
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 () {
_this._audioPlaying = false;
//console.log("~", _this._audioPlayBuffers.length)
if (_this._audioPlayBuffers.length) {
playAudio(_this._audioPlayBuffers.shift());
}
};
var playAudio = function (fromBuffer) {
// _this._isDebug() && console.log('_initAudioPlanar-playAudio');
if (!fromBuffer) return
if (_this._audioPlaying) {
_this._limitAudioPlayBufferSize();
_this._audioPlayBuffers.push(fromBuffer);
return;
}
_this._audioPlaying = true;
copyToCtxBuffer(fromBuffer);
var source = context.createBufferSource();
source.buffer = audioBuffer;
source.connect(context.destination);
// source.onended = playNextBuffer;
source.start();
};
_this._playAudio = playAudio
if (!_this._audioInterval) {
_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) {
this._isDebug() && console.log('_playAudio');
var context = this._audioContext;
this._audioPlaying = false;
var isDecoding = false;
if (!context) return false;
this._audioPlayBuffers = [];
var decodeQueue = []
var _this = this
var playNextBuffer = function (e) {
if (_this._audioPlayBuffers.length) {
playBuffer(_this._audioPlayBuffers.shift())
}
};
var playBuffer = function (buffer) {
_this._audioPlaying = 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 (_this._audioPlaying) {
_this._limitAudioPlayBufferSize();
_this._audioPlayBuffers.push(buffer);
} else {
playBuffer(buffer)
}
}
var playAudio = function (data) {
_this._isDebug() && console.log('_playAudio-playAudio');
decodeQueue.push(...data)
if (!isDecoding) {
isDecoding = true
decodeAudio()
}
}
this._playAudio = playAudio
playAudio(data)
}
Jessibuca.prototype._isDebug = function () {
return this._opt.isDebug;
}
Jessibuca.prototype._initAudioPlay = function (frameCount, samplerate, channels) {
var context = this._audioContext;
this._audioPlaying = false;
this._audioPlayBuffers = [];
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 () {
_this._audioPlaying = false;
_this._isDebug() && console.log("playNextBuffer:", _this._audioPlayBuffers.length)
if (_this._audioPlayBuffers.length) {
playAudio(_this._audioPlayBuffers.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) {
_this._isDebug() && console.log('_initAudioPlay-playAudio,_audioPlaying', _this._audioPlaying);
if (_this._audioPlaying) {
_this._limitAudioPlayBufferSize();
_this._audioPlayBuffers.push(fromBuffer);
return;
}
_this._audioPlaying = 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;
};
/**
*
* @private
*/
Jessibuca.prototype._close = function () {
if (this._audioInterval) {
clearInterval(this._audioInterval)
this._audioInterval = null;
}
this._audioPlayBuffers = [];
this._audioPlaying = false;
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();
}
/**
* close
*/
Jessibuca.prototype.close = function () {
this._close();
this.clearView();
};
/**
* destroy
* @desc delete worker,
*/
Jessibuca.prototype.destroy = function () {
// destroy
this._close();
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.clearView();
}
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;
}
})();