python 通过麦克风播放 mp3 文件

Playing mp3 file through microphone with python

有没有办法使用 python(而不是任何外部软件)像麦克风输入一样播放 mp3 文件?

例如,我有一个 mp3 文件和一个 python 脚本,它会通过我的麦克风播放它,这样语音室中的其他人就能听到它。正如我所说,这只是一个例子。

当然,我做了一些研究。我发现我可以使用一个软件来创建一个虚拟设备并且做一些事情就可以得到结果。但我的观点是,是否可以不安装软件而是使用某种 python 脚本?

如果您的意思是如何使用 Python 播放 MP3,那么,这是一个广泛的问题。

有没有可能,没有任何依赖,是的,但不值得。好吧,播放未压缩的音频是,但是MP3,好吧,我会在下面解释。

要在不安装 pyaudio 或 pygame 或类似软件的情况下播放来自 Python 的原始音频数据,您首先必须知道您的脚本所在的平台 运行.

然后实现一组不错的函数,用于选择音频设备,设置采样率、比特率等属性,mono/stereo...,将流传输到声卡并停止播放。

这并不难,但要做到这一点,您必须在 Windows 上使用 ctypes,在 Mac 上使用 PyObjC,而 Linux 是特殊情况,因为它支持许多音频系统(可能使用套接字连接到 PulseAudio 或通过管道连接到某些进程,例如 aplay/paplay/mpeg123... 或利用 gstreamer。)。

但是,当您拥有带有简单接口来访问和使用音频设备的不错的库时,为什么要经历所有这些只是为了避免依赖性。

PyAudio 很棒。

嗯,这是你关心的问题。

但是,在没有外部库的情况下,从纯 Python 实时播放 MP3,嗯,这并非完全不可能,但很难实现,据我所知甚至没有人尝试过这样做它。

有纯 Python MP3 解码器实现,但比实时音频播放所需的速度慢 10 倍。它可以优化为接近全速,但没有人有兴趣这样做。

它主要具有教育价值,用于不需要实时速度的情况。

这是你应该做的:

安装pygame并直接使用它播放MP3

或:

安装 PyAudio 和一些解码 Mp3 的库,pypi.python.org 上有很多,然后用它来解码 MP3 并将输出提供给 PyAudio。

还有更多的可能性,包括 pymedia,但我认为这些是最简单的解决方案。

好的,我们已经阐明了您真正需要的是答案。

我会完整保留第一个答案,因为您也需要那部分。

现在,您想在录制流中播放音频,以便任何录制音频输入的应用程序都能录制您正在播放的内容。

在 Windows 上,这称为立体声混音,可以在音频输入下的音量控制中找到。

您选择立体声混音作为默认输入。现在,当你打开一个没有 select 自己的输入通道但使用 selected 的录音应用程序(例如 Skype)时,它会记录所有从你的扬声器和进入你的 mic/line英寸

我不能 100% 确定这个选项是否会出现在所有 Windows 上,或者它是您拥有的声卡的一个功能。

我确信 Creative 和 Realtek 声卡支持它。

所以,研究这个。

要 select 来自 Python 的那个选项,您必须使用 ctypes 连接到 winmm.dll 并调用适当的函数。我不知道是哪一个,有什么论点。

如果音量控制中没有此选项,则只能安装虚拟声卡来为您进行环回。

可能有这样的软件打包为库,以便您可以从 Python 或其他任何地方使用它。

在 Linux 上,使用 Pulseaudio 应该很容易。我不知道怎么做,但我知道你可以做到,重定向流等。那里有教程。

然后您可以从 Python 调用该命令,设置为此并重置为正常。

关于Mac,嗯,我真的不知道,但应该是可以的。

如果您希望您的 MP3 只在录音流中播放,而不是在您的扬声器上播放,那么在 Windows 上,如果没有环回音频设备,您将无法做到这一点。

Linux相信你一定能做到,Mac应该可以,但是Q

我目前没有时间浏览库等来为您提供一些有用的代码,因此您必须自己动手。但我希望我的指导对你有所帮助。

有可能,但在 python 中不是 100%,因为它需要安装其他软件。 (另外据我所知,这个特定的答案只适用于 Windows,但它在 Linux 上应该与 PulseAudio 相似,而不是 VB-Audio Cable,但我不是每天 Linux 用户所以我不知道。)

首次下载:https://www.vb-audio.com/Cable/,这将创建一个 "Virtual Audio Cable",程序可以在其中将音乐播放到输入设备(看起来像扬声器),并将其通过管道传输到输出设备(看起来像麦克风的东西)。

然后 运行 在 cmd 中执行此命令:pip install pygame==2.0.0.dev8(或 py -m pip install pygame==2.0.0.dev8,具体取决于您安装的 python)[也是开发版本的原因是它仅在 sdl2 中需要一些功能,而主要分支使用 sdl1)

