Quiero escribir un programa de screencasting para la plataforma Windows, pero no estoy seguro de cómo capturar la pantalla. El único método que conozco es usar GDI, pero tengo curiosidad por saber si hay otras formas de hacerlo, y si las hay, ¿cuál incurre en la menor sobrecarga? La velocidad es una prioridad.
El programa de screencasting será para grabar imágenes del juego, aunque, si esto reduce las opciones, todavía estoy abierto a cualquier otra sugerencia que quede fuera de este alcance. El conocimiento no es malo, después de todo.
Editar : Me encontré con este artículo: Varios métodos para capturar la pantalla . Me ha presentado la forma de hacerlo de la API de Windows Media y la forma de hacerlo de DirectX. En la conclusión se menciona que deshabilitar la aceleración de hardware podría mejorar drásticamente el rendimiento de la aplicación de captura. Tengo curiosidad de por qué es esto. ¿Alguien podría completar los espacios en blanco que faltan por mí?
Editar : leí que los programas de captura de pantalla como Camtasia usan su propio controlador de captura. ¿Podría alguien darme una explicación detallada sobre cómo funciona y por qué es más rápido? También es posible que necesite orientación para implementar algo así, pero estoy seguro de que hay documentación existente de todos modos.
Además, ahora sé cómo FRAPS graba la pantalla. Engancha la API de gráficos subyacente para leer desde el búfer posterior. Por lo que entiendo, esto es más rápido que leer desde el búfer frontal, porque estás leyendo desde la RAM del sistema, en lugar de la RAM de video. Puedes leer el artículo aquí .
MovePlayerLeft()
. Y también registra el tiempo y la duración de las pulsaciones de teclas y otras entradas. Luego, cuando está en modo de reproducción, simplemente ignora la entrada y lee los datos grabados. Si, en los datos, ve una tecla izquierda presionada, llamaMovePlayerLeft()
.Respuestas:
Esto es lo que uso para recopilar fotogramas individuales, pero si modifica esto y mantiene los dos objetivos abiertos todo el tiempo, entonces podría "transmitirlo" al disco usando un contador estático para el nombre del archivo. - No recuerdo dónde encontré esto, pero se ha modificado, ¡gracias a quien sea!
fuente
EDITAR: puedo ver que esto aparece en su primer enlace de edición como "la forma GDI". Esta sigue siendo una forma decente, incluso con el aviso de rendimiento en ese sitio, creo que puede llegar a 30 fps fácilmente.
De este comentario (no tengo experiencia haciendo esto, solo estoy haciendo referencia a alguien que sí lo hace):
No digo que sea el más rápido, pero la
BitBlt
operación generalmente es muy rápida si está copiando entre contextos de dispositivos compatibles.Como referencia, Open Broadcaster Software implementa algo como esto como parte de su método "dc_capture" , aunque en lugar de crear el contexto de destino
hDest
mediante elCreateCompatibleDC
uso de unIDXGISurface1
, que funciona con DirectX 10+. Si no hay apoyo para esto, recurren aCreateCompatibleDC
.Para cambiarlo para usar una aplicación específica, debes cambiar la primera línea a
GetDC(game)
dondegame
está el identificador de la ventana del juego, y luego establecer la derechaheight
ywidth
la ventana del juego también.Una vez que tenga los píxeles en hDest / hbDesktop, aún debe guardarlos en un archivo, pero si está haciendo una captura de pantalla, creo que querría almacenar un cierto número de ellos en la memoria y guardarlos en el archivo de video en fragmentos, por lo que no señalaré el código para guardar una imagen estática en el disco.
fuente
Escribí un software de captura de video, similar a FRAPS para aplicaciones DirectX. El código fuente está disponible y mi artículo explica la técnica general. Mire http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/
Respeto a sus preguntas relacionadas con el rendimiento,
DirectX debería ser más rápido que GDI, excepto cuando está leyendo desde el búfer frontal, que es muy lento. Mi enfoque es similar a FRAPS (lectura de backbuffer). Intercepto un conjunto de métodos de las interfaces Direct3D.
Para la grabación de video en tiempo real (con un impacto mínimo en la aplicación), es esencial un códec rápido. FRAPS usa su propio códec de video sin pérdidas. Lagarith y HUFFYUV son códecs de video genéricos sin pérdidas diseñados para aplicaciones en tiempo real. Debería mirarlos si desea generar archivos de video.
Otro enfoque para grabar screencasts podría ser escribir un Driver Mirror. Según Wikipedia: cuando la duplicación de video está activa, cada vez que el sistema se dirige al dispositivo de video primario en una ubicación dentro del área reflejada, se ejecuta una copia de la operación de dibujo en el dispositivo de video reflejado en tiempo real. Vea los controladores espejo en MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx .
fuente
Uso d3d9 para obtener el backbuffer, y lo guardo en un archivo png usando la biblioteca d3dx:
Para hacer esto, debes crear tu swapbuffer con
(Por lo tanto, usted garantiza que el backbuffer no está dañado antes de tomar la captura de pantalla).
fuente
GetRenderTarget
es?En mi impresión, el enfoque GDI y el enfoque DX son diferentes en su naturaleza. pintar usando GDI aplica el método FLUSH, el enfoque FLUSH dibuja el cuadro, luego lo borra y vuelve a dibujar otro cuadro en el mismo búfer, esto dará como resultado que el parpadeo en los juegos requiera una alta velocidad de cuadros.
Creo que lo que realmente necesitas es un sistema de reproducción, que estoy totalmente de acuerdo con lo que la gente discutió.
fuente
Escribí una clase que implementó el método GDI para la captura de pantalla. Yo también quería velocidad adicional, así que después de descubrir el método DirectX (a través de GetFrontBuffer) lo intenté, esperando que fuera más rápido.
Me consternó descubrir que GDI funciona aproximadamente 2.5 veces más rápido. Después de 100 intentos de capturar mi monitor dual, la implementación de GDI promedió 0.65 segundos por captura de pantalla, mientras que el método DirectX promedió 1.72 segundos. Entonces, GDI es definitivamente más rápido que GetFrontBuffer, según mis pruebas.
No pude hacer que el código de Brandrew funcionara para probar DirectX a través de GetRenderTargetData. La copia de la pantalla salió puramente negra. Sin embargo, ¡podría copiar esa pantalla en blanco súper rápido! Seguiré jugando con eso y espero obtener una versión que funcione para ver resultados reales.
fuente
GetRenderTargetData
enfoque funciona. Tal vez escriba mi propia respuesta cuando termine mi solicitud. O bien, puede actualizar el suyo una vez que tenga todo funcionando.Algunas cosas que he podido deducir: aparentemente usar un "controlador espejo" es rápido, aunque no conozco un OSS.
¿Por qué RDP es tan rápido en comparación con otro software de control remoto?
También, aparentemente, usar algunas convoluciones de StretchRect es más rápido que BitBlt
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
Y el que mencionó (fraps enganchando a las D3D dll) es probablemente la única forma para las aplicaciones D3D, pero no funcionará con la captura de escritorio de Windows XP. Así que ahora solo desearía que hubiera un fraps equivalente en velocidad para las ventanas de escritorio normales ... ¿alguien?
(Creo que con aero podría usar ganchos tipo fraps, pero los usuarios de XP no tendrían suerte).
Aparentemente, también cambia la profundidad de bits de la pantalla y / o deshabilita la aceleración de hardware. podría ayudar (y / o deshabilitar aero).
https://github.com/rdp/screen-capture-recorder-program incluye una utilidad de captura basada en BitBlt razonablemente rápida y un punto de referencia como parte de su instalación, que puede permitirle comparar las velocidades de BitBlt para optimizarlas.
VirtualDub también tiene un módulo de captura de pantalla "opengl" que se dice que es rápido y hace cosas como detección de cambios http://www.virtualdub.org/blog/pivot/entry.php?id=290
fuente
Para C ++ puede usar: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Esto puede no funcionar en todos los tipos de aplicaciones 3D / aplicaciones de video. Entonces este enlace puede ser más útil, ya que describe 3 métodos diferentes que puede usar.
Respuesta anterior (C #):
puede usar System.Drawing.Graphics.Copy , pero no es muy rápido.
Un proyecto de muestra que escribí haciendo exactamente esto: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/
Estoy planeando actualizar esta muestra usando un método más rápido como Direct3D: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/
Y aquí hay un enlace para capturar video: ¿Cómo capturar la pantalla para que sea video usando C # .Net?
fuente
Con Windows 8, Microsoft presentó la API de duplicación de escritorio de Windows. Esa es la forma oficialmente recomendada de hacerlo. Una buena característica que tiene para el screencasting es que detecta el movimiento de la ventana, por lo que puede transmitir deltas de bloque cuando las ventanas se mueven, en lugar de píxeles sin formato. Además, le indica qué rectángulos han cambiado, de un cuadro al siguiente.
El código de ejemplo de Microsoft es bastante complejo, pero la API es realmente simple y fácil de usar. He reunido un proyecto de ejemplo que es mucho más simple que el ejemplo oficial:
https://github.com/bmharper/WindowsDesktopDuplicationSample
Documentos: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api
Código de ejemplo oficial de Microsoft: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
fuente
Puede probar el proyecto de código abierto de c ++ WinRobot @git , un potente capturador de pantalla
Apoyo:
fuente
Yo mismo lo hago con directx y creo que es tan rápido como te gustaría que fuera. No tengo un ejemplo de código rápido, pero encontré esto que debería ser útil. la versión de directx11 no debería diferir mucho, directx9 quizás un poco más, pero ese es el camino a seguir
fuente
Me doy cuenta de que la siguiente sugerencia no responde a su pregunta, pero el método más simple que he encontrado para capturar una vista DirectX que cambia rápidamente, es conectar una cámara de video al puerto S-video de la tarjeta de video y grabar las imágenes como una película. Luego transfiera el video de la cámara a un archivo MPG, WMV, AVI, etc. en la computadora.
fuente
La grabación de pantalla se puede hacer en C # usando la API VLC . He hecho un programa de muestra para demostrar esto. Utiliza LibVLCSharp y VideoLAN.LibVLC.Windows bibliotecas . Podría lograr muchas más funciones relacionadas con la representación de video utilizando esta API multiplataforma.
Para ver la documentación de la API, consulte: LibVLCSharp API Github
fuente
Captura de escritorio DXGI
Proyecto que captura la imagen del escritorio con duplicación DXGI. Guarda la imagen capturada en el archivo en diferentes formatos de imagen (* .bmp; * .jpg; * .tif).
Esta muestra está escrita en C ++. También necesita algo de experiencia con DirectX (D3D11, D2D1).
Lo que puede hacer la aplicación
fuente