Phương pháp chụp màn hình nhanh nhất trên Windows


159

Tôi muốn viết một chương trình ghi hình cho nền tảng Windows, nhưng không chắc chắn về cách chụp màn hình. Phương pháp duy nhất tôi biết là sử dụng GDI, nhưng tôi tò mò liệu có cách nào khác để giải quyết vấn đề này không, và nếu có, có phải chịu ít chi phí nhất không? Tốc độ là ưu tiên hàng đầu.

Chương trình ghi hình sẽ được ghi lại cảnh quay trò chơi, mặc dù, nếu điều này thu hẹp các tùy chọn, tôi vẫn mở cho bất kỳ đề xuất nào khác nằm ngoài phạm vi này. Kiến thức không phải là xấu, sau tất cả.

Chỉnh sửa : Tôi đã xem qua bài viết này: Các phương pháp khác nhau để chụp màn hình . Nó đã giới thiệu cho tôi cách làm Windows Media API và cách làm DirectX. Nó đề cập đến trong Kết luận rằng việc vô hiệu hóa khả năng tăng tốc phần cứng có thể cải thiện đáng kể hiệu năng của ứng dụng chụp. Tôi tò mò về lý do tại sao điều này là. Bất cứ ai có thể điền vào chỗ trống cho tôi?

Chỉnh sửa : Tôi đọc rằng các chương trình ghi hình như Camtasia sử dụng trình điều khiển chụp riêng của họ. Ai đó có thể cho tôi một lời giải thích sâu sắc về cách nó hoạt động, và tại sao nó nhanh hơn? Tôi cũng có thể cần hướng dẫn để thực hiện một cái gì đó như thế, nhưng tôi chắc chắn rằng có tài liệu hiện có.

Ngoài ra, bây giờ tôi biết làm thế nào FRAPS ghi lại màn hình. Nó móc API đồ họa bên dưới để đọc từ bộ đệm phía sau. Theo những gì tôi hiểu, điều này nhanh hơn đọc từ bộ đệm trước, bởi vì bạn đang đọc từ RAM hệ thống, thay vì RAM video. Bạn có thể đọc bài viết ở đây .


Bạn đã xem xét, thay vì ghi lại đồ họa nội dung của màn hình, bằng cách sử dụng một hệ thống phát lại ?
Benjamin Lindley

2
Bạn không cần phải móc bất cứ thứ gì. Bạn chỉ cần viết các sự kiện đầu vào của mình để chúng không điều khiển trò chơi trực tiếp mà thay vào đó gọi các chức năng khác. Ví dụ: nếu người chơi nhấn phím trái, bạn không chỉ đơn giản là giảm vị trí x của người chơi. Thay vào đó, bạn gọi một chức năng, như MovePlayerLeft(). Và bạn cũng ghi lại thời gian và thời lượng của các lần nhấn phím và đầu vào khác. Sau đó, khi bạn ở chế độ phát lại, bạn chỉ cần bỏ qua đầu vào, và thay vào đó đọc dữ liệu đã ghi. Nếu, trong dữ liệu, bạn thấy một phím bấm trái, bạn gọi MovePlayerLeft().
Benjamin Lindley

1
@PigBen Đây sẽ là một ứng dụng chung để ghi lại cảnh quay trò chơi. Nó không dành cho một trò chơi cụ thể. Ai đó nhấn phím trái có thể có nghĩa là di chuyển sang phải, vì tất cả những gì tôi biết. Ngoài ra, bạn chưa xem xét các sự kiện không bị ảnh hưởng bởi người dùng. 'Và những gì về kết xuất?
someguy

1
@someguy Ok Tôi đoán bạn đang làm điều gì đó mãnh liệt hơn nhiều, tôi đã thêm một thói quen sử dụng các phương pháp trên để tiết kiệm phát lại AVI trong một trò chơi ở tốc độ khoảng 30fps mà không gặp trở ngại nào. Tôi đã tạo một trình ghi màn hình nhiều màn hình bằng API windows để "tối ưu hóa lực lượng làm việc" nhưng nó hoạt động kém ngay cả ở 4fps được nhắm mục tiêu.
AJG85

