如何在Windows 11中控制当前活跃媒体播放器的音量?
Windows 11中控制当前活跃媒体应用音量的.NET实现方案
核心方案:调用Windows Core Audio API
Windows Core Audio API提供了对单个应用音频会话的访问控制权,这是实现目标的关键(类似Linux下MPRIS的作用)。你可以通过.NET的P/Invoke调用原生COM接口,实现对指定媒体应用的音量调整。
关键步骤
- 枚举音频会话:通过
IAudioSessionManager2获取所有当前运行的音频会话,筛选出处于活跃状态的会话。 - 控制会话音量:利用
ISimpleAudioVolume接口调整目标会话的音量或设置静音。
C# 示例代码
using System; using System.Runtime.InteropServices; public class AudioSessionController { [ComImport] [Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionManager2 { int GetSessionEnumerator(out IAudioSessionEnumerator sessionEnum); } [ComImport] [Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionEnumerator { int GetCount(out int count); int GetSession(int index, out IAudioSessionControl session); } [ComImport] [Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IAudioSessionControl { int GetState(out AudioSessionState state); } [ComImport] [Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface ISimpleAudioVolume { int SetMasterVolume(float volume, ref Guid eventContext); int GetMasterVolume(out float volume); } private enum AudioSessionState { Inactive = 0, Active = 1, Expired = 2 } public static void AdjustActiveMediaVolume(float delta) { var mmDeviceEnumeratorClsid = new Guid("BCDE0395-E52F-467C-8E3D-C4579291692E"); var audioSessionManagerIid = new Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"); // 获取默认音频输出设备 var enumerator = Activator.CreateInstance(Type.GetTypeFromCLSID(mmDeviceEnumeratorClsid)); var defaultDevice = enumerator.GetType().InvokeMember( "GetDefaultAudioEndpoint", System.Reflection.BindingFlags.InvokeMethod, null, enumerator, new object[] { 0, 0 } // eRender = 0, eConsole = 0 ); // 激活IAudioSessionManager2接口 var sessionManager = (IAudioSessionManager2)defaultDevice.GetType().InvokeMember( "Activate", System.Reflection.BindingFlags.InvokeMethod, null, defaultDevice, new object[] { audioSessionManagerIid, 0, IntPtr.Zero } ); // 枚举所有音频会话 sessionManager.GetSessionEnumerator(out var sessionEnum); sessionEnum.GetCount(out var sessionCount); var emptyGuid = Guid.Empty; for (int i = 0; i < sessionCount; i++) { sessionEnum.GetSession(i, out var sessionControl); sessionControl.GetState(out var state); if (state == AudioSessionState.Active) { var volumeControl = (ISimpleAudioVolume)sessionControl; volumeControl.GetMasterVolume(out var currentVolume); // 调整音量(delta为±0.1,范围0-1) var newVolume = Math.Clamp(currentVolume + delta, 0f, 1f); volumeControl.SetMasterVolume(newVolume, ref emptyGuid); // 找到第一个活跃会话后退出,若需处理多个可移除break break; } } } } class Program { static void Main(string[] args) { // 示例:增加音量10% AudioSessionController.AdjustActiveMediaVolume(0.1f); // 减少音量:AudioSessionController.AdjustActiveMediaVolume(-0.1f); } }
优化建议
- 精准定位目标应用:可以结合你熟悉的SMTC API获取当前活跃媒体的进程ID,再通过
IAudioSessionControl2接口获取会话对应的进程ID,实现精准匹配,避免误调其他活跃音频会话。 - COM对象释放:生产环境中需添加
Marshal.ReleaseComObject调用,避免内存泄漏。 - 参数适配:可将音量增量改为控制台参数,方便可编程按键传入不同指令(加音量、减音量、静音)。
内容的提问来源于stack exchange,提问作者wullxz
相关产品推荐
相关产品推荐

