Tim Roberts veröffentlicht ein comtypes Beispiel in der Python-Win32-Diskussionsliste in Bezug auf wie Control Volume on Windows. Im folgenden Beispiel habe ich Tims Code geändert und Klassenmethoden hinzugefügt, die den Standardaudioendpunkt und seine IAudioEndpointVolume
Schnittstelle zurückgeben.
Der dB-Lautstärkenbereich auf den beiden getesteten Systemen (Windows 7 und Windows 10) normalisierte den Maximalpegel auf 0 dB, aber die Mindestpegel und Lautstärkeinkremente unterschieden sich zwischen den Systemen. Ich empfehle stattdessen, die skalaren und integralen Schrittmethoden zu verwenden. Der Skalarbereich liegt zwischen 0,0 und 1,0.
import ctypes
import comtypes
from ctypes import wintypes
MMDeviceApiLib = comtypes.GUID(
'{2FDAAFA3-7523-4F66-9957-9D5E7FE698F6}')
IID_IMMDevice = comtypes.GUID(
'{D666063F-1587-4E43-81F1-B948E807363F}')
IID_IMMDeviceCollection = comtypes.GUID(
'{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}')
IID_IMMDeviceEnumerator = comtypes.GUID(
'{A95664D2-9614-4F35-A746-DE8DB63617E6}')
IID_IAudioEndpointVolume = comtypes.GUID(
'{5CDF2C82-841E-4546-9722-0CF74078229A}')
CLSID_MMDeviceEnumerator = comtypes.GUID(
'{BCDE0395-E52F-467C-8E3D-C4579291692E}')
# EDataFlow
eRender = 0 # audio rendering stream
eCapture = 1 # audio capture stream
eAll = 2 # audio rendering or capture stream
# ERole
eConsole = 0 # games, system sounds, and voice commands
eMultimedia = 1 # music, movies, narration
eCommunications = 2 # voice communications
LPCGUID = REFIID = ctypes.POINTER(comtypes.GUID)
LPFLOAT = ctypes.POINTER(ctypes.c_float)
LPDWORD = ctypes.POINTER(wintypes.DWORD)
LPUINT = ctypes.POINTER(wintypes.UINT)
LPBOOL = ctypes.POINTER(wintypes.BOOL)
PIUnknown = ctypes.POINTER(comtypes.IUnknown)
class IMMDevice(comtypes.IUnknown):
_iid_ = IID_IMMDevice
_methods_ = (
comtypes.COMMETHOD([], ctypes.HRESULT, 'Activate',
(['in'], REFIID, 'iid'),
(['in'], wintypes.DWORD, 'dwClsCtx'),
(['in'], LPDWORD, 'pActivationParams', None),
(['out','retval'], ctypes.POINTER(PIUnknown), 'ppInterface')),
comtypes.STDMETHOD(ctypes.HRESULT, 'OpenPropertyStore', []),
comtypes.STDMETHOD(ctypes.HRESULT, 'GetId', []),
comtypes.STDMETHOD(ctypes.HRESULT, 'GetState', []))
PIMMDevice = ctypes.POINTER(IMMDevice)
class IMMDeviceCollection(comtypes.IUnknown):
_iid_ = IID_IMMDeviceCollection
PIMMDeviceCollection = ctypes.POINTER(IMMDeviceCollection)
class IMMDeviceEnumerator(comtypes.IUnknown):
_iid_ = IID_IMMDeviceEnumerator
_methods_ = (
comtypes.COMMETHOD([], ctypes.HRESULT, 'EnumAudioEndpoints',
(['in'], wintypes.DWORD, 'dataFlow'),
(['in'], wintypes.DWORD, 'dwStateMask'),
(['out','retval'], ctypes.POINTER(PIMMDeviceCollection),
'ppDevices')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetDefaultAudioEndpoint',
(['in'], wintypes.DWORD, 'dataFlow'),
(['in'], wintypes.DWORD, 'role'),
(['out','retval'], ctypes.POINTER(PIMMDevice), 'ppDevices')))
@classmethod
def get_default(cls, dataFlow, role):
enumerator = comtypes.CoCreateInstance(
CLSID_MMDeviceEnumerator, cls, comtypes.CLSCTX_INPROC_SERVER)
return enumerator.GetDefaultAudioEndpoint(dataFlow, role)
class IAudioEndpointVolume(comtypes.IUnknown):
_iid_ = IID_IAudioEndpointVolume
_methods_ = (
comtypes.STDMETHOD(ctypes.HRESULT, 'RegisterControlChangeNotify', []),
comtypes.STDMETHOD(ctypes.HRESULT, 'UnregisterControlChangeNotify', []),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelCount',
(['out', 'retval'], LPUINT, 'pnChannelCount')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMasterVolumeLevel',
(['in'], ctypes.c_float, 'fLevelDB'),
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMasterVolumeLevelScalar',
(['in'], ctypes.c_float, 'fLevel'),
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMasterVolumeLevel',
(['out','retval'], LPFLOAT, 'pfLevelDB')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMasterVolumeLevelScalar',
(['out','retval'], LPFLOAT, 'pfLevel')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'SetChannelVolumeLevel',
(['in'], wintypes.UINT, 'nChannel'),
(['in'], ctypes.c_float, 'fLevelDB'),
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'SetChannelVolumeLevelScalar',
(['in'], wintypes.UINT, 'nChannel'),
(['in'], ctypes.c_float, 'fLevel'),
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelVolumeLevel',
(['in'], wintypes.UINT, 'nChannel'),
(['out','retval'], LPFLOAT, 'pfLevelDB')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetChannelVolumeLevelScalar',
(['in'], wintypes.UINT, 'nChannel'),
(['out','retval'], LPFLOAT, 'pfLevel')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'SetMute',
(['in'], wintypes.BOOL, 'bMute'),
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetMute',
(['out','retval'], LPBOOL, 'pbMute')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetVolumeStepInfo',
(['out','retval'], LPUINT, 'pnStep'),
(['out','retval'], LPUINT, 'pnStepCount')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'VolumeStepUp',
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'VolumeStepDown',
(['in'], LPCGUID, 'pguidEventContext', None)),
comtypes.COMMETHOD([], ctypes.HRESULT, 'QueryHardwareSupport',
(['out','retval'], LPDWORD, 'pdwHardwareSupportMask')),
comtypes.COMMETHOD([], ctypes.HRESULT, 'GetVolumeRange',
(['out','retval'], LPFLOAT, 'pfLevelMinDB'),
(['out','retval'], LPFLOAT, 'pfLevelMaxDB'),
(['out','retval'], LPFLOAT, 'pfVolumeIncrementDB')))
@classmethod
def get_default(cls):
endpoint = IMMDeviceEnumerator.get_default(eRender, eMultimedia)
interface = endpoint.Activate(cls._iid_, comtypes.CLSCTX_INPROC_SERVER)
return ctypes.cast(interface, ctypes.POINTER(cls))
Zum Beispiel:
if __name__ == '__main__':
def show_vol(ev):
voldb = ev.GetMasterVolumeLevel()
volsc = ev.GetMasterVolumeLevelScalar()
volst, nstep = ev.GetVolumeStepInfo()
print('Master Volume (dB): %0.4f' % voldb)
print('Master Volume (scalar): %0.4f' % volsc)
print('Master Volume (step): %d/%d' % (volst, nstep))
def test():
ev = IAudioEndpointVolume.get_default()
vol = ev.GetMasterVolumeLevelScalar()
vmin, vmax, vinc = ev.GetVolumeRange()
print('Volume Range (min, max, step) (dB): '
'%0.4f, %0.4f, %0.4f' % (vmin, vmax, vinc))
show_vol(ev)
try:
print('\nIncrement the master volume')
ev.VolumeStepUp()
show_vol(ev)
print('\nDecrement the master volume twice')
ev.VolumeStepDown()
ev.VolumeStepDown()
show_vol(ev)
print('\nSet the master volume to 0.75 scalar')
ev.SetMasterVolumeLevelScalar(0.75)
show_vol(ev)
print('\nSet the master volume to 0.25 scalar')
ev.SetMasterVolumeLevelScalar(0.25)
show_vol(ev)
finally:
ev.SetMasterVolumeLevelScalar(vol)
comtypes.CoInitialize()
try:
test()
finally:
comtypes.CoUninitialize()
Darf ich fragen, was Ihre Anwendung ist? Pythons integrierte Audiofunktionen sind sehr schlecht. – TigerhawkT3
Rufen Sie Windows-APIs wie [mixerOpen] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd757308%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396) von Python auf . –
@DavidChing, in Vista und später ändert die winmm.dll-API die Audioeinstellungen pro Anwendung. Zum Einstellen des Master-Volume muss die COM-Schnittstelle "IAudioEndpointVolume" verwendet werden. – eryksun