精确控制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