Ich möchte ein Screencasting-Programm für die Windows-Plattform schreiben, bin mir aber nicht sicher, wie ich den Bildschirm erfassen soll. Die einzige mir bekannte Methode ist die Verwendung von GDI, aber ich bin gespannt, ob es andere Möglichkeiten gibt, dies zu tun, und wenn ja, welche verursachen den geringsten Aufwand? Geschwindigkeit hat Priorität.
Das Screencasting-Programm dient zur Aufnahme von Spielmaterial. Wenn dies jedoch die Optionen einschränkt, bin ich immer noch offen für andere Vorschläge, die nicht in diesen Bereich fallen. Wissen ist schließlich nicht schlecht.
Bearbeiten : Ich bin auf diesen Artikel gestoßen: Verschiedene Methoden zum Erfassen des Bildschirms . Es hat mich in die Windows Media API-Methode und die DirectX-Methode eingeführt. In der Schlussfolgerung wird erwähnt, dass das Deaktivieren der Hardwarebeschleunigung die Leistung der Erfassungsanwendung drastisch verbessern kann. Ich bin gespannt, warum das so ist. Könnte jemand die fehlenden Lücken für mich ausfüllen?
Bearbeiten : Ich habe gelesen, dass Screencasting-Programme wie Camtasia ihren eigenen Capture-Treiber verwenden. Könnte mir jemand eine ausführliche Erklärung geben, wie es funktioniert und warum es schneller ist? Möglicherweise benötige ich auch Anleitungen zur Implementierung von so etwas, aber ich bin mir sicher, dass ohnehin bereits Dokumentation vorhanden ist.
Außerdem weiß ich jetzt, wie FRAPS den Bildschirm aufzeichnet. Es bindet die zugrunde liegende Grafik-API ein, um sie aus dem Backpuffer zu lesen. Soweit ich weiß, ist dies schneller als das Lesen aus dem Frontpuffer, da Sie eher aus dem System-RAM als aus dem Video-RAM lesen. Den Artikel können Sie hier lesen .
MovePlayerLeft()
. Außerdem zeichnen Sie die Zeit und Dauer von Tastendrücken und anderen Eingaben auf. Wenn Sie sich dann im Wiedergabemodus befinden, ignorieren Sie einfach die Eingabe und lesen stattdessen die aufgezeichneten Daten. Wenn Sie in den Daten einen linken Tastendruck sehen, rufen Sie anMovePlayerLeft()
.Antworten:
Dies ist, was ich verwende, um einzelne Frames zu sammeln, aber wenn Sie dies ändern und die beiden Ziele die ganze Zeit offen halten, können Sie es mit einem statischen Zähler für den Dateinamen auf die Festplatte "streamen". - Ich kann mich nicht erinnern, wo ich das gefunden habe, aber es wurde geändert, danke an wen auch immer!
quelle
BEARBEITEN: Ich kann sehen, dass dies unter Ihrem ersten Bearbeitungslink als "GDI-Weg" aufgeführt ist. Dies ist immer noch ein anständiger Weg, auch wenn Sie die Leistungsempfehlung auf dieser Website verwenden. Ich denke, Sie können problemlos 30 fps erreichen.
Aus diesem Kommentar (ich habe keine Erfahrung damit, ich verweise nur auf jemanden, der dies tut):
Ich sage nicht, dass dies der schnellste ist, aber der
BitBlt
Vorgang ist im Allgemeinen sehr schnell, wenn Sie zwischen kompatiblen Gerätekontexten kopieren.Als Referenz öffnen Broadcaster Software implementiert etwas wie dies im Rahmen ihrer „dc_capture“ Methode, obwohl anstatt den Zielkontext zu schaffen
hDest
indemCreateCompatibleDC
sie verwenden einIDXGISurface1
, die mit DirectX 10+ arbeitet. Wenn es dafür keine Unterstützung gibt, greifen sie zurückCreateCompatibleDC
.Um es zu ändern eine bestimmte Anwendung zu verwenden, müssen Sie die erste Zeile ändern ,
GetDC(game)
wogame
ist der Griff des Fensters des Spiels, und dann die richtige Setupheight
undwidth
auch des Fensters des Spiels.Sobald Sie die Pixel in hDest / hbDesktop haben, müssen Sie sie noch in einer Datei speichern. Wenn Sie jedoch eine Bildschirmaufnahme durchführen, sollten Sie eine bestimmte Anzahl davon im Speicher puffern und in der Videodatei speichern in Chunks, daher werde ich nicht auf Code zum Speichern eines statischen Images auf der Festplatte verweisen.
quelle
Ich habe eine Videoerfassungssoftware geschrieben, die FRAPS für DirectX-Anwendungen ähnelt. Der Quellcode ist verfügbar und mein Artikel erklärt die allgemeine Technik. Schauen Sie sich http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/ an.
Respektieren Sie Ihre Fragen zur Leistung,
DirectX sollte schneller als GDI sein, außer wenn Sie aus dem Frontpuffer lesen, der sehr langsam ist. Mein Ansatz ähnelt FRAPS (Lesen aus dem Backbuffer). Ich fange eine Reihe von Methoden von Direct3D-Schnittstellen ab.
Für die Videoaufnahme in Echtzeit (mit minimalen Auswirkungen auf die Anwendung) ist ein schneller Codec unerlässlich. FRAPS verwendet einen eigenen verlustfreien Videocodec. Lagarith und HUFFYUV sind generische verlustfreie Video-Codecs für Echtzeitanwendungen. Sie sollten sie sich ansehen, wenn Sie Videodateien ausgeben möchten.
Ein anderer Ansatz zum Aufzeichnen von Screencasts könnte darin bestehen, einen Spiegeltreiber zu schreiben. Laut Wikipedia: Wenn die Videospiegelung aktiv ist, wird jedes Mal, wenn das System an einer Stelle innerhalb des gespiegelten Bereichs auf das primäre Videogerät zeichnet, eine Kopie des Zeichenvorgangs in Echtzeit auf dem gespiegelten Videogerät ausgeführt. Siehe Spiegeltreiber bei MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx .
quelle
Ich verwende d3d9, um den Backbuffer abzurufen, und speichere ihn mithilfe der d3dx-Bibliothek in einer PNG-Datei:
Dazu sollten Sie Ihren Swapbuffer mit erstellen
(Sie garantieren also, dass der Backbuffer nicht beschädigt wird, bevor Sie den Screenshot machen).
quelle
GetRenderTarget
ist?In meinem Eindruck unterscheiden sich der GDI-Ansatz und der DX-Ansatz in seiner Natur. Beim Malen mit GDI wird die FLUSH-Methode angewendet. Beim FLUSH-Ansatz wird der Frame gezeichnet, dann gelöscht und ein weiterer Frame im selben Puffer neu gezeichnet. Dies führt zu Flackern in Spielen, die eine hohe Framerate erfordern.
Ich denke, was Sie wirklich brauchen, ist ein Wiederholungssystem, dem ich voll und ganz zustimme.
quelle
Ich habe eine Klasse geschrieben, die die GDI-Methode für die Bildschirmaufnahme implementiert hat. Ich wollte auch zusätzliche Geschwindigkeit, also habe ich das versucht, nachdem ich die DirectX-Methode (über GetFrontBuffer) entdeckt hatte, und erwartet, dass sie schneller ist.
Ich war bestürzt festzustellen, dass GDI etwa 2,5-mal schneller arbeitet. Nach 100 Versuchen, mein Dual-Monitor-Display zu erfassen, betrug die GDI-Implementierung durchschnittlich 0,65 Sekunden pro Bildschirmaufnahme, während die DirectX-Methode durchschnittlich 1,72 Sekunden betrug. GDI ist also nach meinen Tests definitiv schneller als GetFrontBuffer.
Ich konnte Brandrews Code nicht zum Testen von DirectX über GetRenderTargetData verwenden. Die Bildschirmkopie war rein schwarz. Es könnte jedoch diesen leeren Bildschirm sehr schnell kopieren! Ich werde weiter daran basteln und hoffe, eine funktionierende Version zu bekommen, um echte Ergebnisse daraus zu sehen.
quelle
GetRenderTargetData
Ansatz funktioniert. Vielleicht schreibe ich meine eigene Antwort, wenn ich meine Bewerbung abgeschlossen habe. Oder Sie können Ihre aktualisieren, sobald alles funktioniert.Ein paar Dinge, die ich herausfinden konnte: Anscheinend ist die Verwendung eines "Spiegeltreibers" schnell, obwohl mir kein OSS bekannt ist.
Warum ist RDP im Vergleich zu anderen Fernbedienungssoftware so schnell?
Auch anscheinend sind einige Faltungen von StretchRect schneller als BitBlt
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
Und die von Ihnen erwähnte (Fraps, die sich in die D3D-DLLs einbinden) ist wahrscheinlich die einzige Möglichkeit für D3D-Anwendungen, funktioniert jedoch nicht mit Windows XP Desktop Capture. Jetzt wünschte ich mir nur, es gäbe ein Fraps, das hinsichtlich der Geschwindigkeit für normale Desktop-Fenster gleichwertig ist ... irgendjemand?
(Ich denke, mit Aero können Sie möglicherweise fraps-ähnliche Haken verwenden, aber XP-Benutzer hätten kein Glück).
Anscheinend auch Ändern der Bildschirmbittiefe und / oder Deaktivieren der Hardwarebeschleunigung. könnte helfen (und / oder Aero deaktivieren).
https://github.com/rdp/screen-capture-recorder-program enthält ein relativ schnelles BitBlt-basiertes Erfassungsdienstprogramm und einen Benchmarker als Teil seiner Installation, mit dem Sie BitBlt-Geschwindigkeiten messen können, um sie zu optimieren.
VirtualDub verfügt außerdem über ein "opengl" -Bildschirmerfassungsmodul, das angeblich schnell ist und beispielsweise Änderungen erkennt ( http://www.virtualdub.org/blog/pivot/entry.php?id=290)
quelle
Für C ++ können Sie Folgendes verwenden: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Dies funktioniert möglicherweise nicht bei allen Arten von 3D-Anwendungen / Video-Apps. Dann kann dieser Link nützlicher sein, da er 3 verschiedene Methoden beschreibt, die Sie verwenden können.
Alte Antwort (C #):
Sie können System.Drawing.Graphics.Copy verwenden , aber es ist nicht sehr schnell.
Ein Beispielprojekt, das ich genau dazu geschrieben habe: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/
Ich plane, dieses Beispiel mit einer schnelleren Methode wie Direct3D zu aktualisieren: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/
Und hier ist ein Link zum Aufnehmen von Videos: Wie wird der Bildschirm mit C # .Net als Video aufgenommen?
quelle
Mit Windows 8 führte Microsoft die Windows Desktop Duplication API ein. Das ist die offiziell empfohlene Vorgehensweise. Eine nette Funktion für Screencasts ist, dass sie Fensterbewegungen erkennt, sodass Sie Blockdeltas übertragen können, wenn Fenster verschoben werden, anstatt Rohpixel. Außerdem erfahren Sie, welche Rechtecke sich von einem Bild zum nächsten geändert haben.
Der Microsoft-Beispielcode ist ziemlich komplex, aber die API ist tatsächlich einfach und benutzerfreundlich. Ich habe ein Beispielprojekt zusammengestellt, das viel einfacher ist als das offizielle Beispiel:
https://github.com/bmharper/WindowsDesktopDuplicationSample
Dokumente: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api
Offizieller Microsoft-Beispielcode: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
quelle
Sie können das Open-Source-Projekt WinRobot @git von c ++ ausprobieren , einen leistungsstarken Screen Capturer
Unterstützung :
quelle
Ich selbst mache es mit DirectX und denke, es ist so schnell, wie Sie es sich wünschen würden. Ich habe kein schnelles Codebeispiel, aber ich fand das, was nützlich sein sollte. Die DirectX11-Version sollte sich nicht sehr unterscheiden, DirectX9 vielleicht ein bisschen mehr, aber das ist der richtige Weg
quelle
Mir ist klar, dass der folgende Vorschlag Ihre Frage nicht beantwortet, aber die einfachste Methode, die ich gefunden habe, um eine sich schnell ändernde DirectX-Ansicht zu erfassen, besteht darin, eine Videokamera an den S-Video-Anschluss der Grafikkarte anzuschließen und die Bilder als aufzunehmen ein Film. Übertragen Sie dann das Video von der Kamera zurück in eine MPG-, WMV-, AVI- usw. Datei auf dem Computer.
quelle
Die Bildschirmaufzeichnung kann in C # mithilfe der VLC-API erfolgen . Ich habe ein Beispielprogramm erstellt, um dies zu demonstrieren. Es verwendet die Bibliotheken LibVLCSharp und VideoLAN.LibVLC.Windows . Mit dieser plattformübergreifenden API können Sie viele weitere Funktionen im Zusammenhang mit dem Rendern von Videos erzielen.
API-Dokumentation finden Sie unter: LibVLCSharp API Github
quelle
DXGI Desktop Capture
Projekt, das das Desktop-Image mit DXGI-Duplizierung erfasst. Speichert das aufgenommene Bild in verschiedenen Bildformaten (* .bmp; * .jpg; * .tif) in der Datei.
Dieses Beispiel ist in C ++ geschrieben. Sie benötigen auch Erfahrung mit DirectX (D3D11, D2D1).
Was die Anwendung kann
quelle