@omnimedia/omnitool
Version:
open source video processing tools
94 lines (75 loc) • 2.06 kB
text/typescript
import {ms} from "../../../units/ms.js"
import {fps} from "../../../units/fps.js"
import {Playback} from "./parts/playback.js"
import {Driver} from "../../../driver/driver.js"
import {TimelineFile} from "../../parts/basics.js"
import {AudioLevelObserver} from "./parts/types.js"
import {DecoderSource} from "../../../driver/fns/schematic.js"
type ResolveMedia = (hash: string) => DecoderSource
export class VideoPlayer {
canvas: HTMLCanvasElement
playback: Playback
readonly audio: {levels: AudioLevelObserver}
#pendingSeek: number | null = null
#flushTask: Promise<void> | null = null
constructor(
private driver: Driver,
resolveMedia: ResolveMedia,
timeline: TimelineFile
) {
this.playback = new Playback(driver, timeline, resolveMedia)
this.audio = {levels: this.playback.audioLevels}
this.canvas = driver.compositor.pixi.renderer.canvas
}
async play() {
await this.playback.start()
}
pause() {
this.playback.pause()
}
seek(timeMs: number) {
this.#pendingSeek = timeMs
return this.#flushTask ??= this.#flushSeeks().finally(() => this.#flushTask = null)
}
setFPS(value: number) {
this.playback.setFps(fps(value))
}
resize(width: number, height: number) {
this.driver.resize(width, height)
}
get isSeeking() {
return this.#flushTask !== null
}
get isPlaying() {
return this.playback.isPlaying
}
get duration() {
return this.playback.duration
}
get currentTime() {
return this.playback.currentTime
}
get playbackRate() {
return this.playback.playbackRate
}
set playbackRate(rate: number) {
this.playback.playbackRate = rate
}
/**
call this whenever your timeline state changes
*/
async update(timeline: TimelineFile) {
this.playback.update(timeline)
if (!this.isPlaying)
await this.seek(this.currentTime)
}
async #flushSeeks() {
while (this.#pendingSeek !== null) {
const next = this.#pendingSeek
this.#pendingSeek = null
const layers = await this.playback.seek(ms(next))
const frame = await this.driver.composite(layers)
frame.close()
}
}
}