1
Có một trình điều khiển nhân bản mã nguồn mở cho các cửa sổ trên trang web kho lưu trữ của UltraVNC tại đây ultravnc.svn.sourceforge.net/viewvc/ultravnc/ Kẻ
Beached

Câu trả lời:


62

Đây là những gì tôi sử dụng để thu thập các khung hình đơn lẻ, nhưng nếu bạn sửa đổi điều này và giữ cho hai mục tiêu luôn mở thì bạn có thể "truyền" nó vào đĩa bằng bộ đếm tĩnh cho tên tệp. - Tôi không thể nhớ lại nơi tôi tìm thấy cái này, nhưng nó đã được sửa đổi, nhờ bất cứ ai!

void dump_buffer()
{
   IDirect3DSurface9* pRenderTarget=NULL;
   IDirect3DSurface9* pDestTarget=NULL;
     const char file[] = "Pickture.bmp";
   // sanity checks.
   if (Device == NULL)
      return;

   // get the render target surface.
   HRESULT hr = Device->GetRenderTarget(0, &pRenderTarget);
   // get the current adapter display mode.
   //hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode);

   // create a destination surface.
   hr = Device->CreateOffscreenPlainSurface(DisplayMde.Width,
                         DisplayMde.Height,
                         DisplayMde.Format,
                         D3DPOOL_SYSTEMMEM,
                         &pDestTarget,
                         NULL);
   //copy the render target to the destination surface.
   hr = Device->GetRenderTargetData(pRenderTarget, pDestTarget);
   //save its contents to a bitmap file.
   hr = D3DXSaveSurfaceToFile(file,
                              D3DXIFF_BMP,
                              pDestTarget,
                              NULL,
                              NULL);

   // clean up.
   pRenderTarget->Release();
   pDestTarget->Release();
}

Cảm ơn. Tôi đã nghe nói về phương pháp này một thời gian trước đây được cho là nhanh hơn đọc từ bộ đệm phía trước. Bạn có trung thực làm theo cách đó và nó hoạt động đúng không?
someguy

Vấn đề với bộ đệm phía trước là một trong những quyền truy cập, nghĩa là cố gắng sao chép một đồng bằng hiện đang được hiển thị "làm gián đoạn" bản sao. Nó hoạt động đủ tốt cho tôi và ăn ổ cứng của tôi!
Brandrew

@bobobobo Tôi không biết chính xác nó sẽ hoạt động như thế nào, nhưng tôi đã nghĩ đến việc sử dụng một cái gì đó như Huffyuv. Chỉnh sửa: Hoặc có thể cho phép người dùng chọn từ các bộ lọc directshow có sẵn.
someguy

1
Tôi chỉ không thể quản lý để thực hiện công việc đó ... DirectX tạo ra một số cuộc gọi không hợp lệ trên phần GetRenderTargetData. Rõ ràng cách bạn tạo ra thiết bị của bạn phải có rất nhiều tầm quan trọng.
LightStriker

12
downvote, nó chỉ hoạt động cho ứng dụng của riêng bạn, vì vậy không thể được sử dụng để ghi lại các chương trình chung
user3125280

32

EDIT: Tôi có thể thấy rằng điều này được liệt kê dưới liên kết chỉnh sửa đầu tiên của bạn là "cách GDI". Đây vẫn là một cách hay để đi ngay cả với tư vấn hiệu suất trên trang web đó, bạn có thể dễ dàng đạt tới 30 khung hình / giây.

Từ nhận xét này (Tôi không có kinh nghiệm làm việc này, tôi chỉ giới thiệu ai đó làm):

HDC hdc = GetDC(NULL); // get the desktop device context
HDC hDest = CreateCompatibleDC(hdc); // create a device context to use yourself

// get the height and width of the screen
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);

// create a bitmap
HBITMAP hbDesktop = CreateCompatibleBitmap( hdc, width, height);

// use the previously created device context with the bitmap
SelectObject(hDest, hbDesktop);

// copy from the desktop device context to the bitmap device context
// call this once per 'frame'
BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);

// after the recording is done, release the desktop context you got..
ReleaseDC(NULL, hdc);

