import { Video as BaseVideo, type FrameTime, type InitConfig } from '$/lib/Player/Video'; import AudioURL from './03. Lemaitre, Jennie A. - Closer - 2min version.flac?url' type FontInfo = { family: string, size: number, weight?: number } const renderText = (ctx: CanvasRenderingContext2D, text: string, color: string, fontInfo: FontInfo, { x, y }: { x: number, y: number }, align = 'left' as CanvasTextAlign) => { ctx.font = `normal normal ${fontInfo.weight ?? 400} ${fontInfo.size}px ${fontInfo.family}`; ctx.fillStyle = color ctx.textAlign = align ctx.fillText(text, x, y) } const getTextSize = (ctx: CanvasRenderingContext2D, text: string, fontInfo: FontInfo) => { ctx.font = `normal normal ${fontInfo.weight ?? 400} ${fontInfo.size}px ${fontInfo.family}`; return ctx.measureText(text) } export default class Video extends BaseVideo { public ctx!: CanvasRenderingContext2D protected isPreview = false; protected px(pixels: number) { return this.isPreview ? pixels / 1.5 : pixels } public async init({ isPreview }: InitConfig): Promise { // this.resize(this.canvas.parentElement.clientWidth,this.canvas.parentElement.clientHeight) this.isPreview = isPreview this.resize(this.px(1920), this.px(1080)) this.ctx = this.canvas.getContext('2d')! const v = document.createElement('video') v.load() await new Promise((rs, rj) => { let debounce = false; const timeout = setTimeout(() => { if (!debounce) rj('Failed to load video - timed out.') }, 1000); v.addEventListener('load', () => { rs(void 0) clearTimeout(timeout) }, { once: true }) }) // } public renderFrame(time: FrameTime): Promise | void { const beat = 1 + ((time.seconds - 0.098) * (92 / 60)) const center = [this.w / 2, this.h / 2] as const if (beat < 13 || beat >= 16) { this.ctx.fillStyle = '#fff'; this.ctx.fillRect(0, 0, this.w, this.h); } else { this.ctx.fillStyle = '#000'; this.ctx.fillRect(0, 0, this.w, this.h); } const AdDefault: FontInfo = { family: 'Inter Variable', size: this.px(52), weight: 450 } if (this.isPreview) renderText(this.ctx, `${(Math.floor(beat * 100) / 100).toFixed(1)}`, '#646663', { ...AdDefault, size: this.px(12), weight: 400 }, { x: this.w - this.px(4), y: this.h - this.px(4) }, 'end') switch (true) { case beat >= 1 && beat < 4.3: renderText(this.ctx, `Need a new AI assistant?`, '#646663', AdDefault, { x: center[0], y: center[1] }, 'center') break; case beat >= 4.3 && beat < 8.4: { const text = `Like${beat >= 4.8 ? ' new' : ''}${beat >= 5.02 ? ' new' : ''}`; const longTextWidth = getTextSize(this.ctx, 'Like new new', AdDefault) renderText(this.ctx, text, '#646663', AdDefault, { x: center[0] - longTextWidth.width / 2, y: center[1] }, 'start') break; } case beat >= 8.4 && beat < 13: { const text = `Like${beat >= 9 ? ` runs random shit in your terminal` : ''}${beat >= 11 ? ' new' : ''}`; const longTextWidth = getTextSize(this.ctx, `Like runs random shit in your terminal new`, AdDefault) renderText(this.ctx, text, '#646663', AdDefault, { x: center[0] - longTextWidth.width / 2, y: center[1] }, 'start') break; } // TODO: default: break; } } // public fps = 59.94; public fps = 30; public length = Math.ceil(2 * 60 * this.fps); public audioUrl = ['03. Lemaitre, Jennie A. - Closer.flac', AudioURL] as const }