ng-cw-v12
Version:
Angular UI component library
353 lines (347 loc) • 19.6 kB
JavaScript
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