Quero escrever um programa de captura de tela para a plataforma Windows, mas não tenho certeza de como capturar a tela. O único método que eu conheço é usar o GDI, mas estou curioso para saber se existem outras maneiras de fazer isso e, se houver, o que implica menos sobrecarga? A velocidade é uma prioridade.
O programa de screencasting será para a gravação de cenas de jogos, embora, se isso restringir as opções, ainda estou aberto a outras sugestões que se enquadram nesse escopo. Afinal, o conhecimento não é ruim.
Edit : Me deparei com este artigo: Vários métodos para capturar a tela . Ele me apresentou a maneira de fazer a API do Windows Media e a maneira de fazer o DirectX. Menciona na conclusão que desabilitar a aceleração de hardware pode melhorar drasticamente o desempenho do aplicativo de captura. Estou curioso para saber por que isso acontece. Alguém poderia preencher os espaços em branco para mim?
Edit : Eu li que programas de screencasting como o Camtasia usam seu próprio driver de captura. Alguém poderia me dar uma explicação detalhada sobre como funciona e por que é mais rápido? Também posso precisar de orientações sobre como implementar algo assim, mas tenho certeza de que existe documentação existente de qualquer maneira.
Além disso, agora eu sei como o FRAPS grava a tela. Ele conecta a API gráfica subjacente para ler a partir do buffer traseiro. Pelo que entendi, isso é mais rápido do que ler no buffer frontal, porque você está lendo na RAM do sistema, em vez da RAM de vídeo. Você pode ler o artigo aqui .
MovePlayerLeft()
. E você também grava a hora e a duração das teclas pressionadas e outras entradas. Então, quando você está no modo de reprodução, simplesmente ignora a entrada e lê os dados gravados. Se, nos dados, você pressionar a tecla esquerda, ligueMovePlayerLeft()
.Respostas:
É isso que eu uso para coletar quadros únicos, mas se você modificar isso e manter os dois destinos abertos o tempo todo, poderá "transmiti-lo" para o disco usando um contador estático para o nome do arquivo. - Não me lembro onde encontrei isso, mas foi modificado, graças a quem!
fonte
Edição: Eu posso ver que isso está listado no seu primeiro link de edição como "o caminho GDI". Esse ainda é um caminho decente, mesmo com o aviso de desempenho nesse site; você pode chegar a 30fps facilmente, eu acho.
A partir deste comentário (não tenho experiência em fazer isso, estou apenas referenciando alguém que faz):
Não estou dizendo que esse é o mais rápido, mas a
BitBlt
operação geralmente é muito rápida se você estiver copiando entre contextos de dispositivos compatíveis.Para referência, Abrir Broadcaster Software implementa algo como isso como parte de sua "dc_capture" método, embora em vez de criar o contexto de destino
hDest
usandoCreateCompatibleDC
eles usam umIDXGISurface1
, que trabalha com DirectX 10 +. Se não houver suporte para isso, eles retornam aoCreateCompatibleDC
.Para alterá-lo para usar um aplicativo específico, você precisa alterar a primeira linha para
GetDC(game)
ondegame
está a alça da janela do jogo e, em seguida, definir a direitaheight
ewidth
a janela do jogo também.Depois de ter os pixels no hDest / hbDesktop, você ainda precisará salvá-lo em um arquivo, mas se estiver fazendo captura de tela, acho que você gostaria de armazenar em buffer um certo número deles na memória e salvá-lo no arquivo de vídeo em pedaços, por isso não apontarei para o código para salvar uma imagem estática no disco.
fonte
Eu escrevi um software de captura de vídeo, semelhante ao FRAPS para aplicativos DirectX. O código fonte está disponível e meu artigo explica a técnica geral. Veja http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/
Respeite suas perguntas relacionadas ao desempenho,
O DirectX deve ser mais rápido que o GDI, exceto quando você está lendo no buffer frontal, que é muito lento. Minha abordagem é semelhante à FRAPS (leitura do backbuffer). Intercepto um conjunto de métodos das interfaces do Direct3D.
Para gravação de vídeo em tempo real (com impacto mínimo no aplicativo), um codec rápido é essencial. O FRAPS usa seu próprio codec de vídeo sem perdas. Lagarith e HUFFYUV são codecs de vídeo genéricos sem perdas, projetados para aplicativos em tempo real. Você deve olhar para eles se quiser gerar arquivos de vídeo.
Outra abordagem para gravar screencasts pode ser escrever um driver de espelho. De acordo com a Wikipedia: Quando o espelhamento de vídeo está ativo, cada vez que o sistema desenha no dispositivo de vídeo principal em um local dentro da área espelhada, uma cópia da operação de desenho é executada no dispositivo de vídeo espelhado em tempo real. Consulte os drivers de espelho no MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx .
fonte
Eu uso o d3d9 para obter o backbuffer e salve-o em um arquivo png usando a biblioteca d3dx:
Para fazer isso, você deve criar seu swapbuffer com
(Portanto, você garante que o backbuffer não seja mutilado antes de fazer a captura de tela).
fonte
GetRenderTarget
é?Na minha impressão, a abordagem GDI e a abordagem DX são diferentes em sua natureza. a pintura usando GDI aplica o método FLUSH, a abordagem FLUSH desenha o quadro, limpe-o e redesenhe outro quadro no mesmo buffer, isso resultará em tremulação nos jogos que exigem alta taxa de quadros.
Eu acho que o que você realmente precisa é de um sistema de repetição, que eu concordo totalmente com o que as pessoas discutiram.
fonte
Eu escrevi uma classe que implementou o método GDI para captura de tela. Eu também queria velocidade extra, então, depois de descobrir o método DirectX (via GetFrontBuffer), tentei isso, esperando que fosse mais rápido.
Fiquei consternado ao descobrir que o GDI executa cerca de 2,5 vezes mais rápido. Após 100 tentativas de captura do meu monitor de dois monitores, a implementação do GDI teve uma média de 0,65s por captura de tela, enquanto o método DirectX obteve uma média de 1,72s. Portanto, o GDI é definitivamente mais rápido que o GetFrontBuffer, de acordo com meus testes.
Não consegui que o código de Brandrew funcionasse para testar o DirectX via GetRenderTargetData. A cópia da tela saiu totalmente preta. No entanto, ele pode copiar a tela em branco super rápido! Vou continuar mexendo nisso e espero obter uma versão funcional para ver resultados reais.
fonte
GetRenderTargetData
abordagem funciona. Talvez eu escreva minha própria resposta quando terminar minha inscrição. Ou você pode atualizar o seu assim que tiver conseguido tudo funcionar.Algumas coisas que consegui entender: aparentemente, o uso de um "driver de espelho" é rápido, embora eu não esteja ciente de um OSS.
Por que o RDP é tão rápido em comparação com outros softwares de controle remoto?
Aparentemente, também o uso de algumas convoluções do StretchRect é mais rápido que o BitBlt
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
E o que você mencionou (fraps conectando-se às DLLs D3D) é provavelmente o único caminho para aplicativos D3D, mas não funcionará com a captura de área de trabalho do Windows XP. Então agora eu só queria que houvesse um equivalente fraps em velocidade para janelas normais de desktop ... alguém?
(Eu acho que com o aero você pode usar ganchos do tipo fraps, mas os usuários do XP ficariam sem sorte).
Aparentemente, também alterando a profundidade dos bits da tela e / ou desativando a aceleração do hardware. pode ajudar (e / ou desativar o Aero).
O https://github.com/rdp/screen-capture-recorder-program inclui um utilitário de captura baseado em BitBlt razoavelmente rápido e um benchmarker como parte de sua instalação, que permite comparar as velocidades de BitBlt para otimizá-las.
O VirtualDub também possui um módulo de captura de tela "opengl", que é rápido e funciona como detecção de alterações http://www.virtualdub.org/blog/pivot/entry.php?id=290
fonte
Para C ++, você pode usar: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Isso pode não funcionar em todos os tipos de aplicativos 3D / aplicativos de vídeo. Então este link pode ser mais útil, pois descreve três métodos diferentes que você pode usar.
Resposta antiga (C #):
Você pode usar System.Drawing.Graphics.Copy , mas não é muito rápido.
Um projeto de amostra que escrevi fazendo exatamente isso: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/
Estou planejando atualizar esse exemplo usando um método mais rápido como o Direct3D: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/
E aqui está um link para capturar em vídeo: Como capturar tela para ser vídeo usando C # .Net?
fonte
Com o Windows 8, a Microsoft apresentou a API de duplicação da área de trabalho do Windows. Essa é a maneira oficialmente recomendada de fazê-lo. Um recurso interessante para a captura de tela é que ele detecta o movimento da janela, para que você possa transmitir deltas de bloco quando a janela é movida, em vez de pixels brutos. Além disso, informa quais retângulos foram alterados, de um quadro para o outro.
O código de exemplo da Microsoft é bastante complexo, mas a API é realmente simples e fácil de usar. Eu montei um projeto de exemplo que é muito mais simples que o exemplo oficial:
https://github.com/bmharper/WindowsDesktopDuplicationSample
Documentos: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api
Código de exemplo oficial da Microsoft: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
fonte
Você pode experimentar o projeto de código aberto c ++ WinRobot @git , um poderoso capturador de tela
Apoio, suporte :
fonte
Eu mesmo faço isso com o directx e acho que é tão rápido quanto você gostaria que fosse. Eu não tenho um exemplo de código rápido, mas achei isso que deve ser útil. a versão do directx11 não deve diferir muito, o directx9 talvez um pouco mais, mas esse é o caminho a percorrer
fonte
Sei que a sugestão a seguir não responde à sua pergunta, mas o método mais simples que encontrei para capturar uma visualização do DirectX que muda rapidamente é conectar uma câmera de vídeo na porta S-video da placa de vídeo e gravar as imagens como um filme. Depois transfira o vídeo da câmera de volta para um arquivo MPG, WMV, AVI etc. no computador.
fonte
A gravação de tela pode ser feita em C # usando a API do VLC . Eu fiz um exemplo de programa para demonstrar isso. Ele usa as bibliotecas LibVLCSharp e VideoLAN.LibVLC.Windows . Você pode obter muitos outros recursos relacionados à renderização de vídeo usando esta API de plataforma cruzada.
Para documentação da API, consulte: LibVLCSharp API Github
fonte
Captura de mesa DXGI
Projeto que captura a imagem da área de trabalho com duplicação de DXGI. Salva a imagem capturada no arquivo em diferentes formatos de imagem (* .bmp; * .jpg; * .tif).
Este exemplo é escrito em C ++. Você também precisa de alguma experiência com o DirectX (D3D11, D2D1).
O que o aplicativo pode fazer
fonte