Welcome to WordPress. This is your first post. Edit or delete it, then start writing!

<!doctype html>
<html lang="en">
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Video Blur 2 | truufseir.com</title>
<style>
[hidden]{display:none!important}
:root{color-scheme:dark;font-family:Segoe UI,Arial,sans-serif;background:#10141f;color:#edf0f8}*{box-sizing:border-box}body{margin:0;padding:28px;max-width:1500px;margin-inline:auto}h1{margin:0;font-size:30px}p{color:#aebbd2;line-height:1.5}header{margin-bottom:24px}.layout{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:22px}.panel{background:#1a2233;border:1px solid #33405a;border-radius:14px;padding:20px}.stage{background:#080b12;min-height:240px;display:flex;align-items:center;justify-content:center;border-radius:9px;overflow:hidden;position:relative}canvas{display:block;max-width:100%;height:auto;touch-action:none;cursor:crosshair}button,.file{background:#6988ff;color:white;border:0;border-radius:7px;padding:11px 15px;font:inherit;cursor:pointer;display:inline-block}button.secondary{background:#34415a}button.danger{background:#633445}button:disabled{opacity:.45;cursor:not-allowed}input{accent-color:#87a0ff}input[type=number]{width:100%;padding:10px;background:#0e1523;border:1px solid #485670;border-radius:6px;color:white;font:inherit}input[type=range]{width:100%}label{display:block;margin:14px 0 6px;color:#ccd5e8}.row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0}.row>*{flex:0 0 auto}.times{display:grid;grid-template-columns:1fr 1fr;gap:12px}.small{font-size:13px;color:#acbad0}.regions{display:grid;gap:8px;margin:15px 0}.region{text-align:left;background:#28334b;width:100%}.region.selected{outline:2px solid #9eb1ff}.status{min-height:44px;white-space:pre-wrap;color:#cad7fb}progress{width:100%;height:18px}a{color:#b6c5ff}#download{display:block;margin-top:16px;font-weight:bold}video{display:none}@media(max-width:850px){body{padding:16px}.layout{grid-template-columns:1fr}}
</style>
<header><h1>Video Blur 2</h1><p>Hide a face, address, or any fixed area for exactly the part of the video you choose. Your video stays on this computer.</p><label class="file">Open video<input id="file" type="file" accept="video/*" hidden></label> <span id="filename" class="small">No video loaded</span><p class="small">A video tool from <a href="https://truufseir.com/">truufseir.com</a></p></header>
<div class="layout"><main class="panel"><div class="stage"><canvas id="canvas" width="960" height="540" aria-label="Video preview. Drag to create a blur rectangle."></canvas></div><video id="video" playsinline preload="auto"></video><div class="row"><button id="play" disabled>Play</button><button id="add" class="secondary" disabled>+ Add blur</button><button id="pencil" class="secondary" disabled aria-disabled="true" title="Pencil is available in the desktop Pencil version">✎ Pencil</button><span id="clock">00:00.00 / 00:00.00</span></div><input id="seek" type="range" min="0" max="1" step="0.01" value="0" disabled aria-label="Video position"><p class="small">Drag on the video to add a blur box. Click an existing box to select it; drag it to move it. Select “Add blur” to draw over an existing box. Boxes stay in the same position; they do not track moving objects.</p><div id="status" class="status" role="status">Open a video to begin.</div><progress id="progress" value="0" max="1" hidden></progress><a id="download" hidden>Download blurred video</a></main>
<aside class="panel"><h2 style="margin-top:0">Blur regions</h2><div id="regions" class="regions"></div><div id="empty" class="small">Draw your first box on the video.</div><fieldset id="editor" disabled style="border:0;padding:0;margin:0"><div class="times"><div><label for="start">Start (seconds)</label><input id="start" type="number" min="0" step="0.01"></div><div><label for="end">End (seconds)</label><input id="end" type="number" min="0" step="0.01"></div></div><div class="row"><button id="setStart" class="secondary">Start here</button><button id="setEnd" class="secondary">End here</button></div><label for="strength">Blur strength <span id="strengthValue"></span></label><input id="strength" type="range" min="4" max="100" value="24"><div class="row"><button id="remove" class="danger">Delete region</button></div></fieldset><hr style="border:0;border-top:1px solid #34415a;margin:22px 0"><button id="export" disabled>Export blurred video</button><button id="cancel" class="danger" hidden>Cancel export</button><p class="small">WebM output, at up to 30 fps. Export runs in real time. Keep this tab visible and your computer awake until it finishes. Audio is included when the source has an audio track.</p></aside></div>
<script>"use strict";(function(){"use strict";const _vb1r=_vb0=>document.getElementById(_vb0),_vb1s=_vb1r("video"),_vb1t=_vb1r("canvas"),_vb1u=_vb1t.getContext("2d");const _vb1v=document.createElement("canvas"),_vb1w=_vb1v.getContext("2d");let _vb1x=[],_vb1y=null,_vb1z=null,_vb20=false,_vb21=false,_vb22=null,_vb23=null,_vb24,_vb25,_vb26,_vb27,_vb28=false,_vb29=null;const _vb2a=_vb1=>_vb1r("status").textContent=_vb1,_vb2b=(_vb2,_vb3,_vb4)=>Math.min(_vb4,Math.max(_vb3,_vb2));const _vb2c=_vb5=>`${String(Math.floor(_vb5/60)).padStart(2,"0")}:${(_vb5%60).toFixed(2).padStart(5,"0")}`;function _vb2d(){return _vb1x.find(_vb6=>_vb6.id===_vb1y)}function _vb2e(_vb7){return Number.isFinite(_vb7.start)&&Number.isFinite(_vb7.end)&&_vb7.start>=0&&_vb7.end>_vb7.start&&_vb7.end<=_vb1s.duration}function _vb2f(){_vb1r("regions").replaceChildren();_vb1x.forEach((_vb8,_vb9)=>{const _vba=document.createElement("button");_vba.className="region"+(_vb8.id===_vb1y?" selected":"");_vba.textContent=`${_vb9+1}. Blur • ${_vb8.start.toFixed(2)}–${_vb8.end.toFixed(2)}s`;_vba.disabled=_vb21;_vba.onclick=()=>{_vb1y=_vb8.id;_vb2f()};_vb1r("regions").append(_vba)});const _vbc=_vb2d();_vb1r("editor").disabled=!_vbc||_vb21;_vb1r("empty").hidden=!!_vb1x.length;if(_vbc){_vb1r("start").value=_vbc.start;_vb1r("end").value=_vbc.end;_vb1r("strength").value=_vbc.strength;_vb1r("strengthValue").textContent=_vbc.strength}_vb1r("export").disabled=_vb21||!_vb1x.length||_vb1x.some(_vbb=>!_vb2e(_vbb))}function _vb2g(){if(_vb1s.readyState>=2){_vb1w.filter="none";_vb1w.drawImage(_vb1s,0,0,_vb1v.width,_vb1v.height);for(const _vbh of _vb1x){if(_vb1s.currentTime<_vbh.start||_vb1s.currentTime>=_vbh.end)continue;const _vbd=_vbh.x*_vb1v.width,_vbe=_vbh.y*_vb1v.height,_vbf=_vbh.w*_vb1v.width,_vbg=_vbh.h*_vb1v.height;_vb1w.save();_vb1w.beginPath();_vb1w.rect(_vbd,_vbe,_vbf,_vbg);_vb1w.clip();_vb1w.filter=`blur(${_vbh.strength*_vb1v.width/960}px)`;_vb1w.drawImage(_vb1s,0,0,_vb1v.width,_vb1v.height);_vb1w.restore()}_vb1u.clearRect(0,0,_vb1t.width,_vb1t.height);_vb1u.drawImage(_vb1v,0,0,_vb1t.width,_vb1t.height);if(!_vb21){for(const _vbj of _vb1x){const _vbi=_vb1s.currentTime>=_vbj.start&&_vb1s.currentTime<_vbj.end;_vb1u.strokeStyle=_vbj.id===_vb1y?"#aabeff":"#ffffff";_vb1u.lineWidth=2;_vb1u.setLineDash(_vbi?[]:[6,4]);_vb1u.strokeRect(_vbj.x*_vb1t.width,_vbj.y*_vb1t.height,_vbj.w*_vb1t.width,_vbj.h*_vb1t.height)}_vb1u.setLineDash([]);if(_vb1z?.type==="draw"){_vb1u.strokeStyle="#8dffdf";_vb1u.strokeRect(_vb1z.x*_vb1t.width,_vb1z.y*_vb1t.height,(_vb1z.lastX-_vb1z.x)*_vb1t.width,(_vb1z.lastY-_vb1z.y)*_vb1t.height)}}_vb1r("seek").value=_vb1s.currentTime;_vb1r("clock").textContent=`${_vb2c(_vb1s.currentTime)} / ${_vb2c(_vb1s.duration)}`;if(_vb21)_vb1r("progress").value=_vb1s.currentTime/_vb1s.duration}requestAnimationFrame(_vb2g)}function _vb2h(_vbk){const _vbl=_vb1t.getBoundingClientRect();return{x:_vb2b((_vbk.clientX-_vbl.left)/_vbl.width,0,1),y:_vb2b((_vbk.clientY-_vbl.top)/_vbl.height,0,1)}}_vb1t.onpointerdown=_vbn=>{if(!_vb22||_vb21||!Number.isFinite(_vb1s.duration))return;_vb1s.pause();const _vbo=_vb2h(_vbn);const _vbp=_vb20?null:[..._vb1x].reverse().find(_vbm=>_vbo.x>=_vbm.x&&_vbo.x<=_vbm.x+_vbm.w&&_vbo.y>=_vbm.y&&_vbo.y<=_vbm.y+_vbm.h);_vb1t.setPointerCapture(_vbn.pointerId);if(_vbp){_vb1y=_vbp.id;_vb1z={type:"move",x:_vbo.x,y:_vbo.y,ox:_vbp.x,oy:_vbp.y};_vb2f()}else _vb1z={type:"draw",..._vbo,lastX:_vbo.x,lastY:_vbo.y}};_vb1t.onpointermove=_vbr=>{if(!_vb1z)return;const _vbs=_vb2h(_vbr);if(_vb1z.type==="move"){const _vbq=_vb2d();_vbq.x=_vb2b(_vb1z.ox+_vbs.x-_vb1z.x,0,1-_vbq.w);_vbq.y=_vb2b(_vb1z.oy+_vbs.y-_vb1z.y,0,1-_vbq.h)}else{_vb1z.lastX=_vbs.x;_vb1z.lastY=_vbs.y}};_vb1t.onpointerup=()=>{if(!_vb1z)return;if(_vb1z.type==="draw"){const _vbu=Math.abs(_vb1z.lastX-_vb1z.x),_vbv=Math.abs(_vb1z.lastY-_vb1z.y);if(_vbu*_vb1t.width>=6&&_vbv*_vb1t.height>=6){const _vbt={id:Date.now()+Math.random(),x:Math.min(_vb1z.x,_vb1z.lastX),y:Math.min(_vb1z.y,_vb1z.lastY),w:_vbu,h:_vbv,start:Math.min(_vb1s.currentTime,Math.max(0,_vb1s.duration-.01)),end:_vb1s.duration,strength:24};_vb1x.push(_vbt);_vb1y=_vbt.id;_vb2a("Blur added. Set its start and end times on the right.")}}_vb1z=null;_vb20=false;_vb2f()};_vb1t.onpointercancel=()=>{_vb1z=null};_vb1r("file").onchange=()=>{const _vbw=_vb1r("file").files[0];if(!_vbw)return;_vb1s.pause();if(_vb22)URL.revokeObjectURL(_vb22);_vb22=URL.createObjectURL(_vbw);_vb1x=[];_vb1y=null;_vb1z=null;_vb1r("download").hidden=true;_vb1r("play").disabled=true;_vb1r("add").disabled=true;_vb1r("seek").disabled=true;_vb1r("filename").textContent=_vbw.name;_vb1s.src=_vb22;_vb2a("Loading video\u2026");_vb2f()};_vb1s.onloadedmetadata=()=>{if(!Number.isFinite(_vb1s.duration)||_vb1s.duration<=0){_vb2a("This video has no usable duration. Try another file.");return}_vb1v.width=_vb1s.videoWidth;_vb1v.height=_vb1s.videoHeight;_vb1t.width=Math.min(1100,_vb1s.videoWidth);_vb1t.height=Math.round(_vb1t.width*_vb1s.videoHeight/_vb1s.videoWidth);_vb1r("seek").max=_vb1s.duration;_vb1r("start").max=_vb1s.duration;_vb1r("end").max=_vb1s.duration;_vb1r("play").disabled=false;_vb1r("add").disabled=false;_vb1r("seek").disabled=false;_vb2a("Drag a rectangle over the area you want to blur.");_vb2f()};_vb1s.onerror=()=>_vb2a("The browser could not read this video. Try an MP4 with H.264 video or a WebM file.");_vb1s.onplay=()=>_vb1r("play").textContent="Pause";_vb1s.onpause=()=>_vb1r("play").textContent="Play";_vb1r("play").onclick=async()=>{if(_vb1s.paused){if(_vb1s.ended)_vb1s.currentTime=0;try{await _vb24?.resume();await _vb1s.play()}catch(_vbx){_vb2a(_vbx.message)}}else _vb1s.pause()};_vb1r("seek").oninput=()=>{_vb1s.currentTime=Number(_vb1r("seek").value)};_vb1r("add").onclick=()=>{_vb20=true;_vb1s.pause();_vb2a("Drag on the preview to draw a new blur box.")};for(const _vb11 of["start","end","strength"])_vb1r(_vb11).oninput=()=>{const _vbz=_vb2d();if(!_vbz)return;const _vb10=_vb1r(_vb11).valueAsNumber;if(!Number.isFinite(_vb10)){_vb2a("Enter a valid number.");_vb1r("export").disabled=true;return}_vbz[_vb11]=_vb10;_vb1r("strengthValue").textContent=_vbz.strength;_vb1r("export").disabled=_vb1x.some(_vby=>!_vb2e(_vby));_vb2a(_vb2e(_vbz)?"Changes applied to preview.":"Start must be before end, and both must be within the video.")};for(const _vb12 of["start","end","strength"])_vb1r(_vb12).onchange=_vb2f;_vb1r("setStart").onclick=()=>{_vb2d().start=_vb1s.currentTime;_vb2f();_vb2a(_vb2e(_vb2d())?"Start time set.":"Start must be before end.")};_vb1r("setEnd").onclick=()=>{_vb2d().end=_vb1s.currentTime;_vb2f();_vb2a(_vb2e(_vb2d())?"End time set.":"End must be after start.")};_vb1r("remove").onclick=()=>{_vb1x=_vb1x.filter(_vb13=>_vb13.id!==_vb1y);_vb1y=_vb1x.at(-1)?.id;_vb2f()};function _vb2i(_vb18){return new Promise((_vb14,_vb15)=>{if(Math.abs(_vb1s.currentTime-_vb18)<.001&&_vb1s.readyState>=2)return _vb14();const _vb16=setTimeout(()=>{_vb1s.removeEventListener("seeked",_vb17);_vb15(new Error("Could not seek video."))},15000);function _vb17(){clearTimeout(_vb16);_vb14()}_vb1s.addEventListener("seeked",_vb17,{once:true});_vb1s.currentTime=_vb18})}function _vb2j(_vb19){_vb21=_vb19;_vb1r("file").disabled=_vb19;_vb1r("play").disabled=_vb19;_vb1r("seek").disabled=_vb19;_vb1r("add").disabled=_vb19;_vb1r("cancel").hidden=!_vb19;_vb1r("progress").hidden=!_vb19;_vb2f()}_vb1r("cancel").onclick=()=>{_vb28=true;_vb1s.pause();if(_vb27?.state!=="inactive")_vb27?.stop()};_vb1r("export").onclick=async()=>{if(_vb1x.some(_vb1a=>!_vb2e(_vb1a)))return;if(!window.MediaRecorder||!_vb1v.captureStream){_vb2a("Export requires a current version of Chrome or Edge.");return}const _vb1n=["video/webm;codecs=vp9,opus","video/webm;codecs=vp8,opus","video/webm"].find(_vb1b=>MediaRecorder.isTypeSupported(_vb1b));if(!_vb1n){_vb2a("This browser does not support WebM recording. Open this app in Chrome or Edge.");return}const _vb1o=_vb1s.currentTime;let _vb1p,_vb1q;_vb28=false;_vb2j(true);_vb1r("download").hidden=true;_vb2a("Exporting\u2026 Keep this tab visible until the download is ready.");try{_vb1s.pause();await _vb2i(0);if(!_vb24){_vb24=new AudioContext;_vb25=_vb24.createMediaElementSource(_vb1s);_vb26=_vb24.createMediaStreamDestination();_vb25.connect(_vb26);_vb25.connect(_vb24.destination)}await _vb24.resume();_vb1w.filter="none";_vb1w.drawImage(_vb1s,0,0,_vb1v.width,_vb1v.height);await new Promise(_vb1c=>requestAnimationFrame(()=>requestAnimationFrame(_vb1c)));_vb1p=_vb1v.captureStream(30);for(const _vb1d of _vb26.stream.getAudioTracks())_vb1p.addTrack(_vb1d.clone());_vb27=new MediaRecorder(_vb1p,{mimeType:_vb1n,videoBitsPerSecond:Math.max(4000000,Math.min(24000000,_vb1v.width*_vb1v.height*5))});const _vb1j=[];const _vb1k=new Promise((_vb1g,_vb1h)=>{_vb27.ondataavailable=_vb1e=>{if(_vb1e.data.size)_vb1j.push(_vb1e.data)};_vb27.onstop=_vb1g;_vb27.onerror=_vb1f=>_vb1h(_vb1f.error||new Error("Recording failed"))});_vb1q=()=>{if(_vb27.state!=="inactive")_vb27.stop()};_vb1s.addEventListener("ended",_vb1q,{once:true});try{_vb29=await navigator.wakeLock?.request("screen")}catch{}_vb27.start(1000);await _vb1s.play();await _vb1k;if(_vb28)_vb2a("Export cancelled. You can keep editing.");else{const _vb1i=new Blob(_vb1j,{type:"video/webm"});if(!_vb1i.size)throw new Error("No video was recorded.");if(_vb23)URL.revokeObjectURL(_vb23);_vb23=URL.createObjectURL(_vb1i);_vb1r("download").href=_vb23;_vb1r("download").download=(_vb1r("file").files[0]?.name||"video").replace(/\.[^.]+$/,"")+"-blurred.webm";_vb1r("download").hidden=false;_vb1r("download").textContent=`Download blurred video (${(_vb1i.size/1048576).toFixed(1)} MB)`;_vb2a("Export complete. Click the download link to save your video.")}}catch(_vb1l){_vb2a("Export failed: "+_vb1l.message)}finally{if(_vb1q)_vb1s.removeEventListener("ended",_vb1q);_vb1s.pause();if(_vb27&&_vb27.state!=="inactive")_vb27.stop();_vb1p?.getTracks().forEach(_vb1m=>_vb1m.stop());await _vb29?.release();_vb29=null;_vb2j(false);try{await _vb2i(_vb1o)}catch{}}};document.addEventListener("visibilitychange",()=>{if(_vb21&&document.hidden){_vb28=true;_vb1s.pause();if(_vb27?.state!=="inactive")_vb27?.stop();_vb2a("Export interrupted because the tab was hidden. Keep the tab visible and export again.")}});_vb2g()})();</script>
</html>