Mercurial > code > home > repos > light9
diff web/light9-vidref-replay.js @ 2376:4556eebe5d73
topdir reorgs; let pdm have its src/ dir; separate vite area from light9/
author | drewp@bigasterisk.com |
---|---|
date | Sun, 12 May 2024 19:02:10 -0700 |
parents | light9/web/light9-vidref-replay.js@b64a4db527e2 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/light9-vidref-replay.js Sun May 12 19:02:10 2024 -0700 @@ -0,0 +1,142 @@ +import { LitElement, TemplateResult, html, css } from '/node_modules/lit-element/lit-element.js'; +import debug from '/lib/debug/debug-build-es6.js'; +import _ from '/lib/underscore/underscore-min-es6.js'; +import { rounding } from '/node_modules/significant-rounding/index.js'; + +const log = debug('replay'); + +class Light9VidrefReplay extends LitElement { + + static get properties() { + return { + uri: { type: String }, + videoUrl: { type: String }, + songToVideo: { type: Object }, + videoTime: { type: Number }, + outVideoCurrentTime: { type: Number }, + timeErr: { type: Number }, + playRate: { type: Number }, + size: { type: String, attribute: true } + }; + } + + estimateRate() { + const n = this.songToVideo.length; + const x0 = Math.round(n * .3); + const x1 = Math.round(n * .6); + const pt0 = this.songToVideo[x0]; + const pt1 = this.songToVideo[x1]; + return (pt1[1] - pt0[1]) / (pt1[0] - pt0[0]); + } + + setVideoTimeFromSongTime(songTime, isPlaying) { + if (!this.songToVideo || !this.outVideo || this.outVideo.readyState < 1) { + return; + } + const i = _.sortedIndex(this.songToVideo, [songTime], + (row) => { return row[0]; }); + if (i == 0 || i > this.songToVideo.length - 1) { + isPlaying = false; + } + + this.videoTime = this.songToVideo[Math.max(0, i - 1)][1]; + + this.outVideoCurrentTime = this.outVideo.currentTime; + + if (isPlaying) { + if (this.outVideo.paused) { + this.outVideo.play(); + this.setRate(this.estimateRate()); + } + const err = this.outVideo.currentTime - this.videoTime; + this.timeErr = err; + + if (Math.abs(err) > window.thresh) { + this.outVideo.currentTime = this.videoTime; + const p = window.p; + if (err > 0) { + this.setRate(this.playRate - err * p); + } else { + this.setRate(this.playRate - err * p); + } + } + } else { + this.outVideo.pause(); + this.outVideoCurrentTime = this.outVideo.currentTime = this.videoTime; + this.timeErr = 0; + } + } + + setRate(r) { + this.playRate = Math.max(.1, Math.min(4, r)); + this.outVideo.playbackRate = this.playRate; + } + + firstUpdated() { + this.outVideo = this.shadowRoot.querySelector('#replay'); + this.playRate = this.outVideo.playbackRate = 1.0; + } + + onDelete() { + const u = new URL(window.location.href); + u.pathname = '/vidref/clips' + u.searchParams.set('uri', this.uri); + fetch(u.toString(), {method: 'DELETE'}).then((resp) => { + let event = new CustomEvent('clips-changed', {detail: {}}); + this.dispatchEvent(event); + }); + } + + static get styles() { + return css` + :host { + border: 2px solid #46a79f; + display: flex; + flex-direction: column; + } + div { + padding: 5px; + } + .num { + display: inline-block; + width: 4em; + color: #29ffa0; + } + a { + color: rgb(97, 97, 255); + } + video { + width: 100%; + } + `; + } + + render() { + let details = ''; + if (this.size != 'small') { + details = html` + <div> + take is <a href="${this.uri}">${this.uri}</a> + (${Object.keys(this.songToVideo).length} frames) + <button @click="${this.onDelete}">Delete</button> + </div> + <!-- here, put a little canvas showing what coverage we have with the + actual/goal time cursors --> + <div> + video time should be <span class="num">${this.videoTime} </span> + actual = <span class="num">${rounding(this.outVideoCurrentTime, 3, 3, true)}</span>, + err = <span class="num">${rounding(this.timeErr, 3, 4, true)}</span> + rate = <span class="num">${rounding(this.playRate, 3, 3, true)}</span> + </div> + `; + } + return html` + <video id="replay" class="size-${this.size}" src="${this.videoUrl}"></video> + ${details} + `; + + } +} +customElements.define('light9-vidref-replay', Light9VidrefReplay); +window.thresh=.3 +window.p=.3