Discord 如何连接到特定进程的音频?

Posted

技术标签:

【中文标题】Discord 如何连接到特定进程的音频?【英文标题】:How does Discord hook into a specific process's audio? 【发布时间】:2021-01-26 06:23:20 【问题描述】:

通过 Google 搜索结果,没有广为人知的方法可以从 Microsoft Windows 上的特定应用程序捕获音频,至少不必求助于解决方法,例如将音频从一个进程发送到单独的虚拟音频环回设备(但是会导致无法听到声音,除非您使用硬件环回播放设备或通过主输出“收听”模拟输入)。

这些变通方法很笨拙,需要为每个特定应用程序进行配置,并且软件通常会出现异常行为,如果在执行期间更改输出设备,则不再成功发出任何声音或直接停止工作。同时,启动Discord“Live Streaming”会话可以让您轻松地通过 VoIP 群组通话共享单个应用程序的声音,而不会失败。其他应用程序的声音被完全删除。查看音频设备,似乎没有发生虚拟环回路由,并且客户端的音频播放绝对零中断。该功能在 macOS 或 Linux 版本的软件上不可用,仅在 Windows 上可用。因此,在 Win32 中可以从特定进程中捕获声音,但为什么没有其他人这样做呢?例如,在这样的功能非常有用的软件分支中实现这样的东西需要什么,比如 OBS 或 Audacity?

【问题讨论】:

我相信 WASAPI Loopback Recording 允许您仍然呈现捕获的输出。虽然我不确定您将如何设置特定于流程的捕获。也许Core Audio API 中有一些东西可以解决这个特定的用例。 @IInspectable WASAPI 仅支持来自所有系统设备组合的渲染输出。它发生在音频接口内的硬件级别,因此不能用于独立捕获进程。令我困扰的是,这是完全有可能以始终如一的可靠方式实现的:Discord 做到了。但似乎没有这方面的具体信息。 嗨,我为这个问题添加了赏金。我也想知道在macos上是怎么做的 @drikoda 感谢您为此添加赏金。不过,我认为应用程序音频捕获在 macOS 上不可用。 @phoenixstudio 我的机器没有 Realtek Audio(没有安装内置音频驱动程序),我使用的是 Focusrite Scarlett 4i4,绝对不是 Discord 的音频接口。无论如何,此功能都有效。我相信此功能适用于所有硬件。 【参考方案1】:

编辑:不确定这是否有用,但我找到了这个页面:https://obsproject.com/forum/threads/audio-sources.465/

尤其是,我觉得这是有用的信息:

这与挂钩 Direct3D 非常相似。你挂钩 IAudioRenderClient 接口,并拦截 GetBuffer 以读取音频样本。

初学者逆向工程时间!

另外,我不能给出明确的答案,但我可以引导你走向正确的方向。

Discord 在其根目录中有一个名为\modules\discord_hook 的目录,在这里我们可以找到一个名为index.jsjavascript 文件,一个名为manifest.json 的json 文件,一个名为.node 的文件,名为discord_hook.node (已编译/加密,我无法读取),带有.dlls 和.exes 的目录,它还会生成一个日志文件,名为hook.log

index.js 似乎只是加载discord_hook.node 并做一些其他对我们不重要的事情。

谷歌搜索 manifest.json 将我带到这里:https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json

manifest.json 文件是每个使用 WebExtension API 的扩展程序必须包含的唯一文件。

.json 文件中,我们发现它引用了.exes、.dlls、discord_hook.nodeindex.js 及其自身。

前面提到的 .node 文件在很大程度上是人类无法读取的。

hook.log 不会输出任何看似有用的信息,只输出有关图形/视频共享的信息。

这让我们在此处查看子目录中的exedll 文件,我不知道asm,但我们可以查看这些二进制文件中留下的一些字符串。

我在DiscordHook.dll 中发现了一段字符串引用了偏移 1266B4 到偏移 126EA6 的音频(这可能而且几乎肯定会在未来版本的不和谐中发生变化)

这里有一些似乎值得在此处发布的字符串。

Audio buffer stopped, WASAPI capture stopping
Failed to get format of WASAPI audio buffer, not capturing, error code [%d]
Failed to get WASAPI audio client from render client, not capturing
Starting capture of WASAPI buffer with sample rate %d, depth %d, %d channels
Starting capture of Windows Sonic stream with downmix sample rate %d, depth %d, %d channels
ISpatialAudioObjectRenderStream::Stop
ISpatialAudioObjectRenderStream::BeginUpdatingAudioObjects
ISpatialAudioObjectRenderStream::EndUpdatingAudioObjects
ISpatialAudioObject::GetBuffer
HookWasapi failed to load audioses.dll
WaveFormatFromRenderClient failed with error code [%d]
LoadWASAPIOffsets failed with error code [%d]
WASAPI module sizes don't match (expected: %lu, actual: %lu)
WASAPI offsets invalid (stop: %lu, getBuffer: %lu, releaseBuffer: %lu, clientOffset: %lu, endpointOffset: %lu)
WASAPI offsets out of bounds (size: %lu, stop: %lu, getBuffer: %lu, releaseBuffer: %lu)
IAudioClient::Stop
IAudioRenderClient::GetBuffer
IAudioRenderClient::ReleaseBuffer
HookWasapi: MH_ApplyQueued failed 0x%x

另外,我用谷歌搜索了“hook process audio”并找到了这个: https://ywjheart.wordpress.com/2017/02/26/audio-captureapihook-based-for-obs-studio/

它没有提供任何代码示例或下载,但它描述了一些关于做这件事的东西,但在 OBS 中。他们还在底部链接了他们用来记录的东西。

祝你好运,我希望所有这些信息都能在某种程度上有所帮助!

【讨论】:

看起来 .node 文件是在 Node.js 中以node-gyp 导入的外部库。

以上是关于Discord 如何连接到特定进程的音频?的主要内容,如果未能解决你的问题,请参考以下文章

如何让基于 Python 的 Discord Bot 随机播放不同的声音?

Discord 机器人类型错误。无法连接到我的服务器

discord.js 不播放音频文件

Discord.js 播放音频文件错误

(Discord.js) 如何让所有成员连接到某个类别的语音频道?

如何连接到 solana discord 开发者频道?