UNPKG

@ngx-telly/player

Version:

Telly - Angular frame-accurate HTML player

285 lines (272 loc) 14.1 kB
import { Subject, fromEvent, merge, Observable, startWith, takeUntil, tap, map, debounceTime } from 'rxjs'; import { InjectionToken, inject } from '@angular/core'; import { Platform } from '@angular/cdk/platform'; var Browser; (function (Browser) { Browser[Browser["Chromium"] = 0] = "Chromium"; Browser[Browser["Webkit"] = 1] = "Webkit"; Browser[Browser["Ios"] = 2] = "Ios"; Browser[Browser["Firefox"] = 3] = "Firefox"; })(Browser || (Browser = {})); var VideoEvent; (function (VideoEvent) { VideoEvent["Abort"] = "abort"; VideoEvent["Error"] = "error"; VideoEvent["CanPlay"] = "canplay"; VideoEvent["CanPlayThrough"] = "canplaythrough"; VideoEvent["Complete"] = "complete"; VideoEvent["DurationChange"] = "durationchange"; VideoEvent["Emptied"] = "emptied"; VideoEvent["Ended"] = "ended"; VideoEvent["Resize"] = "resize"; VideoEvent["LoadStart"] = "loadstart"; VideoEvent["LoadedData"] = "loadeddata"; VideoEvent["LoadedMetadata"] = "loadedmetadata"; VideoEvent["Pause"] = "pause"; VideoEvent["Play"] = "play"; VideoEvent["Playing"] = "playing"; VideoEvent["Progress"] = "progress"; VideoEvent["RateChange"] = "ratechange"; VideoEvent["Seeked"] = "seeked"; VideoEvent["Seeking"] = "seeking"; VideoEvent["Stalled"] = "stalled"; VideoEvent["Suspend"] = "suspend"; VideoEvent["TimeUpdate"] = "timeupdate"; VideoEvent["VolumeChange"] = "volumechange"; VideoEvent["Waiting"] = "waiting"; })(VideoEvent || (VideoEvent = {})); class TellyMedia { constructor(id, el, options) { this.internalEvents$ = new Subject(); this.rateMap = { [1]: 0.1, [2]: 0.2, [3]: 0.1, [4]: 0.2, [5]: 0.5, [6]: 0.6, [7]: 0.7, [8]: 0.8, }; this.id = id; this.element = el; this.opts = { ...options }; this.events = this.createEventStream(); } get events() { return this.nativeEvents$; } set events(events) { this.nativeEvents$ = events; } get messages() { return this.internalEvents$; } get time() { return this.element.currentTime; } set time(time) { this.element.currentTime = time; } get windowTime() { return this.time - this.drift; } get totalDuration() { return this.element.duration; } get duration() { return this.opts?.duration ?? this.element.duration; } set duration(val) { this.opts.duration = val; } get drift() { return this.opts?.drift ?? 0; } set drift(val) { this.opts.drift = val; } get rate() { return this.opts?.rate ?? 1; } get buffered() { return this.element.buffered; } get volume() { return this.element.volume; } set volume(vol) { this.indicate(`Volume ${vol * 100}%`); this.storeVolume(vol); this.element.volume = vol; } get playing() { return this.element.currentTime > 0 && !this.element.paused && !this.element.ended; } play(silent = false) { if (!this.playing && !silent) this.indicate('Play'); this.setRate(1); this.element.play(); } pause(silent = false) { if (this.playing && !silent) this.indicate('Pause'); this.setRate(1); this.element.pause(); this.time = this.element.currentTime; // magic } toggle() { this.element.paused ? this.play() : this.pause(); } stop() { this.element.pause(); this.element.currentTime = 0; this.indicate('Stop'); } seek(second) { this.element.currentTime = second + this.drift; } setRate(rate) { this.opts.rate = rate; clearInterval(this.interval); if (rate === 1) { this.element.playbackRate = rate; } else if (rate > 1) { this.indicate(`Forward x${Math.abs(rate)}`); if (this.opts.smoothFastForward) { this.element.playbackRate = rate; const paused = this.element.paused; if (paused) { this.play(true); } } else { const updateRate = (this.opts.rewindUpdateRate ?? 12) + 1; const next = (rate / 1000) * updateRate; this.interval = setInterval(() => (this.time = this.element.currentTime + next), this.opts.rewindUpdateRate); } } else if (rate < 0) { this.indicate(`Rewind x${Math.abs(rate)}`); const updateRate = (this.opts.rewindUpdateRate ?? 12) + 1; const next = (Math.abs(rate) / 1000) * updateRate; this.interval = setInterval(() => (this.time = this.element.currentTime - next), this.opts.rewindUpdateRate); } } faster() { const rate = this.rate + 1; if (rate > 8) { this.opts.rate = 8; } else if (rate === 0) { this.opts.rate = 1; } else { this.opts.rate = rate; } this.setRate(this.rate); } slower() { const rate = this.rate - 1; if (rate < -8) { this.opts.rate = -8; } else if (rate === 0) { this.opts.rate = -1; } else { this.opts.rate = rate; } this.setRate(this.rate); } indicate(msg) { this.internalEvents$.next(msg); } event(name) { return fromEvent(this.element, name); } createEventStream() { return merge(fromEvent(this.element, VideoEvent.CanPlay), fromEvent(this.element, VideoEvent.CanPlayThrough), fromEvent(this.element, VideoEvent.Complete), fromEvent(this.element, VideoEvent.DurationChange), fromEvent(this.element, VideoEvent.Emptied), fromEvent(this.element, VideoEvent.Ended), fromEvent(this.element, VideoEvent.LoadStart), fromEvent(this.element, VideoEvent.LoadedData), fromEvent(this.element, VideoEvent.LoadedMetadata), fromEvent(this.element, VideoEvent.Play), fromEvent(this.element, VideoEvent.Pause), fromEvent(this.element, VideoEvent.Playing), fromEvent(this.element, VideoEvent.Progress), fromEvent(this.element, VideoEvent.RateChange), fromEvent(this.element, VideoEvent.Seeked), fromEvent(this.element, VideoEvent.Seeking), fromEvent(this.element, VideoEvent.Stalled), fromEvent(this.element, VideoEvent.Suspend), fromEvent(this.element, VideoEvent.TimeUpdate), fromEvent(this.element, VideoEvent.VolumeChange), fromEvent(this.element, VideoEvent.Waiting), fromEvent(this.element, VideoEvent.Error), fromEvent(this.element, VideoEvent.Abort), fromEvent(this.element, VideoEvent.Resize)); } storeVolume(vol) { localStorage.setItem('telly:volume', vol.toString()); } } const tellyConfigToken = new InjectionToken('__TELLY_CONFIG__'); function eventType(types) { return function (source) { return new Observable((subscriber) => { return source.subscribe({ next(ev) { if (types.includes(ev.type)) { return subscriber.next(ev); } }, error(err) { subscriber.next(err); }, complete() { subscriber.complete(); }, }); }); }; } function debounceMove(delay, destroyer, callback) { return function (source) { return source .pipe(startWith(new Event('mousemove')), takeUntil(destroyer), tap(() => callback(false)), map(() => true), debounceTime(delay), tap(hide => callback(hide))); }; } const BROWSER = new InjectionToken('Current browser', { factory() { const platform = inject(Platform); if (platform.WEBKIT) { return Browser.Webkit; } if (platform.FIREFOX) { return Browser.Firefox; } if (platform.IOS) { return Browser.Ios; } return Browser.Chromium; } }); const play = 'M8,5.14V19.14L19,12.14L8,5.14Z'; const pause = 'M14,19H18V5H14M6,19H10V5H6V19Z'; const fastForward = 'M4,5V19L11,12M18,5V19H20V5M11,5V19L18,12'; const rewind = 'M20,5V19L13,12M6,5V19H4V5M13,5V19L6,12'; const fullScreen = 'M5,5H10V7H7V10H5V5M14,5H19V10H17V7H14V5M17,14H19V19H14V17H17V14M10,17V19H5V14H7V17H10Z'; const smallScreen = 'M14,14H19V16H16V19H14V14M5,14H10V19H8V16H5V14M8,5H10V10H5V8H8V5M19,8V10H14V5H16V8H19Z'; const mute = "M12,4L9.91,6.09L12,8.18M4.27,3L3,4.27L7.73,9H3V15H7L12,20V13.27L16.25,17.53C15.58,18.04 14.83,18.46 14,18.7V20.77C15.38,20.45 16.63,19.82 17.68,18.96L19.73,21L21,19.73L12,10.73M19,12C19,12.94 18.8,13.82 18.46,14.64L19.97,16.15C20.62,14.91 21,13.5 21,12C21,7.72 18,4.14 14,3.23V5.29C16.89,6.15 19,8.83 19,12M16.5,12C16.5,10.23 15.5,8.71 14,7.97V10.18L16.45,12.63C16.5,12.43 16.5,12.21 16.5,12Z"; const volumeLow = "M7,9V15H11L16,20V4L11,9H7Z"; const volumeMedium = "M5,9V15H9L14,20V4L9,9M18.5,12C18.5,10.23 17.5,8.71 16,7.97V16C17.5,15.29 18.5,13.76 18.5,12Z"; const volumeHigh = "M14,3.23V5.29C16.89,6.15 19,8.83 19,12C19,15.17 16.89,17.84 14,18.7V20.77C18,19.86 21,16.28 21,12C21,7.72 18,4.14 14,3.23M16.5,12C16.5,10.23 15.5,8.71 14,7.97V16C15.5,15.29 16.5,13.76 16.5,12M3,9V15H7L12,20V4L7,9H3Z"; const fwd5 = "M11.5 3C14.15 3 16.55 4 18.4 5.6L21 3V10H14L16.62 7.38C15.23 6.22 13.46 5.5 11.5 5.5C7.96 5.5 4.95 7.81 3.9 11L1.53 10.22C2.92 6.03 6.85 3 11.5 3M9 12H15V14H11V16H13C14.11 16 15 16.9 15 18V20C15 21.11 14.11 22 13 22H9V20H13V18H9V12Z"; const fwd10 = "M10,12V22H8V14H6V12H10M18,14V20C18,21.11 17.11,22 16,22H14A2,2 0 0,1 12,20V14A2,2 0 0,1 14,12H16C17.11,12 18,12.9 18,14M14,14V20H16V14H14M11.5,3C14.15,3 16.55,4 18.4,5.6L21,3V10H14L16.62,7.38C15.23,6.22 13.46,5.5 11.5,5.5C7.96,5.5 4.95,7.81 3.9,11L1.53,10.22C2.92,6.03 6.85,3 11.5,3Z"; const fwd15 = "M11.5 3C14.15 3 16.55 4 18.4 5.6L21 3V10H14L16.62 7.38C15.23 6.22 13.46 5.5 11.5 5.5C7.96 5.5 4.95 7.81 3.9 11L1.53 10.22C2.92 6.03 6.85 3 11.5 3M10 12V22H8V14H6V12H10M12 12H18V14H14V16H16C17.11 16 18 16.9 18 18V20C18 21.11 17.11 22 16 22H12V20H16V18H12V12Z"; const fwd30 = "M11.5,3C6.85,3 2.92,6.03 1.53,10.22L3.9,11C4.95,7.81 7.96,5.5 11.5,5.5C13.46,5.5 15.23,6.22 16.62,7.38L14,10H21V3L18.4,5.6C16.55,4 14.15,3 11.5,3M19,14V20C19,21.11 18.11,22 17,22H15A2,2 0 0,1 13,20V14A2,2 0 0,1 15,12H17C18.11,12 19,12.9 19,14M15,14V20H17V14H15M11,20C11,21.11 10.1,22 9,22H5V20H9V18H7V16H9V14H5V12H9A2,2 0 0,1 11,14V15.5A1.5,1.5 0 0,1 9.5,17A1.5,1.5 0 0,1 11,18.5V20Z"; const fwd45 = "M11.5 3C14.1 3 16.5 4 18.4 5.6L21 3V10H14L16.6 7.4C15.2 6.2 13.4 5.5 11.5 5.5C8 5.5 4.9 7.8 3.9 11L1.5 10.2C2.9 6 6.8 3 11.5 3M13 12H19V14H15V16H17C18.1 16 19 16.9 19 18V20C19 21.1 18.1 22 17 22H13V20H17V18H13V12M5 12V18H9V22H11V12H9V16H7V12H5Z"; const fwd60 = "M11.5 3C6.8 3 2.9 6 1.5 10.2L3.9 11C4.9 7.8 8 5.5 11.5 5.5C13.5 5.5 15.2 6.2 16.6 7.4L14 10H21V3L18.4 5.6C16.5 4 14.1 3 11.5 3M19 14V20C19 21.1 18.1 22 17 22H15C13.9 22 13 21.1 13 20V14C13 12.9 13.9 12 15 12H17C18.1 12 19 12.9 19 14M15 14V20H17V14H15M7 12C5.9 12 5 12.9 5 14V20C5 21.1 5.9 22 7 22H9C10.1 22 11 21.1 11 20V18C11 16.9 10.1 16 9 16H7V14H11V12H7M7 18H9V20H7V18Z"; const rwd5 = "M12.5 3C17.15 3 21.08 6.03 22.47 10.22L20.1 11C19.05 7.81 16.04 5.5 12.5 5.5C10.54 5.5 8.77 6.22 7.38 7.38L10 10H3V3L5.6 5.6C7.45 4 9.85 3 12.5 3M9 12H15V14H11V16H13C14.11 16 15 16.9 15 18V20C15 21.11 14.11 22 13 22H9V20H13V18H9V12Z"; const rwd10 = "M12.5,3C17.15,3 21.08,6.03 22.47,10.22L20.1,11C19.05,7.81 16.04,5.5 12.5,5.5C10.54,5.5 8.77,6.22 7.38,7.38L10,10H3V3L5.6,5.6C7.45,4 9.85,3 12.5,3M10,12V22H8V14H6V12H10M18,14V20C18,21.11 17.11,22 16,22H14A2,2 0 0,1 12,20V14A2,2 0 0,1 14,12H16C17.11,12 18,12.9 18,14M14,14V20H16V14H14Z"; const rwd15 = "M12.5 3C17.15 3 21.08 6.03 22.47 10.22L20.1 11C19.05 7.81 16.04 5.5 12.5 5.5C10.54 5.5 8.77 6.22 7.38 7.38L10 10H3V3L5.6 5.6C7.45 4 9.85 3 12.5 3M10 12V22H8V14H6V12H10M12 12H18V14H14V16H16C17.11 16 18 16.9 18 18V20C18 21.11 17.11 22 16 22H12V20H16V18H12V12Z"; const rwd30 = "M19,14V20C19,21.11 18.11,22 17,22H15A2,2 0 0,1 13,20V14A2,2 0 0,1 15,12H17C18.11,12 19,12.9 19,14M15,14V20H17V14H15M11,20C11,21.11 10.1,22 9,22H5V20H9V18H7V16H9V14H5V12H9A2,2 0 0,1 11,14V15.5A1.5,1.5 0 0,1 9.5,17A1.5,1.5 0 0,1 11,18.5V20M12.5,3C17.15,3 21.08,6.03 22.47,10.22L20.1,11C19.05,7.81 16.04,5.5 12.5,5.5C10.54,5.5 8.77,6.22 7.38,7.38L10,10H3V3L5.6,5.6C7.45,4 9.85,3 12.5,3Z"; const rwd45 = "M12.5 3C17.1 3 21.1 6 22.5 10.2L20.1 11C19 7.8 16 5.5 12.5 5.5C10.5 5.5 8.8 6.2 7.4 7.4L10 10H3V3L5.6 5.6C7.4 4 9.9 3 12.5 3M13 12H19V14H15V16H17C18.1 16 19 16.9 19 18V20C19 21.1 18.1 22 17 22H13V20H17V18H13V12M5 12V18H9V22H11V12H9V16H7V12H5Z"; const rwd60 = "M19 14V20C19 21.1 18.1 22 17 22H15C13.9 22 13 21.1 13 20V14C13 12.9 13.9 12 15 12H17C18.1 12 19 12.9 19 14M15 14V20H17V14H15M12.5 3C17.1 3 21.1 6 22.5 10.2L20.1 11C19 7.8 16 5.5 12.5 5.5C10.5 5.5 8.8 6.2 7.4 7.4L10 10H3V3L5.6 5.6C7.4 4 9.9 3 12.5 3M7 12C5.9 12 5 12.9 5 14V20C5 21.1 5.9 22 7 22H9C10.1 22 11 21.1 11 20V18C11 16.9 10.1 16 9 16H7V14H11V12H7M7 18H9V20H7V18Z"; const getTime = (seconds) => { const h = Math.max(0, Math.floor(seconds / 3600)); const m = Math.max(0, Math.floor((seconds % 3600) / 60)); const s = Math.max(0, Math.floor(seconds % 60)); return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${(s).toString().padStart(2, '0')}`; }; const tellyPluginToken = new InjectionToken('__TELLY_PLUGIN__'); const tellyPluginConfigToken = new InjectionToken('__TELLY_PLUGIN_CONFIG__'); /** * Generated bundle index. Do not edit. */ export { BROWSER, Browser, TellyMedia, VideoEvent, debounceMove, eventType, fastForward, fullScreen, fwd10, fwd15, fwd30, fwd45, fwd5, fwd60, getTime, mute, pause, play, rewind, rwd10, rwd15, rwd30, rwd45, rwd5, rwd60, smallScreen, tellyConfigToken, tellyPluginConfigToken, tellyPluginToken, volumeHigh, volumeLow, volumeMedium }; //# sourceMappingURL=ngx-telly-player-core.mjs.map