विंडोज पर स्क्रीन कैप्चरिंग का सबसे तेज़ तरीका


159

मैं विंडोज प्लेटफॉर्म के लिए एक स्क्रैचस्टिंग प्रोग्राम लिखना चाहता हूं, लेकिन स्क्रीन को कैसे कैप्चर करना है, इसके बारे में अनिश्चित हूं। जीडीआई का उपयोग करने के लिए केवल एक ही तरीका मुझे पता है, लेकिन मैं उत्सुक हूं कि क्या इस बारे में जाने के अन्य तरीके हैं, और, अगर वहाँ हैं, जो कम से कम ओवरहेड को जन्म देता है? गति एक प्राथमिकता है।

स्क्रैंचेजिंग प्रोग्राम गेम फुटेज रिकॉर्ड करने के लिए होगा, हालांकि, अगर यह विकल्पों को कम करता है, तो मैं इस दायरे से बाहर आने वाले किसी भी अन्य सुझाव के लिए अभी भी खुला हूं। ज्ञान बुरा नहीं है, आखिर।

संपादित करें : मैं इस लेख में आया हूं: स्क्रीन कैप्चर करने के विभिन्न तरीके । इसने मुझे विंडोज मीडिया एपीआई करने का तरीका और इसे करने का डायरेक्टएक्स तरीका पेश किया है। इस निष्कर्ष में उल्लेख किया गया है कि हार्डवेयर त्वरण को अक्षम करने से कैप्चर एप्लिकेशन के प्रदर्शन में काफी सुधार हो सकता है। मैं उत्सुक हूं कि ऐसा क्यों है। क्या कोई मेरे लिए गायब हुए रिक्त स्थान को भर सकता है?

संपादित करें : मैंने पढ़ा है कि कैमकोसिया जैसे स्क्रैचिंग प्रोग्राम अपने स्वयं के कैप्चर ड्राइवर का उपयोग करते हैं। क्या कोई मुझे गहराई से समझा सकता है कि यह कैसे काम करता है, और यह तेज़ क्यों है? मुझे भी ऐसा कुछ लागू करने के लिए मार्गदर्शन की आवश्यकता हो सकती है, लेकिन मुझे यकीन है कि वैसे भी मौजूदा प्रलेखन है।

इसके अलावा, मुझे अब पता है कि FRAPS कैसे स्क्रीन रिकॉर्ड करता है। यह बैकफुट से पढ़ने के लिए अंतर्निहित ग्राफिक्स एपीआई को हुक करता है। जो मैं समझता हूं, यह सामने वाले बफर से पढ़ने की तुलना में तेज है, क्योंकि आप वीडियो रैम के बजाय सिस्टम रैम से पढ़ रहे हैं। आप यहां लेख पढ़ सकते हैं ।


क्या आपने रीप्ले सिस्टम का उपयोग करते हुए, स्क्रीन की सामग्री को रेखांकन के बजाय, माना है ?
बेंजामिन लिंडले

2
आपको कुछ भी करने की जरूरत नहीं है। आपको बस अपनी इनपुट घटनाओं को लिखना होगा ताकि वे सीधे गेम को नियंत्रित न करें, बल्कि अन्य कार्यों को कॉल करें। उदाहरण के लिए, यदि खिलाड़ी बाईं कुंजी को धक्का देता है, तो आप केवल खिलाड़ियों की एक्स स्थिति को नहीं बढ़ाते हैं। इसके बजाय, आप एक फ़ंक्शन को कॉल करते हैं, जैसे MovePlayerLeft()। और आप कुंजी प्रेस और अन्य इनपुट का समय और अवधि भी रिकॉर्ड करते हैं। फिर, जब आप प्लेबैक मोड में होते हैं, तो आप केवल इनपुट को अनदेखा करते हैं, और इसके बजाय रिकॉर्ड किए गए डेटा को पढ़ते हैं। यदि, डेटा में, आप एक बाएँ कुंजी प्रेस देखते हैं, तो आप कॉल करते हैं MovePlayerLeft()
बेंजामिन लिंडले

