gpt4 book ai didi

python - 在后台更改 Windows 10 应用程序音频混合(最好使用 Python)

转载 作者:太空宇宙 更新时间:2023-11-03 15:51:27 25 4
gpt4 key购买 nike

我正在寻找一种方法来更改 Windows 中不同应用程序的音频混合(即 Firefox 音频级别与 Foobar 音频级别),而无需将焦点从当前应用程序上移开。 Python 是我最熟悉的语言,但如果能让事情变得更轻松的话,我会使用其他语言。该代码将用于连接带有一些音量旋钮和按钮的外部 HID 设备。焦点需要保持在当前窗口上,因为将会有一个 VR 游戏在音频混合器之上运行,如果脚本选项卡离开,我将无法重新聚焦于该游戏。

我已经成功地改造了一些older code一起使用 comtypes 模块,但从那里我只能更改左/右平衡,而不能更改应用程序特定的音频级别。

我试图通过 MSDN 上的相关 Windows 文档(特别是 WASAPI)找到自己的方法,但它通常最终会让我陷入微软的兔子洞,并且我陷入了方式。 (我充其量仍然是一个新手程序员)。

我的处理方式完全错误吗?

最佳答案

因此,您提供的“旧代码”在 API 中仍然与 Windows 10 声音 API 的工作原理相关。

此类代码的一个很好的示例目前是用 C# 编写的,可以在此处找到:

StackOverflow - c# - Controling Volume Mixer :

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace SetAppVolumne
{
class Program
{
static void Main(string[] args)
{
const string app = "Mozilla Firefox";

foreach (string name in EnumerateApplications())
{
Console.WriteLine("name:" + name);
if (name == app)
{
// display mute state & volume level (% of master)
Console.WriteLine("Mute:" + GetApplicationMute(app));
Console.WriteLine("Volume:" + GetApplicationVolume(app));

// mute the application
SetApplicationMute(app, true);

// set the volume to half of master volume (50%)
SetApplicationVolume(app, 50);
}
}
}

public static float? GetApplicationVolume(string name)
{
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return null;

float level;
volume.GetMasterVolume(out level);
return level * 100;
}

public static bool? GetApplicationMute(string name)
{
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return null;

bool mute;
volume.GetMute(out mute);
return mute;
}

public static void SetApplicationVolume(string name, float level)
{
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return;

Guid guid = Guid.Empty;
volume.SetMasterVolume(level / 100, ref guid);
}

public static void SetApplicationMute(string name, bool mute)
{
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return;

Guid guid = Guid.Empty;
volume.SetMute(mute, ref guid);
}

public static IEnumerable<string> EnumerateApplications()
{
// get the speakers (1st render + multimedia) device
IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
IMMDevice speakers;
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);

// activate the session manager. we need the enumerator
Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID;
object o;
speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o);
IAudioSessionManager2 mgr = (IAudioSessionManager2)o;

// enumerate sessions for on this device
IAudioSessionEnumerator sessionEnumerator;
mgr.GetSessionEnumerator(out sessionEnumerator);
int count;
sessionEnumerator.GetCount(out count);

for (int i = 0; i < count; i++)
{
IAudioSessionControl ctl;
sessionEnumerator.GetSession(i, out ctl);
string dn;
ctl.GetDisplayName(out dn);
yield return dn;
Marshal.ReleaseComObject(ctl);
}
Marshal.ReleaseComObject(sessionEnumerator);
Marshal.ReleaseComObject(mgr);
Marshal.ReleaseComObject(speakers);
Marshal.ReleaseComObject(deviceEnumerator);
}

private static ISimpleAudioVolume GetVolumeObject(string name)
{
// get the speakers (1st render + multimedia) device
IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
IMMDevice speakers;
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);

// activate the session manager. we need the enumerator
Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID;
object o;
speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o);
IAudioSessionManager2 mgr = (IAudioSessionManager2)o;

// enumerate sessions for on this device
IAudioSessionEnumerator sessionEnumerator;
mgr.GetSessionEnumerator(out sessionEnumerator);
int count;
sessionEnumerator.GetCount(out count);

// search for an audio session with the required name
// NOTE: we could also use the process id instead of the app name (with IAudioSessionControl2)
ISimpleAudioVolume volumeControl = null;
for (int i = 0; i < count; i++)
{
IAudioSessionControl ctl;
sessionEnumerator.GetSession(i, out ctl);
string dn;
ctl.GetDisplayName(out dn);
if (string.Compare(name, dn, StringComparison.OrdinalIgnoreCase) == 0)
{
volumeControl = ctl as ISimpleAudioVolume;
break;
}
Marshal.ReleaseComObject(ctl);
}
Marshal.ReleaseComObject(sessionEnumerator);
Marshal.ReleaseComObject(mgr);
Marshal.ReleaseComObject(speakers);
Marshal.ReleaseComObject(deviceEnumerator);
return volumeControl;
}
}

[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
internal class MMDeviceEnumerator
{
}

internal enum EDataFlow
{
eRender,
eCapture,
eAll,
EDataFlow_enum_count
}

internal enum ERole
{
eConsole,
eMultimedia,
eCommunications,
ERole_enum_count
}

[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDeviceEnumerator
{
int NotImpl1();

[PreserveSig]
int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);

// the rest is not implemented
}

[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDevice
{
[PreserveSig]
int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);

// the rest is not implemented
}

[Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioSessionManager2
{
int NotImpl1();
int NotImpl2();

[PreserveSig]
int GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum);

// the rest is not implemented
}

[Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioSessionEnumerator
{
[PreserveSig]
int GetCount(out int SessionCount);

[PreserveSig]
int GetSession(int SessionCount, out IAudioSessionControl Session);
}

[Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioSessionControl
{
int NotImpl1();

[PreserveSig]
int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);

// the rest is not implemented
}

[Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ISimpleAudioVolume
{
[PreserveSig]
int SetMasterVolume(float fLevel, ref Guid EventContext);

[PreserveSig]
int GetMasterVolume(out float pfLevel);

[PreserveSig]
int SetMute(bool bMute, ref Guid EventContext);

[PreserveSig]
int GetMute(out bool pbMute);
}
}

我发现一个将所有 Windows Core Audio API COMType 导入 Python 的库是 pycaw如果您想学习如何将 Windows API 移植到 Python 中,这将是一个好的开始。

关于python - 在后台更改 Windows 10 应用程序音频混合(最好使用 Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41255148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com