1

is there a way to detect if video playback is running or not with Win32 API?

For audio, I can detect playback processes by:

  1. enumerate playback devices with MMDeviceEnumerator and,
  2. for each device, enumerate sessions with IaudiosessionManager.

I'd like to do the similar thing for video playback. Ideally, a method that works for any application, but if it is impossible, a method that works for specific framework (DirectShow, Media Foundation, etc.) is ok.

Thanks.

Susumu Arai
  • 309
  • 1
  • 2
  • 7
  • 1
    Even if you could reliably do this, what would you do with this information? (i.e. what are you really trying to do?) – selbie Feb 09 '13 at 05:38
  • There is no reliable way – Roman R. Feb 09 '13 at 08:51
  • @selbie possible use case: detecting if machine is idle: `GetLastInputInfo` can give you some idea by timestamp of last input event. However, if the user is watching a video, the session may be non-idle even if there is an extended period with no keyboard/mouse input. So if there was an API they told you if the user was watching a video, you might want to consider the session non-idle as long as that API returns true, even if there was no input in that time – Simon Kissane Mar 04 '23 at 07:12

1 Answers1

0

I'm not aware of a universal method which is guaranteed to work for every possible video playback application. However, in practice, powercfg -requests output will very often tell you if a video is playing. For example:

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.

As you can see, if Chrome is actively playing a video, it will make a DISPLAY power request with reason Video Wake Lock. If you pause or stop the video, the power request is withdrawn. (Recent versions of Microsoft Edge do the same, as does Brave-unsurprising given both are mostly the same code as Chrome.)

A DISPLAY power request isn't necessarily a video though – it could be a computer game or a slide deck, for example. For Chrome, it actually tells you it is a video using the reason message – but not every video player does that. The legacy Windows Media Player 12 (at least in my testing with version 19041.2673) makes a DISPLAY power request, but doesn't populate a reason. (The ability to set a reason on a power request is a relatively new feature of Windows, and Microsoft appears to have never added code to the legacy Windows Media Player to exploit it.) Still, you can see the executable name is wmplayer.exe. Similarly, VideoLan player (VLC) doesn't set a request reason either, but again, you can look at the executable name vlc.exe.

So, by looking at power requests, combined with some heuristics, you can detect video playblack with significant (likely >80% in practice) but not perfect accuracy. A basic heuristic could be:

  1. Check if there is a DISPLAY power request whose reason contains Video (case-insensitive)
  2. Otherwise, check if there is a DISPLAY power request from a known video player executable (e.g. wmplayer.exe)
  3. If there is a DISPLAY power request from unknown executable, you could optionally look at its version resource strings (in particular the description) to see if it contains Media Player, Video Player, etc

If you want to do this programmatically: powercfg -requests ends up invoking the NtPowerInformation system call with a POWER_INFORMATION_LEVEL of GetPowerRequestList. Microsoft has never officially documented the format of the buffer that gets returned, but it has been reverse engineered. Someone has posted open source code on GitHub (diversenok/Powercfg) which does the same as powercfg -requests does, so you could use that code to do it.

Microsoft Photos app (distributed with Windows 10/11) is a good example of where these kinds of heuristics don't quite work though. Despite its name, it doesn't just display photos, it plays videos too. Microsoft.Photos.exe doesn't sound like the name of a video player app though. It does set a reason, but the entirely useless reason of Windows Runtime Package: Microsoft.Windows.Photos_8wekyb3d8bbwe. However, in my testing, it only sets a DISPLAY request for video playback, not when showing a photo (not even for a fullscreen photo). Furthermore, while all three of Chrome, Windows Media Player and VLC withdraw the DISPLAY power request when the video is paused, Microsoft Photos doesn't. Active audio output (e.g. a SYSTEM request from the audio driver, as shown in this example) can be used to distinguish a paused from unpaused video, but that is not 100% accurate (what if the video has no audio? or is muted?)

Another potential gotcha: Video Wake Lock is the string in English, but if the user is using another language edition of Windows, it is possible the string is in their own language instead of English, so heuristics based on searching for the keyword Video may break for non-English users. There are two types of reason strings – DIAGNOSTIC_REASON_SIMPLE_STRING, which is just a raw string, and DIAGNOSTIC_REASON_DETAILED_STRING, which is loading a string resource with the DLL. For the simple string, you just have to hope it is in English, or else you can try searching for keywords in multiple languages (which languages to support? although video, ignoring case and accents, actually works for the majority of European languages). For the detailed string, you could try using SetThreadUILanguage to temporarily change the thread language to English before calling LoadStringW to load the actual string. (Then again, it is also possible that, for your particular scenario, non-English support is a non-requirement.)

Simon Kissane
  • 4,373
  • 3
  • 34
  • 59