// ..delete the bitmap you were using to capture frames..
DeleteObject(hbDesktop);

// ..and delete the context you created
DeleteDC(hDest);

Tôi không nói rằng đây là cách nhanh nhất, nhưng BitBlthoạt động thường rất nhanh nếu bạn sao chép giữa các bối cảnh thiết bị tương thích.

Để tham khảo, Open Broadcaster Software thực hiện một cái gì đó như thế này như là một phần của phương thức "dc_capture" của họ , mặc dù thay vì tạo bối cảnh đích hDestbằng cách CreateCompatibleDChọ sử dụng IDXGISurface1, hoạt động với DirectX 10+. Nếu không có hỗ trợ cho điều này, họ rơi trở lại CreateCompatibleDC.

Để thay đổi nó để sử dụng một ứng dụng cụ thể, bạn cần thay đổi dòng đầu tiên thành GetDC(game)nơi gamexử lý cửa sổ của trò chơi, sau đó đặt bên phải heightwidthcửa sổ của trò chơi.

Khi bạn có các pixel trong hDest / hbDesktop, bạn vẫn cần lưu nó vào một tệp, nhưng nếu bạn đang chụp màn hình thì tôi nghĩ bạn sẽ muốn đệm một số lượng nhất định trong bộ nhớ và lưu vào tệp video trong khối, vì vậy tôi sẽ không trỏ đến mã để lưu hình ảnh tĩnh vào đĩa.


3
msdn.microsoft.com/en-us/library/dd183370%28VS.85%29.aspx Trích: Nếu định dạng màu sắc của nguồn và thiết bị đích bối cảnh không phù hợp, chức năng bitblt chuyển đổi định dạng file gốc màu để phù hợp với điểm đến định dạng.

2
Một số bằng chứng để chứng minh rằng sẽ tốt. Bạn đã xuất bản một so sánh hiệu suất ở đâu đó, hoặc thấy một so sánh chính xác?

2
Hãy thử hồ sơ nó. Như tôi đã nói trong bài đăng, tôi đang giới thiệu một người có kinh nghiệm với GDI. Nếu nó bị rò rỉ bộ nhớ và bạn biết cách khắc phục, hãy chỉnh sửa bài đăng để loại bỏ rò rỉ.

1
Tôi có khoảng 5 khung hình / giây với phương pháp này. Đây là trên một máy tính xách tay có đồ họa tích hợp, vì vậy tôi sẽ mong đợi tốt hơn từ một máy tính để bàn có card đồ họa thực sự, nhưng vẫn rất chậm.
Timmmm

1
@Timmmm Tôi đã thêm một tham chiếu đến cách OBS thực hiện điều này. Hy vọng rằng điều đó có thể tăng tốc mọi thứ lên một chút cho bạn.

19

Tôi đã viết một phần mềm quay video, tương tự như FRAPS cho các ứng dụng DirectX. Mã nguồn có sẵn và bài viết của tôi giải thích kỹ thuật chung. Hãy xem http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-appluggest-to-capture-video-and-calculate-frames-per-second/

Tôn trọng các câu hỏi của bạn liên quan đến hiệu suất,

  • DirectX nên nhanh hơn GDI trừ khi bạn đang đọc từ frontbuffer rất chậm. Cách tiếp cận của tôi tương tự như FRAPS (đọc từ backbuffer). Tôi chặn một tập hợp các phương thức từ giao diện Direct3D.

  • Để quay video trong thời gian thực (với tác động ứng dụng tối thiểu), một codec nhanh là điều cần thiết. FRAPS sử dụng codec video lossless của riêng nó. Lagarith và HUFFYUV là các codec video lossless chung được thiết kế cho các ứng dụng thời gian thực. Bạn nên xem chúng nếu bạn muốn xuất các tập tin video.

  • Một cách tiếp cận khác để ghi lại screencasts có thể là viết Mirror Driver. Theo Wikipedia: Khi phản chiếu video đang hoạt động, mỗi lần hệ thống chuyển sang thiết bị video chính tại một vị trí bên trong khu vực được nhân đôi, một bản sao của thao tác vẽ được thực hiện trên thiết bị video được nhân đôi trong thời gian thực. Xem trình điều khiển nhân bản tại MSDN: http://msdn.microsoft.com/en-us/l Library / windows / hardware / ff568315 (v = vs85) .aspx .


