当前位置: 首页 > 面试题库 >

Linux将音频文件传输到麦克风输入

乐正穆冉
2023-03-14
问题内容

我正在寻找一种将文件中的音频数据馈送到麦克风的方法,因此,当第三方应用程序(例如 arecord
或Chromium的“按语音搜索”功能)使用麦克风进行音频输入时,它们会从文件中接收音频数据代替。

这是我的情况
:我编写的一个应用程序记录了来自麦克风的音频数据(使用ALSA)并将其保存到文件(audioFile0.raw)中。在将来的某个未知时间点,某些未知的第三方应用程序(例如,我没有开发的东西,因此我无法对其进行开发控制,例如Chromium
Web浏览器的“语音搜索”功能)将使用麦克风来获取音频数据。我希望第三方应用程序收集的音频数据来自audioFile.raw,而不是实际的麦克风本身。

我在想是否可以将默认的音频输入设备更改为音频文件,或者将其命名为管道,然后执行类似的操作cat audioFile0.raw > mypipe(因为我不知道何时其他应用程序会尝试从麦克风读取声音)。也许有更简单的方法可以做到这一点?

我希望我提供了足够的细节和清晰度。如果有不清楚的地方,请告诉我。

编辑: 所以我想出了如何通过在主目录中创建以下.asoundrc文件来制作虚拟麦克风的方法:

pcm.!virtmic {
    type file
    slave.pcm "hw:0,0"
    file /dev/null
    infile "/home/charles/audioFiles/audioFile0.raw"
}

pcm.!default {
    type hw
    card 0
}

ctl.!default {
    type hw
    card 0
}

然后调用arecord test.raw -c 1 -f S16_LE -r 16000 -t raw -D virtmic命令行,我能够记录音频数据是在audioFile0.rawtest.raw

我现在的目标是用虚拟麦克风替换默认设备,以便任何访问麦克风的应用程序都将读取音频数据,audioFile0.raw而不是实际的麦克风本身。因此,我编辑了.asoundrc文件,如下所示:

pcm.!virtmic {
    type file
    slave.pcm "hw:0,0"
    file /dev/null
    infile "/home/charles/audioFiles/audioFile0.raw"
}

pcm.!default {
    type asym
    playback.pcm {
        type hw
        card 0
    }
    capture.pcm {
       type plug
       slave.pcm "virtmic"
    }
}

ctl.!default {
    type hw
    card 0
}

然后我arecord test.raw -c 1 -f S16_LE -r 16000 -t raw从命令行调用。然后我播放了,test.raw但是它似乎是从麦克风本身录制的,而不是audioFile0.raw

我究竟做错了什么?如何准确更改默认的捕获设备,使其从中读取数据audioFile0.raw而不是从麦克风输入数据?

编辑2:
好的,所以我走对了。我在主目录中使用了与前面显示的相同的.asoundrc文件,在该文件中我将默认设备更改为virtmic。我需要更改文件,/usr/share/alsa/alsa.conf.d/pulse.conf因此它看起来像这样:

# PulseAudio alsa plugin configuration file to set the pulseaudio plugin as
# default output for applications using alsa when pulseaudio is running.
hook_func.pulse_load_if_running {
    lib "libasound_module_conf_pulse.so"
    func "conf_pulse_hook_load_if_running"
}

@hooks [
    {
        func pulse_load_if_running
        files [
#           "/usr/share/alsa/pulse-alsa.conf"
            "/home/charles/.asoundrc"
        ]
        errors false
    }
]

我唯一要做的就是注释掉该行,"/usr/share/alsa/pulse- alsa.conf"并用它代替,"/home/charles/.asoundrc"所以pulseaudio插件不是使用ALSA的应用程序的默认设置,而是使用我的虚拟麦克风作为默认设置。这可能不是最佳解决方案,但它可以工作。

