Saya ingin menulis program screencasting untuk platform Windows, tetapi saya tidak yakin bagaimana cara menangkap layar. Satu-satunya metode yang saya ketahui adalah menggunakan GDI, tetapi saya ingin tahu apakah ada cara lain untuk melakukan hal ini, dan, jika ada, mana yang mengeluarkan biaya paling murah? Kecepatan adalah prioritas.
Program screencasting akan untuk merekam cuplikan game, meskipun, jika ini mempersempit pilihan, saya masih terbuka untuk saran lain yang tidak termasuk dalam lingkup ini. Bagaimanapun, pengetahuan tidak buruk.
Sunting : Saya menemukan artikel ini: Berbagai metode untuk menangkap layar . Ini telah memperkenalkan saya dengan cara Windows Media API untuk melakukannya dan cara DirectX melakukannya. Disebutkan dalam kesimpulan bahwa menonaktifkan akselerasi perangkat keras dapat secara drastis meningkatkan kinerja aplikasi penangkapan. Saya ingin tahu mengapa ini terjadi. Adakah yang bisa mengisi kekosongan yang hilang untuk saya?
Sunting : Saya membaca bahwa program screencasting seperti Camtasia menggunakan driver tangkap mereka sendiri. Bisakah seseorang memberi saya penjelasan mendalam tentang cara kerjanya, dan mengapa lebih cepat? Saya mungkin juga membutuhkan panduan untuk mengimplementasikan sesuatu seperti itu, tetapi saya yakin ada dokumentasi yang ada.
Juga, saya sekarang tahu bagaimana FRAPS merekam layar. Ini mengaitkan API grafis yang mendasarinya untuk membaca dari buffer belakang. Dari apa yang saya mengerti, ini lebih cepat daripada membaca dari buffer depan, karena Anda membaca dari RAM sistem, bukan RAM video. Anda dapat membaca artikelnya di sini .
MovePlayerLeft()
. Dan Anda juga merekam waktu dan durasi penekanan tombol dan input lainnya. Kemudian, ketika Anda dalam mode pemutaran, Anda mengabaikan input, dan bukannya membaca data yang direkam. Jika, dalam data, Anda melihat tombol kiri tekan, Anda meneleponMovePlayerLeft()
.Jawaban:
Ini yang saya gunakan untuk mengumpulkan frame tunggal, tetapi jika Anda memodifikasi ini dan menjaga dua target terbuka sepanjang waktu maka Anda bisa "stream" ke disk menggunakan penghitung statis untuk nama file. - Saya tidak dapat mengingat di mana saya menemukan ini, tetapi telah dimodifikasi, terima kasih kepada siapa pun!
sumber
EDIT: Saya dapat melihat bahwa ini terdaftar di bawah tautan edit pertama Anda sebagai "cara GDI". Ini masih cara yang layak untuk pergi bahkan dengan penasehat kinerja di situs itu, Anda bisa mendapatkan 30fps dengan mudah saya pikir.
Dari komentar ini (saya tidak punya pengalaman melakukan ini, saya hanya mereferensikan seseorang yang melakukannya):
Saya tidak mengatakan ini adalah yang tercepat, tetapi
BitBlt
operasi ini umumnya sangat cepat jika Anda menyalin antara konteks perangkat yang kompatibel.Sebagai referensi, Open Broadcaster Software mengimplementasikan sesuatu seperti ini sebagai bagian dari metode "dc_capture" mereka , meskipun daripada menciptakan konteks tujuan
hDest
menggunakanCreateCompatibleDC
mereka menggunakanIDXGISurface1
, yang bekerja dengan DirectX 10+. Jika tidak ada dukungan untuk ini mereka kembali keCreateCompatibleDC
.Untuk mengubahnya agar menggunakan aplikasi tertentu, Anda perlu mengubah baris pertama ke
GetDC(game)
tempatgame
pegangan jendela permainan, lalu atur kananheight
danwidth
juga jendela permainan.Setelah Anda memiliki piksel dalam hDest / hbDesktop, Anda masih perlu menyimpannya ke file, tetapi jika Anda melakukan screen capture maka saya akan berpikir Anda ingin buffer dalam jumlah tertentu dalam memori dan menyimpan ke file video dalam potongan, jadi saya tidak akan menunjuk ke kode untuk menyimpan gambar statis ke disk.
sumber
Saya menulis perangkat lunak pengambilan video, mirip dengan FRAPS untuk aplikasi DirectX. Kode sumber tersedia dan artikel saya menjelaskan teknik umum. Lihatlah http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/
Hormati pertanyaan Anda yang terkait dengan kinerja,
DirectX harus lebih cepat daripada GDI kecuali ketika Anda membaca dari frontbuffer yang sangat lambat. Pendekatan saya mirip dengan FRAPS (membaca dari backbuffer). Saya mencegat serangkaian metode dari antarmuka Direct3D.
Untuk merekam video dalam waktu nyata (dengan dampak aplikasi minimal), codec cepat sangat penting. FRAPS menggunakan codec video losslessnya sendiri. Lagarith dan HUFFYUV adalah codec video umum lossless yang dirancang untuk aplikasi waktu nyata. Anda harus melihatnya jika Anda ingin menghasilkan file video.
Pendekatan lain untuk merekam screencasts bisa dengan menulis Driver Cermin. Menurut Wikipedia: Ketika pencerminan video aktif, setiap kali sistem menarik ke perangkat video utama di lokasi di dalam area pencerminan, salinan operasi penarikan dijalankan pada perangkat video cermin secara real-time. Lihat driver cermin di MSDN: http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx .
sumber
Saya menggunakan d3d9 untuk mendapatkan backbuffer, dan menyimpannya ke file png menggunakan pustaka d3dx:
Untuk melakukan ini, Anda harus membuat swapbuffer Anda dengan
(Jadi, Anda menjamin backbuffer tidak hancur sebelum Anda mengambil tangkapan layar).
sumber
GetRenderTarget
?Dalam Impression saya, pendekatan GDI dan pendekatan DX berbeda sifatnya. melukis menggunakan GDI menggunakan metode FLUSH, pendekatan FLUSH menggambar bingkai kemudian membersihkannya dan menggambar ulang bingkai lain dalam buffer yang sama, ini akan mengakibatkan kerlipan dalam game membutuhkan frame rate tinggi.
Saya pikir apa yang sebenarnya Anda butuhkan adalah sistem replay, yang saya sepenuhnya setuju dengan apa yang orang bicarakan.
sumber
Saya menulis sebuah kelas yang menerapkan metode GDI untuk menangkap layar. Saya juga ingin kecepatan ekstra, setelah menemukan metode DirectX (via GetFrontBuffer) saya mencobanya, berharap lebih cepat.
Saya kecewa menemukan bahwa GDI melakukan sekitar 2.5x lebih cepat. Setelah 100 uji coba menangkap layar monitor ganda saya, implementasi GDI rata-rata 0,65 detik per tangkapan layar, sedangkan metode DirectX rata-rata 1,72 detik. Jadi, GDI jelas lebih cepat dari GetFrontBuffer, menurut pengujian saya.
Saya tidak dapat membuat kode Brandrew berfungsi untuk menguji DirectX melalui GetRenderTargetData. Salinan layar benar-benar hitam. Namun, itu bisa menyalin layar kosong itu dengan sangat cepat! Saya akan terus mengutak-atik itu dan berharap mendapatkan versi yang berfungsi untuk melihat hasil nyata dari itu.
sumber
GetRenderTargetData
pendekatan itu berhasil. Mungkin saya akan menulis jawaban saya sendiri ketika saya menyelesaikan aplikasi saya. Atau, Anda dapat memperbarui Anda setelah semuanya berhasil.Beberapa hal yang saya dapat kumpulkan: ternyata menggunakan "driver cermin" adalah cepat meskipun saya tidak mengetahui satu OSS.
Mengapa RDP begitu cepat dibandingkan dengan perangkat lunak remote control lainnya?
Rupanya juga menggunakan beberapa konvolusi dari StretchRect lebih cepat daripada BitBlt
http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193
Dan yang Anda sebutkan (fraps menghubungkan ke D3D dll) mungkin satu-satunya cara untuk aplikasi D3D, tetapi tidak akan bekerja dengan menangkap desktop Windows XP. Jadi sekarang saya hanya berharap ada fraps setara kecepatan-bijaksana untuk windows desktop normal ... siapa pun?
(Saya pikir dengan aero Anda mungkin dapat menggunakan kait seperti fraps, tetapi pengguna XP akan kurang beruntung).
Tampaknya juga mengubah kedalaman bit layar dan / atau menonaktifkan akselerasi perangkat keras. mungkin membantu (dan / atau menonaktifkan aero).
https://github.com/rdp/screen-capture-recorder-program mencakup utilitas penangkapan berbasis BitBlt yang cukup cepat, dan pembanding sebagai bagian dari pemasangannya, yang dapat memungkinkan Anda melakukan benchmark kecepatan BitBlt untuk mengoptimalkannya.
VirtualDub juga memiliki modul tangkapan layar "opengl" yang dikatakan cepat dan melakukan hal-hal seperti deteksi perubahan http://www.virtualdub.org/blog/pivot/entry.php?id=290
sumber
Untuk C ++ Anda dapat menggunakan: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Ini mungkin tidak berfungsi pada semua jenis aplikasi 3D / aplikasi video. Maka tautan ini mungkin lebih bermanfaat karena menjelaskan 3 metode berbeda yang dapat Anda gunakan.
Jawaban lama (C #):
Anda dapat menggunakan System.Drawing.Graphics.Copy , tetapi itu tidak terlalu cepat.
Contoh proyek yang saya tulis melakukan hal ini: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/
Saya berencana untuk memperbarui sampel ini menggunakan metode yang lebih cepat seperti Direct3D: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/
Dan di sini ada tautan untuk merekam video: Bagaimana cara menangkap layar menjadi video menggunakan C # .Net?
sumber
Dengan Windows 8, Microsoft memperkenalkan API Duplikasi Windows Desktop. Itu adalah cara yang direkomendasikan secara resmi untuk melakukannya. Salah satu fitur bagus yang dimilikinya untuk screencasting adalah ia mendeteksi pergerakan jendela, sehingga Anda dapat mengirimkan delta blok ketika windows bergerak, bukan piksel mentah. Juga, ini memberi tahu Anda persegi panjang mana yang telah berubah, dari satu frame ke yang berikutnya.
Contoh kode Microsoft cukup rumit, tetapi API sebenarnya sederhana dan mudah digunakan. Saya telah mengumpulkan contoh proyek yang jauh lebih sederhana daripada contoh resmi:
https://github.com/bmharper/WindowsDesktopDuplicationSample
Documents: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api
Contoh kode resmi Microsoft: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
sumber
Anda dapat mencoba proyek open source c ++ WinRobot @git , screen capturer yang tangguh
Dukung :
sumber
Saya sendiri melakukannya dengan directx dan berpikir itu secepat yang Anda inginkan. saya tidak memiliki contoh kode cepat, tetapi saya menemukan ini yang seharusnya bermanfaat. versi directx11 seharusnya tidak banyak berbeda, directx9 mungkin sedikit lebih, tapi itulah cara untuk pergi
sumber
Saya menyadari bahwa saran berikut tidak menjawab pertanyaan Anda, tetapi metode paling sederhana yang saya temukan untuk menangkap tampilan DirectX yang berubah dengan cepat, adalah menyambungkan kamera video ke port S-video kartu video, dan merekam gambar sebagai film. Kemudian transfer video dari kamera kembali ke file MPG, WMV, AVI dll. Di komputer.
sumber
Perekaman Layar dapat dilakukan dalam C # menggunakan VLC API . Saya telah melakukan program sampel untuk menunjukkan ini. Ini menggunakan LibVLCSharp dan VideoLAN.LibVLC.Windows perpustakaan. Anda dapat mencapai lebih banyak fitur yang terkait dengan rendering video menggunakan lintas platform API ini.
Untuk dokumentasi API, lihat: LibVLCSharp API Github
sumber
Pengambilan Desktop DXGI
Proyek yang menangkap gambar desktop dengan duplikasi DXGI. Menyimpan gambar yang diambil ke file dalam berbagai format gambar (* .bmp; * .jpg; * .tif).
Sampel ini ditulis dalam C ++. Anda juga perlu pengalaman dengan DirectX (D3D11, D2D1).
Apa yang Dapat Dilakukan Aplikasi
sumber