16

Tôi sử dụng d3d9 để lấy backbuffer và lưu nó vào tệp png bằng thư viện d3dx:

    Bề mặt IDirect3DSurface9 *;

    // GetBackBuffer
    idirect3ddevice9-> GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, & bề mặt);

    // lưu bề mặt
    D3DXSaveSurfaceToFileA ("filename.png", D3DXIFF_PNG, bề mặt, NULL, NULL);

    SAFE_RELEASE (bề mặt);

Để làm điều này, bạn nên tạo trình trao đổi của bạn với

d3dpps.SwapEffect = D3DSWAPEFFECT_COPY ; // for screenshots.

(Vì vậy, bạn đảm bảo backbuffer không bị hỏng trước khi bạn chụp ảnh màn hình).


Làm cho ý nghĩa, cảm ơn. Bạn có biết sự khác biệt giữa cái này và GetRenderTargetcái gì không?
someguy

Điều đó chỉ nhận được mục tiêu kết xuất hiện tại (có thể là một bề mặt ngoài màn hình khác nếu ai đó đang kết xuất thành kết cấu tại thời điểm bạn gọi).
bobobobo

13

Trong Ấn tượng của tôi, cách tiếp cận GDI và cách tiếp cận DX khác nhau về bản chất. vẽ bằng GDI áp dụng phương pháp FLUSH, phương pháp FLUSH vẽ khung sau đó xóa nó và vẽ lại khung khác trong cùng bộ đệm, điều này sẽ dẫn đến nhấp nháy trong các trò chơi đòi hỏi tốc độ khung hình cao.

  1. TẠI SAO DX nhanh hơn? trong DX (hoặc thế giới đồ họa), một phương thức hoàn thiện hơn được gọi là kết xuất bộ đệm đôi được áp dụng, trong đó có hai bộ đệm, khi trình bày bộ đệm trước cho phần cứng, bạn cũng có thể kết xuất với bộ đệm khác, sau khung 1 kết thúc kết xuất, hệ thống hoán đổi sang bộ đệm khác (khóa nó để trình bày với phần cứng và giải phóng bộ đệm trước đó), theo cách này, hiệu quả kết xuất được cải thiện rất nhiều.
  2. TẠI SAO giảm tốc độ tăng tốc phần cứng nhanh hơn? mặc dù với kết xuất bộ đệm kép, FPS được cải thiện nhưng thời gian kết xuất vẫn còn hạn chế. phần cứng đồ họa hiện đại thường liên quan đến rất nhiều tối ưu hóa trong quá trình kết xuất thường như khử răng cưa, điều này rất cần tính toán, nếu bạn không yêu cầu đồ họa chất lượng cao đó, tất nhiên bạn chỉ có thể tắt tùy chọn này. và điều này sẽ giúp bạn tiết kiệm thời gian.

Tôi nghĩ những gì bạn thực sự cần là một hệ thống phát lại, tôi hoàn toàn đồng ý với những gì mọi người đã thảo luận.


1
Xem các cuộc thảo luận về lý do tại sao một hệ thống phát lại không khả thi. Chương trình ghi hình không dành cho bất kỳ trò chơi cụ thể nào.
someguy

10

Tôi đã viết một lớp thực hiện phương thức GDI để chụp màn hình. Tôi cũng muốn có thêm tốc độ, vì vậy, sau khi khám phá phương thức DirectX (thông qua GetFrontBuffer) tôi đã thử điều đó, hy vọng nó sẽ nhanh hơn.

Tôi đã mất tinh thần khi thấy rằng GDI thực hiện nhanh hơn khoảng 2,5 lần. Sau 100 thử nghiệm chụp màn hình màn hình kép của tôi, việc triển khai GDI trung bình 0,65 giây cho mỗi lần chụp màn hình, trong khi phương thức DirectX trung bình 1,72 giây. Vì vậy, GDI chắc chắn nhanh hơn GetFrontBuffer, theo các thử nghiệm của tôi.