1
@PigBen यह गेम फुटेज रिकॉर्ड करने के लिए एक सामान्य एप्लिकेशन होगा। यह एक विशिष्ट खेल के लिए नहीं है। किसी को बाईं कुंजी दबाने का मतलब सही चल सकता है, सभी के लिए मुझे पता है। इसके अलावा, आपने उन घटनाओं पर विचार नहीं किया है जो उपयोगकर्ता द्वारा प्रभावित नहीं हैं। 'और प्रतिपादन के बारे में क्या?
18

1
@someguy ठीक है, मुझे लगता है कि आप कुछ अधिक तीव्र कर रहे हैं, मैंने बिना किसी अड़चन के लगभग 30fps पर एक गेम में रीप्ले एवीआई को बचाने के लिए उपरोक्त विधियों का उपयोग करके एक दिनचर्या जोड़ी थी। मैंने "वर्क फोर्स ऑप्टिमाइज़ेशन" के लिए विंडोज़ एपीआई का उपयोग करते हुए एक मल्टीपल मॉनिटर स्क्रीन रिकॉर्डर बनाया, लेकिन लक्षित 4fps पर भी यह बहुत खराब था।
AJG85

1
वहाँ एक खुला स्रोत दर्पण खिड़कियों के लिए UltraVNC के भंडार साइट पर यहाँ ड्राइवर है ultravnc.svn.sourceforge.net/viewvc/ultravnc/...
समुद्रतटीय

जवाबों:


62

यह वह है जो मैं एकल फ़्रेमों को इकट्ठा करने के लिए उपयोग करता हूं, लेकिन यदि आप इसे संशोधित करते हैं और दो लक्ष्यों को हर समय खुला रखते हैं तो आप फ़ाइल नाम के लिए एक स्थिर काउंटर का उपयोग करके डिस्क को "स्ट्रीम" कर सकते हैं। - मुझे याद नहीं है कि मुझे यह कहाँ मिला है, लेकिन इसे संशोधित किया गया है, जो कोई भी धन्यवाद!

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();
}

धन्यवाद। मैंने इस विधि के बारे में कुछ समय पहले सुना था जो सामने वाले बफर से पढ़ने की तुलना में तेज था। क्या आप ईमानदारी से इसे इस तरह से करते हैं और क्या यह ठीक से काम करता है?
Someguy

फ्रंट बफर के साथ समस्या एक पहुंच है, जो कि एक सादे कॉपी करने की कोशिश कर रही है, जो वर्तमान में कॉपी में "बाधित" हो रही है। यह मेरे लिए पर्याप्त काम करता है और मेरी हार्ड ड्राइव को खाता है!
ब्रांडेड

@bobobobo मुझे नहीं पता कि यह कैसे ठीक से काम करेगा, लेकिन मैं हफीव की तरह कुछ का उपयोग करने के बारे में सोच रहा था। संपादित करें: या शायद उपयोगकर्ता को उपलब्ध डायरेक्टशो फिल्टर से चुनने दें।
18

1
मैं बस उस काम को करने के लिए प्रबंधन नहीं कर सकता ... DirectX GetRenderTargetData भाग पर कुछ अमान्य कॉल करता है। जाहिर है जिस तरह से आप अपने डिवाइस को बनाते हैं उसका बहुत अधिक महत्व होना चाहिए।
लाइटस्ट्रीकर

12
डाउनवोट, यह केवल आपके स्वयं के अनुप्रयोग के लिए काम करता है, इसलिए जेनेरिक कार्यक्रमों को रिकॉर्ड करने के लिए उपयोग नहीं किया जा सकता है
user3125280

32

संपादित करें: मैं देख सकता हूं कि यह आपके पहले संपादित लिंक के तहत "GDI तरीका" के रूप में सूचीबद्ध है। यह अभी भी उस साइट पर प्रदर्शन सलाहकार के साथ जाने के लिए एक सभ्य तरीका है, आप आसानी से मुझे लगता है कि 30fps को प्राप्त कर सकते हैं।

