1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="utf-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1"> 6<title>Qwen-Video-Edit â Instruction-based video editing by repurposing an image editing model</title> 7<link rel="preconnect" href="https://fonts.googleapis.com"> 8<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;800&family=JetBrains+Mono:wght@500&display=swap" rel="stylesheet"> 9<style> 10:root{ 11 --ink:#191a23; --muted:#5c5f70; --bg:#fbfaf8; --card:#ffffff; 12 --line:#e8e6e1; --accent:#5b5bd6; --accent2:#d6409f; 13 --grad:linear-gradient(92deg,#5b5bd6 0%,#8e4ec6 55%,#d6409f 100%); 14 --shadow:0 1px 2px rgba(25,26,35,.05),0 12px 32px -12px rgba(25,26,35,.14); 15} 16*{box-sizing:border-box;margin:0;padding:0} 17html{scroll-behavior:smooth} 18body{font-family:Inter,system-ui,-apple-system,sans-serif;background:var(--bg);color:var(--ink);line-height:1.65} 19.wrap{max-width:1120px;margin:0 auto;padding:0 24px} 20a{color:var(--accent);text-decoration:none} 21a:hover{text-decoration:underline} 22 23/* ---------- hero header ---------- */ 24header{padding:72px 0 36px;text-align:center;background: 25 radial-gradient(900px 420px at 50% -160px, rgba(91,91,214,.10), transparent 70%), 26 radial-gradient(700px 380px at 82% -60px, rgba(214,64,159,.07), transparent 70%)} 27h1.title{font-size:clamp(34px,5.4vw,58px);font-weight:800;letter-spacing:-.02em;line-height:1.15} 28.strike{position:relative;display:inline-block;color:var(--muted)} 29.strike::after{content:"";position:absolute;left:-2%;right:-2%;top:54%;height:.09em;border-radius:2px; 30 background:var(--accent2);transform:scaleX(0);transform-origin:left center;animation:strike .5s .7s ease-out forwards;rotate:-4deg} 31@keyframes strike{to{transform:scaleX(1)}} 32.videoword{position:relative;display:inline-block;background:var(--grad); 33 -webkit-background-clip:text;background-clip:text;color:transparent; 34 opacity:0;translate:0 .35em;animation:pop .55s 1.15s cubic-bezier(.2,1.4,.4,1) forwards} 35@keyframes pop{to{opacity:1;translate:0 0}} 36.subtitle{margin-top:14px;font-size:clamp(16px,2vw,21px);color:var(--muted);font-weight:500} 37.authors{margin-top:16px;font-size:clamp(15px,1.8vw,19px);color:var(--ink);font-weight:600} 38.authors span{margin:0 10px;white-space:nowrap} 39.authors a{color:inherit;text-decoration:none;border-bottom:1.5px solid var(--accent)} 40.authors a:hover{color:var(--accent)} 41.byline{margin-top:10px;color:var(--muted);font-size:14.5px} 42.btns{margin-top:26px;display:flex;gap:12px;justify-content:center;flex-wrap:wrap} 43.btn{display:inline-flex;align-items:center;gap:8px;padding:10px 20px;border-radius:999px;font-weight:600;font-size:15px; 44 border:1.5px solid var(--line);background:var(--card);color:var(--ink);box-shadow:var(--shadow);transition:.15s} 45.btn:hover{border-color:var(--accent);text-decoration:none;translate:0 -1px} 46.btn.primary{background:var(--grad);color:#fff;border:none} 47 48/* ---------- sections ---------- */ 49section{padding:44px 0} 50h2{font-size:clamp(24px,3vw,32px);font-weight:800;letter-spacing:-.01em;margin-bottom:8px} 51.sec-sub{color:var(--muted);margin-bottom:26px;max-width:820px} 52.center{text-align:center}.center .sec-sub{margin-left:auto;margin-right:auto} 53 54/* ---------- comparison slider ---------- */ 55.cmp{position:relative;border-radius:16px;overflow:hidden;background:#111;box-shadow:var(--shadow); 56 user-select:none;-webkit-user-select:none;touch-action:pan-y} 57.cmp video{display:block;width:100%;height:auto;pointer-events:none} 58.cmp .after-wrap{position:absolute;inset:0} 59.cmp .divider{position:absolute;top:0;bottom:0;width:2px;background:rgba(255,255,255,.9);box-shadow:0 0 8px rgba(0,0,0,.35);cursor:ew-resize} 60.cmp .handle{position:absolute;top:50%;left:50%;translate:-50% -50%;width:26px;height:26px;border-radius:50%; 61 background:rgba(255,255,255,.75);backdrop-filter:blur(2px);box-shadow:0 1px 6px rgba(0,0,0,.3); 62 display:flex;align-items:center;justify-content:center;font-size:10px;color:#444;font-weight:700; 63 transition:opacity .3s;opacity:.85} 64.cmp:hover .handle{opacity:1} 65.cmp .tag{position:absolute;top:10px;padding:4px 11px;border-radius:999px;font-size:12px;font-weight:700; 66 background:rgba(255,255,255,.92);color:#333;pointer-events:none} 67.cmp .tag.before{left:10px}.cmp .tag.after{right:10px} 68
69/* ---------- hero videos ---------- */ 70/* Landscape slightly narrower than the exact equal-height ratio (3.82:1); 71 the taller portrait gets more width and the landscape card is vertically 72 centered against it. */ 73.heroWrap{max-width:1240px} 74.heroGrid{display:grid;grid-template-columns:2.9fr 1fr;gap:26px;align-items:center} 75@media(max-width:840px){.heroGrid{grid-template-columns:1fr}} 76.heroCard .cap{margin-top:10px;color:var(--muted);font-size:14px;text-align:center} 77 78/* ---------- gallery ---------- */ 79.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(310px,1fr));gap:22px} 80.card{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:12px;box-shadow:var(--shadow)} 81.prompt{margin-top:10px;font-size:14px;color:var(--ink)} 82.prompt b{color:var(--accent)} 83.empty{padding:40px;text-align:center;color:var(--muted);border:2px dashed var(--line);border-radius:18px} 84 85/* ---------- method ---------- */ 86.methodCard{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:28px;box-shadow:var(--shadow)} 87.flow{display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-content:center;margin:22px 0 6px} 88.node{padding:10px 16px;border-radius:12px;font-size:13.5px;font-weight:600;border:1.5px solid var(--line);background:#fff} 89.node.frozen{border-style:dashed;color:var(--muted)} 90.node.train{background:linear-gradient(92deg,rgba(91,91,214,.10),rgba(214,64,159,.10));border-color:var(--accent)} 91.arrow{color:var(--muted);font-weight:700} 92.legend{display:flex;gap:18px;justify-content:center;margin-top:14px;font-size:12.5px;color:var(--muted)} 93.dotT{display:inline-block;width:10px;height:10px;border-radius:3px;background:linear-gradient(92deg,rgba(91,91,214,.5),rgba(214,64,159,.5));margin-right:6px} 94.dotF{display:inline-block;width:10px;height:10px;border-radius:3px;border:1.5px dashed var(--muted);margin-right:6px} 95 96/* ---------- bibtex / footer ---------- */ 97pre.bib{background:#f4f2ee;border:1px solid var(--line);border-radius:14px;padding:20px;overflow-x:auto; 98 font-family:"JetBrains Mono",monospace;font-size:13px;line-height:1.6} 99footer{padding:44px 0 60px;color:var(--muted);font-size:14px;text-align:center;border-top:1px solid var(--line);margin-top:30px} 100</style> 101</head> 102<body> 103 104<header> 105 <div class="wrap"> 106 <h1 class="title">Qwen-<span class="strike">Image</span> <span class="videoword">Video</span>-Edit</h1> 107 <p class="subtitle">Instruction-based video editing by repurposing an image editing model</p> 108 <p class="authors"><span><a href="https://yunpeng1998.github.io/">Yunpeng Bai</a></span><span>Yossi Gandelsman</span><span>Michaël Gharbi</span><span>Qixing Huang</span></p> 109 <p class="byline">No video-pretrained transformer required â an image editing DiT edits video-VAE latents directly.</p> 110 <div class="btns"> 111 <a class="btn primary" href="https://arxiv.org/abs/2608.14790">ð Report</a> <!-- TODO: arXiv link --> 112 <a class="btn" href="https://github.com/yunpeng1998/Qwen-Video-Edit">Code</a> 113 <a class="btn" href="https://huggingface.co/yunpeng1998/Qwen-Video-Edit">ð¤ Model</a> 114 <a class="btn" href="#method">Method</a> 115 </div> 116 </div> 117</header> 118 119<section> 120 <div class="wrap heroWrap"> 121 <div class="heroGrid"> 122 <div class="heroCard"> 123 <div class="cmp" data-before="assets/hero2_before.mp4" data-after="assets/hero2_after.mp4"></div> 124 <p class="cap">Long-video editing â every 45-frame segment edited with a <em>different</em> instruction. Drag to compare.</p> 125 </div> 126 <div class="heroCard"> 127 <div class="cmp" data-before="assets/hero1_before.mp4" data-after="assets/hero1_after.mp4"></div> 128 <p class="cap">Portrait videos supported natively (aspect-preserving).</p> 129 </div> 130 </div> 131 </div> 132</section> 133 134<section id="method"> 135 <div class="wrap"> 136 <h2>How it works</h2> 137 <p class="sec-sub"> 138 Video generation models read and write <b>video-VAE latents</b>. We teach 139 <a href="https://huggingface.co/Qwen/Qwen-Image-Edit">Qwen-Image-Edit</a>'s transformer to edit those latents 140 directly: two tiny projections bridge Wan 2.1's latent space into the DiT's token space, warm-started from the 141 DiT's own input/output layers so that a <em>static</em> video is embedded exactly like an image the model already 142 understands. The latent frames are arranged as tiles of one big virtual image â the same positional treatment the
143 image model was pretrained on. Fine-tuned with LoRA or full parameters on 144 <a href="https://github.com/EzioBy/Ditto">Ditto-1M</a> (source, edited, instruction) triplets, then refined by a 145 few steps of Wan 2.2 denoising-enhancement. 146 </p> 147 <div class="methodCard"> 148 <div class="flow"> 149 <span class="node frozen">Source video</span><span class="arrow">â</span> 150 <span class="node frozen">Wan 2.1 VAE â</span><span class="arrow">â</span> 151 <span class="node train">In-projection ð¥</span><span class="arrow">â</span> 152 <span class="node train">Qwen-Image-Edit DiT ð¥<br><small>grid RoPE over latent frames · prompt via Qwen2.5-VL</small></span><span class="arrow">â</span> 153 <span class="node train">Out-projection ð¥</span><span class="arrow">â</span> 154 <span class="node frozen">Wan 2.1 VAE â</span><span class="arrow">â</span> 155 <span class="node frozen">Wan 2.2 enhance â</span><span class="arrow">â</span> 156 <span class="node frozen">Edited video</span> 157 </div> 158 <div class="legend"><span><span class="dotT"></span>trained (LoRA / full FT)</span><span><span class="dotF"></span>frozen</span></div> 159 </div> 160 </div> 161</section> 162 163<section> 164 <div class="wrap center"> 165 <h2>Results</h2> 166 <p class="sec-sub">Drag the divider on any clip to compare the original (left) with the edited result (right).</p> 167 <div class="grid" id="gallery"></div> 168 <div class="empty" id="galleryEmpty" style="display:none"> 169 Gallery is empty â drop <code>{name}_enhanced_f4b4.mp4 / {name}_input.mp4 / {name}.txt</code> triples into 170 <code>assets/gallery/</code> and run <code>python build_gallery.py</code>. 171 </div> 172 </div> 173</section> 174 175<section> 176 <div class="wrap"> 177 <h2>BibTeX</h2> 178<pre class="bib">@misc{qwenvideoedit2026, 179 title = {Qwen-Video-Edit: Instruction-based Video Editing by Repurposing an Image Editing Model}, 180 author = {Yunpeng Bai, Yossi Gandelsman, Michaël Gharbi, Qixing Huang}, 181 year = {2026}, 182 url = {https://github.com/yunpeng1998/Qwen-Video-Edit} 183}</pre> 184 </div> 185</section> 186 187<footer> 188 Built on <a href="https://github.com/modelscope/DiffSynth-Studio">DiffSynth-Studio</a>, 189 <a href="https://huggingface.co/Qwen/Qwen-Image-Edit-2511">Qwen-Image-Edit</a>, 190 <a href="https://github.com/Wan-Video">Wan 2.1 / 2.2</a> and 191 <a href="https://github.com/EzioBy/Ditto">Ditto</a>. 192</footer> 193
194<script src="assets/gallery.js"></script>
vendor: 1 bytes, line 194
194
195<script> 196/* ---------- before/after comparison slider with frame-synced videos ---------- */ 197function buildCompare(el){ 198 const before=document.createElement("video"), after=document.createElement("video"); 199 for(const v of [before,after]){v.muted=true;v.loop=true;v.playsInline=true;v.setAttribute("playsinline","");v.preload="metadata";} 200 before.src=el.dataset.before; after.src=el.dataset.after; 201 const wrapA=document.createElement("div"); wrapA.className="after-wrap"; wrapA.appendChild(after); 202 const divider=document.createElement("div"); divider.className="divider"; 203 const handle=document.createElement("div"); handle.className="handle"; handle.textContent="ââ¸"; 204 divider.appendChild(handle); 205 const tagB=document.createElement("span"); tagB.className="tag before"; tagB.textContent="Original"; 206 const tagA=document.createElement("span"); tagA.className="tag after"; tagA.textContent="Edited"; 207 el.append(before,wrapA,divider,tagB,tagA); 208 209 let pos=0.5; 210 function render(){ 211 wrapA.style.clipPath=`inset(0 0 0 ${pos*100}%)`; 212 divider.style.left=`calc(${pos*100}% - 1.25px)`; 213 } 214 render(); 215 function setFromEvent(e){ 216 const r=el.getBoundingClientRect(); 217 pos=Math.min(1,Math.max(0,(e.clientX-r.left)/r.width)); 218 render(); 219 } 220 let dragging=false; 221 el.addEventListener("pointerdown",e=>{dragging=true;el.setPointerCapture(e.pointerId);setFromEvent(e);}); 222 el.addEventListener("pointermove",e=>{if(dragging)setFromEvent(e);}); 223 el.addEventListener("pointerup",()=>dragging=false); 224 el.addEventListener("pointercancel",()=>dragging=false); 225 226 /* keep the two videos frame-locked: 'before' is the clock */ 227 function tick(){ 228 if(!before.paused && Math.abs(after.currentTime-before.currentTime)>0.08){ 229 after.currentTime=before.currentTime; 230 } 231 requestAnimationFrame(tick); 232 } 233 requestAnimationFrame(tick); 234 235 /* play only while on screen (dozens of videos on one page) */ 236 new IntersectionObserver(entries=>{ 237 for(const en of entries){ 238 if(en.isIntersecting){before.play().catch(()=>{});after.play().catch(()=>{});} 239 else{before.pause();after.pause();} 240 } 241 },{threshold:0.15}).observe(el); 242} 243 244document.querySelectorAll(".cmp").forEach(buildCompare); 245 246/* ---------- gallery from manifest ---------- */ 247const gallery=document.getElementById("gallery"); 248const items=(window.GALLERY||[]); 249if(items.length===0){document.getElementById("galleryEmpty").style.display="block";} 250for(const item of items){ 251 const card=document.createElement("div"); card.className="card"; 252 const cmp=document.createElement("div"); cmp.className="cmp"; 253 cmp.dataset.before=item.before; cmp.dataset.after=item.after; 254 card.appendChild(cmp); 255 if(item.prompt){ 256 const p=document.createElement("p"); p.className="prompt"; 257 p.innerHTML="<b>Prompt:</b> "; 258 p.appendChild(document.createTextNode(item.prompt)); 259 card.appendChild(p); 260 } 261 gallery.appendChild(card); 262 buildCompare(cmp); 263} 264</script>
264 265</body> 266</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.