Tôi không thể làm cho mã của Brandrew hoạt động để kiểm tra DirectX thông qua GetRenderTargetData. Bản sao màn hình xuất hiện hoàn toàn màu đen. Tuy nhiên, nó có thể sao chép màn hình trống siêu nhanh đó! Tôi sẽ tiếp tục mày mò điều đó và hy vọng sẽ có được một phiên bản hoạt động để xem kết quả thực sự từ nó.


Cảm ơn bạn đã thông tin. Tôi chưa kiểm tra mã của Brandrew, nhưng tôi biết rằng GetRenderTargetDatacách tiếp cận này có hiệu quả. Có lẽ tôi sẽ viết câu trả lời của riêng mình khi tôi hoàn thành đơn đăng ký của mình. Hoặc, bạn có thể cập nhật thông tin của mình sau khi bạn đã làm mọi thứ.
someguy

0,65 mỗi Screencapture?! Việc triển khai GDI tốt (giữ các thiết bị xung quanh, v.v.) nên thực hiện 30fps trong 1920x1200 một cách dễ dàng trên máy tính hiện đại.
Christopher Oezbek

Tôi cho rằng chất lượng hình ảnh được GDI hiển thị chắc chắn kém hơn DX
zinking

Tôi đã thực hiện thử nghiệm này trong C # với SlimDX và thật ngạc nhiên, đã tìm thấy kết quả tương tự. Có lẽ điều này có thể phải làm với thực tế là, bằng cách sử dụng SlimDX, người ta phải tạo một luồng mới và một bitmap mới cho mỗi lần cập nhật khung hình, thay vì tạo nó một lần, tua lại và ghi đè lên cùng một vị trí.
Cesar

Chỉ cần làm rõ: thực ra, "kết quả tương tự" đã đề cập đến GDI nhanh hơn - như @Christopher đã đề cập, 30fps + là rất khả thi và vẫn còn nhiều CPU dự phòng.
Cesar

8

Một vài điều tôi có thể lượm lặt được: rõ ràng là sử dụng "trình điều khiển gương" rất nhanh mặc dù tôi không biết về một OSS.

Tại sao RDP quá nhanh so với các phần mềm điều khiển từ xa khác?

Ngoài ra, rõ ràng việc sử dụng một số cấu trúc của StretchRect nhanh hơn BitBlt

http://betterlogic.com/roger/2010/07/fast-screen-capture/comment-page-1/#comment-5193

Và cách bạn đã đề cập (yếu tố nối vào D3D dll) có lẽ là cách duy nhất cho các ứng dụng D3D, nhưng sẽ không hoạt động với chụp màn hình Windows XP. Vì vậy, bây giờ tôi chỉ ước có một điểm yếu tương đương tốc độ cho các cửa sổ máy tính để bàn bình thường ... bất cứ ai?

(Tôi nghĩ với aero, bạn có thể sử dụng các hook giống như fraps, nhưng người dùng XP sẽ không gặp may).

Cũng rõ ràng thay đổi độ sâu bit màn hình và / hoặc vô hiệu hóa phần cứng. có thể giúp (và / hoặc vô hiệu hóa aero).

https://github.com/rdp/screen-capture-recorder-program bao gồm tiện ích chụp dựa trên BitBlt khá nhanh và một công cụ đo điểm chuẩn như một phần trong quá trình cài đặt của nó, có thể cho phép bạn đánh giá tốc độ BitBlt để tối ưu hóa chúng.

VirtualDub cũng có một mô-đun chụp màn hình "opengl" được cho là nhanh và thực hiện những việc như phát hiện thay đổi http://www.virtualdub.org/blog/pOLL/entry.php?id=290


Tôi tự hỏi, sẽ nhanh hơn khi sử dụng "trình ghi lại màn hình" của bạn hoặc sử dụng BitBlt? Có một số tối ưu hóa trong dự án của bạn?
blez

Nếu bạn sử dụng Bitblt, bạn có thể tránh được một memcpy thêm (memcpy thường không phải là nút cổ chai lớn nhất, mặc dù nó có thêm một chút thời gian - tôi chỉ đề cập đến nó ở đây cho tiện ích điểm chuẩn của nó, nhưng nếu bạn cần thứ gì đó hoặc directshow thì nó rất tuyệt )
rogerdpack

