精确控制windows全局音量(Python)

话不多说,直接上代码:

  1 import ctypes,time
  2 import comtypes
  3 from ctypes import wintypes
  4 
  5 MMDeviceApiLib = comtypes.GUID(
  6     '{2FDAAFA3-7523-4F66-9957-9D5E7FE698F6}')
  7 IID_IMMDevice = comtypes.GUID(
  8     '{D666063F-1587-4E43-81F1-B948E807363F}')
  9 IID_IMMDeviceCollection = comtypes.GUID(
 10     '{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}')
 11 IID_IMMDeviceEnumerator = comtypes.GUID(
 12     '{A95664D2-9614-4F35-A746-DE8DB63617E6}')
 13 IID_IAudioEndpointVolume = comtypes.GUID(
 14     '{5CDF2C82-841E-4546-9722-0CF74078229A}')
 15 CLSID_MMDeviceEnumerator = comtypes.GUID(
 16     '{BCDE0395-E52F-467C-8E3D-C4579291692E}')
 17 
 18 # EDataFlow
 19 eRender = 0 # audio rendering stream
 20 eCapture = 1 # audio capture stream
 21 eAll = 2 # audio rendering or capture stream
 22 
 23 # ERole
 24 eConsole = 0 # games, system sounds, and voice commands
 25 eMultimedia = 1 # music, movies, narration
 26 eCommunications = 2 # voice communications
 27 
 28 LPCGUID = REFIID = ctypes.POINTER(comtypes.GUID)
 29 LPFLOAT = ctypes.POINTER(ctypes.c_float)
 30 LPDWORD = ctypes.POINTER(wintypes.DWORD)
 31 LPUINT = ctypes.POINTER(wintypes.UINT)
 32 LPBOOL = ctypes.POINTER(wintypes.BOOL)
 33 PIUnknown = ctypes.POINTER(comtypes.IUnknown)
 34 
 35 class IMMDevice(comtypes.IUnknown):
 36     _iid_ = IID_IMMDevice
 37     _methods_ = (
 38         comtypes.COMMETHOD([], ctypes.HRESULT, 'Activate',
 39             (['in'], REFIID, 'iid'),
 40             (['in'], wintypes.DWORD, 'dwClsCtx'),
 41             (['in'], LPDWORD, 'pActivationParams', None),
 42             (['out','retval'], ctypes.POINTER(PIUnknown), 'ppInterface')),
 43         comtypes.STDMETHOD(ctypes.HRESULT, 'OpenPropertyStore', []),
 44         comtypes.STDMETHOD(ctypes.HRESULT, 'GetId', []),
 45         comtypes.STDMETHOD(ctypes.HRESULT, 'GetState', []))
 46 
 47 PIMMDevice = ctypes.POINTER(IMMDevice)
 48 
 49 class IMMDeviceCollection(comtypes.IUnknown):
 50     _iid_ = IID_IMMDeviceCollection
 51 
 52 PIMMDeviceCollection = ctypes.POINTER(IMMDeviceCollection)
 53 
 54 class IMMDeviceEnumerator(comtypes.IUnknown):
 55     _iid_ = IID_IMMDeviceEnumerator
 56     _methods_ = (
 57         comtypes.COMMETHOD([], ctypes.HRESULT, 'EnumAudioEndpoints',
 58             (['in'], wintypes.DWORD, 'dataFlow'),
 59             (['in'], wintypes.DWORD, 'dwStateMask'),
 60             (['out','retval'], ctypes.POINTER(PIMMDeviceCollection),
 61              'ppDevices')),
 62         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetDefaultAudioEndpoint',
 63             (['in'], wintypes.DWORD, 'dataFlow'),
 64             (['in'], wintypes.DWORD, 'role'),
 65             (['out','retval'], ctypes.POINTER(PIMMDevice), 'ppDevices')))
 66     @classmethod
 67     def get_default(cls, dataFlow, role):
 68         enumerator = comtypes.CoCreateInstance(
 69             CLSID_MMDeviceEnumerator, cls, comtypes.CLSCTX_INPROC_SERVER)
 70         return enumerator.GetDefaultAudioEndpoint(dataFlow, role)
 71 
 72 class IAudioEndpointVolume(comtypes.IUnknown):
 73     _iid_ = IID_IAudioEndpointVolume
 74     _methods_ = (
 75         comtypes.STDMETHOD(ctypes.HRESULT, 'RegisterControlChangeNotify', []),
 76         comtypes.STDMETHOD(ctypes.HRESULT, 'UnregisterControlChangeNotify', []),
 77         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelCount',
 78             (['out', 'retval'], LPUINT, 'pnChannelCount')),
 79         comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMasterVolumeLevel',
 80             (['in'], ctypes.c_float, 'fLevelDB'),
 81             (['in'], LPCGUID, 'pguidEventContext', None)),
 82         comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMasterVolumeLevelScalar',
 83             (['in'], ctypes.c_float, 'fLevel'),
 84             (['in'], LPCGUID, 'pguidEventContext', None)),
 85         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMasterVolumeLevel',
 86             (['out','retval'], LPFLOAT, 'pfLevelDB')),
 87         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMasterVolumeLevelScalar',
 88             (['out','retval'], LPFLOAT, 'pfLevel')),
 89         comtypes.COMMETHOD([], ctypes.HRESULT, 'SetChannelVolumeLevel',
 90             (['in'], wintypes.UINT, 'nChannel'),
 91             (['in'], ctypes.c_float, 'fLevelDB'),
 92             (['in'], LPCGUID, 'pguidEventContext', None)),
 93         comtypes.COMMETHOD([], ctypes.HRESULT, 'SetChannelVolumeLevelScalar',
 94             (['in'], wintypes.UINT, 'nChannel'),
 95             (['in'], ctypes.c_float, 'fLevel'),
 96             (['in'], LPCGUID, 'pguidEventContext', None)),
 97         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelVolumeLevel',
 98             (['in'], wintypes.UINT, 'nChannel'),
 99             (['out','retval'], LPFLOAT, 'pfLevelDB')),
