-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest.htm
More file actions
268 lines (263 loc) · 36.9 KB
/
test.htm
File metadata and controls
268 lines (263 loc) · 36.9 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
<!DOCTYPE html>
<html>
<head>
<title>Pippy - Click to activate</title>
<style>
body {
padding:0;
margin:0;
}
.frost-foot {
position:fixed;
bottom:10px;
right:10px;
font-size:15px;
text-align:right;
width:100%;
color:black;
opacity:0.4;
pointer-events:none;
}
.pipy-hidden {
opacity:0;position:absolute;pointer-events:none;
}
</style>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width'>
<script>
//Vanilangy/webm-muxer MIT license
var WebMMuxer=(()=>{var wt=Object.defineProperty;var si=Object.getOwnPropertyDescriptor;var ai=Object.getOwnPropertyNames;var ni=Object.prototype.hasOwnProperty;var oi=(d,e)=>{for(var i in e)wt(d,i,{get:e[i],enumerable:!0})},hi=(d,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ai(e))!ni.call(d,s)&&s!==i&&wt(d,s,{get:()=>e[s],enumerable:!(r=si(e,s))||r.enumerable});return d};var di=d=>hi(wt({},"__esModule",{value:!0}),d);var pt=(d,e,i)=>{if(!e.has(d))throw TypeError("Cannot "+i)};var t=(d,e,i)=>(pt(d,e,"read from private field"),i?i.call(d):e.get(d)),a=(d,e,i)=>{if(e.has(d))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(d):e.set(d,i)},l=(d,e,i,r)=>(pt(d,e,"write to private field"),r?r.call(d,i):e.set(d,i),i);var o=(d,e,i)=>(pt(d,e,"access private method"),i);var Ti={};oi(Ti,{ArrayBufferTarget:()=>ee,FileSystemWritableFileStreamTarget:()=>te,Muxer:()=>Je,StreamTarget:()=>z,SubtitleEncoder:()=>ct});var J=class{constructor(e){this.value=e}},O=class{constructor(e){this.value=e}};var gt=d=>d<1<<8?1:d<1<<16?2:d<1<<24?3:d<2**32?4:d<2**40?5:6,zt=d=>{if(d<(1<<7)-1)return 1;if(d<(1<<14)-1)return 2;if(d<(1<<21)-1)return 3;if(d<(1<<28)-1)return 4;if(d<2**35-1)return 5;if(d<2**42-1)return 6;throw new Error("EBML VINT size not supported "+d)};var W=(d,e,i)=>{let r=0;for(let s=e;s<i;s++){let n=Math.floor(s/8),u=d[n],m=7-(s&7),p=(u&1<<m)>>m;r<<=1,r|=p}return r},Vt=(d,e,i,r)=>{for(let s=e;s<i;s++){let n=Math.floor(s/8),u=d[n],m=7-(s&7);u&=~(1<<m),u|=(r&1<<i-s-1)>>i-s-1<<m,d[n]=u}};var ui=Symbol("isTarget"),H=class{};ui;var ee=class extends H{constructor(){super(...arguments);this.buffer=null}},z=class extends H{constructor(i){super();this.options=i;if(typeof i!="object")throw new TypeError("StreamTarget requires an options object to be passed to its constructor.");if(i.onData){if(typeof i.onData!="function")throw new TypeError("options.onData, when provided, must be a function.");if(i.onData.length<2)throw new TypeError("options.onData, when provided, must be a function that takes in at least two arguments (data and position). Ignoring the position argument, which specifies the byte offset at which the data is to be written, can lead to broken outputs.")}if(i.onHeader&&typeof i.onHeader!="function")throw new TypeError("options.onHeader, when provided, must be a function.");if(i.onCluster&&typeof i.onCluster!="function")throw new TypeError("options.onCluster, when provided, must be a function.");if(i.chunked!==void 0&&typeof i.chunked!="boolean")throw new TypeError("options.chunked, when provided, must be a boolean.");if(i.chunkSize!==void 0&&(!Number.isInteger(i.chunkSize)||i.chunkSize<1024))throw new TypeError("options.chunkSize, when provided, must be an integer and not smaller than 1024.")}},te=class extends H{constructor(i,r){super();this.stream=i;this.options=r;if(!(i instanceof FileSystemWritableFileStream))throw new TypeError("FileSystemWritableFileStreamTarget requires a FileSystemWritableFileStream instance.");if(r!==void 0&&typeof r!="object")throw new TypeError("FileSystemWritableFileStreamTarget's options, when provided, must be an object.");if(r&&r.chunkSize!==void 0&&(!Number.isInteger(r.chunkSize)||r.chunkSize<=0))throw new TypeError("options.chunkSize, when provided, must be a positive integer")}};var S,c,$e,Dt,je,Rt,Ke,Ft,Ce,yt,qe,Pt,We=class{constructor(){a(this,$e);a(this,je);a(this,Ke);a(this,Ce);a(this,qe);this.pos=0;a(this,S,new Uint8Array(8));a(this,c,new DataView(t(this,S).buffer));this.offsets=new WeakMap;this.dataOffsets=new WeakMap}seek(e){this.pos=e}writeEBMLVarInt(e,i=zt(e)){let r=0;switch(i){case 1:t(this,c).setUint8(r++,1<<7|e);break;case 2:t(this,c).setUint8(r++,1<<6|e>>8),t(this,c).setUint8(r++,e);break;case 3:t(this,c).setUint8(r++,1<<5|e>>16),t(this,c).setUint8(r++,e>>8),t(this,c).setUint8(r++,e);break;case 4:t(this,c).setUint8(r++,1<<4|e>>24),t(this,c).setUint8(r++,e>>16),t(this,c).setUint8(r++,e>>8),t(this,c).setUint8(r++,e);break;case 5:t(this,c).setUint8(r++,1<<3|e/2**32&7),t(this,c).setUint8(r++,e>>24),t(this,c).setUint8(r++,e>>16),t(this,c).setUint8(r++,e>>8),t(this,c).setUint8(r++,e);break;case 6:t(this,c).setUint8(r++,1<<2|e/2**40&3),t(this,c).setUint8(r++,e/2**32|0),t(this,c).setUint8(r++,e>>24),t(this,c).setUint8(r++,e>>16),t(this,c).setUint8(r++,e>>8),t(this,c).setUint8(r++,e);break;default:throw new Error("Bad EBML VINT size "+i)}this.write(t(this,S).subarray(0,r))}writeEBML(e){if(e!==null)if(e instanceof Uint8Array)this.write(e);else if(Array.isArray(e))for(let i of e)this.writeEBML(i);else if(this.offsets.set(e,this.pos),o(this,Ce,yt).call(this,e.id),Array.isArray(e.data)){let i=this.pos,r=e.size===-1?1:e.size??4;e.size===-1?o(this,$e,Dt).call(this,255):this.seek(this.pos+r);let s=this.pos;if(this.dataOffsets.set(e,s),this.writeEBML(e.data),e.size!==-1){let n=this.pos-s,u=this.pos;this.seek(i),this.writeEBMLVarInt(n,r),this.seek(u)}}else if(typeof e.data=="number"){let i=e.size??gt(e.data);this.writeEBMLVarInt(i),o(this,Ce,yt).call(this,e.data,i)}else typeof e.data=="string"?(this.writeEBMLVarInt(e.data.length),o(this,qe,Pt).call(this,e.data)):e.data instanceof Uint8Array?(this.writeEBMLVarInt(e.data.byteLength,e.size),this.write(e.data)):e.data instanceof J?(this.writeEBMLVarInt(4),o(this,je,Rt).call(this,e.data.value)):e.data instanceof O&&(this.writeEBMLVarInt(8),o(this,Ke,Ft).call(this,e.data.value))}};S=new WeakMap,c=new WeakMap,$e=new WeakSet,Dt=function(e){t(this,c).setUint8(0,e),this.write(t(this,S).subarray(0,1))},je=new WeakSet,Rt=function(e){t(this,c).setFloat32(0,e,!1),this.write(t(this,S).subarray(0,4))},Ke=new WeakSet,Ft=function(e){t(this,c).setFloat64(0,e,!1),this.write(t(this,S))},Ce=new WeakSet,yt=function(e,i=gt(e)){let r=0;switch(i){case 6:t(this,c).setUint8(r++,e/2**40|0);case 5:t(this,c).setUint8(r++,e/2**32|0);case 4:t(this,c).setUint8(r++,e>>24);case 3:t(this,c).setUint8(r++,e>>16);case 2:t(this,c).setUint8(r++,e>>8);case 1:t(this,c).setUint8(r++,e);break;default:throw new Error("Bad UINT size "+i)}this.write(t(this,S).subarray(0,r))},qe=new WeakSet,Pt=function(e){this.write(new Uint8Array(e.split("").map(i=>i.charCodeAt(0))))};var xe,V,ie,Se,Tt,He=class extends We{constructor(i){super();a(this,Se);a(this,xe,void 0);a(this,V,new ArrayBuffer(2**16));a(this,ie,new Uint8Array(t(this,V)));l(this,xe,i)}write(i){o(this,Se,Tt).call(this,this.pos+i.byteLength),t(this,ie).set(i,this.pos),this.pos+=i.byteLength}finalize(){o(this,Se,Tt).call(this,this.pos),t(this,xe).buffer=t(this,V).slice(0,this.pos)}};xe=new WeakMap,V=new WeakMap,ie=new WeakMap,Se=new WeakSet,Tt=function(i){let r=t(this,V).byteLength;for(;r<i;)r*=2;if(r===t(this,V).byteLength)return;let s=new ArrayBuffer(r),n=new Uint8Array(s);n.set(t(this,ie),0),l(this,V,s),l(this,ie,n)};var B,g,y,D,F=class extends We{constructor(i){super();this.target=i;a(this,B,!1);a(this,g,void 0);a(this,y,void 0);a(this,D,void 0)}write(i){if(!t(this,B))return;let r=this.pos;if(r<t(this,y)){if(r+i.byteLength<=t(this,y))return;i=i.subarray(t(this,y)-r),r=0}let s=r+i.byteLength-t(this,y),n=t(this,g).byteLength;for(;n<s;)n*=2;if(n!==t(this,g).byteLength){let u=new Uint8Array(n);u.set(t(this,g),0),l(this,g,u)}t(this,g).set(i,r-t(this,y)),l(this,D,Math.max(t(this,D),r+i.byteLength))}startTrackingWrites(){l(this,B,!0),l(this,g,new Uint8Array(2**10)),l(this,y,this.pos),l(this,D,this.pos)}getTrackedWrites(){if(!t(this,B))throw new Error("Can't get tracked writes since nothing was tracked.");let r={data:t(this,g).subarray(0,t(this,D)-t(this,y)),start:t(this,y),end:t(this,D)};return l(this,g,void 0),l(this,B,!1),r}};B=new WeakMap,g=new WeakMap,y=new WeakMap,D=new WeakMap;var li=2**24,fi=2,R,$,re,se,C,w,Ae,kt,Ge,Mt,Ye,Nt,ae,Oe,ne=class extends F{constructor(i,r){super(i);a(this,Ae);a(this,Ge);a(this,Ye);a(this,ae);a(this,R,[]);a(this,$,0);a(this,re,void 0);a(this,se,void 0);a(this,C,void 0);a(this,w,[]);l(this,re,r),l(this,se,i.options?.chunked??!1),l(this,C,i.options?.chunkSize??li)}write(i){super.write(i),t(this,R).push({data:i.slice(),start:this.pos}),this.pos+=i.byteLength}flush(){if(t(this,R).length===0)return;let i=[],r=[...t(this,R)].sort((s,n)=>s.start-n.start);i.push({start:r[0].start,size:r[0].data.byteLength});for(let s=1;s<r.length;s++){let n=i[i.length-1],u=r[s];u.start<=n.start+n.size?n.size=Math.max(n.size,u.start+u.data.byteLength-n.start):i.push({start:u.start,size:u.data.byteLength})}for(let s of i){s.data=new Uint8Array(s.size);for(let n of t(this,R))s.start<=n.start&&n.start<s.start+s.size&&s.data.set(n.data,n.start-s.start);if(t(this,se))o(this,Ae,kt).call(this,s.data,s.start),o(this,ae,Oe).call(this);else{if(t(this,re)&&s.start<t(this,$))throw new Error("Internal error: Monotonicity violation.");this.target.options.onData?.(s.data,s.start),l(this,$,s.start+s.data.byteLength)}}t(this,R).length=0}finalize(){t(this,se)&&o(this,ae,Oe).call(this,!0)}};R=new WeakMap,$=new WeakMap,re=new WeakMap,se=new WeakMap,C=new WeakMap,w=new WeakMap,Ae=new WeakSet,kt=function(i,r){let s=t(this,w).findIndex(b=>b.start<=r&&r<b.start+t(this,C));s===-1&&(s=o(this,Ye,Nt).call(this,r));let n=t(this,w)[s],u=r-n.start,m=i.subarray(0,Math.min(t(this,C)-u,i.byteLength));n.data.set(m,u);let p={start:u,end:u+m.byteLength};if(o(this,Ge,Mt).call(this,n,p),n.written[0].start===0&&n.written[0].end===t(this,C)&&(n.shouldFlush=!0),t(this,w).length>fi){for(let b=0;b<t(this,w).length-1;b++)t(this,w)[b].shouldFlush=!0;o(this,ae,Oe).call(this)}m.byteLength<i.byteLength&&o(this,Ae,kt).call(this,i.subarray(m.byteLength),r+m.byteLength)},Ge=new WeakSet,Mt=function(i,r){let s=0,n=i.written.length-1,u=-1;for(;s<=n;){let m=Math.floor(s+(n-s+1)/2);i.written[m].start<=r.start?(s=m+1,u=m):n=m-1}for(i.written.splice(u+1,0,r),(u===-1||i.written[u].end<r.start)&&u++;u<i.written.length-1&&i.written[u].end>=i.written[u+1].start;)i.written[u].end=Math.max(i.written[u].end,i.written[u+1].end),i.written.splice(u+1,1)},Ye=new WeakSet,Nt=function(i){let s={start:Math.floor(i/t(this,C))*t(this,C),data:new Uint8Array(t(this,C)),written:[],shouldFlush:!1};return t(this,w).push(s),t(this,w).sort((n,u)=>n.start-u.start),t(this,w).indexOf(s)},ae=new WeakSet,Oe=function(i=!1){for(let r=0;r<t(this,w).length;r++){let s=t(this,w)[r];if(!(!s.shouldFlush&&!i)){for(let n of s.written){if(t(this,re)&&s.start+n.start<t(this,$))throw new Error("Internal error: Monotonicity violation.");this.target.options.onData?.(s.data.subarray(n.start,n.end),s.start+n.start),l(this,$,s.start+n.end)}t(this,w).splice(r--,1)}}};var Be=class extends ne{constructor(e,i){super(new z({onData:(r,s)=>e.stream.write({type:"write",data:r,position:s}),chunked:!0,chunkSize:e.options?.chunkSize}),i)}};var oe=1,Ee=2,Ze=3,ci=1,mi=2,bi=17,wi=2**15,Ue=2**13,_t="https://github.com/Vanilagy/webm-muxer",Ot=6,Wt=5,pi=["strict","offset","permissive"],f,h,ue,le,x,j,K,P,q,E,G,Y,T,fe,Z,U,v,M,ce,me,L,Q,ze,be,we,et,Ht,tt,Bt,it,$t,rt,jt,st,Kt,at,qt,nt,Gt,Ve,Ct,De,xt,ot,Yt,N,he,_,de,ht,Zt,dt,Lt,pe,Le,ge,Qe,ut,Qt,k,A,X,ve,ye,Xe,lt,Xt,Re,St,Te,Ie,Je=class{constructor(e){a(this,et);a(this,tt);a(this,it);a(this,rt);a(this,st);a(this,at);a(this,nt);a(this,Ve);a(this,De);a(this,ot);a(this,N);a(this,_);a(this,ht);a(this,dt);a(this,pe);a(this,ge);a(this,ut);a(this,k);a(this,X);a(this,ye);a(this,lt);a(this,Re);a(this,Te);a(this,f,void 0);a(this,h,void 0);a(this,ue,void 0);a(this,le,void 0);a(this,x,void 0);a(this,j,void 0);a(this,K,void 0);a(this,P,void 0);a(this,q,void 0);a(this,E,void 0);a(this,G,void 0);a(this,Y,void 0);a(this,T,void 0);a(this,fe,void 0);a(this,Z,0);a(this,U,[]);a(this,v,[]);a(this,M,[]);a(this,ce,void 0);a(this,me,void 0);a(this,L,-1);a(this,Q,-1);a(this,ze,-1);a(this,be,void 0);a(this,we,!1);o(this,et,Ht).call(this,e),l(this,f,{type:"webm",firstTimestampBehavior:"strict",...e}),this.target=e.target;let i=!!t(this,f).streaming;if(e.target instanceof ee)l(this,h,new He(e.target));else if(e.target instanceof z)l(this,h,new ne(e.target,i));else if(e.target instanceof te)l(this,h,new Be(e.target,i));else throw new Error(`Invalid target: ${e.target}`);o(this,tt,Bt).call(this)}addVideoChunk(e,i,r){if(!(e instanceof EncodedVideoChunk))throw new TypeError("addVideoChunk's first argument (chunk) must be of type EncodedVideoChunk.");if(i&&typeof i!="object")throw new TypeError("addVideoChunk's second argument (meta), when provided, must be an object.");if(r!==void 0&&(!Number.isFinite(r)||r<0))throw new TypeError("addVideoChunk's third argument (timestamp), when provided, must be a non-negative real number.");let s=new Uint8Array(e.byteLength);e.copyTo(s),this.addVideoChunkRaw(s,e.type,r??e.timestamp,i)}addVideoChunkRaw(e,i,r,s){if(!(e instanceof Uint8Array))throw new TypeError("addVideoChunkRaw's first argument (data) must be an instance of Uint8Array.");if(i!=="key"&&i!=="delta")throw new TypeError("addVideoChunkRaw's second argument (type) must be either 'key' or 'delta'.");if(!Number.isFinite(r)||r<0)throw new TypeError("addVideoChunkRaw's third argument (timestamp) must be a non-negative real number.");if(s&&typeof s!="object")throw new TypeError("addVideoChunkRaw's fourth argument (meta), when provided, must be an object.");if(o(this,Te,Ie).call(this),!t(this,f).video)throw new Error("No video track declared.");t(this,ce)===void 0&&l(this,ce,r),s&&o(this,ht,Zt).call(this,s);let n=o(this,ge,Qe).call(this,e,i,r,oe);for(t(this,f).video.codec==="V_VP9"&&o(this,dt,Lt).call(this,n),l(this,L,n.timestamp);t(this,v).length>0&&t(this,v)[0].timestamp<=n.timestamp;){let u=t(this,v).shift();o(this,k,A).call(this,u,!1)}!t(this,f).audio||n.timestamp<=t(this,Q)?o(this,k,A).call(this,n,!0):t(this,U).push(n),o(this,pe,Le).call(this),o(this,N,he).call(this)}addAudioChunk(e,i,r){if(!(e instanceof EncodedAudioChunk))throw new TypeError("addAudioChunk's first argument (chunk) must be of type EncodedAudioChunk.");if(i&&typeof i!="object")throw new TypeError("addAudioChunk's second argument (meta), when provided, must be an object.");if(r!==void 0&&(!Number.isFinite(r)||r<0))throw new TypeError("addAudioChunk's third argument (timestamp), when provided, must be a non-negative real number.");let s=new Uint8Array(e.byteLength);e.copyTo(s),this.addAudioChunkRaw(s,e.type,r??e.timestamp,i)}addAudioChunkRaw(e,i,r,s){if(!(e instanceof Uint8Array))throw new TypeError("addAudioChunkRaw's first argument (data) must be an instance of Uint8Array.");if(i!=="key"&&i!=="delta")throw new TypeError("addAudioChunkRaw's second argument (type) must be either 'key' or 'delta'.");if(!Number.isFinite(r)||r<0)throw new TypeError("addAudioChunkRaw's third argument (timestamp) must be a non-negative real number.");if(s&&typeof s!="object")throw new TypeError("addAudioChunkRaw's fourth argument (meta), when provided, must be an object.");if(o(this,Te,Ie).call(this),!t(this,f).audio)throw new Error("No audio track declared.");t(this,me)===void 0&&l(this,me,r),s?.decoderConfig&&(t(this,f).streaming?l(this,E,o(this,X,ve).call(this,s.decoderConfig.description)):o(this,ye,Xe).call(this,t(this,E),s.decoderConfig.description));let n=o(this,ge,Qe).call(this,e,i,r,Ee);for(l(this,Q,n.timestamp);t(this,U).length>0&&t(this,U)[0].timestamp<=n.timestamp;){let u=t(this,U).shift();o(this,k,A).call(this,u,!0)}!t(this,f).video||n.timestamp<=t(this,L)?o(this,k,A).call(this,n,!t(this,f).video):t(this,v).push(n),o(this,pe,Le).call(this),o(this,N,he).call(this)}addSubtitleChunk(e,i,r){if(typeof e!="object"||!e)throw new TypeError("addSubtitleChunk's first argument (chunk) must be an object.");if(!(e.body instanceof Uint8Array))throw new TypeError("body must be an instance of Uint8Array.");if(!Number.isFinite(e.timestamp)||e.timestamp<0)throw new TypeError("timestamp must be a non-negative real number.");if(!Number.isFinite(e.duration)||e.duration<0)throw new TypeError("duration must be a non-negative real number.");if(e.additions&&!(e.additions instanceof Uint8Array))throw new TypeError("additions, when present, must be an instance of Uint8Array.");if(typeof i!="object")throw new TypeError("addSubtitleChunk's second argument (meta) must be an object.");if(o(this,Te,Ie).call(this),!t(this,f).subtitles)throw new Error("No subtitle track declared.");i?.decoderConfig&&(t(this,f).streaming?l(this,G,o(this,X,ve).call(this,i.decoderConfig.description)):o(this,ye,Xe).call(this,t(this,G),i.decoderConfig.description));let s=o(this,ge,Qe).call(this,e.body,"key",r??e.timestamp,Ze,e.duration,e.additions);l(this,ze,s.timestamp),t(this,M).push(s),o(this,pe,Le).call(this),o(this,N,he).call(this)}finalize(){if(t(this,we))throw new Error("Cannot finalize a muxer more than once.");for(;t(this,U).length>0;)o(this,k,A).call(this,t(this,U).shift(),!0);for(;t(this,v).length>0;)o(this,k,A).call(this,t(this,v).shift(),!0);for(;t(this,M).length>0&&t(this,M)[0].timestamp<=t(this,Z);)o(this,k,A).call(this,t(this,M).shift(),!1);if(t(this,T)&&o(this,Re,St).call(this),t(this,h).writeEBML(t(this,Y)),!t(this,f).streaming){let e=t(this,h).pos,i=t(this,h).pos-t(this,_,de);t(this,h).seek(t(this,h).offsets.get(t(this,ue))+4),t(this,h).writeEBMLVarInt(i,Ot),t(this,K).data=new O(t(this,Z)),t(this,h).seek(t(this,h).offsets.get(t(this,K))),t(this,h).writeEBML(t(this,K)),t(this,x).data[0].data[1].data=t(this,h).offsets.get(t(this,Y))-t(this,_,de),t(this,x).data[1].data[1].data=t(this,h).offsets.get(t(this,le))-t(this,_,de),t(this,x).data[2].data[1].data=t(this,h).offsets.get(t(this,j))-t(this,_,de),t(this,h).seek(t(this,h).offsets.get(t(this,x))),t(this,h).writeEBML(t(this,x)),t(this,h).seek(e)}o(this,N,he).call(this),t(this,h).finalize(),l(this,we,!0)}};f=new WeakMap,h=new WeakMap,ue=new WeakMap,le=new WeakMap,x=new WeakMap,j=new WeakMap,K=new WeakMap,P=new WeakMap,q=new WeakMap,E=new WeakMap,G=new WeakMap,Y=new WeakMap,T=new WeakMap,fe=new WeakMap,Z=new WeakMap,U=new WeakMap,v=new WeakMap,M=new WeakMap,ce=new WeakMap,me=new WeakMap,L=new WeakMap,Q=new WeakMap,ze=new WeakMap,be=new WeakMap,we=new WeakMap,et=new WeakSet,Ht=function(e){if(typeof e!="object")throw new TypeError("The muxer requires an options object to be passed to its constructor.");if(!(e.target instanceof H))throw new TypeError("The target must be provided and an instance of Target.");if(e.video){if(typeof e.video.codec!="string")throw new TypeError(`Invalid video codec: ${e.video.codec}. Must be a string.`);if(!Number.isInteger(e.video.width)||e.video.width<=0)throw new TypeError(`Invalid video width: ${e.video.width}. Must be a positive integer.`);if(!Number.isInteger(e.video.height)||e.video.height<=0)throw new TypeError(`Invalid video height: ${e.video.height}. Must be a positive integer.`);if(e.video.frameRate!==void 0&&(!Number.isFinite(e.video.frameRate)||e.video.frameRate<=0))throw new TypeError(`Invalid video frame rate: ${e.video.frameRate}. Must be a positive number.`);if(e.video.alpha!==void 0&&typeof e.video.alpha!="boolean")throw new TypeError(`Invalid video alpha: ${e.video.alpha}. Must be a boolean.`)}if(e.audio){if(typeof e.audio.codec!="string")throw new TypeError(`Invalid audio codec: ${e.audio.codec}. Must be a string.`);if(!Number.isInteger(e.audio.numberOfChannels)||e.audio.numberOfChannels<=0)throw new TypeError(`Invalid number of audio channels: ${e.audio.numberOfChannels}. Must be a positive integer.`);if(!Number.isInteger(e.audio.sampleRate)||e.audio.sampleRate<=0)throw new TypeError(`Invalid audio sample rate: ${e.audio.sampleRate}. Must be a positive integer.`);if(e.audio.bitDepth!==void 0&&(!Number.isInteger(e.audio.bitDepth)||e.audio.bitDepth<=0))throw new TypeError(`Invalid audio bit depth: ${e.audio.bitDepth}. Must be a positive integer.`)}if(e.subtitles&&typeof e.subtitles.codec!="string")throw new TypeError(`Invalid subtitles codec: ${e.subtitles.codec}. Must be a string.`);if(e.type!==void 0&&!["webm","matroska"].includes(e.type))throw new TypeError(`Invalid type: ${e.type}. Must be 'webm' or 'matroska'.`);if(e.firstTimestampBehavior&&!pi.includes(e.firstTimestampBehavior))throw new TypeError(`Invalid first timestamp behavior: ${e.firstTimestampBehavior}`);if(e.streaming!==void 0&&typeof e.streaming!="boolean")throw new TypeError(`Invalid streaming option: ${e.streaming}. Must be a boolean.`)},tt=new WeakSet,Bt=function(){t(this,h)instanceof F&&t(this,h).target.options.onHeader&&t(this,h).startTrackingWrites(),o(this,it,$t).call(this),t(this,f).streaming||o(this,at,qt).call(this),o(this,nt,Gt).call(this),o(this,rt,jt).call(this),o(this,st,Kt).call(this),t(this,f).streaming||(o(this,Ve,Ct).call(this),o(this,De,xt).call(this)),o(this,ot,Yt).call(this),o(this,N,he).call(this)},it=new WeakSet,$t=function(){let e={id:440786851,data:[{id:17030,data:1},{id:17143,data:1},{id:17138,data:4},{id:17139,data:8},{id:17026,data:t(this,f).type??"webm"},{id:17031,data:2},{id:17029,data:2}]};t(this,h).writeEBML(e)},rt=new WeakSet,jt=function(){l(this,q,{id:236,size:4,data:new Uint8Array(Ue)}),l(this,E,{id:236,size:4,data:new Uint8Array(Ue)}),l(this,G,{id:236,size:4,data:new Uint8Array(Ue)})},st=new WeakSet,Kt=function(){l(this,P,{id:21936,data:[{id:21937,data:2},{id:21946,data:2},{id:21947,data:2},{id:21945,data:0}]})},at=new WeakSet,qt=function(){let e=new Uint8Array([28,83,187,107]),i=new Uint8Array([21,73,169,102]),r=new Uint8Array([22,84,174,107]),s={id:290298740,data:[{id:19899,data:[{id:21419,data:e},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:i},{id:21420,size:5,data:0}]},{id:19899,data:[{id:21419,data:r},{id:21420,size:5,data:0}]}]};l(this,x,s)},nt=new WeakSet,Gt=function(){let e={id:17545,data:new O(0)};l(this,K,e);let i={id:357149030,data:[{id:2807729,data:1e6},{id:19840,data:_t},{id:22337,data:_t},t(this,f).streaming?null:e]};l(this,le,i)},Ve=new WeakSet,Ct=function(){let e={id:374648427,data:[]};l(this,j,e),t(this,f).video&&e.data.push({id:174,data:[{id:215,data:oe},{id:29637,data:oe},{id:131,data:ci},{id:134,data:t(this,f).video.codec},t(this,q),t(this,f).video.frameRate?{id:2352003,data:1e9/t(this,f).video.frameRate}:null,{id:224,data:[{id:176,data:t(this,f).video.width},{id:186,data:t(this,f).video.height},t(this,f).video.alpha?{id:21440,data:1}:null,t(this,P)]}]}),t(this,f).audio&&(l(this,E,t(this,f).streaming?t(this,E)||null:{id:236,size:4,data:new Uint8Array(Ue)}),e.data.push({id:174,data:[{id:215,data:Ee},{id:29637,data:Ee},{id:131,data:mi},{id:134,data:t(this,f).audio.codec},t(this,E),{id:225,data:[{id:181,data:new J(t(this,f).audio.sampleRate)},{id:159,data:t(this,f).audio.numberOfChannels},t(this,f).audio.bitDepth?{id:25188,data:t(this,f).audio.bitDepth}:null]}]})),t(this,f).subtitles&&e.data.push({id:174,data:[{id:215,data:Ze},{id:29637,data:Ze},{id:131,data:bi},{id:134,data:t(this,f).subtitles.codec},t(this,G)]})},De=new WeakSet,xt=function(){let e={id:408125543,size:t(this,f).streaming?-1:Ot,data:[t(this,f).streaming?null:t(this,x),t(this,le),t(this,j)]};if(l(this,ue,e),t(this,h).writeEBML(e),t(this,h)instanceof F&&t(this,h).target.options.onHeader){let{data:i,start:r}=t(this,h).getTrackedWrites();t(this,h).target.options.onHeader(i,r)}},ot=new WeakSet,Yt=function(){l(this,Y,{id:475249515,data:[]})},N=new WeakSet,he=function(){t(this,h)instanceof ne&&t(this,h).flush()},_=new WeakSet,de=function(){return t(this,h).dataOffsets.get(t(this,ue))},ht=new WeakSet,Zt=function(e){if(!!e.decoderConfig){if(e.decoderConfig.colorSpace){let i=e.decoderConfig.colorSpace;if(l(this,be,i),t(this,P).data=[{id:21937,data:{rgb:1,bt709:1,bt470bg:5,smpte170m:6}[i.matrix]},{id:21946,data:{bt709:1,smpte170m:6,"iec61966-2-1":13}[i.transfer]},{id:21947,data:{bt709:1,bt470bg:5,smpte170m:6}[i.primaries]},{id:21945,data:[1,2][Number(i.fullRange)]}],!t(this,f).streaming){let r=t(this,h).pos;t(this,h).seek(t(this,h).offsets.get(t(this,P))),t(this,h).writeEBML(t(this,P)),t(this,h).seek(r)}}e.decoderConfig.description&&(t(this,f).streaming?l(this,q,o(this,X,ve).call(this,e.decoderConfig.description)):o(this,ye,Xe).call(this,t(this,q),e.decoderConfig.description))}},dt=new WeakSet,Lt=function(e){if(e.type!=="key"||!t(this,be))return;let i=0;if(W(e.data,0,2)!==2)return;i+=2;let r=(W(e.data,i+1,i+2)<<1)+W(e.data,i+0,i+1);i+=2,r===3&&i++;let s=W(e.data,i+0,i+1);if(i++,s)return;let n=W(e.data,i+0,i+1);if(i++,n!==0)return;i+=2;let u=W(e.data,i+0,i+24);if(i+=24,u!==4817730)return;r>=2&&i++;let m={rgb:7,bt709:2,bt470bg:1,smpte170m:3}[t(this,be).matrix];Vt(e.data,i+0,i+3,m)},pe=new WeakSet,Le=function(){let e=Math.min(t(this,f).video?t(this,L):1/0,t(this,f).audio?t(this,Q):1/0),i=t(this,M);for(;i.length>0&&i[0].timestamp<=e;)o(this,k,A).call(this,i.shift(),!t(this,f).video&&!t(this,f).audio)},ge=new WeakSet,Qe=function(e,i,r,s,n,u){let m=o(this,ut,Qt).call(this,r,s);return{data:e,additions:u,type:i,timestamp:m,duration:n,trackNumber:s}},ut=new WeakSet,Qt=function(e,i){let r=i===oe?t(this,L):i===Ee?t(this,Q):t(this,ze);if(i!==Ze){let s=i===oe?t(this,ce):t(this,me);if(t(this,f).firstTimestampBehavior==="strict"&&r===-1&&e!==0)throw new Error(`The first chunk for your media track must have a timestamp of 0 (received ${e}). Non-zero first timestamps are often caused by directly piping frames or audio data from a MediaStreamTrack into the encoder. Their timestamps are typically relative to the age of the document, which is probably what you want.
If you want to offset all timestamps of a track such that the first one is zero, set firstTimestampBehavior: 'offset' in the options.
If you want to allow non-zero first timestamps, set firstTimestampBehavior: 'permissive'.
`);t(this,f).firstTimestampBehavior==="offset"&&(e-=s)}if(e<r)throw new Error(`Timestamps must be monotonically increasing (went from ${r} to ${e}).`);if(e<0)throw new Error(`Timestamps must be non-negative (received ${e}).`);return e},k=new WeakSet,A=function(e,i){t(this,f).streaming&&!t(this,j)&&(o(this,Ve,Ct).call(this),o(this,De,xt).call(this));let r=Math.floor(e.timestamp/1e3),s=r-t(this,fe),n=i&&e.type==="key"&&s>=1e3,u=s>=wi;if((!t(this,T)||n||u)&&(o(this,lt,Xt).call(this,r),s=0),s<0)return;let m=new Uint8Array(4),p=new DataView(m.buffer);if(p.setUint8(0,128|e.trackNumber),p.setInt16(1,s,!1),e.duration===void 0&&!e.additions){p.setUint8(3,Number(e.type==="key")<<7);let b={id:163,data:[m,e.data]};t(this,h).writeEBML(b)}else{let b=Math.floor(e.duration/1e3),Et={id:160,data:[{id:161,data:[m,e.data]},e.duration!==void 0?{id:155,data:b}:null,e.additions?{id:30113,data:e.additions}:null]};t(this,h).writeEBML(Et)}l(this,Z,Math.max(t(this,Z),r))},X=new WeakSet,ve=function(e){return{id:25506,size:4,data:new Uint8Array(e)}},ye=new WeakSet,Xe=function(e,i){let r=t(this,h).pos;t(this,h).seek(t(this,h).offsets.get(e));let s=2+4+i.byteLength,n=Ue-s;if(n<0){let u=i.byteLength+n;i instanceof ArrayBuffer?i=i.slice(0,u):i=i.buffer.slice(0,u),n=0}e=[o(this,X,ve).call(this,i),{id:236,size:4,data:new Uint8Array(n)}],t(this,h).writeEBML(e),t(this,h).seek(r)},lt=new WeakSet,Xt=function(e){t(this,T)&&o(this,Re,St).call(this),t(this,h)instanceof F&&t(this,h).target.options.onCluster&&t(this,h).startTrackingWrites(),l(this,T,{id:524531317,size:t(this,f).streaming?-1:Wt,data:[{id:231,data:e}]}),t(this,h).writeEBML(t(this,T)),l(this,fe,e);let i=t(this,h).offsets.get(t(this,T))-t(this,_,de);t(this,Y).data.push({id:187,data:[{id:179,data:e},t(this,f).video?{id:183,data:[{id:247,data:oe},{id:241,data:i}]}:null,t(this,f).audio?{id:183,data:[{id:247,data:Ee},{id:241,data:i}]}:null]})},Re=new WeakSet,St=function(){if(!t(this,f).streaming){let e=t(this,h).pos-t(this,h).dataOffsets.get(t(this,T)),i=t(this,h).pos;t(this,h).seek(t(this,h).offsets.get(t(this,T))+4),t(this,h).writeEBMLVarInt(e,Wt),t(this,h).seek(i)}if(t(this,h)instanceof F&&t(this,h).target.options.onCluster){let{data:e,start:i}=t(this,h).getTrackedWrites();t(this,h).target.options.onCluster(e,i,t(this,fe))}},Te=new WeakSet,Ie=function(){if(t(this,we))throw new Error("Cannot add new video or audio chunks after the file has been finalized.")};var Fe=/(?:(.+?)\n)?((?:\d{2}:)?\d{2}:\d{2}.\d{3})\s+-->\s+((?:\d{2}:)?\d{2}:\d{2}.\d{3})/g,gi=/^WEBVTT.*?\n{2}/,yi=/(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})/,It=/<(?:(\d{2}):)?(\d{2}):(\d{2}).(\d{3})>/g,At=new TextEncoder,I,Pe,Me,Ne,_e,ke,ft,mt,Jt,ct=class{constructor(e){a(this,ke);a(this,mt);a(this,I,void 0);a(this,Pe,void 0);a(this,Me,!1);a(this,Ne,void 0);a(this,_e,!1);l(this,I,e)}configure(e){if(e.codec!=="webvtt")throw new Error("Codec must be 'webvtt'.");l(this,Pe,e)}encode(e){if(!t(this,Pe))throw new Error("Encoder not configured.");e=e.replace(`\r
`,`
`).replace("\r",`
`),Fe.lastIndex=0;let i;if(!t(this,Me)){if(!gi.test(e)){let s=new Error("WebVTT preamble incorrect.");throw t(this,I).error(s),s}i=Fe.exec(e);let r=e.slice(0,i?.index??e.length).trimEnd();if(!r){let s=new Error("No WebVTT preamble provided.");throw t(this,I).error(s),s}l(this,Ne,At.encode(r)),l(this,Me,!0),i&&(e=e.slice(i.index),Fe.lastIndex=0)}for(;i=Fe.exec(e);){let r=e.slice(0,i.index),s=i[1]||"",n=i.index+i[0].length,u=e.indexOf(`
`,n)+1,m=e.slice(n,u).trim(),p=e.indexOf(`
`,n);p===-1&&(p=e.length);let b=o(this,ke,ft).call(this,i[2]),ei=o(this,ke,ft).call(this,i[3])-b,bt=e.slice(u,p),Ut=`${m}
${s}
${r}`;It.lastIndex=0,bt=bt.replace(It,ii=>{let ri=o(this,ke,ft).call(this,ii.slice(1,-1))-b;return`<${o(this,mt,Jt).call(this,ri)}>`}),e=e.slice(p).trimStart(),Fe.lastIndex=0;let ti={body:At.encode(bt),additions:Ut.trim()===""?void 0:At.encode(Ut),timestamp:b*1e3,duration:ei*1e3},vt={};t(this,_e)||(vt.decoderConfig={description:t(this,Ne)},l(this,_e,!0)),t(this,I).output(ti,vt)}}};I=new WeakMap,Pe=new WeakMap,Me=new WeakMap,Ne=new WeakMap,_e=new WeakMap,ke=new WeakSet,ft=function(e){let i=yi.exec(e);if(!i)throw new Error("Expected match.");return 60*60*1e3*Number(i[1]||"0")+60*1e3*Number(i[2])+1e3*Number(i[3])+Number(i[4])},mt=new WeakSet,Jt=function(e){let i=Math.floor(e/36e5),r=Math.floor(e%(60*60*1e3)/(60*1e3)),s=Math.floor(e%(60*1e3)/1e3),n=e%1e3;return i.toString().padStart(2,"0")+":"+r.toString().padStart(2,"0")+":"+s.toString().padStart(2,"0")+"."+n.toString().padStart(3,"0")};return di(Ti);})();
</script>
</head>
<body lang='en'>
<canvas id='pipy-canvas' width='1280' height='720' class='pipy-hidden'></canvas>
<video id='pipy-video' class='pipy-hidden'></video>
<footer class='frost-foot'>Pippy v1.0<br>© Frostbyte 2025. aGPLv3.0</footer>
<script>
/*
TODO:
Add text input
Closest by other axis
*/
const canvas = document.getElementById('pipy-canvas');
const video = document.getElementById('pipy-video');
const ctx = canvas.getContext('2d');
let focused = null;
class PipElement {
constructor(x,y,w,h,bk='red'){
this.focusable = false;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.bk = bk;
this.children = [];
this.activatebind = [];
}
draw(x,y){
ctx.fillStyle = this.bk;
ctx.fillRect((x+this.x)*canvas.width,(y+this.y)*canvas.height,(this.w)*canvas.width,(this.h)*canvas.height);
}
append(e){this.children.push(e)}
}
class PipInteractable extends PipElement{
constructor(x,y,w,h,bk='red'){
super(x,y,w,h,bk);
this.focusable = true;
this.activatebind = [];
}
activate(){
for(let i=0;i<this.activatebind.length;i++)this.activatebind[i]();
}
onactivate(f){this.activatebind.push(f)}
offactivate(f){this.activatebind.splice(this.activatebind.indexOf(f),1)}
}
class PipLabel extends PipElement {
constructor(text,x,y,w,h,bk='white',color='black',font='30px sans-serif'){
super(x,y,w,h,bk);
this.text = text;
this.color = color;
this.font = font;
}
draw(x,y){
const comx = (x+this.x)*canvas.width;
const comy = (y+this.y)*canvas.height;
const comw = this.w*canvas.width;
const comh = this.h*canvas.height;
ctx.fillStyle = this.bk;
ctx.fillRect(comx,comy,comw,comh);
ctx.fillStyle = this.color;
ctx.font = this.font;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillText(this.text,comx+comw/2,comy+comh/2);
}
}
class PipButton extends PipInteractable {
constructor(text,x,y,w,h,bk='lightgrey',color='black',font='30px sans-serif'){
super(x,y,w,h,bk);
this.text = text;
this.color = color;
this.font = font;
}
draw(x,y){
const comx = (x+this.x)*canvas.width;
const comy = (y+this.y)*canvas.height;
const comw = this.w*canvas.width;
const comh = this.h*canvas.height;
ctx.fillStyle = this.bk;
ctx.fillRect(comx,comy,comw,comh);
ctx.fillStyle = this.color;
ctx.font = this.font;
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillText(this.text,comx+comw/2,comy+comh/2);
if(focused == this){
ctx.strokeStyle = 'black';
ctx.strokeRect(comx,comy,comw,comh);
}
}
}
let val = 0;
const randBtn = new PipButton('Random',0.2,0.5,0.15,0.2,'lightgrey','black','40px Tahoma');
randBtn.onactivate(()=>val=Math.random());
const addBtn = new PipButton('+',0.4,0.5,0.1,0.1,'lightgreen');
addBtn.onactivate(()=>val++);
const subBtn = new PipButton('-',0.4,0.7,0.1,0.1,'red');
subBtn.onactivate(()=>val--);
focused = randBtn;
const labelText = new PipLabel('0',0.5,0.25,0,0,'white','black','60px monospace');
const updatebind = [()=>labelText.text=val.toString()];
const elements = [randBtn,addBtn,subBtn,labelText];
const controls = [
['🞛','#00ff00',()=>focused.activate()],
['🠈','#8aaccf',()=>{
const cur = focused;
focused = null;
for(let i=0;i<elements.length;i++){
if(elements[i].focusable && elements[i].x<cur.x && (focused ? elements[i].x>=focused.x && Math.abs(cur.y-elements[i].y) <= Math.abs(cur.y-focused.y) : true))focused = elements[i];
}
if(!focused)focused=cur;
redraw();
}],
['🠊','#8aaccf',()=>{
const cur = focused;
focused = null;
for(let i=0;i<elements.length;i++){
if(elements[i].focusable && elements[i].x>cur.x && (focused ? elements[i].x<=focused.x && Math.abs(cur.y-elements[i].y) <= Math.abs(cur.y-focused.y) : true))focused = elements[i];
}
if(!focused)focused=cur;
redraw();
}],
['🠉','#8aaccf',()=>{
const cur = focused;
focused = null;
for(let i=0;i<elements.length;i++){
if(elements[i].focusable && elements[i].y<cur.y && (focused ? elements[i].y>=focused.y && Math.abs(cur.x-elements[i].x) <= Math.abs(cur.x-focused.x) : true))focused = elements[i];
}
if(!focused)focused=cur;
redraw();
}],
['🠋','#8aaccf',()=>{
const cur = focused;
focused = null;
for(let i=0;i<elements.length;i++){
if(elements[i].focusable && elements[i].y>cur.y && (focused ? elements[i].y<=focused.y && Math.abs(cur.x-elements[i].x) <= Math.abs(cur.x-focused.x) : true))focused = elements[i];
}
if(!focused)focused=cur;
redraw();
}],
['⌨','#ff6691',()=>{alert('Not Implemented');val = 67}]
];
function drawTimeline(ind){
ctx.textBaseline = 'top';
ctx.textAlign = 'left';
ctx.font = '50px sans-serif';
for (let i=0;i<controls.length;i++) {
const h = (i==ind ? 100 : 50);
ctx.fillStyle = controls[i][1];
ctx.fillRect((i/controls.length)*canvas.width,canvas.height-h,canvas.width/controls.length,h);
ctx.fillStyle = 'black';
ctx.fillText(controls[i][0],(i/controls.length)*canvas.width,canvas.height-h)
}
}
function drawCopyright(){
ctx.textBaseline = 'top';
ctx.textAlign = 'right';
ctx.font = '20px Arial';
ctx.fillStyle = 'rgba(0,0,0,0.5)';
ctx.fillText('Pippy 1.0 © Frostbyte 2025. aGPLv3.0',canvas.width*0.95,canvas.height*0.05);
}
async function generateVideo() {
const muxer = new WebMMuxer.Muxer({
target: new WebMMuxer.ArrayBufferTarget,
video: {
codec: 'V_VP8',
width: canvas.width,
height: canvas.height
}
});
const encoder = new VideoEncoder({
output:(c,m)=>muxer.addVideoChunk(c,m),
error:e=>console.error(e)
});
encoder.configure({
codec: 'vp8',
width: canvas.width,
height: canvas.height,
bitrate: 100000,
framerate: 1
});
for(let i=0;i<updatebind.length;i++)updatebind[i]();
ctx.fillStyle = 'white';
ctx.fillRect(0,0,canvas.width,canvas.height);
for(let j=0;j<elements.length;j++){
elements[j].draw(0,0);
}
drawCopyright();
const documentImage = ctx.getImageData(0,0,canvas.width,canvas.height);
for(let i=0;i<controls.length;i++){
ctx.putImageData(documentImage,0,0);
drawTimeline(i);
const frame = new VideoFrame(canvas,{timestamp:i*1000000});
encoder.encode(frame,{keyFrame:true});
frame.close();
}
const endFrame = new VideoFrame(canvas,{timestamp:controls.length*1000000});
encoder.encode(endFrame);
endFrame.close();
await encoder.flush();
encoder.close();
muxer.finalize();
video.src = URL.createObjectURL(new Blob([muxer.target.buffer],{type:'video/webm'}));
}
async function redraw(){
const time = video.currentTime;
URL.revokeObjectURL(video.src);
await generateVideo();
video.currentTime = time;
}
generateVideo();
video.addEventListener('play',async ()=>{
controls[Math.floor(video.currentTime)][2]();
redraw();
});
document.addEventListener('click',()=>{
if(document.pictureInPictureEnabled)
video.requestPictureInPicture();
else alert('Picture in picture is not supported!');
})
window.onbeforeunload=()=>1;
</script>
</body>
</html>