8

Đối với C ++, bạn có thể sử dụng: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
Điều này có thể không hoạt động trên tất cả các loại ứng dụng 3D / ứng dụng video. Sau đó, liên kết này có thể hữu ích hơn vì nó mô tả 3 phương pháp khác nhau mà bạn có thể sử dụng.

Câu trả lời cũ (C #):
Bạn có thể sử dụng System.Drawing.Graphics.Copy , nhưng nó không nhanh lắm.

Một dự án mẫu tôi đã viết thực hiện chính xác điều này: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/

Tôi dự định cập nhật mẫu này bằng phương pháp nhanh hơn như Direct3D: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/

Và đây là một liên kết để quay video: Làm thế nào để quay màn hình thành video bằng C # .Net?


2
À, tôi quên đề cập đến việc tôi đang lập trình trong C (có thể là C ++) và tôi không có kế hoạch sử dụng .NET. Rất xin lỗi: /.
someguy

Tôi đã biết về BitBlt (GDI). Tuy nhiên, tôi sẽ xem xét Direct3D. Cảm ơn!
someguy

Tôi đã xem xét điều này một vài tuần trước, nhưng vẫn chưa có cơ hội để thực hiện nó. Direct3D là !! cách !! nhanh hơn phương thức dựng sẵn C # đang sử dụng GDI +.
Tedd Hansen

Tôi đã cập nhật bài viết gốc của mình. Theo liên kết, DirectX chậm khi phải gọi GetFrontBufferData (). Đây có phải là bất cứ điều gì để xem xét khi ghi lại đoạn phim trò chơi? Bạn có thể bối cảnh này cho tôi?
someguy

1
GDI chậm, do đó, nó không phù hợp với miền có vấn đề, DirectX hoặc OpenGL sẽ là đề xuất hợp lý duy nhất.

6

Với Windows 8, Microsoft đã giới thiệu API sao chép Windows Desktop. Đó là cách làm chính thức được đề nghị. Một tính năng hay mà nó có để ghi lại là nó phát hiện chuyển động của cửa sổ, vì vậy bạn có thể truyền các khối deltas khi các cửa sổ được di chuyển xung quanh, thay vì các pixel thô. Ngoài ra, nó cho bạn biết hình chữ nhật nào đã thay đổi, từ khung này sang khung khác.

Mã ví dụ của Microsoft khá phức tạp, nhưng API thực sự đơn giản và dễ sử dụng. Tôi đã kết hợp một dự án ví dụ đơn giản hơn nhiều so với ví dụ chính thức:

https://github.com/bmharper/WindowsDesktopD repeatationSample

Tài liệu: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api

Mã ví dụ chính thức của Microsoft: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Dsplation-Sample-da4c696a


Dự án Github hoạt động hoàn hảo trên Windows 10, được thử nghiệm với video trên web và Resident Evil 7. Điều tốt nhất là thang tải CPU với tốc độ nâng cấp đồ họa.
jw_

Ngay khi bạn khởi chạy GPU-Z, chương trình này sẽ dừng lấy màn hình.
Marino Šimić

5

Bạn có thể thử dự án mã nguồn mở c ++ WinRobot @git , một trình chụp màn hình mạnh mẽ

CComPtr<IWinRobotService> pService;
hr = pService.CoCreateInstance(__uuidof(ServiceHost) );

//get active console session
CComPtr<IUnknown> pUnk;
hr = pService->GetActiveConsoleSession(&pUnk);
CComQIPtr<IWinRobotSession> pSession = pUnk;

// capture screen
pUnk = 0;
hr = pSession->CreateScreenCapture(0,0,1280,800,&pUnk);

// get screen image data(with file mapping)
CComQIPtr<IScreenBufferStream> pBuffer = pUnk;

Ủng hộ :

  • Cửa sổ UAC
  • Winlogon
  • DirectShowOverlay

1
Đó là ... rất nhiều móc cấp thấp. Tốc độ chụp là tuyệt vời nếu bạn có quyền quản trị tho.
toster-cx

Tôi thấy winrobot rất mạnh mẽ và mượt mà.
ashishgupta_mca

Tôi đã nghiên cứu mã WinRobot và thấy không có gì chụp màn hình wrt đột phá: nó đang sử dụng cùng một CreatCompiverseDC..BitBlt. Trừ khi có một số phép thuật khi điều này được thực hiện trong bối cảnh dịch vụ?
shekh

@shekh: Việc học của bạn quá hời hợt. Mã này sử dụng IDirectDrawSurface7-> BltFast () để sao chép màn hình từ bề mặt bản vẽ màn hình sang bề mặt DD sao chép, sau đó nó sử dụng một Bản ghi để sao chép hình ảnh. Nó khá phức tạp vì mã đang chạy trong một dịch vụ mà bạn không thể dễ dàng truy cập vào máy tính để bàn.
Elmue

2

Bản thân tôi làm điều đó với directx và nghĩ rằng nó nhanh như bạn muốn. Tôi không có một mẫu mã nhanh, nhưng tôi thấy cái này sẽ hữu ích. phiên bản directx11 không nên khác biệt nhiều, directx9 có thể nhiều hơn một chút, nhưng đó là cách để đi


2

Tôi nhận thấy đề xuất sau đây không trả lời câu hỏi của bạn, nhưng phương pháp đơn giản nhất tôi đã tìm thấy để xem chế độ xem DirectX thay đổi nhanh chóng, là cắm máy quay video vào cổng video S của thẻ video và ghi lại hình ảnh như một bộ phim. Sau đó chuyển video từ máy ảnh trở lại tệp MPG, WMV, AVI, vv trên máy tính.


2

Ghi màn hình có thể được thực hiện trong C # bằng API VLC . Tôi đã thực hiện một chương trình mẫu để chứng minh điều này. Nó sử dụng LibVLCSharpVideoLAN.LibVLC.Windows thư viện. Bạn có thể đạt được nhiều tính năng hơn liên quan đến kết xuất video bằng API đa nền tảng này.

Để biết tài liệu API, hãy xem: LibVLCSharp API Github

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using LibVLCSharp.Shared;

namespace ScreenRecorderNetApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Core.Initialize();

            using (var libVlc = new LibVLC())
            using (var mediaPlayer = new MediaPlayer(libVlc))
            {
                var media = new Media(libVlc, "screen://", FromType.FromLocation);
                media.AddOption(":screen-fps=24");
                media.AddOption(":sout=#transcode{vcodec=h264,vb=0,scale=0,acodec=mp4a,ab=128,channels=2,samplerate=44100}:file{dst=testvlc.mp4}");
                media.AddOption(":sout-keep");

                mediaPlayer.Play(media);
                Thread.Sleep(10*1000);
                mediaPlayer.Stop();
            }
        }
    }
}

