Fedezze fel a WebCodecs erejĂ©t! ĂštmutatĂł a videĂłkĂ©pkocka-adatok VideoFrame sĂkokon keresztĂĽli elĂ©rĂ©sĂ©hez Ă©s manipulálásához a böngĂ©szĹ‘ben.
WebCodecs VideoFrame sĂk: MĂ©lyrehatĂł betekintĂ©s a videĂłkĂ©pkocka-adatok elĂ©rĂ©sĂ©be
A WebCodecs paradigmaváltást jelent a webalapĂş mĂ©diafeldolgozásban. Alacsony szintű hozzáfĂ©rĂ©st biztosĂt a mĂ©dia Ă©pĂtĹ‘köveihez, lehetĹ‘vĂ© tĂ©ve a fejlesztĹ‘k számára, hogy kifinomult alkalmazásokat hozzanak lĂ©tre közvetlenĂĽl a böngĂ©szĹ‘ben. A WebCodecs egyik leghatĂ©konyabb funkciĂłja a VideoFrame objektum, Ă©s ezen belĂĽl a VideoFrame sĂkok, amelyek a videĂłkĂ©pkockák nyers pixeladatait teszik elĂ©rhetĹ‘vĂ©. Ez a cikk átfogĂł ĂştmutatĂłt nyĂşjt a VideoFrame sĂkok megĂ©rtĂ©sĂ©hez Ă©s felhasználásához a fejlett videĂłmanipuláciĂłhoz.
A VideoFrame objektum megértése
MielĹ‘tt belemerĂĽlnĂ©nk a sĂkokba, ismĂ©teljĂĽk át magát a VideoFrame objektumot. Egy VideoFrame egyetlen videĂłkĂ©pkockát kĂ©pvisel. Magába foglalja a dekĂłdolt (vagy kĂłdolt) videĂładatokat, valamint a hozzájuk tartozĂł metaadatokat, mint az idĹ‘bĂ©lyeg, idĹ‘tartam Ă©s formátuminformáciĂłk. A VideoFrame API a következĹ‘kre kĂnál metĂłdusokat:
- Pixeladatok olvasása: Itt jönnek kĂ©pbe a sĂkok.
- Képkockák másolása: Új
VideoFrameobjektumok lĂ©trehozása meglĂ©vĹ‘kbĹ‘l. - KĂ©pkockák lezárása: A kĂ©pkocka által lefoglalt erĹ‘források felszabadĂtása.
A VideoFrame objektum a dekódolási folyamat során jön létre, általában egy VideoDecoder által, vagy manuálisan, egyedi képkocka létrehozásakor.
Mik azok a VideoFrame sĂkok?
Egy VideoFrame pixeladatai gyakran több sĂkba vannak rendezve, kĂĽlönösen az YUV-hoz hasonlĂł formátumokban. Minden sĂk a kĂ©p egy másik komponensĂ©t kĂ©pviseli. PĂ©ldául egy YUV420 formátumban három sĂk van:
- Y (Luma): A kĂ©p fĂ©nyerejĂ©t (luminancia) kĂ©pviseli. Ez a sĂk tartalmazza a szĂĽrkeárnyalatos informáciĂłt.
- U (Cb): A kĂ©k-kĂĽlönbsĂ©gi szĂnkomponenst (kroma) kĂ©pviseli.
- V (Cr): A vörös-kĂĽlönbsĂ©gi szĂnkomponenst (kroma) kĂ©pviseli.
Az RGB formátumok, bár látszĂłlag egyszerűbbek, bizonyos esetekben szintĂ©n használhatnak több sĂkot. A sĂkok száma Ă©s jelentĂ©sĂĽk teljes mĂ©rtĂ©kben a VideoFrame VideoPixelFormat-játĂłl fĂĽgg.
A sĂkok használatának elĹ‘nye, hogy lehetĹ‘vĂ© teszi a specifikus szĂnkomponensek hatĂ©kony elĂ©rĂ©sĂ©t Ă©s manipulálását. PĂ©ldául elĹ‘fordulhat, hogy csak a fĂ©nyerĹ‘t (Y sĂk) szeretnĂ© mĂłdosĂtani anĂ©lkĂĽl, hogy a szĂnt (U Ă©s V sĂkok) befolyásolná.
A VideoFrame sĂkok elĂ©rĂ©se: Az API
A VideoFrame API a következĹ‘ metĂłdusokat biztosĂtja a sĂkok adatainak elĂ©rĂ©sĂ©hez:
copyTo(destination, options): AVideoFrametartalmát egy cĂ©lba másolja, amely lehet egy másikVideoFrame, egyCanvasImageBitmapvagy egyArrayBufferView. Azoptionsobjektum szabályozza, hogy mely sĂkok Ă©s hogyan kerĂĽljenek másolásra. Ez a sĂkok elĂ©rĂ©sĂ©nek elsĹ‘dleges mechanizmusa.
Az options objektum a copyTo metódusban lehetővé teszi, hogy meghatározza a videóképkocka adatainak elrendezését és célját. Kulcsfontosságú tulajdonságok:
format: A másolt adatok kĂvánt pixelformátuma. Ez lehet ugyanaz, mint az eredetiVideoFrameformátuma, vagy egy másik formátum (pl. YUV-bĂłl RGB-be konvertálás).codedWidthĂ©scodedHeight: A videĂłkĂ©pkocka szĂ©lessĂ©ge Ă©s magassága pixelekben.layout: Egy objektumokbĂłl állĂł tömb, amely leĂrja az egyes sĂkok memĂłriabeli elrendezĂ©sĂ©t. A tömb minden objektuma meghatározza:offset: Az eltolás bájtban, az adatpuffer elejĂ©tĹ‘l a sĂk adatainak kezdetĂ©ig.stride: A bájtok száma az egyes sorok kezdete között a sĂkban. Ez kulcsfontosságĂş a kitöltĂ©s (padding) kezelĂ©sĂ©hez.
Nézzünk egy példát egy YUV420 VideoFrame nyers pufferbe másolására:
asynkron funkciĂł copyYUV420ToBuffer(videoFrame, buffer) {
const width = videoFrame.codedWidth;
const height = videoFrame.codedHeight;
// A YUV420 3 sĂkbĂłl áll: Y, U Ă©s V
const yPlaneSize = width * height;
const uvPlaneSize = width * height / 4;
const layout = [
{ offset: 0, stride: width }, // Y sĂk
{ offset: yPlaneSize, stride: width / 2 }, // U sĂk
{ offset: yPlaneSize + uvPlaneSize, stride: width / 2 } // V sĂk
];
await videoFrame.copyTo(buffer, {
format: 'I420',
codedWidth: width,
codedHeight: height,
layout: layout
});
videoFrame.close(); // Fontos az erĹ‘források felszabadĂtása
}
Magyarázat:
- KiszámĂtjuk az egyes sĂkok mĂ©retĂ©t a
widthĂ©sheightalapján. Az Y teljes felbontásĂş, mĂg az U Ă©s V alulmintavĂ©telezett (4:2:0). - A
layouttömb definiálja a memĂłriakiosztást. Azoffsetmegadja, hogy hol kezdĹ‘dik az egyes sĂk a pufferben, astridepedig azt, hogy hány bájtot kell ugrani a következĹ‘ sorhoz az adott sĂkban. - A
formatopciĂł 'I420'-ra van állĂtva, ami egy gyakori YUV420 formátum. - Kritikusan fontos, hogy a másolás után a
videoFrame.close()meghĂvásra kerĂĽljön az erĹ‘források felszabadĂtása Ă©rdekĂ©ben.
Pixelformátumok: A lehetőségek világa
A pixelformátumok megĂ©rtĂ©se elengedhetetlen a VideoFrame sĂkokkal valĂł munkához. A VideoPixelFormat határozza meg, hogyan kĂłdolĂłdik a szĂninformáciĂł a videĂłkĂ©pkockán belĂĽl. ĂŤme nĂ©hány gyakori pixelformátum, amellyel találkozhat:
- I420 (YUV420p): Egy sĂkbeli (planar) YUV formátum, ahol az Y, U Ă©s V komponensek kĂĽlön sĂkokban tárolĂłdnak. Az U Ă©s V komponensek mind vĂzszintes, mind fĂĽggĹ‘leges irányban 2-es faktorral alulmintavĂ©telezettek. Ez egy nagyon gyakori Ă©s hatĂ©kony formátum.
- NV12 (YUV420sp): Egy fĂ©lsĂkbeli (semi-planar) YUV formátum, ahol az Y egy sĂkban, az U Ă©s V komponensek pedig összefĂ©sĂĽlve egy második sĂkban tárolĂłdnak.
- RGBA: A vörös, zöld, kĂ©k Ă©s alfa komponensek egyetlen sĂkban tárolĂłdnak, jellemzĹ‘en 8 bittel komponensenkĂ©nt (32 bit pixelenkĂ©nt). A komponensek sorrendje változhat (pl. BGRA).
- RGB565: A vörös, zöld Ă©s kĂ©k komponensek egyetlen sĂkban tárolĂłdnak 5 bittel a vörös, 6 bittel a zöld Ă©s 5 bittel a kĂ©k számára (16 bit pixelenkĂ©nt).
- GRAYSCALE: Szürkeárnyalatos képeket reprezentál, minden pixelhez egyetlen luma (fényerő) értékkel.
A VideoFrame.format tulajdonság megmondja egy adott kĂ©pkocka pixelformátumát. MielĹ‘tt megprĂłbálná elĂ©rni a sĂkokat, mindenkĂ©ppen ellenĹ‘rizze ezt a tulajdonságot. A támogatott formátumok teljes listáját a WebCodecs specifikáciĂłjában találja.
Gyakorlati felhasználási esetek
A VideoFrame sĂkok elĂ©rĂ©se számos lehetĹ‘sĂ©get nyit meg a fejlett videĂłfeldolgozás számára a böngĂ©szĹ‘ben. ĂŤme nĂ©hány pĂ©lda:
1. Valós idejű videóeffektek
ValĂłs idejű videĂłeffekteket alkalmazhat a VideoFrame pixeladatainak manipulálásával. PĂ©ldául implementálhat egy szĂĽrkeárnyalatos szűrĹ‘t Ăşgy, hogy átlagolja egy RGBA kĂ©pkocka minden pixelĂ©nek R, G Ă©s B komponensĂ©t, majd mindhárom komponenst erre az átlagĂ©rtĂ©kre állĂtja. LĂ©trehozhat szĂ©pia tĂłnusĂş effektet, vagy beállĂthatja a fĂ©nyerĹ‘t Ă©s a kontrasztot is.
asynkron funkciĂł 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; // Vörös
rgba[i + 1] = gray; // Zöld
rgba[i + 2] = gray; // Kék
}
// Ăšj VideoFrame lĂ©trehozása a mĂłdosĂtott adatokbĂłl.
const newFrame = new VideoFrame(rgba, {
format: 'RGBA',
codedWidth: width,
codedHeight: height,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
videoFrame.close(); // Eredeti kĂ©pkocka felszabadĂtása
return newFrame;
}
2. Gépi látás alkalmazások
A VideoFrame sĂkok közvetlen hozzáfĂ©rĂ©st biztosĂtanak a gĂ©pi látási feladatokhoz szĂĽksĂ©ges pixeladatokhoz. Ezeket az adatokat felhasználhatja objektumfelismerĂ©si, arcfelismerĂ©si, mozgáskövetĂ©si Ă©s egyĂ©b algoritmusok implementálásához. A kĂłd teljesĂtmĂ©nykritikus rĂ©szeihez használhatja a WebAssembly-t.
PĂ©ldául egy szĂnes VideoFrame-et szĂĽrkeárnyalatossá konvertálhat, majd egy Ă©lfelismerĹ‘ algoritmust (pl. Sobel-operátor) alkalmazhat a kĂ©pen lĂ©vĹ‘ Ă©lek azonosĂtására. Ez elĹ‘feldolgozási lĂ©pĂ©skĂ©nt használhatĂł az objektumfelismerĂ©shez.
3. Videószerkesztés és kompozitálás
A VideoFrame sĂkokat használhatja videĂłszerkesztĂ©si funkciĂłk, pĂ©ldául vágás, mĂ©retezĂ©s, forgatás Ă©s kompozitálás implementálásához. A pixeladatok közvetlen manipulálásával egyedi átmeneteket Ă©s effekteket hozhat lĂ©tre.
PĂ©ldául egy VideoFrame-et megvághat Ăşgy, hogy csak a pixeladatok egy rĂ©szĂ©t másolja át egy Ăşj VideoFrame-be. Ehhez megfelelĹ‘en kell mĂłdosĂtania a layout eltolásait Ă©s lĂ©pĂ©sközeit.
4. Egyedi kodekek és átkódolás
Bár a WebCodecs beĂ©pĂtett támogatást nyĂşjt olyan gyakori kodekekhez, mint az AV1, VP9 Ă©s H.264, használhatja egyedi kodekek vagy átkĂłdolási folyamatok implementálására is. A kĂłdolási Ă©s dekĂłdolási folyamatot saját magának kell kezelnie, de a VideoFrame sĂkok lehetĹ‘vĂ© teszik a nyers pixeladatok elĂ©rĂ©sĂ©t Ă©s manipulálását. Ez hasznos lehet rĂ©spiacot cĂ©lzĂł videĂłformátumok vagy speciális kĂłdolási követelmĂ©nyek esetĂ©n.
5. Fejlett analitika
Az alapul szolgálĂł pixeladatok elĂ©rĂ©sĂ©vel mĂ©lyrehatĂłan elemezheti a videĂłtartalmat. Ez magában foglal olyan feladatokat, mint egy jelenet átlagos fĂ©nyerejĂ©nek mĂ©rĂ©se, a domináns szĂnek azonosĂtása vagy a jelenet tartalmában bekövetkezĹ‘ változások Ă©szlelĂ©se. Ez lehetĹ‘vĂ© teszi fejlett videĂłanalitikai alkalmazások lĂ©trehozását biztonsági, megfigyelĂ©si vagy tartalomelemzĂ©si cĂ©lokra.
Munka a Canvasszal és a WebGL-lel
Bár közvetlenĂĽl manipulálhatja a pixeladatokat a VideoFrame sĂkokban, gyakran szĂĽksĂ©g van az eredmĂ©ny kĂ©pernyĹ‘re renderelĂ©sĂ©re. A CanvasImageBitmap interfĂ©sz hidat kĂ©pez a VideoFrame Ă©s a <canvas> elem között. LĂ©trehozhat egy CanvasImageBitmap-et egy VideoFrame-bĹ‘l, majd a drawImage() metĂłdussal a vászonra rajzolhatja.
asynkron funkciĂł renderVideoFrameToCanvas(videoFrame, canvas) {
const bitmap = await createImageBitmap(videoFrame);
const ctx = canvas.getContext('2d');
ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close(); // Bitmap erĹ‘források felszabadĂtása
videoFrame.close(); // VideoFrame erĹ‘források felszabadĂtása
}
Fejlettebb renderelĂ©shez használhatja a WebGL-t. Feltöltheti a pixeladatokat a VideoFrame sĂkokbĂłl a WebGL textĂşrákba, majd shadereket használhat effektek Ă©s transzformáciĂłk alkalmazására. Ez lehetĹ‘vĂ© teszi a GPU kihasználását a nagy teljesĂtmĂ©nyű videĂłfeldolgozáshoz.
TeljesĂtmĂ©nnyel kapcsolatos megfontolások
A nyers pixeladatokkal valĂł munka számĂtásigĂ©nyes lehet, ezĂ©rt kulcsfontosságĂş a teljesĂtmĂ©nyoptimalizálás figyelembevĂ©tele. ĂŤme nĂ©hány tipp:
- Minimalizálja a másolásokat: Kerülje a pixeladatok felesleges másolását. Amikor csak lehetséges, próbálja meg a műveleteket helyben elvégezni.
- Használjon WebAssembly-t: A kĂłd teljesĂtmĂ©nykritikus rĂ©szeihez fontolja meg a WebAssembly használatát. A WebAssembly közel natĂv teljesĂtmĂ©nyt nyĂşjthat a számĂtásigĂ©nyes feladatokhoz.
- Optimalizálja a memĂłriakiosztást: Válassza ki az alkalmazásához megfelelĹ‘ pixelformátumot Ă©s memĂłriakiosztást. Fontolja meg a tömörĂtett formátumok (pl. RGBA) használatát, ha nincs szĂĽksĂ©ge az egyes szĂnkomponensek gyakori elĂ©rĂ©sĂ©re.
- Használjon OffscreenCanvas-t: A háttérfeldolgozáshoz használjon
OffscreenCanvas-t, hogy elkerĂĽlje a fĹ‘ szál blokkolását. - Profilozza a kĂłdját: Használja a böngĂ©szĹ‘ fejlesztĹ‘i eszközeit a kĂłd profilozásához Ă©s a teljesĂtmĂ©nybeli szűk keresztmetszetek azonosĂtásához.
Böngészőkompatibilitás
A WebCodecs és a VideoFrame API a legtöbb modern böngészőben támogatott, beleértve a Chrome-ot, a Firefoxot és a Safarit. A támogatás szintje azonban változhat a böngésző verziójától és az operációs rendszertől függően. Ellenőrizze a legfrissebb böngészőkompatibilitási táblázatokat olyan oldalakon, mint az MDN Web Docs, hogy megbizonyosodjon arról, hogy a használt funkciók támogatottak a célböngészőkben. A böngészők közötti kompatibilitás érdekében a funkcióészlelés (feature detection) ajánlott.
Gyakori buktatĂłk Ă©s hibaelhárĂtás
ĂŤme nĂ©hány gyakori buktatĂł, amelyet Ă©rdemes elkerĂĽlni a VideoFrame sĂkokkal valĂł munka során:
- Helytelen elrendezés: Győződjön meg arról, hogy a
layouttömb pontosan leĂrja a pixeladatok memĂłriakiosztását. A helytelen eltolások vagy lĂ©pĂ©sközök sĂ©rĂĽlt kĂ©pekhez vezethetnek. - Nem egyezĹ‘ pixelformátumok: GyĹ‘zĹ‘djön meg arrĂłl, hogy a
copyTometódusban megadott pixelformátum megegyezik aVideoFrametényleges formátumával. - Memóriaszivárgás: Mindig zárja le a
VideoFrameĂ©sCanvasImageBitmapobjektumokat, miután vĂ©gzett velĂĽk, hogy felszabadĂtsa az alapul szolgálĂł erĹ‘forrásokat. Ennek elmulasztása memĂłriaszivárgáshoz vezethet. - Aszinkron műveletek: Ne feledje, hogy a
copyToegy aszinkron művelet. Használja azawait-et, hogy biztosĂtsa a másolási művelet befejezĹ‘dĂ©sĂ©t, mielĹ‘tt hozzáfĂ©rne a pixeladatokhoz. - Biztonsági korlátozások: Legyen tisztában a biztonsági korlátozásokkal, amelyek a más eredetű (cross-origin) videĂłkbĂłl származĂł pixeladatok elĂ©rĂ©sekor Ă©rvĂ©nyesĂĽlhetnek.
Példa: YUV-ból RGB-be konvertálás
NĂ©zzĂĽnk egy összetettebb pĂ©ldát: egy YUV420 VideoFrame átalakĂtása RGB VideoFrame-mĂ©. Ez magában foglalja az Y, U Ă©s V sĂkok olvasását, RGB Ă©rtĂ©kekkĂ© konvertálását, majd egy Ăşj RGB VideoFrame lĂ©trehozását.
Ez a konverziĂł a következĹ‘ kĂ©plettel valĂłsĂthatĂł meg:
R = Y + 1.402 * (Cr - 128)
G = Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)
B = Y + 1.772 * (Cb - 128)
Itt a kĂłd:
asynkron funkciĂł 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 sĂk
{ offset: yPlaneSize, stride: width / 2 }, // U sĂk
{ offset: yPlaneSize + uvPlaneSize, stride: width / 2 } // V sĂk
];
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(); // Eredeti kĂ©pkocka felszabadĂtása
return newFrame;
}
Ez a pĂ©lda bemutatja a VideoFrame sĂkokkal valĂł munka erejĂ©t Ă©s összetettsĂ©gĂ©t. JĂł ismereteket igĂ©nyel a pixelformátumokrĂłl, a memĂłriakiosztásrĂłl Ă©s a szĂntĂ©r-konverziĂłkrĂłl.
Következtetés
A WebCodecs VideoFrame sĂk API Ăşj szintű vezĂ©rlĂ©st tesz lehetĹ‘vĂ© a videĂłfeldolgozás felett a böngĂ©szĹ‘ben. Annak megĂ©rtĂ©sĂ©vel, hogyan lehet közvetlenĂĽl hozzáfĂ©rni Ă©s manipulálni a pixeladatokat, fejlett alkalmazásokat hozhat lĂ©tre valĂłs idejű videĂłeffektekhez, gĂ©pi látáshoz, videĂłszerkesztĂ©shez Ă©s mĂ©g sok máshoz. Bár a VideoFrame sĂkokkal valĂł munka kihĂvást jelenthet, a lehetsĂ©ges jutalom jelentĹ‘s. Ahogy a WebCodecs tovább fejlĹ‘dik, kĂ©tsĂ©gtelenĂĽl elengedhetetlen eszközzĂ© válik a mĂ©diával dolgozĂł webfejlesztĹ‘k számára.
BátorĂtjuk Ă–nt, hogy kĂsĂ©rletezzen a VideoFrame sĂk API-val Ă©s fedezze fel kĂ©pessĂ©geit. Az alapelvek megĂ©rtĂ©sĂ©vel Ă©s a legjobb gyakorlatok alkalmazásával innovatĂv Ă©s nagy teljesĂtmĂ©nyű videĂłalkalmazásokat hozhat lĂ©tre, amelyek feszegetik a böngĂ©szĹ‘ben lehetsĂ©ges határokat.
További tanulnivalók
- MDN Web Docs a WebCodecs-rĂłl
- WebCodecs specifikáció
- WebCodecs mintakód gyűjtemények a GitHubon.