Miksi videosi esikatselu valehtelee viennin suhteen
Videoeditorisi näyttää valmiilta. Esikatselu on terävä, tekstitykset ovat juuri siinä, mihin käyttäjä ne raahasi, ja aikajana selaa sujuvasti. Sitten käyttäjä painaa Export-nappia, ja tekstitys ilmestyy väärään paikkaan, vääränkokoisena, joskus jopa kokonaan leikattuna reunan yli. Mikään ei kaatunut, lokissa ei ole virhettä – esikatselu ja tiedosto ovat yksinkertaisesti eri mieltä.
Tämä on yleisin virhe jokaisessa videoeditorissa, ja se on ennemmin datamallinnusongelma kuin renderöintiongelma. Alla on tapa, joka tekee tästä virheestä mahdottoman, miten kehykset mitoitetaan oikein kuvasuhteen perusteella ja miten raahaaminen pysyy nopeana edullisissakin puhelimissa. Ideat soveltuvat mihin tahansa kieleen tai UI-kehykseen.
Kuvasuhde on muoto, resoluutio on koko
Useimmat kehysvirheet alkavat tästä. Kuvasuhde kuvaa kehyksen muotoa eikä mitään muuta: 9:16 on pystysuuntainen, 16:9 on vaakasuuntainen. Resoluutio kuvaa kokoa pikseleinä, kuten 1080x1920. Yksi muoto tukee monia kokoja, joten näitä kahta arvoa ei voi koskaan vaihtaa keskenään.
| Kuvasuhde | Numeerinen arvo | Tyypillinen käyttö |
| 16:9 | 1.78 | YouTube, vaakasuuntainen verkko |
| 9:16 | 0.56 | Reels, TikTok, Shorts |
| 1:1 | 1.00 | Neliönmuotoiset syötepostaukset |
| 4:5 | 0.80 | Pystysuuntaiset syötepostaukset |
Tallenna kuvasuhde pelkkänä tekstinä ja muunna se luvuksi vain matemaattisia operaatioita tehdessäsi. Tallenna viennille tavoitekorkeus ja johda sitten leveys kuvasuhteesta. Pakota molemmat luvut parillisiksi ennen kuin ne saavuttavat enkooderin. Parittomat mitat ovat yllättävän monien epäonnistuneiden vientien hiljainen syy.
height = width / ratioToNumber(ratio) // sizing the preview box
function widthFromHeight(ratio, height): raw = height * ratioToNumber(ratio) return makeEven(round(raw)) // encoders require even sides
// 9:16 at 1080 tall -> 608 x 1080// 16:9 at 1080 tall -> 1920 x 1080
Tallenna sijainnit murtolukuina, ei koskaan pikseleinä
Editori elää kolmessa maailmassa kolmessa eri koossa: tallennettu dokumentti, näytön esikatselu ja viety tiedosto. Dokumentti on ainoa totuuden lähde – kaksi muuta ovat vain sen renderöintejä eri mittakaavassa.
Project -> Clip (source, trim, filters) -> Overlay (text / sticker)
Document Preview renderer Export renderer x = 0.5, y = 0.9 --> x * 360 px --> x * 1080 px --> MP4 | ^ ^ +------------------------+------------------------+ yksi tallennettu murtoluku, yksi kaava, kaksi kokoa
Jos tallennat 540 pikseliä, tämä luku on oikea vain laitteella, jolla se mitattiin. Jos tallennat 0.5, se tarkoittaa "vaakasuuntaista keskikohtaa" kaikissa koissa ikuisesti. Jokaisen sijainnin, siirtymän ja skaalan mallissa tulisi olla murtoluku välillä 0 ja 1.
type Overlay { x: number // 0.0-1.0 leveydeltä (0.5 = keskellä) y: number // 0.0-1.0 korkeudelta (0.9 = lähellä pohjaa) scale: number // 1.0 = normaali koko rotation: number // asteina startTimeMs: number // milloin se ilmestyy endTimeMs: number // milloin se katoaa}
Vienti muuttuu sitten melkein tylsäksi, mikä onkin tarkoitus. Renderöijä käyttää samaa kaavaa kuin esikatselu suuremmalla kertoimella: px = overlay.x * exportWidth. FFmpeg käsittelee itse kehyksen, ja sen keskityslauseke (ow-iw)/2 on samaa aritmetiikkaa, jota esikatselu käyttää letterbox-efektiin. Koska tallennettu arvo ei koskaan muuttunut, tekstitys asettuu täsmälleen oikeaan paikkaan.
ffmpeg -i input.mp4 \ -vf "scale=1080:1920:force_original_aspect_ratio=decrease,\ pad=1080:1920:(ow-iw)/2:(oh-ih)/2:0xD3D3D3" \ -c:v libx264 -crf 23 -pix_fmt yuv420p -c:a aac output.mp4
Piirrä esikatselu yhdellä kierroksella
Mittaa esikatselulaatikko ajon aikana sen sijaan, että koodaisit sen kiinteästi, sillä puhelin, tabletti ja uudelleenkokoinen työpöytäikkuna antavat kaikki eri koon. Piirrä jokainen overlay yhdellä canvas-kierroksella sen sijaan, että asettaisit jokaisen erilliseksi UI-elementiksi – yksi kierros pysyy sulavana sormen liikkuessa.
Kaksi sääntöä pitävät silmukan rehellisenä. Ohita kaikki overlayt, jotka ovat aikavälinsä ulkopuolella, ja yhdistä aina save() ja restore(), jotta yksi elementti ei voi vuotaa muunnostaan seuraavaan.
function drawPreview(canvas, overlays, currentTime, box): for each overlay in overlays: if currentTime < overlay.startTimeMs: skip if currentTime > overlay.endTimeMs: skip
px = overlay.x * box.width // avainkaava py = overlay.y * box.height
canvas.save() canvas.move(px, py) canvas.rotate(overlay.rotation) canvas.resize(overlay.scale) canvas.drawText(overlay.content) canvas.restore() // ei koskaan valinnainen
Pidä raahaaminen sujuvana kaksitasoisella tilalla
Raahaava sormi ilmoittaa noin kuusikymmentä sijaintia sekunnissa. Jos jokainen niistä kirjoittaa projektitallennukseen, maksat validoinnista, pysyvyydestä ja täydellisestä tilan uudelleenrakentamisesta kuusikymmentä kertaa sekunnissa, ja raahaaminen nykii näkyvästi. Jaa työ sen sijaan kahteen tasoon:
- Taso 1, lyhytikäinen: pieni
liveDrag-kartta, joka sisältää sormen nykyisen sijainnin. Päivitä se jokaisella liikkeellä ja maalaa canvas uudelleen. Mikään muu ei käynnisty. - Taso 2, kestävä: raahaamisen päättyessä tallenna lopullinen murtoluku overlaylle projektimalliin, tyhjennä
liveDrag-merkintä ja tallenna yksi kumoa-vaihe.
Hyöty ulottuu ruutunopeuden yli. Kumoa-historia pysyy hyödyllisenä, koska raahaus tuottaa yhden merkinnän satojen sijaan, ja automaattinen tallennus lopettaa levyn piiskaamisen. Näin Figma ja Canva pitävät suoran manipuloinnin responsiivisena.
Reaalimaailman konteksti
MicrocosmWorksilla otimme käyttöön lyhytmuotoisen editorin, jonka tekstitykset siirtyilivät viennin yhteydessä. Tiimi oli tallentanut overlay-sijainnit laitteen pikseleinä, jotka oli luettu suoraan esikatselu-canvasilta, joten pienellä puhelimella tehty tekstitys ilmestyi korkealle ja pienenä 1080p-tiedostoon, ja kuvasuhteen vaihtaminen työnsi joitakin overlayta kokonaan pois kehyksestä.
Siirsimme mallin normalisoituihin 0–1-koordinaatteihin, saimme molemmat renderöijät jakamaan yhden murtoluku-kertaa-koko -apuohjelman ja pakotimme tallennetusta suhteesta johdetut parilliset ulostulomitat. Esikatselu ja vienti täsmäsivät jokaisella testilaitteella. Raahaustoimintojen siirtäminen raahauksen loppuun poisti viiveen, josta käyttäjät olivat raportoineet heikompitehoisilla Android-laitteilla. Voit nähdä, millaisia lyhytmuotoisia videoita ja editointitöitä tästä on syntynyt projektisalkussamme.
Yhteenveto
Esikatselu ja vienti ovat kaksi saman dokumentin renderöintiä, joten anna niille yksi totuuden lähde. Tallenna sijainnit murtolukuina, käytä samaa murtoluku-kertaa-koko -kaavaa molemmissa renderöijissä, johda leveys kuvasuhteesta, pidä mitat tasaisina ja tallenna raahaamisen muutokset vasta kun sormi nousee. Nämä viisi tapaa poistavat kokonaisen virhekategorian jo ennen sen syntymistä.
Medianmoottorien rakentaminen, joissa interaktiivinen näkymä ja lopullinen tiedosto ovat yhtäpitäviä, on MicrocosmWorksin video- ja streaming-tekniikkamme ydinosaamista.
Oletko julkaisemassa video- tai sisällöneditoria ja haluatko, että esikatselu ja vienti todella vastaavat toisiaan? Olemme ratkaisseet tämän tarkan virheluokan lyhytmuotoisissa editointityökaluissa. Ota yhteyttä insinööritiimiimme →
Lue lisää tiimiltämme
1. Kanavan logon optimointi eri videoresoluutioille
2. Kuvaa lautanen, kirjaa ateria: Tietokonenäön ravitsemusputki