से इस टिप्पणी (मैं यह कर रहा, मैं सिर्फ कोई है जो करता है को संदर्भित कर रहा हूँ कोई अनुभव नहीं है):

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);

मैं यह नहीं कह रहा हूं कि यह सबसे तेज़ है, लेकिन BitBltयदि आप संगत डिवाइस संदर्भों के बीच कॉपी कर रहे हैं तो ऑपरेशन आम तौर पर बहुत तेज़ है।

संदर्भ के लिए, ओपन ब्रॉडकास्टर सॉफ्टवेयर उनके "dc_capture" पद्धति के भाग के रूप में कुछ इस तरह लागू होता है , हालांकि गंतव्य संदर्भ बनाने के बजाय वे एक hDestका उपयोग CreateCompatibleDCकरते हैं IDXGISurface1, जो DirectX 10+ के साथ काम करता है। अगर इसके लिए कोई समर्थन नहीं है, तो वे वापस गिर जाते हैं CreateCompatibleDC

किसी विशिष्ट एप्लिकेशन का उपयोग करने के लिए इसे बदलने के लिए, आपको पहली पंक्ति को बदलने की आवश्यकता है GetDC(game)जहां gameगेम की विंडो को संभालना है, और फिर गेम की विंडो के दाईं heightऔर भी सेट करें width

एक बार जब आपके पास hDest / hbDesktop में पिक्सेल आ जाते हैं, तब भी आपको इसे किसी फ़ाइल में सहेजने की आवश्यकता होती है, लेकिन यदि आप स्क्रीन कैप्चर कर रहे हैं, तो मुझे लगता है कि आप इनकी निश्चित संख्या को मेमोरी में बफर करना चाहते हैं और वीडियो फ़ाइल में सहेजना चाहेंगे चंक्स में, इसलिए मैं एक स्थिर छवि को डिस्क पर सहेजने के लिए कोड को इंगित नहीं करूंगा।


3
msdn.microsoft.com/en-us/library/dd183370%28VS.85%29.aspx अंश: यदि स्रोत और गंतव्य डिवाइस संदर्भों की रंग प्रारूपों से मेल नहीं खाते, BitBlt समारोह स्रोत रंग प्रारूप गंतव्य से मिलान करने के लिए धर्मान्तरित प्रारूप।

2
कुछ सबूतों को पुष्ट करने के लिए कि अच्छा होगा। क्या आपने कहीं एक प्रदर्शन तुलना प्रकाशित की है, या एक सटीक देखा है?

2
इसे प्रोफाइलिंग करके देखें। जैसा कि मैंने पोस्ट में कहा, मैं किसी ऐसे व्यक्ति को संदर्भित कर रहा हूं जिसे GDI का अनुभव है। यदि यह मेमोरी लीक करता है, और आप इसे ठीक करना जानते हैं, तो लीक को खत्म करने के लिए पोस्ट को संपादित करें।

1
मुझे इस विधि से लगभग 5 एफपीएस मिले। यह एकीकृत ग्राफिक्स वाले लैपटॉप पर था, इसलिए मैं वास्तविक ग्राफिक्स कार्ड वाले डेस्कटॉप से ​​बेहतर उम्मीद करूंगा, लेकिन फिर भी, यह बहुत धीमा है।
टिम्मम

1
@Timmmm मैंने OBS के इसे लागू करने के तरीके से एक संदर्भ जोड़ा है। उम्मीद है कि यह आपके लिए चीजों को थोड़ा तेज कर सकता है।

19

मैंने DirectX अनुप्रयोगों के लिए FRAPS के समान एक वीडियो कैप्चर सॉफ़्टवेयर लिखा। स्रोत कोड उपलब्ध है और मेरा लेख सामान्य तकनीक की व्याख्या करता है। को देखो http://blog.nektra.com/main/2013/07/23/instrumenting-direct3d-applications-to-capture-video-and-calculate-frames-per-second/

