import { type FrameTime, type InitConfig } from '$/lib/Player/Video'; import ThreeVideo from './ThreeVideo'; 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 ThreeVideo { protected isPreview = false; protected px(pixels: number) { return this.isPreview ? pixels / 1.5 : pixels } public async init(config: InitConfig): Promise { const { isPreview } = config this.isPreview = isPreview this.resize(this.px(1920), this.px(1080)) const threeInit = super.init(config).catch(e => ([1, e] as const)) // 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 // }) // }) const rs = await threeInit if (rs && rs[0] === 1) { console.error(rs[1]); throw new Error('Failed to initialize ThreeJS!'); } } 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 }