100         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelVolumeLevelScalar',
101             (['in'], wintypes.UINT, 'nChannel'),
102             (['out','retval'], LPFLOAT, 'pfLevel')),
103         comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMute',
104             (['in'], wintypes.BOOL, 'bMute'),
105             (['in'], LPCGUID, 'pguidEventContext', None)),
106         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMute',
107             (['out','retval'], LPBOOL, 'pbMute')),
108         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetVolumeStepInfo',
109             (['out','retval'], LPUINT, 'pnStep'),
110             (['out','retval'], LPUINT, 'pnStepCount')),
111         comtypes.COMMETHOD([], ctypes.HRESULT, 'VolumeStepUp',
112             (['in'], LPCGUID, 'pguidEventContext', None)),
113         comtypes.COMMETHOD([], ctypes.HRESULT, 'VolumeStepDown',
114             (['in'], LPCGUID, 'pguidEventContext', None)),
115         comtypes.COMMETHOD([], ctypes.HRESULT, 'QueryHardwareSupport',
116             (['out','retval'], LPDWORD, 'pdwHardwareSupportMask')),
117         comtypes.COMMETHOD([], ctypes.HRESULT, 'GetVolumeRange',
118             (['out','retval'], LPFLOAT, 'pfLevelMinDB'),
119             (['out','retval'], LPFLOAT, 'pfLevelMaxDB'),
120             (['out','retval'], LPFLOAT, 'pfVolumeIncrementDB')))
121     @classmethod
122     def get_default(cls):
123         endpoint = IMMDeviceEnumerator.get_default(eRender, eMultimedia)
124         interface = endpoint.Activate(cls._iid_, comtypes.CLSCTX_INPROC_SERVER)
125         return ctypes.cast(interface, ctypes.POINTER(cls))
126 
127 
128 
129 
130 
131 if __name__ == '__main__':
132 
133     def show_vol(ev):
134         time.sleep(2)
135         voldb = ev.GetMasterVolumeLevel()
136         volsc = ev.GetMasterVolumeLevelScalar()
137         volst, nstep = ev.GetVolumeStepInfo()
138         print('Master Volume (dB): %0.4f' % voldb)
139         print('Master Volume (scalar): %0.4f' % volsc)#当前音量
140         print('Master Volume (step): %d / %d' % (volst, nstep))
141 
142     def test():
143         ev = IAudioEndpointVolume.get_default()
144         vol = ev.GetMasterVolumeLevelScalar()
145         vmin, vmax, vinc = ev.GetVolumeRange()
146         print('Volume Range (min, max, step) (dB): '
147               '%0.4f, %0.4f, %0.4f' % (vmin, vmax, vinc))
148         show_vol(ev)
149         try:
150             print('\nIncrement the master volume')
151             ev.VolumeStepUp()#音量加
152             show_vol(ev)
153             print('\nDecrement the master volume twice')
154             ev.VolumeStepDown()#音量减
155             ev.VolumeStepDown()
156             show_vol(ev)
157             print('\nSet the master volume to 0.75 scalar')
158             ev.SetMasterVolumeLevelScalar(0.75)#音量百分比设置
159             show_vol(ev)
160             print('\nSet the master volume to 0.25 scalar')
161             ev.SetMasterVolumeLevelScalar(0.25)#音量百分比设置
162             show_vol(ev)
163         finally:
164             ev.SetMasterVolumeLevelScalar(vol)
165 
166     comtypes.CoInitialize()
167     try:
168         test()
169     finally:
170         comtypes.CoUninitialize()

简单逻辑就是先获取ev对象(

ev = IAudioEndpointVolume.get_default()

然后有几个方法:

方法一(获取当前音量):(

volsc = ev.GetMasterVolumeLevelScalar()

方法二(音量加/减):(

ev.VolumeStepUp()#音量加
ev.VolumeStepDown()#音量减

方法三(设置音量):(

ev.SetMasterVolumeLevelScalar(0.75)#音量百分比设置

另附简单调用win32API加减音量:

import ctypes,operator

WM_APPCOMMAND = 0x319
APPCOMMAND_VOLUME_UP = 0x0a
APPCOMMAND_VOLUME_DOWN = 0x09
APPCOMMAND_VOLUME_MUTE = 0x08

def setSpeakerVol(volume):
        hwnd = ctypes.windll.user32.GetForegroundWindow()

        # ctypes.windll.winmm.waveOutSetVolume(hwnd, 0xffffffff)

        print(hwnd)
        ctypes.windll.user32.PostMessageA(hwnd, WM_APPCOMMAND, 0, APPCOMMAND_VOLUME_DOWN * 0x10000)
#
if __name__ == '__main__':

    setSpeakerVol(0)

利用:

PostMessageA

 

posted @ 2020-03-31 14:10  我惠依旧  阅读(3082)  评论(2编辑  收藏  举报