UNPKG

@atmtfy/video-background

Version:

Automatic background video from various sources (Youtube, MP4, vimeo) with autoplay across devices. No JS dependencies.

201 lines (160 loc) 4.03 kB
import { getVideoID } from "../utils/vidUtils" import Player from "youtube-player" import type {YouTubePlayer} from "youtube-player/dist/types" import VideoPlayer from "./videoPlayer" export class YoutubePlayer extends VideoPlayer{ source: string id: string |false wrapper: HTMLElement player?: YouTubePlayer looper?: ReturnType<typeof setInterval> constructor(config:PlayerConfigInput) { super(config); this.type = 'youtube'; this.id = getVideoID(config.source) this.wrapper = this.parent.ownerDocument.createElement('div') const innerWrap = this.parent.ownerDocument.createElement('div') this.wrapper.append(innerWrap); this.setupWrapper() this.source = config.source![0].url; if (!this.id) { return; } this.player = Player(innerWrap, { playerVars: { autoplay: 1, playsinline: 0, modestbranding: 1, rel: 0, fs: 0, start: this.config.startTime, controls: 0, loop: 1, }}) this.player.loadVideoById(this.id); if (this.props.muted != false) { this.player.mute() } this.build(); } setupWrapper() { // this.wrapper.id = this.source this.wrapper.classList.add('vbg__video'); this.wrapper.classList.add('vbg--loading'); this.parent.append(this.wrapper) } unbuild() { this.clearLoop(); if (this.player) { this.player.destroy(); } } build() { this.afterPlayerSetup().then(() => { this.status.ready = true; this.status.apiReady = true; this.do('ready') }) } startPlayLoop() { this.looper = setInterval(() => { if (this.player && this.player.getDuration() > 0) { if (this.player.getCurrentTime() >= this.player.getDuration() - 6) { this.player.seekTo(this.config.startTime, false); } } else { this.clearLoop(); } }, 3000); } clearLoop(){ if (this.looper) { clearInterval(this.looper) } } async afterPlayerSetup() { if (this.player) { this.iframe = this.player.getIframe(); this.player.seekTo(this.config.startTime, true) this.getAspectRatio().then((data)=> { this.props.aspectRatio = data; window.setTimeout(this.resize.bind(this), 400) }); } this.parent.status = "ready" return false } async getAspectRatio() { try { const resp = await fetch (`https://noembed.com/embed?url=https://youtube.com/embed/${this.id}`, { }) const data:{height:number, width: number} = await resp.json() if (data && data.height && data.width) { return data.height / data.width } return 0.5625; } catch(e) { return 0.5624 } } get playing() { return this.player?.getPlayerState() == 1 } get buffering() { return this.player?.getPlayerState() == 3 } get aspectRatio() { return 1 } get currentTime() { return 0 } async play() { if (this.player) { if (this.wrapper) { this.wrapper.classList.remove('vbg--loading'); } else { this.parent.querySelector('iframe')!.classList.remove('vbg--loading'); } if (this.status.started == false) { this.player.playVideo(); } else { this.player.playVideo(); this.status.started = true } return true } else { this.on('ready', this.play.bind(this), 'playCheck') return false } } async pause() { if (this.player) { this.clearLoop(); this.player.pauseVideo() return true } else { return false } } get paused() { return this.player?.getPlayerState() == 2 } get muted() { return this.player?.isMuted() } async mute() { if (this.player) { this.player.mute() return } return } async unmute() { if (this.player) { return this.player.unMute() } else { this.on('ready', this.unmute.bind(this), 'muteCheck') } return; } }