Tengo una página web donde incrusté un video de YouTube en un iframe. Necesito capturar la captura de pantalla del video de YouTube. El uso de bibliotecas como html2canvas y dom2image no funcionó debido a las limitaciones entre dominios.
Entonces, se me ocurrió la idea de capturar la captura de pantalla de la ventana completa del navegador usando getDisplayMedia() y luego recortar la parte relevante usando drawImage() . En mi cabeza, parece tener mucho sentido, solo identificando la ubicación del iframe y luego usando drawImage para recortarlo. Sin embargo, no recorta la parte relevante en todos los tamaños de pantalla. Cuando cambio la resolución de la pantalla o hago zoom, parece romperse.
Otra idea sería escribir un algoritmo de IA para capturar esto. Pero creo que es una exageración. ¿Alguna idea sobre cómo hacer que funcione para todos los tamaños y resoluciones de pantalla?
<h1>Hello</h1> <div style="margin: 10;"> <iframe id="youtubeiframe" width="640" height="340" src="https://www.youtube.com/embed/vDYP6AKw8bk?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen> </iframe> </div> <div id="picture" style="margin-top:60; background-color:'gray'"></div> <script> navigator.mediaDevices.getDisplayMedia({ preferCurrentTab: true }).then(stream => { captureStream = stream; track = captureStream.getVideoTracks()[0]; const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); const offsets = document.getElementById("youtubeiframe")?.getBoundingClientRect(); const posX = offsets.left; const posY = offsets.top; const width = offsets.width; const height = offsets.height; canvas.width = width; canvas.height = height; let image = new ImageCapture(track); const bitmap = image.grabFrame().then(bitmap => { context?.drawImage(bitmap, posX, posY, width, height, 0, 0, width, height); const pic = document.getElementById("picture"); if(pic.childElementCount > 0) pic.replaceChild(canvas,pic.children[0]); else pic.appendChild(canvas); }); }); </script>Introduje un paso intermedio en el que la imagen se escala al mismo tamaño que la ventana del navegador y luego el recorte funciona como se esperaba. Aquí está el código para ello:
const tempCanvas = document.createElement("canvas"); tempCanvas.width = window.innerWidth; tempCanvas.height = window.innerHeight; const tempContext = tempCanvas.getContext("2d"); tempContext?.drawImage(bitmap,0,0,tempCanvas.width,tempCanvas.height); context?.drawImage(tempCanvas, posX, posY, width, height, 0, 0, width, height);Aquí está el código completo, incluida la solución anterior:
<h1>Hello</h1> <div style="margin: 10;"> <iframe id="youtubeiframe" width="640" height="340" src="https://www.youtube.com/embed/vDYP6AKw8bk?controls=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen> </iframe> </div> <div id="picture" style="margin-top:60; background-color:'gray'"></div> <script> navigator.mediaDevices.getDisplayMedia({ preferCurrentTab: true }).then(stream => { captureStream = stream; track = captureStream.getVideoTracks()[0]; const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); const offsets = document.getElementById("youtubeiframe")?.getBoundingClientRect(); const posX = offsets.left; const posY = offsets.top; const width = offsets.width; const height = offsets.height; canvas.width = width; canvas.height = height; let image = new ImageCapture(track); const bitmap = image.grabFrame().then(bitmap => { const tempCanvas = document.createElement("canvas"); tempCanvas.width = window.innerWidth; tempCanvas.height = window.innerHeight; const tempContext = tempCanvas.getContext("2d"); tempContext?.drawImage(bitmap,0,0,tempCanvas.width,tempCanvas.height); context?.drawImage(tempCanvas, posX, posY, width, height, 0, 0, width, height); const pic = document.getElementById("picture"); if(pic.childElementCount > 0) pic.replaceChild(canvas,pic.children[0]); else pic.appendChild(canvas); }); }); </script>