有没有一种方法可以使用 Win32 API 检测视频播放是否正在运行?
对于音频,我可以通过以下方式检测播放过程:
我想对视频播放做类似的事情。 理想情况下,适用于任何应用程序的方法,但如果不可能,适用于特定框架(DirectShow、Media Foundation 等)的方法也可以。
谢谢。
我不知道有一种通用方法可以保证适用于所有可能的视频播放应用程序。然而,在实践中,
powercfg -requests
输出通常会告诉您视频是否正在播放。例如:
C:\> powercfg -requests
DISPLAY:
[PROCESS] \Device\HarddiskVolume3\Program Files\Google\Chrome\Application\chrome.exe
Video Wake Lock
SYSTEM:
[DRIVER] NVIDIA High Definition Audio (HDAUDIO\FUNC_01&VEN_10DE&DEV_0099&SUBSYS_1462C75A&REV_1001\5&c8f5c72&0&0001)
An audio stream is currently in use.
AWAYMODE:
None.
EXECUTION:
[PROCESS] \Device\HarddiskVolume3\Program Files\Google\Chrome\Application\chrome.exe
Playing audio
PERFBOOST:
None.
ACTIVELOCKSCREEN:
None.
如您所见,如果 Chrome 正在播放视频,它会发出
DISPLAY
电源请求,原因是 Video Wake Lock
。如果您暂停或停止视频,电源请求将被撤回。 (最近版本的 Microsoft Edge 也做同样的事情——这并不奇怪,因为它与 Chrome 的代码基本相同。)
DISPLAY
电源请求虽然不一定是视频 – 例如,它 可以是电脑游戏或幻灯片。对于 Chrome,它实际上会使用原因消息告诉您这是一个视频——但并非每个视频播放器都这样做。旧版 Windows Media Player 12(至少在我对版本 19041.2673 的测试中)提出了 DISPLAY
电源请求,但没有给出原因。 (在电源请求上设置原因的能力是 Windows 的一项相对较新的功能,Microsoft 似乎从未向旧版 Windows Media Player 添加代码来利用它。)不过,您可以看到可执行文件名称是 wmplayer.exe
.同样,VideoLan player (VLC) 也没有设置请求原因,但同样,您可以查看可执行文件名称vlc.exe
.
因此,通过查看电源请求并结合一些启发式方法,您可以检测到视频播放黑屏的准确度很高(在实践中可能 >80%)但不是完美的准确度。一个基本的启发式可能是:
DISPLAY
电源请求,其原因包含Video
(不区分大小写)DISPLAY
电源请求(例如 wmplayer.exe
)DISPLAY
电源请求,您可以选择查看其版本资源字符串(特别是描述)以查看它是否包含 Media Player
、Video Player
等如果您想以编程方式执行此操作:
powercfg -requests
最终调用 NtPowerInformation
系统调用 POWER_INFORMATION_LEVEL
GetPowerRequestList
。 Microsoft 从未正式记录返回缓冲区的格式,但它已被逆向工程。有人在 GitHub (diversenok/Powercfg
) 上发布了开源代码,其功能与 powercfg -requests
相同,因此您可以使用该代码来完成它。
Microsoft Photos 应用程序(与 Windows 10/11 一起分发)是一个很好的例子,说明这些启发式方法在哪些方面不太奏效。尽管它的名字如此,但它不仅可以显示照片,还可以播放视频。
Microsoft.Photos.exe
听起来不像是视频播放器应用程序的名称。它确实设置了一个原因,但是Windows Runtime Package: Microsoft.Windows.Photos_8wekyb3d8bbwe
这个完全没用的理由。然而,在我的测试中,它只设置了视频播放的 DISPLAY
请求,而不是在显示照片时(即使是全屏照片)。此外,虽然 Chrome、Windows Media Player 和 VLC 这三者在视频暂停时都会撤回DISPLAY
电源请求,但 Microsoft Photos 不会。活动音频输出(例如来自音频驱动程序的 SYSTEM
请求,如本例所示)可用于区分暂停和未暂停的视频,但这不是 100% 准确(如果视频没有音频怎么办?或者是静音?)
另一个潜在的陷阱:
Video Wake Lock
是英文字符串,但如果用户使用的是 Windows 的其他语言版本,则字符串可能是他们自己的语言而不是英文,因此基于搜索关键字的启发式Video
对于非英语用户可能会中断。原因字符串有两种类型——DIAGNOSTIC_REASON_SIMPLE_STRING
,它只是一个原始字符串,以及 DIAGNOSTIC_REASON_DETAILED_STRING
,它正在使用 DLL 加载字符串资源。对于简单的字符串,你只希望它是英文的,否则你可以尝试搜索多种语言的关键字(支持哪些语言?虽然video
,忽略大小写和重音,实际上适用于大多数欧洲语言).对于详细的字符串,您可以尝试使用 SetThreadUILanguage
暂时将线程语言更改为英语,然后再调用 LoadStringW
加载实际的字符串。 (话又说回来,对于您的特定情况,也可能不需要非英语支持。)