प्रदर्शन से संबंधित आपके प्रश्नों का सम्मान,

  • डायरेक्टएक्स को जीडीआई से तेज होना चाहिए सिवाय जब आप फ्रंटबफ़र से पढ़ रहे हैं जो बहुत धीमा है। मेरा दृष्टिकोण FRAPS (बैकबफ़र से पढ़ने) के समान है। मैं Direct3D इंटरफेस से तरीकों का एक सेट इंटरसेप्ट करता हूं।

  • वास्तविक समय में वीडियो रिकॉर्डिंग के लिए (न्यूनतम आवेदन प्रभाव के साथ), एक तेज कोडेक आवश्यक है। FRAPS यह स्वयं दोषरहित वीडियो कोडेक का उपयोग करता है। Lagarith और HUFFYUV वास्तविक समय के अनुप्रयोगों के लिए डिज़ाइन किए गए सामान्य दोषरहित वीडियो कोडेक्स हैं। यदि आप वीडियो फ़ाइलों को आउटपुट करना चाहते हैं तो आपको उन्हें देखना चाहिए।

  • मिरर ड्रायवर लिखने के लिए एक और तरीका है रेकॉर्डिंग रिकॉर्डिंग। विकिपीडिया के अनुसार: जब वीडियो मिररिंग सक्रिय होता है, तो हर बार सिस्टम मिरर किए गए क्षेत्र के अंदर एक स्थान पर प्राथमिक वीडियो डिवाइस पर आ जाता है, ड्रॉ ऑपरेशन की एक कॉपी वास्तविक समय में मिरर किए गए वीडियो डिवाइस पर निष्पादित की जाती है। : MSDN पर दर्पण ड्राइवरों देखें http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx


16

मैं बैकबफ़र प्राप्त करने के लिए d3d9 का उपयोग करता हूं, और d3dx लाइब्रेरी का उपयोग करके png फ़ाइल में सहेजता हूं:

    IDirect3DSurface9 * सतह;

    // GetBackBuffer
    idirect3ddevice9-> GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, और सतह);

    // सतह को बचाओ
    D3DXSaveSurfaceToFileA ("filename.png", D3DXIFF_PNG, सतह, NULL, NULL);

    SAFE_RELEASE (सतह);

ऐसा करने के लिए आपको अपना स्वैबफ़र बनाना चाहिए

d3dpps.SwapEffect = D3DSWAPEFFECT_COPY ; // for screenshots.

(इसलिए आप स्क्रीनशॉट लेने से पहले बैकबफ़र की गारंटी नहीं लेते हैं)।


समझ में आता है, धन्यवाद। क्या आप जानते हैं कि इसमें और क्या अंतर GetRenderTargetहै?
18

यह सिर्फ वर्तमान रेंडर टार्गेट प्राप्त करता है (यदि आप कॉल करते समय किसी को बनावट प्रदान कर रहे हैं तो यह एक और ऑफस्क्रीन सतह हो सकती है)।
बोबोबो

13

मेरी छाप में, GDI दृष्टिकोण और DX दृष्टिकोण इसकी प्रकृति में भिन्न हैं। GDI का उपयोग करते हुए पेंटिंग FLUSH विधि को लागू करती है, FLUSH दृष्टिकोण फ्रेम को खींचता है और फिर इसे उसी बफर में एक और फ्रेम को फिर से तैयार करता है, इससे खेल में झिलमिलाहट को उच्च फ्रेम दर की आवश्यकता होगी।

  1. क्यों DX तेज? डीएक्स (या ग्राफिक्स वर्ल्ड) में, डबल बफर रेंडरिंग नामक एक अधिक परिपक्व विधि लागू की जाती है, जहां दो बफ़र्स मौजूद होते हैं, जब हार्डवेयर के सामने बफर पेश करते हैं, तो आप अन्य बफर को भी प्रस्तुत कर सकते हैं, फिर फ्रेम 1 के बाद रेंडरिंग समाप्त, सिस्टम दूसरे बफ़र पर स्वैप होता है (इसे हार्डवेयर को प्रस्तुत करने के लिए लॉक करता है, और पिछले बफ़र को रिलीज़ करता है), इस तरह से रेंडर की अक्षमता में बहुत सुधार होता है।
  2. क्यों हार्डवेयर त्वरण नीचे बारी जल्दी? यद्यपि डबल बफर रेंडरिंग के साथ, एफपीएस में सुधार हुआ है, लेकिन रेंडरिंग का समय अभी भी सीमित है। आधुनिक ग्राफिक हार्डवेयर में आम तौर पर एंटी-अलियासिंग जैसे प्रतिपादन के दौरान बहुत अधिक अनुकूलन शामिल होता है, यह बहुत ही गहन गणना है, यदि आपको उस उच्च गुणवत्ता वाले ग्राफिक्स की आवश्यकता नहीं है, तो निश्चित रूप से आप इस विकल्प को अक्षम कर सकते हैं। और यह आपको कुछ समय बचाएगा।

