WebCodecs APIãšãã®VideoFrameã€ã³ã¿ãŒãã§ãŒã¹ãæ·±ãæãäžããWebã¢ããªã±ãŒã·ã§ã³å ã§çŽæ¥é«åºŠãªãããªåŠçãè¡ããã®æ©èœãæ¢ããŸãã
WebCodecs VideoFrame: ãã©ãŠã¶ã§ãã¬ãŒã ã¬ãã«ã®ãããªåŠçãè§£ãæŸã€
WebCodecs APIã¯ãWebããŒã¹ã®ã¡ãã£ã¢åŠçã«ãšã£ãŠå€§ããªé²æ©ãæå³ããéçºè
ã«JavaScriptããçŽæ¥ãããªããã³ãªãŒãã£ãªã³ãŒããã¯ãžã®äœã¬ãã«ã¢ã¯ã»ã¹ãæäŸããŸãããã®åŒ·åãªæ©èœã®äžã§ããVideoFrameã€ã³ã¿ãŒãã§ãŒã¹ã¯ãé«åºŠãªãã¬ãŒã ã¬ãã«ã®ãããªæäœãå®çŸããããã®éèŠãªèŠçŽ ãšããŠéç«ã£ãŠããŸãããã®èšäºã§ã¯ãVideoFrameã®æ©èœã«æ·±ãè¿«ãããã®ãŠãŒã¹ã±ãŒã¹ãå©ç¹ãããã³å®è·µçãªå®è£
äŸãæ¢ããŸãã
WebCodecsãšã¯äœãïŒ
WebCodecsã¯ãäœã¬ãã«ã®ã³ãŒããã¯APIïŒãããªããã³ãªãŒãã£ãªïŒããŠã§ãã«å
¬éããŸããããã¯ããã©ãŠã¶ã®çµã¿èŸŒã¿ã¡ãã£ã¢åŠçæ©èœã«é Œãã®ã§ã¯ãªããéçºè
ããšã³ã³ãŒãã£ã³ã°ããã³ãã³ãŒãã£ã³ã°ããã»ã¹ã«å¯ŸããŠãã现ããªå¶åŸ¡ãè¡ããããšãæå³ããŸããããã«ããã<video>ããã³<audio>èŠçŽ ã®æ©èœã«ãã£ãŠä»¥åã¯å¶éãããŠããå¹
åºãã¢ããªã±ãŒã·ã§ã³ãžã®éãéãããŸãã
WebCodecsã®äž»ãªå©ç¹ã¯æ¬¡ã®ãšããã§ãã
- äœã¬ãã«ã¢ã¯ã»ã¹: ãšã³ã³ãŒãã£ã³ã°ããã³ãã³ãŒãã£ã³ã°ãã©ã¡ãŒã¿ãçŽæ¥å¶åŸ¡ã§ããŸãã
- ããã©ãŒãã³ã¹ã®åäž: ããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã掻çšããŠå¹ççãªåŠçãå®çŸããŸãã
- æè»æ§: ããŸããŸãªã³ãŒããã¯ãšã³ã³ãã圢åŒããµããŒãããŸãã
- ãªã¢ã«ã¿ã€ã åŠç: ãªã¢ã«ã¿ã€ã ã®ãããªããã³ãªãŒãã£ãªã¢ããªã±ãŒã·ã§ã³ãå¯èœã«ããŸãã
VideoFrameã®ç޹ä»
VideoFrameã€ã³ã¿ãŒãã§ãŒã¹ã¯ããããªã®åäžãã¬ãŒã ã衚ããŸããããã«ããããããªãã¬ãŒã ã®çã®ãã¯ã»ã«ããŒã¿ã«ã¢ã¯ã»ã¹ããããã°ã©ã ã§æäœããããšãã§ããŸãããã®æ©èœã¯ã次ã®ãããªã¿ã¹ã¯ã«äžå¯æ¬ ã§ãã
- ãããªç·šé: åã ã®ãã¬ãŒã ã«ãã£ã«ã¿ããšãã§ã¯ããããã³å€æãé©çšããŸãã
- ã³ã³ãã¥ãŒã¿ããžã§ã³: ãªããžã§ã¯ãæ€åºãé¡èªèããã®ä»ã®æ©æ¢°åŠç¿ã¿ã¹ã¯ã®ããã«ãããªã³ã³ãã³ããåæããŸãã
- ãªã¢ã«ã¿ã€ã ãããªåŠç: ãããªã¹ããªãŒã ã«ãªã¢ã«ã¿ã€ã ãšãã§ã¯ããšåæãé©çšããŸãã
- ã«ã¹ã¿ã ã³ãŒããã¯: ã«ã¹ã¿ã ã®ãšã³ã³ãŒãã£ã³ã°ããã³ãã³ãŒãã£ã³ã°ããžãã¯ãå®è£ ããŸãã
äž»èŠãªããããã£ãšã¡ãœãã
VideoFrameã€ã³ã¿ãŒãã§ãŒã¹ã¯ãããã€ãã®éèŠãªããããã£ãšã¡ãœãããæäŸããŸãã
format: ãããªãã¬ãŒã ã®ãã©ãŒãããïŒäŸ: "I420", "RGBA"ïŒãè¿ããŸããcodedWidth: ãããªãã¬ãŒã ã®ç¬Šå·åãããå¹ ããã¯ã»ã«åäœã§è¿ããŸããcodedHeight: ãããªãã¬ãŒã ã®ç¬Šå·åãããé«ãããã¯ã»ã«åäœã§è¿ããŸããdisplayWidth: ãããªãã¬ãŒã ã®è¡šç€ºå¹ ããã¯ã»ã«åäœã§è¿ããŸããdisplayHeight: ãããªãã¬ãŒã ã®è¡šç€ºé«ãããã¯ã»ã«åäœã§è¿ããŸããtimestamp: ãããªãã¬ãŒã ã®ã¿ã€ã ã¹ã¿ã³ãããã€ã¯ãç§åäœã§è¿ããŸããduration: ãããªãã¬ãŒã ã®æéããã€ã¯ãç§åäœã§è¿ããŸããcopyTo(destination, options): ãããªãã¬ãŒã ããŒã¿ãå®å ã«ã³ããŒããŸããclose(): ãããªãã¬ãŒã ã«é¢é£ä»ãããããªãœãŒã¹ãè§£æŸããŸãã
VideoFrameã®ãŠãŒã¹ã±ãŒã¹
VideoFrameã€ã³ã¿ãŒãã§ãŒã¹ã¯ãWebããŒã¹ã®ãããªåŠçã«å¹
åºãå¯èœæ§ãåºããŸãã以äžã«ãããã€ãã®é
åçãªãŠãŒã¹ã±ãŒã¹ã瀺ããŸãã
1. ã«ã¹ã¿ã ãšãã§ã¯ãä»ããªã¢ã«ã¿ã€ã ãããªäŒè°
ãããªäŒè°ã¢ããªã±ãŒã·ã§ã³ã¯ãVideoFrameãæŽ»çšããŠãããªã¹ããªãŒã ã«ãªã¢ã«ã¿ã€ã ãšãã§ã¯ããé©çšã§ããŸããããšãã°ãèæ¯ã®ãŒãããããŒãã£ã«èæ¯ããŸãã¯é¡ãã£ã«ã¿ãŒããã©ãŠã¶ã§çŽæ¥å®è£
ã§ããŸããããã«ã¯ããŠãŒã¶ãŒã®ã«ã¡ã©ãããããªã¹ããªãŒã ããã£ããã£ããWebCodecsã䜿çšããŠãã¬ãŒã ããã³ãŒãããç®çã®ãšãã§ã¯ããVideoFrameã«é©çšãããã®åŸã倿Žããããã¬ãŒã ãåãšã³ã³ãŒãããŠéä¿¡ããå¿
èŠããããŸããäžçäžã®ããŒã ããããžã§ã¯ãã§ååããŠãããšãããæ³åããŠã¿ãŠãã ãããåã¡ã³ããŒã¯ããšããã§ã«å¡ãäžéã®é·åãããã¥ããã¥ãªã©ãèªèº«ã®æåçéºç£ã衚ãèæ¯ãéžæã§ããè·é¢ãè¶
ããäžäœæãè²ãããšãã§ããŸãã
äŸ: èæ¯ã®ãŒãã
ãã®äŸã§ã¯ããããªãã¬ãŒã ã®èæ¯ã«åçŽãªãŒãã广ãé©çšããæ¹æ³ã瀺ããŸããããã¯ç°¡ç¥åãããäŸã§ãããå®çšŒåã«å¯Ÿå¿ããå®è£ ã§ã¯ãèæ¯ã»ã°ã¡ã³ããŒã·ã§ã³ãªã©ã®ããé«åºŠãªæè¡ãå¿ èŠã«ãªããŸãã
// Assuming you have a VideoFrame object named 'frame'
// 1. Copy the frame data to a canvas
const canvas = document.createElement('canvas');
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const ctx = canvas.getContext('2d');
const imageData = new ImageData(frame.format === 'RGBA' ? frame.data : convertToRGBA(frame), frame.displayWidth, frame.displayHeight);
ctx.putImageData(imageData, 0, 0);
// 2. Apply a blur filter (using a library or custom implementation)
// This is a simplified example; a real blur filter would be more complex
for (let i = 0; i < 5; i++) { // Apply the blur multiple times for a stronger effect
ctx.filter = 'blur(5px)';
ctx.drawImage(canvas, 0, 0);
}
ctx.filter = 'none'; // Reset the filter
// 3. Get the processed image data
const blurredImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 4. Create a new VideoFrame from the processed data
const blurredFrame = new VideoFrame(blurredImageData.data, {
format: 'RGBA',
codedWidth: frame.codedWidth,
codedHeight: frame.codedHeight,
displayWidth: frame.displayWidth,
displayHeight: frame.displayHeight,
timestamp: frame.timestamp,
duration: frame.duration,
});
// 5. Replace the original frame with the blurred frame
frame.close(); // Release the original frame
frame = blurredFrame;
éèŠãªèæ ®äºé :
- ããã©ãŒãã³ã¹: ãªã¢ã«ã¿ã€ã ãããªåŠçã¯èšç®è² è·ãé«ãã§ããã³ãŒããæé©åããå¯èœãªå Žåã¯ããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã掻çšããŠãã ããã
- èæ¯ã»ã°ã¡ã³ããŒã·ã§ã³: ãã©ã¢ã°ã©ãŠã³ãïŒäººç©ïŒãèæ¯ããæ£ç¢ºã«åé¢ããããšã¯ããªã¢ã«ãªãšãã§ã¯ãã«ãšã£ãŠéèŠã§ããæ©æ¢°åŠç¿ããŒã¹ã®èæ¯ã»ã°ã¡ã³ããŒã·ã§ã³æè¡ã®äœ¿çšãæ€èšããŠãã ããã
- ã³ãŒããã¯äºææ§: ãšã³ã³ãŒãã£ã³ã°ããã³ãã³ãŒãã£ã³ã°ã³ãŒããã¯ããã¿ãŒã²ãããã©ãããã©ãŒã ããã³ãã©ãŠã¶ãšäºææ§ãããããšã確èªããŠãã ããã
2. é«åºŠãªãããªç·šéãšåŸåŠç
VideoFrameã¯ããã©ãŠã¶ã§çŽæ¥ãé«åºŠãªãããªç·šéããã³åŸåŠçæ©èœãå®çŸããŸããããã«ã¯ãè²è£æ£ãèŠèŠå¹æããã¬ãŒã ããšã®ã¢ãã¡ãŒã·ã§ã³ãªã©ã®æ©èœãå«ãŸããŸããã ã³ãã€ã®æ ç»è£œäœè
ããã«ãªã³ã®ã°ã©ãã£ãã¯ãã¶ã€ããŒãããµã³ãŒã«ã¹ã®ãµãŠã³ããšã³ãžãã¢ãããŠã§ãããŒã¹ã®ç·šéã¹ã€ãŒãå
ã§å®å
šã«çç·šæ ç»ãå
±åå¶äœããVideoFrameã®åãæŽ»çšããŠæ£ç¢ºãªèŠèŠèª¿æŽãè¡ã£ãŠãããšãããæ³åããŠã¿ãŠãã ããã
äŸ: è²è£æ£
ãã®äŸã§ã¯ããããªãã¬ãŒã ã®æãããšã³ã³ãã©ã¹ãã調æŽãããåçŽãªè²è£æ£æè¡ã瀺ããŸãã
// Assuming you have a VideoFrame object named 'frame'
// 1. Copy the frame data to a canvas
const canvas = document.createElement('canvas');
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const ctx = canvas.getContext('2d');
const imageData = new ImageData(frame.format === 'RGBA' ? frame.data : convertToRGBA(frame), frame.displayWidth, frame.displayHeight);
ctx.putImageData(imageData, 0, 0);
// 2. Adjust the brightness and contrast
const brightness = 0.2; // Adjust as needed
const contrast = 1.2; // Adjust as needed
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// Red
data[i] = (data[i] - 128) * contrast + 128 + brightness * 255;
// Green
data[i + 1] = (data[i + 1] - 128) * contrast + 128 + brightness * 255;
// Blue
data[i + 2] = (data[i + 2] - 128) * contrast + 128 + brightness * 255;
}
// 3. Update the canvas with the modified image data
ctx.putImageData(imageData, 0, 0);
// 4. Create a new VideoFrame from the processed data
const correctedFrame = new VideoFrame(imageData.data, {
format: 'RGBA',
codedWidth: frame.codedWidth,
codedHeight: frame.codedHeight,
displayWidth: frame.displayWidth,
displayHeight: frame.displayHeight,
timestamp: frame.timestamp,
duration: frame.duration,
});
// 5. Replace the original frame with the corrected frame
frame.close(); // Release the original frame
frame = correctedFrame;
äž»èŠãªèæ ®äºé :
- ããã©ãŒãã³ã¹: è€éãªãšãã§ã¯ãã¯èšç®ã³ã¹ããé«ããªãå¯èœæ§ããããŸããã³ãŒããæé©åããããã©ãŒãã³ã¹ãéèŠãªã¿ã¹ã¯ã«ã¯WebAssemblyã®äœ¿çšãæ€èšããŠãã ããã
- è²ç©ºé: ãããªã§äœ¿çšãããŠããè²ç©ºéã«æ³šæããè²è£æ£ã¢ã«ãŽãªãºã ãç¹å®ã®è²ç©ºéã«é©ããŠããããšã確èªããŠãã ããã
- éç Žå£ç·šé: ãŠãŒã¶ãŒãç°¡åã«å€æŽãå ã«æ»ããããã«ãéç Žå£ç·šéã¯ãŒã¯ãããŒãå®è£ ããŠãã ããã
3. ã³ã³ãã¥ãŒã¿ããžã§ã³ã¢ããªã±ãŒã·ã§ã³
VideoFrameã䜿çšãããšããããªãã¬ãŒã ãããã¯ã»ã«ããŒã¿ãæœåºãããããã³ã³ãã¥ãŒã¿ããžã§ã³ã¢ã«ãŽãªãºã ã«å
¥åã§ããŸããããã«ããããªããžã§ã¯ãæ€åºãé¡èªèãã¢ãŒã·ã§ã³è¿œè·¡ãªã©ã®ã¢ããªã±ãŒã·ã§ã³ã®å¯èœæ§ãåºãããŸããäŸãã°ãã·ã³ã¬ããŒã«ã®èŠåäŒç€Ÿã¯ãVideoFrameã䜿çšããŠç£èŠæ åããªã¢ã«ã¿ã€ã ã§åæããäžå¯©ãªæŽ»åãæ€åºããåœå±ã«èŠåããããšãã§ããŸãããã©ãžã«ã®èŸ²æ¥æè¡äŒæ¥ã¯ããããŒã³ã§æ®åœ±ããäœç©ã®æ åãåæããåã
ã®VideoFrameã«ã³ã³ãã¥ãŒã¿ããžã§ã³æè¡ãé©çšããŠãç
æ°ã害è«ã®åœ±é¿ãåããŠããé åãç¹å®ããããšãã§ããŸãã
äŸ: åçŽãªãšããžæ€åº
ãã®äŸã§ã¯ãSobelãªãã¬ãŒã¿ã䜿çšããéåžžã«åºæ¬çãªãšããžæ€åºã¢ã«ãŽãªãºã ã瀺ããŸããããã¯ç°¡ç¥åãããäŸã§ãããå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ããæŽç·Žãããæè¡ã䜿çšãããŸãã
// Assuming you have a VideoFrame object named 'frame'
// 1. Copy the frame data to a canvas
const canvas = document.createElement('canvas');
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const ctx = canvas.getContext('2d');
const imageData = new ImageData(frame.format === 'RGBA' ? frame.data : convertToGrayscale(frame), frame.displayWidth, frame.displayHeight);
ctx.putImageData(imageData, 0, 0);
// 2. Apply the Sobel operator for edge detection
const data = imageData.data;
const width = frame.displayWidth;
const height = frame.displayHeight;
const edgeData = new Uint8ClampedArray(data.length);
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < width - 1; x++) {
const i = (y * width + x) * 4;
// Sobel operators
const gx = (data[(y - 1) * width + (x - 1)] * -1) + (data[(y - 1) * width + (x + 1)] * 1) +
(data[y * width + (x - 1)] * -2) + (data[y * width + (x + 1)] * 2) +
(data[(y + 1) * width + (x - 1)] * -1) + (data[(y + 1) * width + (x + 1)] * 1);
const gy = (data[(y - 1) * width + (x - 1)] * -1) + (data[(y - 1) * width + x] * -2) + (data[(y - 1) * width + (x + 1)] * -1) +
(data[(y + 1) * width + (x - 1)] * 1) + (data[(y + 1) * width + x] * 2) + (data[(y + 1) * width + (x + 1)] * 1);
// Calculate the magnitude
const magnitude = Math.sqrt(gx * gx + gy * gy);
// Normalize the magnitude
const edgeValue = Math.min(magnitude, 255);
edgeData[i] = edgeValue;
edgeData[i + 1] = edgeValue;
edgeData[i + 2] = edgeValue;
edgeData[i + 3] = 255; // Alpha
}
}
// 3. Create a new ImageData object with the edge data
const edgeImageData = new ImageData(edgeData, width, height);
// 4. Update the canvas with the edge data
ctx.putImageData(edgeImageData, 0, 0);
// 5. Create a new VideoFrame from the processed data
const edgeFrame = new VideoFrame(edgeImageData.data, {
format: 'RGBA',
codedWidth: frame.codedWidth,
codedHeight: frame.codedHeight,
displayWidth: frame.displayWidth,
displayHeight: frame.displayHeight,
timestamp: frame.timestamp,
duration: frame.duration,
});
// 6. Replace the original frame with the edge-detected frame
frame.close(); // Release the original frame
frame = edgeFrame;
function convertToGrayscale(frame) {
const rgbaData = frame.data;
const width = frame.displayWidth;
const height = frame.displayHeight;
const grayscaleData = new Uint8ClampedArray(width * height);
for (let i = 0; i < rgbaData.length; i += 4) {
const r = rgbaData[i];
const g = rgbaData[i + 1];
const b = rgbaData[i + 2];
const grayscale = 0.299 * r + 0.587 * g + 0.114 * b;
const index = i / 4;
grayscaleData[index] = grayscale;
}
return grayscaleData;
}
éèŠãªèæ ®äºé :
- ããã©ãŒãã³ã¹: ã³ã³ãã¥ãŒã¿ããžã§ã³ã¢ã«ãŽãªãºã ã¯èšç®ã³ã¹ããé«ããªãå¯èœæ§ããããŸããæé©ãªããã©ãŒãã³ã¹ã®ããã«ãWebAssemblyãŸãã¯å°çšã®ã³ã³ãã¥ãŒã¿ããžã§ã³ã©ã€ãã©ãªãå©çšããŠãã ããã
- ããŒã¿åœ¢åŒ: å ¥åããŒã¿åœ¢åŒã䜿çšããã³ã³ãã¥ãŒã¿ããžã§ã³ã¢ã«ãŽãªãºã ãšäºææ§ãããããšã確èªããŠãã ããã
- å«ççèæ ®äºé : ã³ã³ãã¥ãŒã¿ããžã§ã³æè¡ãç¹ã«é¡èªèãç£èŠãªã©ã®åéã§ã®äœ¿çšã«ãããå«çç圱é¿ã«çæããŠãã ããããã©ã€ãã·ãŒèŠå¶ãéµå®ããããŒã¿åŠçã®å®è·µã«ãããŠéææ§ã確ä¿ããŠãã ããã
WebCodecsã䜿çšããå®è·µçãªå®è£
VideoFrameã广çã«äœ¿çšããã«ã¯ãWebCodecs APIãšçµ±åããå¿
èŠããããŸãã以äžã«ããã®ããã»ã¹ã®äžè¬çãªæŠèŠã瀺ããŸãã
- ãããªã¹ããªãŒã ã®ååŸ: ãŠãŒã¶ãŒã®ã«ã¡ã©ãããããªã¹ããªãŒã ããã£ããã£ãããããããªãã¡ã€ã«ãèªã¿èŸŒã¿ãŸãã
- VideoDecoderã®äœæ:
VideoDecoderãªããžã§ã¯ããã€ã³ã¹ã¿ã³ã¹åããŠãããªã¹ããªãŒã ããã³ãŒãããŸãã - VideoDecoderã®èšå®: é©åãªã³ãŒããã¯ãšèšå®ã§
VideoDecoderãèšå®ããŸãã - ãããªãã¬ãŒã ã®ãã³ãŒã: ãšã³ã³ãŒãããããããªããŒã¿ã
VideoDecoderã«äŸçµŠããVideoFrameãªããžã§ã¯ããåºåãããŸãã - ãããªãã¬ãŒã ã®åŠç: å¿
èŠã«å¿ããŠ
VideoFrameãªããžã§ã¯ããæäœãããã£ã«ã¿ããšãã§ã¯ãããŸãã¯ã³ã³ãã¥ãŒã¿ããžã§ã³ã¢ã«ãŽãªãºã ãé©çšããŸãã - ãããªãã¬ãŒã ã®ãšã³ã³ãŒã (ãªãã·ã§ã³): åŠçããããããªãã¬ãŒã ãåãšã³ã³ãŒãããå¿
èŠãããå Žåã¯ã
VideoEncoderãªããžã§ã¯ããäœæããVideoFrameãªããžã§ã¯ãããšã³ã³ãŒãããŸãã - ãããªã®è¡šç€º: ãã³ãŒããŸãã¯ãšã³ã³ãŒãããããããªãã¬ãŒã ã
<canvas>èŠçŽ ãŸãã¯ãã®ä»ã®é©åãªè¡šç€ºã¡ã«ããºã ã§è¡šç€ºããŸãã
äŸ: ãããªãã¬ãŒã ã®ãã³ãŒããšè¡šç€º
ãã®äŸã§ã¯ãWebCodecsã䜿çšããŠãããªãã¬ãŒã ããã³ãŒããããã£ã³ãã¹ã«è¡šç€ºããæ¹æ³ã瀺ããŸãã
async function decodeAndDisplay(encodedData) {
const decoder = new VideoDecoder({
output: (frame) => {
// Display the frame on the canvas
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
const imageData = new ImageData(frame.format === 'RGBA' ? frame.data : convertToRGBA(frame), frame.displayWidth, frame.displayHeight);
ctx.putImageData(imageData, 0, 0);
frame.close(); // Release the frame
},
error: (e) => {
console.error('Decoding error:', e);
},
});
// Configure the decoder (replace with your actual codec information)
const config = {
codec: 'avc1.42E01E', // Example: H.264 Baseline Profile
codedWidth: 640,
codedHeight: 480,
};
decoder.configure(config);
// Decode the encoded data
const chunk = new EncodedVideoChunk({
type: 'key',
timestamp: 0,
duration: 0,
data: encodedData,
});
decoder.decode(chunk);
// Flush the decoder
await decoder.flush();
}
VideoFrameã䜿çšããå©ç¹
VideoFrameã䜿çšãããšãåŸæ¥ã®WebããŒã¹ã®ãããªåŠçæè¡ãšæ¯èŒããŠãããã€ãã®å©ç¹ããããŸãã
- ããã©ãŒãã³ã¹:
VideoFrameã¯ãå¹ççãªãããªåŠçã®ããã«ããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã掻çšããããã©ãŒãã³ã¹ã®åäžãšCPU䜿çšçã®åæžãå®çŸããŸãã - æè»æ§:
VideoFrameã¯ããããªåŠçã«å¯ŸããŠãã现ããªå¶åŸ¡ãæäŸããã«ã¹ã¿ã ã¢ã«ãŽãªãºã ããšãã§ã¯ãã®å®è£ ãå¯èœã«ããŸãã - çµ±å:
VideoFrameã¯ãWebAssemblyãWebGLãªã©ã®ä»ã®Webãã¯ãããžãŒãšã·ãŒã ã¬ã¹ã«çµ±åããæŽç·ŽããããããªåŠçã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãã - ã€ãããŒã·ã§ã³:
VideoFrameã¯ãWebããŒã¹ã®ãããªã¢ããªã±ãŒã·ã§ã³ã«æ°ããªå¯èœæ§ãåºããã€ãããŒã·ã§ã³ãšåµé æ§ãè²ã¿ãŸãã
課é¡ãšèæ ®äºé
VideoFrameã¯å€§ããªå©ç¹ãæäŸããŸãããçæãã¹ãããã€ãã®èª²é¡ãšèæ
®äºé
ããããŸãã
- è€éæ§: äœã¬ãã«ã®ã³ãŒããã¯APIãæäœããããšã¯è€éã§ããããããªãšã³ã³ãŒãã£ã³ã°ãšãã³ãŒãã£ã³ã°ã®ååãååã«çè§£ããŠããå¿ èŠããããŸãã
- ãã©ãŠã¶äºææ§: WebCodecs APIã¯æ¯èŒçæ°ããããã©ãŠã¶ã®ãµããŒãã¯ãŸã é²åäžã§ããã¿ãŒã²ãããã©ãŠã¶ãå¿ èŠãªæ©èœããµããŒãããŠããããšã確èªããŠãã ããã
- ããã©ãŒãã³ã¹æé©å: æé©ãªããã©ãŒãã³ã¹ãéæããã«ã¯ãã³ãŒãã®æ³šææ·±ãæé©åãšããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ã®å¹æçãªæŽ»çšãå¿ èŠã§ãã
- ã»ãã¥ãªãã£: ãŠãŒã¶ãŒçæã®ãããªã³ã³ãã³ããæ±ãéã¯ãã»ãã¥ãªãã£ãªã¹ã¯ã«çæããé©åãªã»ãã¥ãªãã£å¯Ÿçãå®è£ ããŠãã ããã
çµè«
WebCodecs VideoFrameã€ã³ã¿ãŒãã§ãŒã¹ã¯ããã©ãŠã¶ã§ãã¬ãŒã ã¬ãã«ã®ãããªåŠçæ©èœãè§£æŸããããã®åŒ·åãªããŒã«ã§ããéçºè
ã«ãããªãã¬ãŒã ãžã®äœã¬ãã«ã¢ã¯ã»ã¹ãæäŸããããšã«ãããVideoFrameã¯ãã«ã¹ã¿ã ãšãã§ã¯ãä»ããªã¢ã«ã¿ã€ã ãããªäŒè°ãé«åºŠãªãããªç·šéãã³ã³ãã¥ãŒã¿ããžã§ã³ãªã©ãå¹
åºãã¢ããªã±ãŒã·ã§ã³ãå¯èœã«ããŸããå
æãã¹ã課é¡ã¯ãããŸãããVideoFrameã䜿çšããæœåšçãªå©ç¹ã¯å€§ããã§ããWebCodecsã®ãã©ãŠã¶ãµããŒããæ¡å€§ãç¶ããã«ã€ããŠãVideoFrameã®åãæŽ»çšããŠãŠã§ãã§ã®ãããªãšã®ã€ã³ã¿ã©ã¯ã·ã§ã³æ¹æ³ãå€é©ãããããã«é©æ°çã§åºæ¿çãªã¢ããªã±ãŒã·ã§ã³ãç»å ŽããããšãæåŸ
ãããŸãã
æè²ã«ãããããŒãã£ã«æå亀æµããã°ã©ã ã®å®çŸããããªã¢ã«ã¿ã€ã ç»å匷調ã«ããã°ããŒãã«ãªé éå»ççžè«ã®ä¿é²ãŸã§ããã®å¯èœæ§ã¯äºå®äžç¡éã§ããWebCodecsãšVideoFrameã®åãæŽ»çšãããŠã§ãããŒã¹ã®ãããªåŠçã®æªæ¥ãåãéããŸãããã