Files
@ 3ae1e7f8db23
Branch filter:
Location: light9/light9/web/light9-vidref-replay.js - annotation
3ae1e7f8db23
4.0 KiB
application/javascript
vidref playback smoothness, autodelete short clips, manual-delete clips, vidref keyboard shortcuts
Ignore-this: 6daccf686fd66561029f3252ed4dbafd
Ignore-this: 6daccf686fd66561029f3252ed4dbafd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 3ae1e7f8db23 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 9f0f2b39ad95 3ae1e7f8db23 3ae1e7f8db23 | 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 }
};
}
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]; });
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 {
margin: 5px;
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);
}
`;
}
render() {
return html`
<video id="replay" src="${this.videoUrl}"></video>
<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)}</span>,
err = <span class="num">${rounding(this.timeErr, 3)} </span>
rate = <span class="num">${rounding(this.playRate, 3)}</span>
</div>
`;
}
}
customElements.define('light9-vidref-replay', Light9VidrefReplay);
window.thresh=.3
window.p=.3
|