当我这样做的时候,这行得通arecord test.raw -t raw -c 1 -f S16_LE -r 16000。它从而audiofile0.raw不是麦克风那里获取数据!我使用该命令lsof /dev/snd/*来查看在arecord命令运行时访问音频设备的确切位置。输出如下:

COMMAND    PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
pulseaudi 2044 charles   22u   CHR  116,6      0t0 8977 /dev/snd/controlC0
pulseaudi 2044 charles   29u   CHR  116,6      0t0 8977 /dev/snd/controlC0
arecord   4051 charles  mem    CHR  116,5          8976 /dev/snd/pcmC0D0c
arecord   4051 charles    4u   CHR  116,5      0t0 8976 /dev/snd/pcmC0D0c

然后,我尝试使用Chromium浏览器的“语音搜索”功能,发现无法从中进行记录audioFile0.raw。然后lsof /dev/snd/*,我习惯查看访问音频设备的确切方式。

COMMAND    PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
pulseaudi 2044 charles  mem    CHR  116,5          8976 /dev/snd/pcmC0D0c
pulseaudi 2044 charles   22u   CHR  116,6      0t0 8977 /dev/snd/controlC0
pulseaudi 2044 charles   29u   CHR  116,6      0t0 8977 /dev/snd/controlC0
pulseaudi 2044 charles   30r   CHR 116,33      0t0 7992 /dev/snd/timer
pulseaudi 2044 charles   31u   CHR  116,5      0t0 8976 /dev/snd/pcmC0D0c

我看到它们都具有相同的PID,即2044。它们都使用pulseaudio守护程序,而不是通过ALSA。

我的问题:
默认情况下,如何让Pulseaudio使用虚拟麦克风,以便所有通过PulseAudio进行音频输入的应用程序将从文件而不是麦克风获取音频数据?


问题答案:

经过数小时的辛苦工作,我终于得到了可以接受的工作。我撤消了我对ALSA所做的所有操作(因为默认情况下,ALSA改用PulseAudio代替了它,而我最初将其覆盖)。我创建了一个简单的bash脚本,install_virtmic.sh以创建一个供PulseAudio以及PulseAudio客户端使用的“虚拟麦克风”:

#!/bin/bash

# This script will create a virtual microphone for PulseAudio to use and set it as the default device.

# Load the "module-pipe-source" module to read audio data from a FIFO special file.
echo "Creating virtual microphone."
pactl load-module module-pipe-source source_name=virtmic file=/home/charles/audioFiles/virtmic format=s16le rate=16000 channels=1

# Set the virtmic as the default source device.
echo "Set the virtual microphone as the default device."
pactl set-default-source virtmic

# Create a file that will set the default source device to virtmic for all 
PulseAudio client applications.
echo "default-source = virtmic" > /home/charles/.config/pulse/client.conf

# Write the audio file to the named pipe virtmic. This will block until the named pipe is read.
echo "Writing audio file to virtual microphone."
while true; do
    cat audioFile0.raw > /home/charles/audioFiles/virtmic
done

uninstall_virtmic.sh撤消安装脚本完成的所有操作的快速脚本:

#!/bin/bash

# Uninstall the virtual microphone.

pactl unload-module module-pipe-source
rm /home/charles/.config/pulse/client.conf

然后,我启动Chromium,然后单击麦克风以使用其语音搜索功能,它可以正常工作!我也尝试过arecord test.raw -t raw -f S16_LE -c 1 -r 16000,它也起作用!这不是完美的,因为我一直virtmic在脚本的无限循环中写入命名管道(这很快使我的test.raw文件变得异常大),但是现在就可以了。

如果有任何人找到更好的解决方案,请随时告诉我!



 类似资料:
  • 我正在尝试获取传入的麦克风音频并将其流式传输到另一部iPhone。基本上是一个电话,但通过蓝牙。我有音频通过进入: 然后我尝试使用来自这里的-StreamReader from@martin-r 使用: 然后使用以下方法将数据发送到另一台设备: 我将行转换为NSData,然后使用dispatch_after 0.5秒不断运行,我通过蓝牙将其发送到另一台设备。 它似乎不起作用,我不认为这是一种实用的

  • 我正在尝试创建一个麦克风应用程序,在会议中用作观众的真正麦克风。我们将把Android设备连接到Wi-Fi局域网,任何人都可以从他们的应用程序中触发麦克风,向他人讲话。数据将进入局域网内的服务器Java程序,并从那里进入扬声器。 我不知道该怎么做。有人能帮我吗???提前谢谢

  • 根据官方文件 Android 10 (API level 29)和更高版本采用了一种优先级方案,可以在应用程序运行时在它们之间切换输入音频流。在大多数情况下,如果一个新的应用程序获得了音频输入,以前捕获的应用程序会继续运行,但会收到静音。在某些情况下,系统可以继续向两个应用程序发送音频。下面解释了各种共享场景。 除某些特殊情况外,应用程序之间不共享音频。 但是我看到许多应用程序共享音频输入,而没有

  • 有没有办法通过耳机传送麦克风输入,同时通过智能手机扬声器使用音频输出? 我已经看了几个小时了,我看到这在iOS上显然是不可能的,但是Android呢... 我用的是三星Galaxy S4。 这是我的代码的一部分,即使耳机已插入,也可以通过扬声器路由音频输出: 但当我试图通过耳机的麦克风控制我的应用程序时,什么都没有。所以我试着用智能手机的那一个,它显然起作用了。 它看起来不像其他AudioMana

  • 问题内容: 我正在尝试通过Apples Multipeer Connectivity框架将音频从麦克风流式传输到另一个iPhone。为了进行音频捕获和回放,我使用了AVAudioEngine。 我通过在输入上安装一个抽头来从麦克风接收数据,由此我得到了AVAudioPCMBuffer,然后将其转换为UInt8数组,然后将其流式传输到另一部电话。 但是,当我将数组转换回AVAudioPCMBuffe

  • 对不起我的英语不好:( 我开始我的android应用程序项目,这个应用程序录制麦克风,如果我点击开始录制按钮,应用程序获取麦克风并将其写入文件,当我点击停止时,一个文件保存到SD卡中。 项目代码: 输出文件 开始录音 停止录制 播放声音录制文件 我想录下声音并将其放入变量ByteArray中,在不将音频文件保存到SD卡的情况下播放 我有一个像我想要的项目,但它是用actionscript 3编写的