UNPKG

ng-cw-v12

Version:

Angular UI component library

353 lines (347 loc) 19.6 kB
import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Component, Input, Output, NgModule } from '@angular/core'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import { __awaiter } from 'tslib'; import Hls from 'hls.js'; import flvjs from 'flv.js'; class LocalService { constructor() { } /** * 格式化时间 * @param type 格式化类型yyyy-MM-dd HH:mm:ss,注意MM为月份、mm为分钟 * @param time 可选。默认当前时间 * @returns yyyy-MM-dd HH:mm:ss */ formatDate(type, time) { if (!time) { time = new Date(); } else { time = new Date(time); } if (!type) { return ''; } const year = time.getFullYear(); const month = (time.getMonth() + 1).toString().padStart(2, '0'); const date = (time.getDate()).toString().padStart(2, '0'); const hours = (time.getHours()).toString().padStart(2, '0'); const minute = (time.getMinutes()).toString().padStart(2, '0'); const second = (time.getSeconds()).toString().padStart(2, '0'); return type.replace('yyyy', year).replace('MM', month).replace('dd', date).replace('HH', hours).replace('mm', minute).replace('ss', second); } /** * 获取文件后缀 * @param filename string 文件名 * @returns extension */ getFileExtension(filename) { if (!filename) { return ''; } const filenameArr = filename.split('.'); if (filenameArr.length == 0) { return ''; } else { const extension = filenameArr.pop(); return extension.toLowerCase(); } } } LocalService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: LocalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); LocalService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: LocalService, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: LocalService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: function () { return []; } }); class VideoComponent { constructor(eleRef, ls) { this.eleRef = eleRef; this.ls = ls; this.videoUrl = ''; this.videoHover = false; this.playError = false; this.ncCoverUrl = ''; //封面图片地址 this.ncLoaded = new EventEmitter(); //返回video this.ncPlaying = new EventEmitter(); //返回播放状态 this.mutedMode = true; this.autoplayMode = false; this.loopMode = false; this.fillMode = false; this.screenshotMode = false; this.coverMode = false; this.controlsMode = true; } set ncUrl(value) { this.videoUrl = value; setTimeout(() => { //加延迟,防止其他传入参数未获取到 this.initVideo(); }); } ; //静音 set ncMuted(value) { this.mutedMode = value !== null && value !== undefined && value !== false && value !== 'false'; } //自动播放 set ncAutoplay(value) { this.autoplayMode = value !== null && value !== undefined && value !== false && value !== 'false'; } //循环播放 set ncLoop(value) { this.loopMode = value !== null && value !== undefined && value !== false && value !== 'false'; } //铺满 set ncFill(value) { this.fillMode = value !== null && value !== undefined && value !== false && value !== 'false'; } //截图 set ncScreenshot(value) { this.screenshotMode = value !== null && value !== undefined && value !== false && value !== 'false'; } //封面 set ncCover(value) { this.coverMode = value !== null && value !== undefined && value !== false && value !== 'false'; } //隐藏控制栏 set ncControls(value) { this.controlsMode = value !== null && value !== undefined && value !== false && value !== 'false'; } ngOnInit() { } ngOnDestroy() { this.destroyAll(); } //初始化 initVideo() { return __awaiter(this, void 0, void 0, function* () { this.destroyAll(); //加载前先销毁 this.video = this.eleRef.nativeElement.querySelector('#video'); //获取video const extension = this.ls.getFileExtension(this.videoUrl); //判断地址类型 if (extension == 'm3u8') { //hls(m3u8) if (this.video.canPlayType('application/vnd.apple.mpegurl')) { this.video.src = this.videoUrl; } else if (Hls.isSupported()) { this.hls = new Hls(); this.hls.loadSource(this.videoUrl); this.hls.attachMedia(this.video); //错误监听 this.hls.on(Hls.Events.ERROR, (event, data) => { if (data.details == 'bufferStalledError') { console.warn('warning:', data.error); } else if (data.details == 'fragParsingError') { console.warn('warning:', data.error); } else if (data.details == 'bufferNudgeOnStall') { console.warn('warning:', data.error); } else { this.playError = true; console.error('error:', data.details); console.error('error:', data.error); } }); } } else if (extension == 'flv') { //HTTP-FLV(flv) if (flvjs.isSupported()) { this.flv = flvjs.createPlayer({ type: 'flv', url: this.videoUrl }); this.flv.attachMediaElement(this.video); this.flv.load(); //错误监听 this.flv.on(flvjs.Events.ERROR, (error) => { this.playError = true; console.error('error:', error); }); } } else { //静态视频地址 this.video.src = this.videoUrl; } //封面 if (this.coverMode) { const img = document.createElement('img'); img.style.width = '100%'; img.style.height = '100%'; const coverDom = this.eleRef.nativeElement.querySelector('.cover'); this.video.addEventListener('play', () => { coverDom.style.display = 'none'; }); if (!this.ncCoverUrl) { //使用默认封面 const dataUrl = yield this.captureVideoFrame(this.videoUrl); img.src = dataUrl; } else { //使用传入封面 img.src = this.ncCoverUrl; } coverDom.appendChild(img); } //播放监听 this.video.addEventListener('play', () => { this.ncPlaying.emit(true); }); //暂停监听 this.video.addEventListener('pause', () => { this.ncPlaying.emit(false); }); //返回video对象 this.ncLoaded.emit(this.video); }); } //截图 screenshot() { const canvas = document.createElement('canvas'); canvas.width = this.video.videoWidth; canvas.height = this.video.videoHeight; canvas.getContext('2d').drawImage(this.video, 0, 0, canvas.width, canvas.height); const a = document.createElement('a'); a.download = '截图【' + this.ls.formatDate('yyyy-MM-dd HH-mm-ss') + '】'; a.href = canvas.toDataURL('image/png'); a.click(); } //销毁 destroyAll() { if (this.hls) { this.hls.destroy(); } if (this.flv) { this.flv.destroy(); } if (this.video) { this.destroyVideo(this.video); } } destroyVideo(video) { video.pause(); video.src = ''; video.removeEventListener('play', () => { }); video.removeEventListener('pause', () => { }); video.removeEventListener('loadedmetadata', () => { }); video.remove(); } //获取视频截图作为封面 captureVideoFrame(url, time = 1) { return new Promise((resolve) => { const video = document.createElement('video'); video.crossOrigin = "anonymous"; video.currentTime = time; video.muted = true; video.autoplay = true; const extension = this.ls.getFileExtension(url); //判断地址类型 let hls; let flv; if (extension == 'm3u8') { //hls(m3u8) hls = new Hls(); hls.loadSource(url); hls.attachMedia(video); } else if (extension == 'flv') { //HTTP-FLV(flv) flv = flvjs.createPlayer({ type: 'flv', url: url }); flv.attachMediaElement(video); flv.load(); } else { //静态视频地址 video.src = url; } video.addEventListener('loadedmetadata', () => { video.oncanplay = () => { const canvas = document.createElement('canvas'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); const dataUrl = canvas.toDataURL('image/png'); resolve(dataUrl); if (hls) { hls.destroy(); } if (flv) { flv.destroy(); } if (video) { this.destroyVideo(video); } }; }); }); } } VideoComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: VideoComponent, deps: [{ token: i0.ElementRef }, { token: LocalService }], target: i0.ɵɵFactoryTarget.Component }); VideoComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: VideoComponent, selector: "nc-video", inputs: { ncUrl: "ncUrl", ncCoverUrl: "ncCoverUrl", ncMuted: "ncMuted", ncAutoplay: "ncAutoplay", ncLoop: "ncLoop", ncFill: "ncFill", ncScreenshot: "ncScreenshot", ncCover: "ncCover", ncControls: "ncControls" }, outputs: { ncLoaded: "ncLoaded", ncPlaying: "ncPlaying" }, ngImport: i0, template: "<div class=\"video-container\" (mouseenter)=\"videoHover = true\" (mouseleave)=\"videoHover = false\">\r\n <div class=\"playError\" *ngIf=\"playError\">\r\n <svg t=\"1724830569178\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\r\n p-id=\"10496\" width=\"64\" height=\"64\">\r\n <path\r\n d=\"M725.333333 469.333333c129.6 0 234.666667 105.066667 234.666667 234.666667s-105.066667 234.666667-234.666667 234.666667-234.666667-105.066667-234.666666-234.666667 105.066667-234.666667 234.666666-234.666667z m128-341.333333a128 128 0 0 1 128 128v294.101333a300.224 300.224 0 0 0-85.312-91.221333L896 426.666667h-59.605333c-34.346667-13.76-71.808-21.333333-111.061334-21.333334v-192H298.666667v597.333334h147.626666a298.453333 298.453333 0 0 0 50.282667 85.354666L170.666667 896a128 128 0 0 1-128-128V256a128 128 0 0 1 128-128h682.666666z m-119.466666 661.333333h-17.066667a21.333333 21.333333 0 0 0-21.333333 21.333334v17.066666a21.333333 21.333333 0 0 0 21.333333 21.333334h17.066667a21.333333 21.333333 0 0 0 21.333333-21.333334V810.666667a21.333333 21.333333 0 0 0-21.333333-21.333334zM213.333333 682.666667H128v85.333333a42.666667 42.666667 0 0 0 39.466667 42.56L170.666667 810.666667h42.666666v-128z m520.533334-128h-17.066667a21.333333 21.333333 0 0 0-21.184 18.837333L695.466667 576v149.333333a21.333333 21.333333 0 0 0 18.837333 21.184L716.8 746.666667h17.066667a21.333333 21.333333 0 0 0 21.184-18.837334L755.2 725.333333v-149.333333a21.333333 21.333333 0 0 0-21.333333-21.333333z m-266.026667-187.114667l2.773333 1.6 114.090667 71.296a298.965333 298.965333 0 0 0-154.432 217.002667 42.24 42.24 0 0 1-24.832-35.584L405.333333 618.666667V405.333333c0-32.426667 34.517333-52.608 62.506667-37.781333zM213.333333 426.666667H128v170.666666h85.333333v-170.666666z m0-213.333334H170.666667a42.666667 42.666667 0 0 0-42.56 39.466667L128 256v85.333333h85.333333v-128z m640 0h-42.666666v128h85.333333v-85.333333a42.666667 42.666667 0 0 0-39.466667-42.56L853.333333 213.333333z\"\r\n fill=\"#cdcdcd\" p-id=\"10497\"></path>\r\n </svg>\r\n <div class=\"errorText\">\u64AD\u653E\u5931\u8D25</div>\r\n </div>\r\n <div class=\"cover\" *ngIf=\"coverMode\"></div>\r\n <div class=\"screenshot\" *ngIf=\"screenshotMode && videoHover\" (click)=\"screenshot()\" title=\"\u622A\u56FE\">\r\n <svg t=\"1720708671726\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\r\n p-id=\"1830\" width=\"24\" height=\"24\">\r\n <path\r\n d=\"M981.333333 789.333333h-106.666666V256c0-59.733333-46.933333-106.666667-106.666667-106.666667H234.666667V42.666667c0-25.6-17.066667-42.666667-42.666667-42.666667s-42.666667 17.066667-42.666667 42.666667v106.666666H42.666667c-25.6 0-42.666667 17.066667-42.666667 42.666667s17.066667 42.666667 42.666667 42.666667h106.666666V768c0 59.733333 46.933333 106.666667 106.666667 106.666667h533.333333V981.333333c0 25.6 17.066667 42.666667 42.666667 42.666667s42.666667-17.066667 42.666667-42.666667v-106.666666H981.333333c25.6 0 42.666667-17.066667 42.666667-42.666667s-17.066667-42.666667-42.666667-42.666667z m-213.333333-554.666666c12.8 0 21.333333 8.533333 21.333333 21.333333v341.333333l-145.066666-140.8c-17.066667-17.066667-42.666667-17.066667-59.733334 0l-140.8 145.066667L384 541.866667c-17.066667-17.066667-38.4-17.066667-55.466667-4.266667l-89.6 72.533333V234.666667H768z m-512 554.666666c-12.8 0-21.333333-8.533333-21.333333-21.333333v-42.666667l115.2-93.866666 64 64c8.533333 8.533333 17.066667 12.8 29.866666 12.8s21.333333-4.266667 29.866667-12.8l140.8-145.066667 174.933333 166.4v72.533333H256z\"\r\n p-id=\"1831\" fill=\"#ffffff\"></path>\r\n <path\r\n d=\"M384 482.133333c51.2 0 93.866667-42.666667 93.866667-93.866666s-42.666667-93.866667-93.866667-93.866667-93.866667 38.4-93.866667 89.6 42.666667 98.133333 93.866667 98.133333z m0-128c17.066667 0 34.133333 12.8 34.133333 34.133334s-17.066667 29.866667-34.133333 29.866666-34.133333-17.066667-34.133333-34.133333 17.066667-29.866667 34.133333-29.866667z\"\r\n p-id=\"1832\" fill=\"#ffffff\"></path>\r\n </svg>\r\n </div>\r\n <video class=\"video\" [ngStyle]=\"{'object-fit': fillMode ? 'fill' : 'contain' }\" crossOrigin=\"anonymous\"\r\n [controls]=\"controlsMode\" [muted]=\"mutedMode\" [autoplay]=\"autoplayMode\" [loop]=\"loopMode\" id=\"video\"></video>\r\n</div>", styles: [".video-container{width:100%;height:100%;position:relative}.video-container .playError{background-color:#000;width:100%;height:100%;position:absolute;left:0;top:0;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:2}.video-container .playError .errorText{color:#cdcdcd;font-size:16px;margin-top:10px;letter-spacing:1px}.video-container .cover{width:100%;height:100%;position:absolute;left:0;right:0}.video-container .screenshot{z-index:1;position:absolute;right:5px;top:5px;background-color:#2b333fb3;padding:3px;border-radius:2px;display:flex;align-items:center;justify-content:center;cursor:pointer}.video-container .screenshot:hover{background-color:#2b333fcc}.video-container .video{width:100%;height:100%}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: VideoComponent, decorators: [{ type: Component, args: [{ selector: 'nc-video', templateUrl: './video.component.html', styleUrls: ['./video.component.less'] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: LocalService }]; }, propDecorators: { ncUrl: [{ type: Input }], ncCoverUrl: [{ type: Input }], ncLoaded: [{ type: Output }], ncPlaying: [{ type: Output }], ncMuted: [{ type: Input }], ncAutoplay: [{ type: Input }], ncLoop: [{ type: Input }], ncFill: [{ type: Input }], ncScreenshot: [{ type: Input }], ncCover: [{ type: Input }], ncControls: [{ type: Input }] } }); class NcVideoModule { } NcVideoModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcVideoModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); NcVideoModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcVideoModule, declarations: [VideoComponent], imports: [CommonModule], exports: [VideoComponent] }); NcVideoModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcVideoModule, imports: [[ CommonModule ]] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcVideoModule, decorators: [{ type: NgModule, args: [{ declarations: [ VideoComponent ], imports: [ CommonModule ], exports: [ VideoComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { NcVideoModule, VideoComponent }; //# sourceMappingURL=ng-cw-v12-video.js.map