所以我尝试在Python中捕获网络摄像头快照ctypes,这是代码:
import ctypes
from ctypes import wintypes
def CaptureWebcam(index: int, filePath: str) -> bool:
avicap32 = ctypes.windll.avicap32
WS_CHILD = 0x40000000
WM_CAP_DRIVER_CONNECT = 0x0400 + 10
WM_CAP_DRIVER_DISCONNECT = 0x0402
WM_CAP_FILE_SAVEDIB = 0x0400 + 100 + 25
hcam = avicap32.capCreateCaptureWindowW(
wintypes.LPWSTR("Blank"),
WS_CHILD,
0, 0, 0, 0,
ctypes.windll.user32.GetDesktopWindow(), 0
)
result = False
if hcam:
if ctypes.windll.user32.SendMessageA(hcam, WM_CAP_DRIVER_CONNECT, index, 0):
if ctypes.windll.user32.SendMessageA(hcam, WM_CAP_FILE_SAVEDIB, 0, wintypes.LPWSTR(filePath)):
result = True
ctypes.windll.user32.SendMessageA(hcam, WM_CAP_DRIVER_DISCONNECT, 0, 0)
ctypes.windll.user32.DestroyWindow(hcam)
return result
然而,当我跑到这里时,正在发生的事情;
我的网络摄像头的 LED 指示灯亮起,这意味着脚本正在访问我的网络摄像头,但它正在将一个空文件(0 字节)保存到磁盘中,并且该函数返回 False。
最佳实践是为每个函数完全定义
.argtypes
和 .restype
,并且不要混合 A 和 W 版本的 API。
请注意,HWND 在 64 位系统上是 64 位值。
.restype
默认为 c_int
,因此较大的值可能会被截断。
我没有网络摄像头,但下面是我通过挖掘 Windows SDK 标头并完全遵循定义而使用的(未经测试)。 尝试一下吧。
import ctypes as ct
import ctypes.wintypes as w
WS_CHILD = 0x40000000
WM_USER = 0x400
WM_CAP_START = WM_USER
WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10
WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11
WM_CAP_UNICODE_START = WM_USER + 100
WM_CAP_FILE_SAVEDIBW = WM_CAP_UNICODE_START + 25
LRESULT = LONG_PTR = ct.c_ssize_t
avicap32 = ct.WinDLL('avicap32', use_last_error=True)
capCreateCaptureWindowW = avicap32.capCreateCaptureWindowW
capCreateCaptureWindowW.argtypes = w.LPCWSTR, w.DWORD, ct.c_int, ct.c_int, ct.c_int, ct.c_int, w.HWND, ct.c_int
capCreateCaptureWindowW.restype = w.HWND
user32 = ct.WinDLL('user32')
GetDesktopWindow = user32.GetDesktopWindow
GetDesktopWindow.argtypes = ()
GetDesktopWindow.restype = w.HWND
SendMessageW = user32.SendMessageW
SendMessageW.argtypes = w.HWND, w.UINT, w.WPARAM, w.LPARAM
SendMessageW.restype = LRESULT
DestroyWindow = user32.DestroyWindow
DestroyWindow.argtypes = w.HWND,
DestroyWindow.restype = w.BOOL
IsWindow = user32.IsWindow
IsWindow.argtypes = w.HWND,
IsWindow.restype = w.BOOL
def AVICapSM(hwnd, m, w, l):
return SendMessageW(hwnd, m, w, l) if IsWindow(hwnd) else 0
def capFileSaveDIB(hwnd, szName):
return AVICapSM(hwnd, WM_CAP_FILE_SAVEDIBW, 0, szName)
def capDriverConnect(hwnd, i):
return AVICapSM(hwnd, WM_CAP_DRIVER_CONNECT, i, 0)
def capDriverDisconnect(hwnd):
return AVICapSM(hwnd, WM_CAP_DRIVER_DISCONNECT, 0, 0)
def CaptureWebcam(index, filePath):
hcam = capCreateCaptureWindowW('Blank', WS_CHILD, 0, 0, 0, 0, GetDesktopWindow(), 0)
result = False
if hcam:
if capDriverConnect(hwnd, 0):
result = capFileSaveDIB(filePath)
capDriveDisconnect(hwnd)
DestroyWindow(hcam)
return result