मुझे लगता है कि आपको वास्तव में एक रीप्ले सिस्टम की आवश्यकता है, जिसे मैं पूरी तरह से सहमत हूं कि लोगों ने क्या चर्चा की।


1
इस बात पर चर्चा करें कि क्यों एक रिप्ले सिस्टम संभव नहीं है। स्क्रैचिंग प्रोग्राम किसी विशिष्ट गेम के लिए नहीं है।
someguy

10

मैंने एक वर्ग लिखा था जिसने स्क्रीन कैप्चर के लिए जीडीआई पद्धति लागू की थी। मैं भी अतिरिक्त गति चाहता था, इसलिए डायरेक्टएक्स विधि (गेटफॉर्स्ट बफ़र के माध्यम से) की खोज के बाद, मैंने कोशिश की कि यह तेज़ हो।

मुझे यह जानकर निराशा हुई कि जीडीआई लगभग 2.5 गुना तेजी से प्रदर्शन करता है। मेरे दोहरे मॉनिटर डिस्प्ले पर कब्जा करने के 100 परीक्षणों के बाद, GDI कार्यान्वयन औसतन स्क्रीन कैप्चरिंग 0.65s था, जबकि DirectX विधि औसतन 1.72s थी। इसलिए GDI निश्चित रूप से GetFrontBuffer की तुलना में तेज़ है, मेरे परीक्षणों के अनुसार।

मैं GetRenderTargetData के माध्यम से DirectX का परीक्षण करने के लिए Brandrew का कोड प्राप्त करने में असमर्थ था। स्क्रीन कॉपी शुद्ध रूप से काली निकली। हालाँकि, यह उस रिक्त स्क्रीन को सुपर फास्ट कॉपी कर सकता है! मैं इसके साथ छेड़छाड़ करता रहूंगा और इसके वास्तविक परिणाम देखने के लिए कार्यशील संस्करण प्राप्त करने की उम्मीद करूंगा।


जानकारी के लिए धन्यवाद। मैंने ब्रैंड्री के कोड का परीक्षण नहीं किया है, लेकिन मुझे पता है कि GetRenderTargetDataदृष्टिकोण काम कर रहा है। जब मैं अपना आवेदन पूरा करूंगा तो शायद मैं अपना जवाब लिख दूंगा। या, आप अपना सब कुछ काम करने के बाद अपडेट कर सकते हैं।
someguy

0.65 प्रति स्क्रेपेंचर ?! एक अच्छा GDI कार्यान्वयन (उपकरणों को इधर-उधर रखना आदि) 1920x1200 में 30fps आसानी से एक आधुनिक कंप्यूटर पर करना चाहिए।
क्रिस्टोफर ओजबेक

मुझे लगता है कि GDI द्वारा प्रदान की गई छवि गुणवत्ता निश्चित रूप से DX की तुलना में अधिक खराब है
ज़ंक करना

मैंने स्लिम # X के साथ C # में यह परीक्षण किया है और आश्चर्यजनक रूप से उसी परिणाम को पाया है। शायद यह इस तथ्य के साथ करना पड़ सकता है कि, स्लिमडीएक्स का उपयोग करके, एक को हर फ्रेम अपडेट के लिए एक नया स्ट्रीम और एक नया बिटमैप बनाना होगा, बजाय इसे एक बार बनाने, रिवाइंड करने और उसी स्थान को ओवरराइट करने के लिए।
सीजर