1
Đối với người mà nó có thể quan tâm: Xin lưu ý rằng libvlc được phát hành theo GPL. Nếu bạn không có ý định phát hành mã của mình theo GPL thì đừng sử dụng libvlc.
Sebastian Cabot

Điều đó không hoàn toàn chính xác, LibVLC là LGPL - nó đã được phát hành lại vào năm 2011. Bản thân ứng dụng VLC vẫn là GPL: videolan.org/press/lgpl-libvlc.html
Andrew

0

Chụp màn hình DXGI

Dự án chụp ảnh máy tính để bàn với sao chép DXGI. Lưu hình ảnh đã chụp vào tệp ở các định dạng hình ảnh khác nhau (* .bmp; * .jpg; * .tif).

Mẫu này được viết bằng C ++. Bạn cũng cần một số kinh nghiệm với DirectX (D3D11, D2D1).

Ứng dụng có thể làm gì

  • Nếu bạn có nhiều hơn một màn hình máy tính để bàn, bạn có thể chọn.
  • Thay đổi kích thước hình ảnh máy tính để bàn.
  • Chọn các chế độ chia tỷ lệ khác nhau.
  • Bạn có thể hiển thị hoặc ẩn biểu tượng chuột trong hình ảnh đầu ra.
  • Bạn có thể xoay hình ảnh cho hình ảnh đầu ra hoặc để nó như mặc định.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.