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.
1709 lines
73 KiB
1709 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;
|
|
this._opt.rotate = typeof opt.rotate === 'number' ? opt.rotate : 0;
|
|
|
|
if (!opt.forceNoGL) this._initContextGL();
|
|
this._audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
this._gainNode = this._audioContext.createGain();
|
|
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._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._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,ts', msg.ts);
|
|
_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;
|
|
};
|
|
|
|
/**
|
|
* link to cancelMute
|
|
*/
|
|
Jessibuca.prototype.audioResume = function () {
|
|
this.cancelMute();
|
|
};
|
|
|
|
/**
|
|
* 设置旋转角度
|
|
*/
|
|
Jessibuca.prototype.setRotate = function (deg) {
|
|
deg = parseInt(deg, 10)
|
|
const list = [0, 90, 270];
|
|
if (this._opt.rotate === deg || list.indexOf(deg) === -1) {
|
|
return;
|
|
}
|
|
this._opt.rotate = deg;
|
|
this.resize();
|
|
};
|
|
|
|
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]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var playNextBuffer = function () {
|
|
_this._audioPlaying = false;
|
|
if (_this._audioPlayBuffers.length) {
|
|
playAudio(_this._audioPlayBuffers.shift());
|
|
}
|
|
};
|
|
var playAudio = function (fromBuffer) {
|
|
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;
|
|
// _this._isDebug() && console.log('audioBuffer', audioBuffer.duration * 1000)
|
|
source.connect(_this._gainNode);
|
|
_this._gainNode.connect(context.destination);
|
|
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(_this._gainNode);
|
|
_this._gainNode.connect(context.destination);
|
|
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(_this._gainNode);
|
|
_this._gainNode.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 rotate = this._opt.rotate;
|
|
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;
|
|
}
|
|
|
|
let transform = "scale(" + scale + ")";
|
|
|
|
if (rotate) {
|
|
transform += ' rotate(' + rotate + 'deg)'
|
|
}
|
|
|
|
this._opt.isDebug && console.log('wScale', wScale, 'hScale', hScale, 'scale', scale, 'rotate', rotate);
|
|
this._canvasElement.style.transform = transform;
|
|
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) {
|
|
volume = parseFloat(volume);
|
|
if (isNaN(volume)) {
|
|
return;
|
|
}
|
|
this._isDebug() && console.log('set volume:', volume);
|
|
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;
|
|
}
|
|
})();
|