बस एक स्पष्टीकरण: वास्तव में, "वही परिणाम" जीडीआई के तेजी से होने की बात कर रहा था - जैसा कि @ क्रिसटन ने उल्लेख किया है, 30 एफपीएस + बहुत उल्लेखनीय था और अभी भी बहुत सारे सीपीयू छोड़ दिया है।
सीजर

8

कुछ चीजें जो मैं चमकाने में सक्षम रहा हूं: जाहिरा तौर पर "मिरर ड्राइवर" का उपयोग करना तेज है, हालांकि मुझे ओएसएस एक के बारे में पता नहीं है।

आरडीपी अन्य रिमोट कंट्रोल सॉफ्टवेयर की तुलना में इतना तेज क्यों है?

स्पष्ट रूप से स्ट्रेच-रेक्ट के कुछ संकल्पों का उपयोग करना बिटबेल्ट की तुलना में तेज़ है

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

और आपने जो उल्लेख किया है (डी 3 डी डीएल में हुकिंग करते हुए) डी 3 डी अनुप्रयोगों के लिए एकमात्र तरीका है, लेकिन विंडोज एक्सपी डेस्कटॉप कैप्चर के साथ काम नहीं करेगा। तो अब मैं बस चाहता हूँ कि सामान्य डेस्कटॉप खिड़कियों के लिए एक समान गति-वार समरूप थे ... कोई भी?

(मुझे लगता है कि एयरो के साथ आप फ़्रेप्स जैसे हुक का उपयोग करने में सक्षम हो सकते हैं, लेकिन XP उपयोगकर्ता भाग्य से बाहर होंगे)।

जाहिरा तौर पर स्क्रीन की गहराई को बदलने और / या हार्डवेयर की गति को अक्षम करने के लिए। मदद (और / या अक्षम एयरो) कर सकते हैं।

https://github.com/rdp/screen-capture-recorder-program में इसकी स्थापना के भाग के रूप में एक यथोचित तेजी से बिटब्लैट आधारित कैप्चर उपयोगिता और एक बेंचमार्कर शामिल है, जो आपको बिटब्लैट की गति को अनुकूलित करने के लिए बेंचमार्क गति दे सकते हैं।

VirtualDub में एक "ओपेंगल" स्क्रीन कैप्चर मॉड्यूल भी है, जो तेजी से कहा जाता है और परिवर्तन का पता लगाने जैसे काम करता है http://www.virtualdub.org/blog/pivot/entry.php?id=290


मुझे आश्चर्य है, क्या यह आपके "स्क्रीन-कैप्चर-रिकॉर्डर" का उपयोग करने के लिए तेजी से होगा या खुद BitBlt का उपयोग करेगा? क्या आपके प्रोजेक्ट में कुछ अनुकूलन है?
ब्लेज़

यदि आप अपने आप Bitblt का उपयोग करते हैं तो आप एक अतिरिक्त मेम्ची से बच सकते हैं। )
हेगड़ेपैक

8

C ++ के लिए आप उपयोग कर सकते हैं: http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html
यह सभी प्रकार के 3D एप्लिकेशन / वीडियो ऐप्स पर काम नहीं कर सकता है। फिर यह लिंक अधिक उपयोगी हो सकता है क्योंकि यह 3 अलग-अलग तरीकों का वर्णन करता है जो आप उपयोग कर सकते हैं।