然后:

>>> from pygame._sdl2 import get_num_audio_devices, get_audio_device_name #Get playback device names
>>> from pygame import mixer #Playing sound
>>> mixer.init() #Initialize the mixer, this will allow the next command to work
>>> [get_audio_device_name(x, 0).decode() for x in range(get_num_audio_devices(0))] #Returns playback devices
['Headphones (Oculus Virtual Audio Device)', 'MONITOR (2- NVIDIA High Definition Audio)', 'Speakers (High Definition Audio Device)', 'Speakers (NVIDIA RTX Voice)', 'CABLE Input (VB-Audio Virtual Cable)']
>>> mixer.quit() #Quit the mixer as it's initialized on your main playback device
>>> mixer.init(devicename='CABLE Input (VB-Audio Virtual Cable)') #Initialize it with the correct device
>>> mixer.music.load("Megalovania.mp3") #Load the mp3
>>> mixer.music.play() #Play it

要停止音乐,请执行以下操作:mixer.music.stop()

此外,音乐不会通过您的扬声器播放,因此您将有另一个 python 脚本或线程 运行ning 来处理通过您的扬声器播放音乐。 (此外,如果你想让它在按下按钮时播放,我建议使用 python 库键盘,GitHub 文档非常好,你应该能够自己弄清楚。)

PS:这花了我一段时间才弄明白,欢迎。

PPS:我还在想办法把你自己的麦克风也通过管道传输到那里,因为这种方法显然不会把你真正的麦克风也通过管道传输,但要查看源代码pygame 让我很头疼,因为它都是用 C 写的。

如果要播放本地目录下的音频文件,可以按照这个流程进行。

#!/usr/bin/env python

import pyaudio
import socket
import sys
import os

CHUNK = 4096

output = os.path.join(BASE_DIR, "speech.wav") #WAV format Output file  name
wf = wave.open(output, 'rb')

p = pyaudio.PyAudio()

stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 
    channels=wf.getnchannels(), 
    rate=wf.getframerate(), 
    output=True)

try:
    while True:  
        data = wf.readframes(CHUNK)
        stream.write(data)  
        
except KeyboardInterrupt:
    pass

print('Shutting down')
s.close()
stream.close()
audio.terminate()

只是对 @PyPylia 的回答进行了更新,以造福于像我一样努力实施此问题的任何人。

Current Package Version: pygame 2.1.2 (SDL 2.0.18, Python 3.9.10)

Tested Systems: Windows 10 (21H2 - 19044.1288), (Should be the same process on Mac but this is untested as of now...)

首先,您需要下载并安装适用于您各自平台的 VB-Cable Virtual Mic 驱动程序。这为我们提供了一个虚拟麦克风,允许我们在使用视频通话软件(Google Meet、Microsoft Teams、Zoom)时将我们在机器上播放的音频作为麦克风输入传递。之后就全部通过pygame模块的音频包处理了。

获取音频设备列表:

from pygame import mixer, _sdl2 as devicer

mixer.init() # Initialize the mixer, this will allow the next command to work

# Returns playback devices, Boolean value determines whether they are Input or Output devices.
print("Inputs:", sdl2.audio.get_audio_device_names(True))
print("Outputs:", sdl2.audio.get_audio_device_names(False))

mixer.quit() # Quit the mixer as it's initialized on your main playback device

例如,我的设备returns:

Inputs: ['Microphone (High Definition Audio Device)', 'CABLE Output (VB-Audio Virtual Cable)']
Outputs: ['Speakers (High Definition Audio Device)', 'CABLE Input (VB-Audio Virtual Cable)']

然后,播放音频:

import time
from pygame import mixer

mixer.init(devicename = 'CABLE Input (VB-Audio Virtual Cable)') # Initialize it with the correct device
mixer.music.load("Toby Fox - Megalovania.mp3") # Load the mp3
mixer.music.play() # Play it

while mixer.music.get_busy():  # wait for music to finish playing
    time.sleep(1)

如果您希望连续播放多个曲目,请将以下代码段添加到上面的 while 循环中:

...

else:
    mixer.music.unload() # Unload the mp3 to free up system resources

mixer.music.load("Sleeping at Last - Saturn.wav") # Load the wav

...

然后,在另一端,在视频通话软件中,只需将麦克风输入从默认更改为 CABLE Output (VB-Audio Virtual Cable) 即可让另一端的软管听到来自源的音频。

如果您使用的是较新版本的软件包,并且由于 AttributeError: module 'pygame' has no attribute {method_name} 而列出的某些方法似乎不起作用,请使用 pyup 和搜索有问题的方法,查看是否对该方法的调用方式进行了任何更改。这是 @PyPylia 的代码片段不再有效的主要原因,除非您使用旧版本的 pygame.