WebCodecs APIతో వీడియోఫ్రేమ్ ప్లేన్ డేటాను నేరుగా యాక్సెస్ చేయడం మరియు మార్చడం నేర్చుకోండి. బ్రౌజర్లో కస్టమ్ వీడియో ఎఫెక్ట్స్ మరియు విశ్లేషణను సాధ్యం చేయండి.
వెబ్కోడెక్స్ వీడియోఫ్రేమ్ ప్లేన్ యాక్సెస్: రా వీడియో డేటా మానిప్యులేషన్పై ఒక లోతైన విశ్లేషణ
సంవత్సరాలుగా, వెబ్ బ్రౌజర్లో హై-పర్ఫార్మెన్స్ వీడియో ప్రాసెసింగ్ ఒక సుదూర కలలా అనిపించింది. డెవలపర్లు తరచుగా <video> ఎలిమెంట్ మరియు 2D కాన్వాస్ API యొక్క పరిమితులకు కట్టుబడి ఉండేవారు, ఇవి శక్తివంతమైనవే అయినప్పటికీ, పనితీరులో ఆటంకాలను మరియు అంతర్లీన రా వీడియో డేటాకు పరిమిత యాక్సెస్ను పరిచయం చేశాయి. వెబ్కోడెక్స్ API రాక ఈ పరిస్థితిని ప్రాథమికంగా మార్చేసింది, బ్రౌజర్ యొక్క అంతర్నిర్మిత మీడియా కోడెక్లకు తక్కువ-స్థాయి యాక్సెస్ను అందిస్తోంది. దీని అత్యంత విప్లవాత్మక ఫీచర్లలో ఒకటి VideoFrame ఆబ్జెక్ట్ ద్వారా వ్యక్తిగత వీడియో ఫ్రేమ్ల రా డేటాను నేరుగా యాక్సెస్ చేయడం మరియు మార్చడం.
ఈ వ్యాసం సాధారణ వీడియో ప్లేబ్యాక్ను దాటి వెళ్లాలనుకునే డెవలపర్ల కోసం ఒక సమగ్ర మార్గదర్శి. మేము VideoFrame ప్లేన్ యాక్సెస్ యొక్క చిక్కులను అన్వేషిస్తాము, కలర్ స్పేస్లు మరియు మెమరీ లేఅవుట్ వంటి భావనలను వివరిస్తాము మరియు రియల్-టైమ్ ఫిల్టర్ల నుండి అధునాతన కంప్యూటర్ విజన్ పనుల వరకు, బ్రౌజర్లో తదుపరి తరం వీడియో అప్లికేషన్లను రూపొందించడానికి మీకు శక్తినిచ్చే ఆచరణాత్మక ఉదాహరణలను అందిస్తాము.
అవసరాలు
ఈ గైడ్ నుండి గరిష్ట ప్రయోజనం పొందడానికి, మీకు వీటిపై మంచి అవగాహన ఉండాలి:
- ఆధునిక జావాస్క్రిప్ట్: అసమకాలిక ప్రోగ్రామింగ్ (
async/await, ప్రామిసెస్) తో సహా. - ప్రాథమిక వీడియో భావనలు: ఫ్రేమ్లు, రిజల్యూషన్, మరియు కోడెక్లు వంటి పదాలతో పరిచయం సహాయపడుతుంది.
- బ్రౌజర్ APIలు: కాన్వాస్ 2D లేదా WebGL వంటి APIలతో అనుభవం ప్రయోజనకరంగా ఉంటుంది కానీ ఖచ్చితంగా అవసరం లేదు.
వీడియో ఫ్రేమ్లు, కలర్ స్పేస్లు, మరియు ప్లేన్లను అర్థం చేసుకోవడం
APIలోకి ప్రవేశించే ముందు, మనం మొదట ఒక వీడియో ఫ్రేమ్ యొక్క డేటా వాస్తవానికి ఎలా ఉంటుందో ఒక దృఢమైన మానసిక నమూనాను నిర్మించుకోవాలి. ఒక డిజిటల్ వీడియో అనేది స్టిల్ ఇమేజ్లు లేదా ఫ్రేమ్ల క్రమం. ప్రతి ఫ్రేమ్ పిక్సెల్ల గ్రిడ్, మరియు ప్రతి పిక్సెల్కు ఒక రంగు ఉంటుంది. ఆ రంగు ఎలా నిల్వ చేయబడుతుంది అనేది కలర్ స్పేస్ మరియు పిక్సెల్ ఫార్మాట్ ద్వారా నిర్వచించబడుతుంది.
RGBA: వెబ్ యొక్క సహజ భాష
చాలా మంది వెబ్ డెవలపర్లకు RGBA కలర్ మోడల్తో పరిచయం ఉంది. ప్రతి పిక్సెల్ నాలుగు కాంపోనెంట్లతో సూచించబడుతుంది: రెడ్, గ్రీన్, బ్లూ, మరియు ఆల్ఫా (పారదర్శకత). డేటా సాధారణంగా మెమరీలో ఇంటర్లీవ్డ్ పద్ధతిలో నిల్వ చేయబడుతుంది, అంటే ఒకే పిక్సెల్ కోసం R, G, B, మరియు A విలువలు వరుసగా నిల్వ చేయబడతాయి:
[R1, G1, B1, A1, R2, G2, B2, A2, ...]
ఈ మోడల్లో, మొత్తం ఇమేజ్ ఒకే, నిరంతర మెమరీ బ్లాక్లో నిల్వ చేయబడుతుంది. దీనిని మనం ఒకే "ప్లేన్" డేటా ఉన్నట్లుగా భావించవచ్చు.
YUV: వీడియో కంప్రెషన్ యొక్క భాష
అయితే, వీడియో కోడెక్లు నేరుగా RGBAతో చాలా అరుదుగా పనిచేస్తాయి. అవి YUV (లేదా మరింత కచ్చితంగా, Y'CbCr) కలర్ స్పేస్లను ఇష్టపడతాయి. ఈ మోడల్ ఇమేజ్ సమాచారాన్ని ఇలా విభజిస్తుంది:
- Y (లూమా): ప్రకాశం లేదా గ్రేస్కేల్ సమాచారం. మానవ కన్ను లూమాలోని మార్పులకు అత్యంత సున్నితంగా ఉంటుంది.
- U (Cb) మరియు V (Cr): క్రోమినెన్స్ లేదా కలర్-డిఫరెన్స్ సమాచారం. మానవ కన్ను ప్రకాశం వివరాల కన్నా రంగు వివరాలకు తక్కువ సున్నితంగా ఉంటుంది.
ఈ విభజన సమర్థవంతమైన కంప్రెషన్ కోసం కీలకం. U మరియు V కాంపోనెంట్ల రిజల్యూషన్ను తగ్గించడం ద్వారా — ఈ టెక్నిక్ను క్రోమా సబ్శాంప్లింగ్ అంటారు — మనం నాణ్యతలో అతితక్కువ నష్టంతో ఫైల్ సైజును గణనీయంగా తగ్గించవచ్చు. ఇది ప్లానార్ పిక్సెల్ ఫార్మాట్లకు దారితీస్తుంది, ఇక్కడ Y, U, మరియు V కాంపోనెంట్లు వేర్వేరు మెమరీ బ్లాక్లు లేదా "ప్లేన్లలో" నిల్వ చేయబడతాయి.
ఒక సాధారణ ఫార్మాట్ I420 (YUV 4:2:0 యొక్క ఒక రకం), ఇక్కడ ప్రతి 2x2 పిక్సెల్ల బ్లాక్కు, నాలుగు Y నమూనాలు ఉంటాయి కానీ కేవలం ఒక U మరియు ఒక V నమూనా మాత్రమే ఉంటాయి. దీని అర్థం U మరియు V ప్లేన్లు Y ప్లేన్ యొక్క వెడల్పు మరియు ఎత్తులో సగం ఉంటాయి.
ఈ వ్యత్యాసాన్ని అర్థం చేసుకోవడం చాలా ముఖ్యం ఎందుకంటే వెబ్కోడెక్స్ మీకు డీకోడర్ అందించిన విధంగానే ఈ ప్లేన్లకు నేరుగా యాక్సెస్ ఇస్తుంది.
VideoFrame ఆబ్జెక్ట్: పిక్సెల్ డేటాకు మీ గేట్వే
ఈ పజిల్ యొక్క కేంద్ర భాగం VideoFrame ఆబ్జెక్ట్. ఇది వీడియో యొక్క ఒకే ఫ్రేమ్ను సూచిస్తుంది మరియు పిక్సెల్ డేటాతో పాటు ముఖ్యమైన మెటాడేటాను కూడా కలిగి ఉంటుంది.
VideoFrame యొక్క ముఖ్య లక్షణాలు
format: పిక్సెల్ ఫార్మాట్ను సూచించే ఒక స్ట్రింగ్ (ఉదా., 'I420', 'NV12', 'RGBA').codedWidth/codedHeight: కోడెక్కు అవసరమైన ఏదైనా ప్యాడింగ్తో సహా, మెమరీలో నిల్వ చేయబడిన ఫ్రేమ్ యొక్క పూర్తి కొలతలు.displayWidth/displayHeight: ఫ్రేమ్ను ప్రదర్శించడానికి ఉపయోగించాల్సిన కొలతలు.timestamp: ఫ్రేమ్ యొక్క ప్రెజెంటేషన్ టైమ్స్టాంప్ మైక్రోసెకన్లలో.duration: ఫ్రేమ్ యొక్క వ్యవధి మైక్రోసెకన్లలో.
మ్యాజిక్ మెథడ్: copyTo()
రా పిక్సెల్ డేటాను యాక్సెస్ చేయడానికి ప్రాథమిక పద్ధతి videoFrame.copyTo(destination, options). ఈ అసమకాలిక పద్ధతి ఫ్రేమ్ యొక్క ప్లేన్ డేటాను మీరు అందించిన బఫర్లోకి కాపీ చేస్తుంది.
destination: డేటాను ఉంచడానికి సరిపడా పెద్దదైనArrayBufferలేదా ఒక టైప్డ్ అర్రే (Uint8Arrayవంటిది).options: ఏ ప్లేన్లను కాపీ చేయాలో మరియు వాటి మెమరీ లేఅవుట్ను పేర్కొనే ఒక ఆబ్జెక్ట్. దీనిని వదిలేస్తే, అది అన్ని ప్లేన్లను ఒకే నిరంతర బఫర్లోకి కాపీ చేస్తుంది.
ఈ పద్ధతి ఒక ప్రామిస్ను రిటర్న్ చేస్తుంది, ఇది ఫ్రేమ్లోని ప్రతి ప్లేన్కు ఒకటి చొప్పున PlaneLayout ఆబ్జెక్ట్ల అర్రేతో రిసాల్వ్ అవుతుంది. ప్రతి PlaneLayout ఆబ్జెక్ట్లో రెండు కీలకమైన సమాచార భాగాలు ఉంటాయి:
offset: ఈ ప్లేన్ యొక్క డేటా డెస్టినేషన్ బఫర్లో ఎక్కడ మొదలవుతుందో సూచించే బైట్ ఆఫ్సెట్.stride: ఆ ప్లేన్ కోసం ఒక వరుస పిక్సెల్ల ప్రారంభం నుండి తదుపరి వరుస ప్రారంభం మధ్య ఉన్న బైట్ల సంఖ్య.
ఒక కీలకమైన భావన: స్ట్రైడ్ వర్సెస్ విడ్త్
తక్కువ-స్థాయి గ్రాఫిక్స్ ప్రోగ్రామింగ్కు కొత్తగా వచ్చిన డెవలపర్లకు ఇది గందరగోళానికి అత్యంత సాధారణ కారణాలలో ఒకటి. పిక్సెల్ డేటా యొక్క ప్రతి వరుస ఒకదాని తర్వాత ఒకటి గట్టిగా ప్యాక్ చేయబడిందని మీరు ఊహించలేరు.
- విడ్త్ అనేది ఇమేజ్ యొక్క ఒక వరుసలోని పిక్సెల్ల సంఖ్య.
- స్ట్రైడ్ (పిచ్ లేదా లైన్ స్టెప్ అని కూడా అంటారు) అనేది మెమరీలో ఒక వరుస ప్రారంభం నుండి తదుపరి వరుస ప్రారంభం వరకు ఉన్న బైట్ల సంఖ్య.
తరచుగా, stride అనేది width * bytes_per_pixel కంటే ఎక్కువగా ఉంటుంది. ఎందుకంటే CPU లేదా GPU ద్వారా వేగవంతమైన ప్రాసెసింగ్ కోసం మెమరీ తరచుగా హార్డ్వేర్ బౌండరీలతో (ఉదా., 32- లేదా 64-బైట్ బౌండరీలు) సమలేఖనం చేయడానికి ప్యాడ్ చేయబడుతుంది. ఒక నిర్దిష్ట వరుసలోని పిక్సెల్ యొక్క మెమరీ చిరునామాను లెక్కించడానికి మీరు ఎల్లప్పుడూ స్ట్రైడ్ను ఉపయోగించాలి.
స్ట్రైడ్ను విస్మరించడం వలన వక్రీకరించిన చిత్రాలు మరియు తప్పు డేటా యాక్సెస్ జరుగుతుంది.
ఆచరణాత్మక ఉదాహరణ 1: గ్రేస్కేల్ ప్లేన్ను యాక్సెస్ చేయడం మరియు ప్రదర్శించడం
ఒక సరళమైన కానీ శక్తివంతమైన ఉదాహరణతో ప్రారంభిద్దాం. వెబ్లోని చాలా వీడియోలు I420 వంటి YUV ఫార్మాట్లో ఎన్కోడ్ చేయబడతాయి. 'Y' ప్లేన్ సమర్థవంతంగా ఇమేజ్ యొక్క పూర్తి గ్రేస్కేల్ ప్రాతినిధ్యం. మనం కేవలం ఈ ప్లేన్ను సంగ్రహించి, దానిని ఒక కాన్వాస్కు రెండర్ చేయవచ్చు.
async function displayGrayscale(videoFrame) {
// videoFrame 'I420' లేదా 'NV12' వంటి YUV ఫార్మాట్లో ఉందని మేము భావిస్తున్నాము.
if (!videoFrame.format.startsWith('I4')) {
console.error('ఈ ఉదాహరణకు YUV 4:2:0 ప్లానార్ ఫార్మాట్ అవసరం.');
videoFrame.close();
return;
}
const yPlaneInfo = videoFrame.layout[0]; // Y ప్లేన్ ఎల్లప్పుడూ మొదటిది.
// కేవలం Y ప్లేన్ డేటాను ఉంచడానికి ఒక బఫర్ను సృష్టించండి.
const yPlaneData = new Uint8Array(yPlaneInfo.stride * videoFrame.codedHeight);
// Y ప్లేన్ను మా బఫర్లోకి కాపీ చేయండి.
await videoFrame.copyTo(yPlaneData, {
rect: { x: 0, y: 0, width: videoFrame.codedWidth, height: videoFrame.codedHeight },
layout: [yPlaneInfo]
});
// ఇప్పుడు, yPlaneData లో రా గ్రేస్కేల్ పిక్సెల్లు ఉన్నాయి.
// మనం దానిని రెండర్ చేయాలి. కాన్వాస్ కోసం ఒక RGBA బఫర్ను సృష్టిస్తాము.
const canvas = document.getElementById('my-canvas');
canvas.width = videoFrame.displayWidth;
canvas.height = videoFrame.displayHeight;
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);
// కాన్వాస్ పిక్సెల్లపై ఇటరేట్ చేసి, Y ప్లేన్ డేటా నుండి వాటిని నింపండి.
for (let y = 0; y < videoFrame.displayHeight; y++) {
for (let x = 0; x < videoFrame.displayWidth; x++) {
// ముఖ్యం: సరైన సోర్స్ ఇండెక్స్ను కనుగొనడానికి స్ట్రైడ్ను ఉపయోగించండి!
const yIndex = y * yPlaneInfo.stride + x;
const luma = yPlaneData[yIndex];
// RGBA ImageData బఫర్లో డెస్టినేషన్ ఇండెక్స్ను లెక్కించండి.
const rgbaIndex = (y * canvas.width + x) * 4;
imageData.data[rgbaIndex] = luma; // రెడ్
imageData.data[rgbaIndex + 1] = luma; // గ్రీన్
imageData.data[rgbaIndex + 2] = luma; // బ్లూ
imageData.data[rgbaIndex + 3] = 255; // ఆల్ఫా
}
}
ctx.putImageData(imageData, 0, 0);
// కీలకం: మెమరీని విడుదల చేయడానికి ఎల్లప్పుడూ VideoFrame ను క్లోజ్ చేయండి.
videoFrame.close();
}
ఈ ఉదాహరణ అనేక కీలకమైన దశలను హైలైట్ చేస్తుంది: సరైన ప్లేన్ లేఅవుట్ను గుర్తించడం, డెస్టినేషన్ బఫర్ను కేటాయించడం, డేటాను సంగ్రహించడానికి copyTo ను ఉపయోగించడం, మరియు కొత్త చిత్రాన్ని నిర్మించడానికి stride ను ఉపయోగించి డేటాపై సరిగ్గా ఇటరేట్ చేయడం.
ఆచరణాత్మక ఉదాహరణ 2: ఇన్-ప్లేస్ మానిప్యులేషన్ (సెపియా ఫిల్టర్)
ఇప్పుడు మనం ప్రత్యక్ష డేటా మానిప్యులేషన్ చేద్దాం. సెపియా ఫిల్టర్ ఒక క్లాసిక్ ఎఫెక్ట్, దీనిని అమలు చేయడం సులభం. ఈ ఉదాహరణ కోసం, RGBA ఫ్రేమ్తో పనిచేయడం సులభం, దీనిని మీరు కాన్వాస్ లేదా WebGL కాంటెక్స్ట్ నుండి పొందవచ్చు.
async function applySepiaFilter(videoFrame) {
// ఈ ఉదాహరణ ఇన్పుట్ ఫ్రేమ్ 'RGBA' లేదా 'BGRA' అని ఊహిస్తుంది.
if (videoFrame.format !== 'RGBA' && videoFrame.format !== 'BGRA') {
console.error('సెపియా ఫిల్టర్ ఉదాహరణకు RGBA ఫ్రేమ్ అవసరం.');
videoFrame.close();
return null;
}
// పిక్సెల్ డేటాను ఉంచడానికి ఒక బఫర్ను కేటాయించండి.
const frameDataSize = videoFrame.allocationSize();
const frameData = new Uint8Array(frameDataSize);
await videoFrame.copyTo(frameData);
const layout = videoFrame.layout[0]; // RGBA ఒకే ప్లేన్
// ఇప్పుడు, బఫర్లోని డేటాను మార్చండి.
for (let y = 0; y < videoFrame.codedHeight; y++) {
for (let x = 0; x < videoFrame.codedWidth; x++) {
const pixelIndex = y * layout.stride + x * 4; // ప్రతి పిక్సెల్కు 4 బైట్లు (R,G,B,A)
const r = frameData[pixelIndex];
const g = frameData[pixelIndex + 1];
const b = frameData[pixelIndex + 2];
const tr = 0.393 * r + 0.769 * g + 0.189 * b;
const tg = 0.349 * r + 0.686 * g + 0.168 * b;
const tb = 0.272 * r + 0.534 * g + 0.131 * b;
frameData[pixelIndex] = Math.min(255, tr);
frameData[pixelIndex + 1] = Math.min(255, tg);
frameData[pixelIndex + 2] = Math.min(255, tb);
// ఆల్ఫా (frameData[pixelIndex + 3]) మారదు.
}
}
// మార్చిన డేటాతో ఒక *కొత్త* VideoFrame ను సృష్టించండి.
const newFrame = new VideoFrame(frameData, {
format: videoFrame.format,
codedWidth: videoFrame.codedWidth,
codedHeight: videoFrame.codedHeight,
timestamp: videoFrame.timestamp,
duration: videoFrame.duration
});
// అసలు ఫ్రేమ్ను క్లోజ్ చేయడం మర్చిపోవద్దు!
videoFrame.close();
return newFrame;
}
ఇది పూర్తి రీడ్-మాడిఫై-రైట్ సైకిల్ను ప్రదర్శిస్తుంది: డేటాను కాపీ చేయడం, స్ట్రైడ్ ఉపయోగించి దాని ద్వారా లూప్ చేయడం, ప్రతి పిక్సెల్కు గణిత పరివర్తనను వర్తింపజేయడం, మరియు ఫలిత డేటాతో కొత్త VideoFrameను నిర్మించడం. ఈ కొత్త ఫ్రేమ్ను తర్వాత కాన్వాస్కు రెండర్ చేయవచ్చు, VideoEncoderకు పంపవచ్చు, లేదా మరొక ప్రాసెసింగ్ దశకు పంపవచ్చు.
పనితీరు ముఖ్యం: జావాస్క్రిప్ట్ వర్సెస్ వెబ్అసెంబ్లీ (WASM)
ప్రతి ఫ్రేమ్ కోసం మిలియన్ల కొద్దీ పిక్సెల్లపై ఇటరేట్ చేయడం (ఒక 1080p ఫ్రేమ్లో 2 మిలియన్లకు పైగా పిక్సెల్లు, లేదా RGBAలో 8 మిలియన్ డేటా పాయింట్లు ఉంటాయి) జావాస్క్రిప్ట్లో నెమ్మదిగా ఉంటుంది. ఆధునిక JS ఇంజిన్లు చాలా వేగంగా ఉన్నప్పటికీ, హై-రిజల్యూషన్ వీడియో (HD, 4K) యొక్క రియల్-టైమ్ ప్రాసెసింగ్ కోసం, ఈ విధానం ప్రధాన థ్రెడ్ను సులభంగా ముంచెత్తగలదు, ఇది ఒక అస్థిరమైన వినియోగదారు అనుభవానికి దారితీస్తుంది.
ఇక్కడే వెబ్అసెంబ్లీ (WASM) ఒక ముఖ్యమైన సాధనంగా మారుతుంది. WASM బ్రౌజర్ లోపల C++, రస్ట్, లేదా గో వంటి భాషలలో వ్రాసిన కోడ్ను దాదాపు నేటివ్ స్పీడ్లో అమలు చేయడానికి మిమ్మల్ని అనుమతిస్తుంది. వీడియో ప్రాసెసింగ్ కోసం వర్క్ఫ్లో ఇలా మారుతుంది:
- జావాస్క్రిప్ట్లో: రా పిక్సెల్ డేటాను
ArrayBufferలోకి పొందడానికిvideoFrame.copyTo()ను ఉపయోగించండి. - WASMకు పంపండి: ఈ బఫర్ యొక్క రిఫరెన్స్ను మీ కంపైల్డ్ WASM మాడ్యూల్లోకి పంపండి. ఇది డేటాను కాపీ చేయనందున చాలా వేగవంతమైన ఆపరేషన్.
- WASMలో (C++/రస్ట్): మీ అత్యంత ఆప్టిమైజ్ చేయబడిన ఇమేజ్ ప్రాసెసింగ్ అల్గారిథమ్లను నేరుగా మెమరీ బఫర్పై అమలు చేయండి. ఇది జావాస్క్రిప్ట్ లూప్ కంటే ఎన్నో రెట్లు వేగంగా ఉంటుంది.
- జావాస్క్రిప్ట్కు తిరిగి రండి: WASM పూర్తయిన తర్వాత, నియంత్రణ జావాస్క్రిప్ట్కు తిరిగి వస్తుంది. అప్పుడు మీరు మార్చిన బఫర్ను ఉపయోగించి కొత్త
VideoFrameను సృష్టించవచ్చు.
వర్చువల్ బ్యాక్గ్రౌండ్లు, ఆబ్జెక్ట్ డిటెక్షన్, లేదా సంక్లిష్ట ఫిల్టర్లు వంటి ఏదైనా తీవ్రమైన, రియల్-టైమ్ వీడియో మానిప్యులేషన్ అప్లికేషన్ కోసం — వెబ్అసెంబ్లీని ఉపయోగించడం ఒక ఎంపిక మాత్రమే కాదు; అది ఒక అవసరం.
వివిధ పిక్సెల్ ఫార్మాట్లను నిర్వహించడం (ఉదా., I420, NV12)
RGBA సరళమైనదే అయినప్పటికీ, మీరు చాలా తరచుగా VideoDecoder నుండి ప్లానార్ YUV ఫార్మాట్లలో ఫ్రేమ్లను అందుకుంటారు. I420 వంటి పూర్తి ప్లానార్ ఫార్మాట్ను ఎలా నిర్వహించాలో చూద్దాం.
I420 ఫార్మాట్లోని VideoFrame దాని layout అర్రేలో మూడు లేఅవుట్ డిస్క్రిప్టర్లను కలిగి ఉంటుంది:
layout[0]: Y ప్లేన్ (లూమా). కొలతలుcodedWidthxcodedHeight.layout[1]: U ప్లేన్ (క్రోమా). కొలతలుcodedWidth/2xcodedHeight/2.layout[2]: V ప్లేన్ (క్రోమా). కొలతలుcodedWidth/2xcodedHeight/2.
మూడు ప్లేన్లను ఒకే బఫర్లోకి ఎలా కాపీ చేయాలో ఇక్కడ ఉంది:
async function extractI420Planes(videoFrame) {
const totalSize = videoFrame.allocationSize({ format: 'I420' });
const allPlanesData = new Uint8Array(totalSize);
const layouts = await videoFrame.copyTo(allPlanesData);
// layouts అనేది 3 PlaneLayout ఆబ్జెక్ట్ల అర్రే
console.log('Y Plane Layout:', layouts[0]); // { offset: 0, stride: ... }
console.log('U Plane Layout:', layouts[1]); // { offset: ..., stride: ... }
console.log('V Plane Layout:', layouts[2]); // { offset: ..., stride: ... }
// మీరు ఇప్పుడు `allPlanesData` బఫర్లోని ప్రతి ప్లేన్ను యాక్సెస్ చేయవచ్చు
// దాని నిర్దిష్ట ఆఫ్సెట్ మరియు స్ట్రైడ్ ఉపయోగించి.
const yPlaneView = new Uint8Array(
allPlanesData.buffer,
layouts[0].offset,
layouts[0].stride * videoFrame.codedHeight
);
// క్రోమా కొలతలు సగానికి తగ్గాయని గమనించండి!
const uPlaneView = new Uint8Array(
allPlanesData.buffer,
layouts[1].offset,
layouts[1].stride * (videoFrame.codedHeight / 2)
);
const vPlaneView = new Uint8Array(
allPlanesData.buffer,
layouts[2].offset,
layouts[2].stride * (videoFrame.codedHeight / 2)
);
console.log('Accessed Y plane size:', yPlaneView.byteLength);
console.log('Accessed U plane size:', uPlaneView.byteLength);
videoFrame.close();
}
మరొక సాధారణ ఫార్మాట్ NV12, ఇది సెమీ-ప్లానార్. దీనికి రెండు ప్లేన్లు ఉంటాయి: ఒకటి Y కోసం, మరియు రెండవ ప్లేన్లో U మరియు V విలువలు ఇంటర్లీవ్ చేయబడి ఉంటాయి (ఉదా., [U1, V1, U2, V2, ...]). వెబ్కోడెక్స్ API దీనిని పారదర్శకంగా నిర్వహిస్తుంది; NV12 ఫార్మాట్లోని VideoFrame దాని layout అర్రేలో కేవలం రెండు లేఅవుట్లను కలిగి ఉంటుంది.
సవాళ్లు మరియు ఉత్తమ పద్ధతులు
ఈ తక్కువ స్థాయిలో పనిచేయడం శక్తివంతమైనది, కానీ ఇది బాధ్యతలతో కూడి ఉంటుంది.
మెమరీ నిర్వహణ చాలా ముఖ్యం
ఒక VideoFrame గణనీయమైన మొత్తంలో మెమరీని కలిగి ఉంటుంది, ఇది తరచుగా జావాస్క్రిప్ట్ గార్బేజ్ కలెక్టర్ యొక్క హీప్ వెలుపల నిర్వహించబడుతుంది. మీరు ఈ మెమరీని స్పష్టంగా విడుదల చేయకపోతే, మీరు బ్రౌజర్ ట్యాబ్ను క్రాష్ చేయగల మెమరీ లీక్కు కారణమవుతారు.
మీరు ఒక ఫ్రేమ్తో పూర్తి చేసిన తర్వాత ఎల్లప్పుడూ, ఎల్లప్పుడూ videoFrame.close() ను కాల్ చేయండి.
అసమకాలిక స్వభావం
అన్ని డేటా యాక్సెస్ అసమకాలికంగా ఉంటుంది. మీ అప్లికేషన్ యొక్క ఆర్కిటెక్చర్ రేస్ కండిషన్లను నివారించడానికి మరియు సున్నితమైన ప్రాసెసింగ్ పైప్లైన్ను నిర్ధారించడానికి ప్రామిసెస్ మరియు async/await ప్రవాహాన్ని సరిగ్గా నిర్వహించాలి.
బ్రౌజర్ అనుకూలత
వెబ్కోడెక్స్ ఒక ఆధునిక API. అన్ని ప్రధాన బ్రౌజర్లలో మద్దతు ఉన్నప్పటికీ, దాని లభ్యతను ఎల్లప్పుడూ తనిఖీ చేయండి మరియు ఏదైనా విక్రేత-నిర్దిష్ట అమలు వివరాలు లేదా పరిమితుల గురించి తెలుసుకోండి. APIని ఉపయోగించడానికి ప్రయత్నించే ముందు ఫీచర్ డిటెక్షన్ను ఉపయోగించండి.
ముగింపు: వెబ్ వీడియో కోసం ఒక కొత్త సరిహద్దు
వెబ్కోడెక్స్ API ద్వారా VideoFrame యొక్క రా ప్లేన్ డేటాను నేరుగా యాక్సెస్ చేయడం మరియు మార్చగల సామర్థ్యం వెబ్-ఆధారిత మీడియా అప్లికేషన్ల కోసం ఒక నమూనా మార్పు. ఇది <video> ఎలిమెంట్ యొక్క బ్లాక్ బాక్స్ను తొలగిస్తుంది మరియు డెవలపర్లకు గతంలో నేటివ్ అప్లికేషన్లకు మాత్రమే రిజర్వ్ చేయబడిన గ్రాన్యులర్ నియంత్రణను ఇస్తుంది.
వీడియో మెమరీ లేఅవుట్ యొక్క ప్రాథమికాలను — ప్లేన్లు, స్ట్రైడ్, మరియు కలర్ ఫార్మాట్లను అర్థం చేసుకోవడం ద్వారా — మరియు పనితీరు-క్లిష్టమైన కార్యకలాపాల కోసం వెబ్అసెంబ్లీ యొక్క శక్తిని ఉపయోగించుకోవడం ద్వారా, మీరు ఇప్పుడు బ్రౌజర్లో నేరుగా అద్భుతమైన అధునాతన వీడియో ప్రాసెసింగ్ సాధనాలను నిర్మించవచ్చు. రియల్-టైమ్ కలర్ గ్రేడింగ్ మరియు కస్టమ్ విజువల్ ఎఫెక్ట్స్ నుండి క్లయింట్-సైడ్ మెషిన్ లెర్నింగ్ మరియు వీడియో విశ్లేషణ వరకు, అవకాశాలు విస్తారమైనవి. వెబ్లో హై-పర్ఫార్మెన్స్, తక్కువ-స్థాయి వీడియో యొక్క యుగం నిజంగా ప్రారంభమైంది.