पुराना उत्तर (C #):
आप System.Drawing.Graphics.Copy का उपयोग कर सकते हैं , लेकिन यह बहुत तेज़ नहीं है।

एक नमूना परियोजना जो मैंने ठीक से लिखी है: http://blog.tedd.no/index.php/2010/08/16/c-image-analysis-auto-gaming-with-source/

मैं Direct3D जैसे तेज विधि का उपयोग करके इस नमूने को अपडेट करने की योजना बना रहा हूं: http://spazzarama.com/2009/02/07/screencapture-with-direct3d/

और यहाँ वीडियो पर कब्जा करने के लिए एक लिंक दिया गया है: C # .Net का उपयोग करके वीडियो कैसे कैप्चर किया जाए?


2
आह, मैं उल्लेख करना भूल गया कि मैं C (संभवतः C ++) में प्रोग्रामिंग कर रहा हूं और .NET का उपयोग करने की योजना नहीं बना रहा हूं। बहुत खेद है :/।
someguy

मुझे पहले से ही BitBlt (GDI) के बारे में पता था। मैं Direct3D में देखूंगा, हालाँकि। धन्यवाद!
someguy

मैं इसे कुछ हफ़्ते पहले देख रहा था, लेकिन इसे अभी तक लागू करने के लिए आस-पास नहीं गया है। Direct3D है !! रास्ता !! GDI + का उपयोग करने वाली C # बिल्टिन विधि की तुलना में तेज़ है।
टेड हेन्सन

मैंने अपनी मूल पोस्ट अपडेट कर दी है। लिंक के अनुसार, GetFrontBufferData () को कॉल करने पर DirectX धीमा है। क्या यह कुछ भी है जब गेम फुटेज रिकॉर्ड करने पर विचार करना है? क्या आप मेरे लिए इसका संदर्भ बना सकते हैं?
someguy

1
GDI धीमा है, इसलिए यह समस्या डोमेन के लिए उपयुक्त नहीं है, DirectX, या OpenGL केवल समझदार अनुशंसा होगी।

6

विंडोज 8 के साथ, माइक्रोसॉफ्ट ने विंडोज डेस्कटॉप डुप्लीकेशन एपीआई पेश किया। इसे करने का आधिकारिक तौर पर अनुशंसित तरीका है। स्क्रैचिंग के लिए इसमें एक अच्छी विशेषता यह है कि यह विंडो मूवमेंट का पता लगाता है, इसलिए आप जब कच्चे पिक्सल के बजाय विंडो को इधर-उधर खिसकाते हैं, तो आप ब्लॉक डेल्टास को ट्रांसमिट कर सकते हैं। इसके अलावा, यह आपको बताता है कि कौन सी आयतें बदल गई हैं, एक फ्रेम से अगले तक।

Microsoft उदाहरण कोड बहुत जटिल है, लेकिन एपीआई वास्तव में सरल और उपयोग में आसान है। मैंने एक उदाहरण परियोजना को एक साथ रखा है जो आधिकारिक उदाहरण की तुलना में बहुत सरल है:

https://github.com/bmharper/WindowsDesktopDuplicationSample

डॉक्स: https://docs.microsoft.com/en-gb/windows/desktop/direct3ddxgi/desktop-dup-api

Microsoft आधिकारिक उदाहरण कोड: https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a


जीथब परियोजना विंडोज 10 पर पूरी तरह से काम करती है, जिसे वेब वीडियो और रेजिडेंट ईविल 7. के साथ परीक्षण किया गया है। सबसे अच्छी बात ग्राफिक्स अपग्रेड दर के साथ सीपीयू लोड स्केल है।
jw_

जैसे ही आप GPU-Z लॉन्च करते हैं यह प्रोग्राम स्क्रीन को हथियाना बंद कर देता है।
मैरिनो Marimić

5

आप c ++ ओपन सोर्स प्रोजेक्ट WinRobot @git , एक शक्तिशाली स्क्रीन कैप्चरर की कोशिश कर सकते हैं

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;

सहयोग :

  • UAC विंडो
  • Winlogon
  • DirectShowOverlay

1
यह ... बहुत कम स्तर के हुक हैं। यदि आपके पास व्यवस्थापक अधिकार हैं, तो कैप्चर की गति अद्भुत है।
टस्टर-सीएक्स

मैंने वाइनब्रोट को बहुत शक्तिशाली और चिकना पाया।
ashishgupta_mca

मैंने WinRobot कोड का अध्ययन किया और wrt स्क्रीन कैप्चरिंग में कुछ भी नहीं देखा: यह एक ही CreateCompatibleDC..BBBlt का उपयोग कर रहा है। जब तक कि सेवा के संदर्भ में कुछ जादू न हो जाए?
शेख

@ शेख: आपका अध्ययन बहुत सतही था। कोड स्क्रीन ड्रॉइंग सतह से कॉपी डीडी सतह तक स्क्रीन को कॉपी करने के लिए IDirectDrawSurface7-> BltFast () का उपयोग करता है, फिर यह इमेज को कॉपी करने के लिए एक फिल्पेमिंग का उपयोग करता है। यह काफी जटिल है क्योंकि कोड एक सेवा में चल रहा है जहां आप आसानी से डेस्कटॉप तक नहीं पहुंच सकते हैं।
एल्म्यू

2

मैं खुद इसे डायरेक्टएक्स के साथ करता हूं और लगता है कि यह उतना ही तेज है जितना आप इसे चाहते हैं। मेरे पास एक त्वरित कोड नमूना नहीं है, लेकिन मुझे यह मिला जो उपयोगी होना चाहिए। Directx11 संस्करण में बहुत अधिक अंतर नहीं होना चाहिए, Directx9 शायद थोड़ा अधिक है, लेकिन जाने का रास्ता है


2

मुझे लगता है कि निम्नलिखित सुझाव से आपके प्रश्न का उत्तर नहीं मिलता है, लेकिन सबसे सरल तरीका जो मैंने तेजी से बदलते हुए DirectX दृश्य को कैप्चर करने के लिए पाया है, वह है वीडियो कैमरा को वीडियो कार्ड के S- वीडियो पोर्ट में प्लग करना और छवियों को रिकॉर्ड करना एक चलचित्र। फिर कैमरे से वीडियो को कंप्यूटर पर एमपीजी, डब्ल्यूएमवी, एवीआई आदि फाइल में ट्रांसफर करें।


2

VLC API का उपयोग करके C # में स्क्रीन रिकॉर्डिंग की जा सकती है । मैंने इसे प्रदर्शित करने के लिए एक नमूना कार्यक्रम किया है। यह LibVLCSharp और VideoLAN.LibVLC.Windows पुस्तकालयों का उपयोग करता है। आप इस क्रॉस प्लेटफॉर्म एपीआई का उपयोग करके वीडियो रेंडरिंग से संबंधित कई और सुविधाएँ प्राप्त कर सकते हैं।

API प्रलेखन के लिए देखें: 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
जिनके लिए यह चिंता का विषय हो सकता है: कृपया ध्यान दें कि libvlc को GPL के तहत जारी किया गया है। यदि आप GPL के तहत अपना कोड जारी करने का इरादा नहीं रखते हैं, तो libvlc का उपयोग न करें।
सेबस्टियन कैबोट

यह काफी सटीक नहीं है, LibVLC एलजीपीएल है - इसे 2011 में फिर से शुरू किया गया था। वीएलसी आवेदन जीपीएल ही रहता है: videolan.org/press/lgpl-libvlc.html
एंड्रयू

0

DXGI डेस्कटॉप कैप्चर

प्रोजेक्ट जो डेस्कटॉप छवि को DXGI दोहराव के साथ कैप्चर करता है। फ़ाइल को कैप्चर की गई छवि को विभिन्न छवि प्रारूपों (* .bmp; * .jpg; * .tif) में सहेजता है।

यह नमूना C ++ में लिखा गया है। आपको DirectX (D3D11, D2D1) के साथ कुछ अनुभव भी चाहिए।

आवेदन क्या कर सकते हैं

  • यदि आपके पास एक से अधिक डेस्कटॉप मॉनिटर हैं, तो आप चुन सकते हैं।
  • कैप्चर की गई डेस्कटॉप छवि का आकार बदलें।
  • विभिन्न स्केलिंग मोड चुनें।
  • आप आउटपुट छवि में माउस आइकन दिखा या छिपा सकते हैं।
  • आप आउटपुट चित्र के लिए छवि को घुमा सकते हैं, या इसे डिफ़ॉल्ट के रूप में छोड़ सकते हैं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.