Atraskite WebCodecs galią! Išsamus vadovas, kaip pasiekti ir manipuliuoti vaizdo kadrų duomenimis naudojant VideoFrame plokštumas. Sužinokite apie pikselių formatus ir pažangų vaizdo apdorojimą naršyklėje.
WebCodecs VideoFrame plokštuma: išsami vaizdo kadro duomenų prieigos analizė
WebCodecs reiškia paradigmos pokytį žiniatinklio medijos apdorojime. Jis suteikia žemo lygio prieigą prie medijos sudedamųjų dalių, leisdamas kūrėjams kurti sudėtingas programas tiesiogiai naršyklėje. Viena galingiausių WebCodecs funkcijų yra VideoFrame objektas, o jame esančios VideoFrame plokštumos, kurios atveria neapdorotus vaizdo kadrų pikselių duomenis. Šiame straipsnyje pateikiamas išsamus vadovas, kaip suprasti ir naudoti VideoFrame plokštumas pažangiam vaizdo manipuliavimui.
VideoFrame objekto supratimas
Prieš gilinantis į plokštumas, prisiminkime patį VideoFrame objektą. VideoFrame atspindi vieną vaizdo kadrą. Jame yra dekoduoti (arba užkoduoti) vaizdo duomenys kartu su susijusiais metaduomenimis, tokiais kaip laiko žymė, trukmė ir formato informacija. VideoFrame API siūlo metodus:
- Pikselių duomenų skaitymas: Čia ir pasirodo plokštumos.
- Kadrų kopijavimas: Naujų
VideoFrameobjektų kūrimas iš esamų. - Kadrų uždarymas: Atlaisvinami kadro laikomi pagrindiniai resursai.
VideoFrame objektas sukuriamas dekodavimo proceso metu, paprastai naudojant VideoDecoder, arba rankiniu būdu, kuriant individualų kadrą.
Kas yra VideoFrame plokštumos?
VideoFrame pikselių duomenys dažnai yra suskirstyti į kelias plokštumas, ypač formatuose, tokiuose kaip YUV. Kiekviena plokštuma atspindi skirtingą vaizdo komponentą. Pavyzdžiui, YUV420 formate yra trys plokštumos:
- Y (Luma): Atspindi vaizdo ryškumą (šviesumą). Šioje plokštumoje yra pilkumo tonų informacija.
- U (Cb): Atspindi mėlynos spalvos skirtumo chromatinį komponentą.
- V (Cr): Atspindi raudonos spalvos skirtumo chromatinį komponentą.
RGB formatai, nors ir atrodo paprastesni, kai kuriais atvejais taip pat gali naudoti kelias plokštumas. Plokštumų skaičius ir jų reikšmė visiškai priklauso nuo VideoFrame VideoPixelFormat.
Plokštumų naudojimo privalumas yra tas, kad tai leidžia efektyviai pasiekti ir manipuliuoti konkrečiais spalvų komponentais. Pavyzdžiui, galite norėti koreguoti tik šviesumą (Y plokštumą), nepaveikiant spalvos (U ir V plokštumų).
Prieiga prie VideoFrame plokštumų: API
VideoFrame API suteikia šiuos metodus prieigai prie plokštumų duomenų:
copyTo(destination, options): NukopijuojaVideoFrameturinį į paskirties vietą, kuri gali būti kitasVideoFrame,CanvasImageBitmaparbaArrayBufferView.optionsobjektas kontroliuoja, kurios plokštumos ir kaip kopijuojamos. Tai yra pagrindinis mechanizmas prieigai prie plokštumų.
options objektas copyTo metode leidžia nurodyti vaizdo kadro duomenų išdėstymą ir paskirties vietą. Pagrindinės savybės apima:
format: Norimas nukopijuotų duomenų pikselių formatas. Tai gali būti tas pats formatas kaip ir originalausVideoFramearba kitas formatas (pvz., konvertuojant iš YUV į RGB).codedWidthircodedHeight: Vaizdo kadro plotis ir aukštis pikseliais.layout: Objektų masyvas, aprašantis kiekvienos plokštumos išdėstymą atmintyje. Kiekvienas masyvo objektas nurodo:offset: Poslinkis baitais nuo duomenų buferio pradžios iki plokštumos duomenų pradžios.stride: Baitų skaičius tarp kiekvienos eilutės pradžios plokštumoje. Tai labai svarbu tvarkant užpildymą (padding).
Pažvelkime į YUV420 VideoFrame kopijavimo į neapdorotą buferį pavyzdį:
async function copyYUV420ToBuffer(videoFrame, buffer) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
// YUV420 turi 3 plokštumas: Y, U ir V
const yPlaneSize = width * height;
const uvPlaneSize = width * height / 4;
const layout = [
{ offset: 0, stride: width }, // Y plokštuma
{ offset: yPlaneSize, stride: width / 2 }, // U plokštuma
{ offset: yPlaneSize + uvPlaneSize, stride: width / 2 } // V plokštuma
];
await videoFrame.copyTo(buffer, {
format: 'I420',
codedWidth: width,
codedHeight: height,
layout: layout
});
videoFrame.close(); // Svarbu atlaisvinti resursus
}
Paaiškinimas:
- Apskaičiuojame kiekvienos plokštumos dydį pagal
widthirheight. Y yra pilnos raiškos, o U ir V yra sumažintos raiškos (4:2:0). layoutmasyvas apibrėžia atminties išdėstymą.offsetnurodo, kur kiekviena plokštuma prasideda buferyje, ostridenurodo baitų skaičių, kurį reikia peršokti, norint pasiekti kitą eilutę toje plokštumoje.formatparinktis nustatyta į 'I420', kuris yra įprastas YUV420 formatas.- Svarbiausia, kad po kopijavimo yra iškviečiamas
videoFrame.close(), kad būtų atlaisvinti resursai.
Pikselių formatai: galimybių pasaulis
Pikselių formatų supratimas yra būtinas dirbant su VideoFrame plokštumomis. VideoPixelFormat apibrėžia, kaip spalvų informacija yra užkoduota vaizdo kadre. Štai keletas įprastų pikselių formatų, su kuriais galite susidurti:
- I420 (YUV420p): Planarinis YUV formatas, kuriame Y, U ir V komponentai saugomi atskirose plokštumose. U ir V raiška sumažinta 2 kartus tiek horizontaliai, tiek vertikaliai. Tai labai įprastas ir efektyvus formatas.
- NV12 (YUV420sp): Pusiau planarinis YUV formatas, kuriame Y saugomas vienoje plokštumoje, o U ir V komponentai yra sujungti antroje plokštumoje.
- RGBA: Raudonos, žalios, mėlynos ir alfa komponentai saugomi vienoje plokštumoje, paprastai su 8 bitais kiekvienam komponentui (32 bitai vienam pikseliui). Komponentų tvarka gali skirtis (pvz., BGRA).
- RGB565: Raudonos, žalios ir mėlynos spalvos komponentai saugomi vienoje plokštumoje su 5 bitais raudonai, 6 bitais žaliai ir 5 bitais mėlynai (16 bitų vienam pikseliui).
- GRAYSCALE: Atspindi pilkumo tonų vaizdus su viena šviesumo (brightness) reikšme kiekvienam pikseliui.
VideoFrame.format savybė jums pasakys konkretaus kadro pikselių formatą. Būtinai patikrinkite šią savybę prieš bandydami pasiekti plokštumas. Visą palaikomų formatų sąrašą galite rasti WebCodecs specifikacijoje.
Praktiniai panaudojimo atvejai
Prieiga prie VideoFrame plokštumų atveria platų galimybių spektrą pažangiam vaizdo apdorojimui naršyklėje. Štai keletas pavyzdžių:
1. Realaus laiko vaizdo efektai
Galite taikyti realaus laiko vaizdo efektus manipuliuodami pikselių duomenimis VideoFrame. Pavyzdžiui, galėtumėte įdiegti pilkumo tonų filtrą, apskaičiuodami R, G ir B komponentų vidurkį kiekviename RGBA kadro pikseliuje ir tada nustatydami visus tris komponentus šia vidutine reikšme. Taip pat galite sukurti sepijos tono efektą arba reguliuoti ryškumą ir kontrastą.
async function applyGrayscale(videoFrame) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
const buffer = new ArrayBuffer(width * height * 4); // RGBA
const rgba = new Uint8ClampedArray(buffer);
await videoFrame.copyTo(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height
});
for (let i = 0; i < rgba.length; i += 4) {
const r = rgba[i];
const g = rgba[i + 1];
const b = rgba[i + 2];
const gray = (r + g + b) / 3;
rgba[i] = gray; // Raudona
rgba[i + 1] = gray; // Žalia
rgba[i + 2] = gray; // Mėlyna
}
// Sukurti naują VideoFrame iš modifikuotų duomenų.
const newFrame = new VideoFrame(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
videoFrame.close(); // Atlaisvinti pradinį kadrą
return newFrame;
}
2. Kompiuterinės regos taikomosios programos
VideoFrame plokštumos suteikia tiesioginę prieigą prie pikselių duomenų, reikalingų kompiuterinės regos užduotims. Galite naudoti šiuos duomenis algoritmams, skirtiems objektų aptikimui, veidų atpažinimui, judesio sekimui ir kt. Galite pasitelkti WebAssembly našumui kritiškose kodo dalyse.
Pavyzdžiui, galėtumėte konvertuoti spalvotą VideoFrame į pilkumo tonus ir tada taikyti kraštinių aptikimo algoritmą (pvz., Sobelio operatorių), kad nustatytumėte vaizdo kraštines. Tai galėtų būti naudojama kaip išankstinio apdorojimo etapas objektų atpažinimui.
3. Vaizdo redagavimas ir kompozicija
Galite naudoti VideoFrame plokštumas vaizdo redagavimo funkcijoms, tokioms kaip apkarpymas, mastelio keitimas, pasukimas ir kompozicija, įgyvendinti. Tiesiogiai manipuliuodami pikselių duomenimis, galite sukurti individualius perėjimus ir efektus.
Pavyzdžiui, galėtumėte apkarpyti VideoFrame, nukopijuodami tik dalį pikselių duomenų į naują VideoFrame. Atitinkamai reikėtų pakoreguoti layout poslinkius ir žingsnius.
4. Individualūs kodekai ir perkodavimas
Nors WebCodecs teikia integruotą palaikymą įprastiems kodekams, tokiems kaip AV1, VP9 ir H.264, jį taip pat galite naudoti individualiems kodekams ar perkodavimo grandinėms įgyvendinti. Jums reikėtų patiems tvarkyti kodavimo ir dekodavimo procesą, tačiau VideoFrame plokštumos leidžia pasiekti ir manipuliuoti neapdorotais pikselių duomenimis. Tai galėtų būti naudinga nišiniams vaizdo formatams ar specializuotiems kodavimo reikalavimams.
5. Pažangi analizė
Pasiekdami pagrindinius pikselių duomenis, galite atlikti išsamią vaizdo turinio analizę. Tai apima užduotis, tokias kaip vidutinio scenos ryškumo matavimas, dominuojančių spalvų nustatymas ar scenos turinio pokyčių aptikimas. Tai gali įgalinti pažangias vaizdo analizės programas saugumui, stebėjimui ar turinio analizei.
Darbas su Canvas ir WebGL
Nors galite tiesiogiai manipuliuoti pikselių duomenimis VideoFrame plokštumose, dažnai rezultatą reikia atvaizduoti ekrane. CanvasImageBitmap sąsaja suteikia tiltą tarp VideoFrame ir <canvas> elemento. Galite sukurti CanvasImageBitmap iš VideoFrame ir tada jį nupiešti ant drobės naudojant drawImage() metodą.
async function renderVideoFrameToCanvas(videoFrame, canvas) {
const bitmap = await createImageBitmap(videoFrame);
const ctx = canvas.getContext('2d');
ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close(); // Atlaisvinti bitmap resursus
videoFrame.close(); // Atlaisvinti VideoFrame resursus
}
Pažangesniam atvaizdavimui galite naudoti WebGL. Galite įkelti pikselių duomenis iš VideoFrame plokštumų į WebGL tekstūras ir tada naudoti šešėlius (shaders) efektams ir transformacijoms taikyti. Tai leidžia išnaudoti GPU didelio našumo vaizdo apdorojimui.
Našumo aspektai
Darbas su neapdorotais pikselių duomenimis gali būti skaičiavimo požiūriu intensyvus, todėl labai svarbu atsižvelgti į našumo optimizavimą. Štai keletas patarimų:
- Minimizuokite kopijavimą: Venkite nereikalingo pikselių duomenų kopijavimo. Stenkitės atlikti operacijas vietoje, kai tik įmanoma.
- Naudokite WebAssembly: Našumui kritiškose kodo dalyse apsvarstykite galimybę naudoti WebAssembly. WebAssembly gali suteikti beveik natūralų našumą skaičiavimo požiūriu intensyvioms užduotims.
- Optimizuokite atminties išdėstymą: Pasirinkite tinkamą pikselių formatą ir atminties išdėstymą savo programai. Apsvarstykite galimybę naudoti supakuotus formatus (pvz., RGBA), jei jums nereikia dažnai pasiekti atskirų spalvų komponentų.
- Naudokite OffscreenCanvas: Foniniam apdorojimui naudokite
OffscreenCanvas, kad neužblokuotumėte pagrindinės gijos. - Profiluokite savo kodą: Naudokite naršyklės kūrėjų įrankius, kad profiliuotumėte savo kodą ir nustatytumėte našumo problemas.
Naršyklių suderinamumas
WebCodecs ir VideoFrame API yra palaikomi daugumoje šiuolaikinių naršyklių, įskaitant Chrome, Firefox ir Safari. Tačiau palaikymo lygis gali skirtis priklausomai nuo naršyklės versijos ir operacinės sistemos. Patikrinkite naujausias naršyklių suderinamumo lenteles svetainėse, tokiose kaip MDN Web Docs, kad įsitikintumėte, jog jūsų naudojamos funkcijos yra palaikomos jūsų tikslinėse naršyklėse. Siekiant suderinamumo tarp naršyklių, rekomenduojama atlikti funkcijų aptikimą.
Dažniausios klaidos ir trikčių šalinimas
Štai keletas dažniausiai pasitaikančių klaidų, kurių reikėtų vengti dirbant su VideoFrame plokštumomis:
- Neteisingas išdėstymas: Įsitikinkite, kad
layoutmasyvas tiksliai aprašo pikselių duomenų atminties išdėstymą. Neteisingi poslinkiai ar žingsniai gali sukelti sugadintus vaizdus. - Nesutampantys pikselių formatai: Įsitikinkite, kad pikselių formatas, kurį nurodote
copyTometode, atitinka faktinįVideoFrameformatą. - Atminties nutekėjimas: Visada uždarykite
VideoFrameirCanvasImageBitmapobjektus, kai baigiate su jais dirbti, kad atlaisvintumėte pagrindinius resursus. To nepadarius, gali atsirasti atminties nutekėjimas. - Asinchroninės operacijos: Atminkite, kad
copyToyra asinchroninė operacija. Naudokiteawait, kad užtikrintumėte, jog kopijavimo operacija bus baigta prieš pasiekiant pikselių duomenis. - Saugumo apribojimai: Būkite informuoti apie saugumo apribojimus, kurie gali būti taikomi pasiekiant pikselių duomenis iš kitos kilmės vaizdo įrašų.
Pavyzdys: YUV konvertavimas į RGB
Apsvarstykime sudėtingesnį pavyzdį: YUV420 VideoFrame konvertavimą į RGB VideoFrame. Tai apima Y, U ir V plokštumų skaitymą, jų konvertavimą į RGB reikšmes ir tada naujo RGB VideoFrame sukūrimą.
Šį konvertavimą galima įgyvendinti naudojant šią formulę:
R = Y + 1.402 * (Cr - 128)
G = Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)
B = Y + 1.772 * (Cb - 128)
Štai kodas:
async function convertYUV420ToRGBA(videoFrame) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
const yPlaneSize = width * height;
const uvPlaneSize = width * height / 4;
const yuvBuffer = new ArrayBuffer(yPlaneSize + 2 * uvPlaneSize);
const yuvPlanes = new Uint8ClampedArray(yuvBuffer);
const layout = [
{ offset: 0, stride: width }, // Y plokštuma
{ offset: yPlaneSize, stride: width / 2 }, // U plokštuma
{ offset: yPlaneSize + uvPlaneSize, stride: width / 2 } // V plokštuma
];
await videoFrame.copyTo(yuvPlanes, {
format: 'I420',
codedWidth: width,
codedHeight: height,
layout: layout
});
const rgbaBuffer = new ArrayBuffer(width * height * 4);
const rgba = new Uint8ClampedArray(rgbaBuffer);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const yIndex = y * width + x;
const uIndex = Math.floor(y / 2) * (width / 2) + Math.floor(x / 2) + yPlaneSize;
const vIndex = Math.floor(y / 2) * (width / 2) + Math.floor(x / 2) + yPlaneSize + uvPlaneSize;
const Y = yuvPlanes[yIndex];
const U = yuvPlanes[uIndex] - 128;
const V = yuvPlanes[vIndex] - 128;
let R = Y + 1.402 * V;
let G = Y - 0.34414 * U - 0.71414 * V;
let B = Y + 1.772 * U;
R = Math.max(0, Math.min(255, R));
G = Math.max(0, Math.min(255, G));
B = Math.max(0, Math.min(255, B));
const rgbaIndex = y * width * 4 + x * 4;
rgba[rgbaIndex] = R;
rgba[rgbaIndex + 1] = G;
rgba[rgbaIndex + 2] = B;
rgba[rgbaIndex + 3] = 255; // Alfa
}
}
const newFrame = new VideoFrame(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
videoFrame.close(); // Atlaisvinti pradinį kadrą
return newFrame;
}
Šis pavyzdys parodo galią ir sudėtingumą dirbant su VideoFrame plokštumomis. Tam reikia gerai suprasti pikselių formatus, atminties išdėstymą ir spalvų erdvių konvertavimą.
Išvada
VideoFrame plokštumų API WebCodecs'e atveria naują vaizdo apdorojimo valdymo lygį naršyklėje. Suprasdami, kaip tiesiogiai pasiekti ir manipuliuoti pikselių duomenimis, galite kurti pažangias programas realaus laiko vaizdo efektams, kompiuterinei regai, vaizdo redagavimui ir kt. Nors darbas su VideoFrame plokštumomis gali būti sudėtingas, potenciali nauda yra didelė. WebCodecs toliau tobulėjant, jis neabejotinai taps esminiu įrankiu žiniatinklio kūrėjams, dirbantiems su medija.
Raginame jus eksperimentuoti su VideoFrame plokštumų API ir tyrinėti jos galimybes. Suprasdami pagrindinius principus ir taikydami geriausias praktikas, galite sukurti inovatyvias ir našias vaizdo programas, kurios peržengia naršyklėje įmanomų dalykų ribas.
Tolimesniam mokymuisi
- MDN Web Docs apie WebCodecs
- WebCodecs specifikacija
- WebCodecs pavyzdinio kodo repozitorijos GitHub'e.