Linux管道音频文件到麦克风输入 [英] Linux pipe audio file to microphone input

查看:54
本文介绍了Linux管道音频文件到麦克风输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种将文件中的音频数据输入麦克风的方法,以便在 3rd 方应用程序(例如 arecord 或 Chromium 的语音搜索"功能)使用麦克风获取音频时输入,他们从文件中接收音频数据.

I'm looking for a way to feed audio data from a file into the microphone so when 3rd party applications (such as arecord or Chromium's "search by voice" feature) use the microphone for audio input, they receive the audio data from the file instead.

这是我的场景:我编写的应用程序从麦克风(使用 ALSA)记录音频数据并将其保存到文件 (audioFile0.raw).在未来某个未知的时间点,一些未知的 3rd 方应用程序(例如,我没有开发所以我无法控制开发的东西,例如 Chromium 网络浏览器的通过语音搜索"功能)将使用麦克风来获取音频数据.我希望第 3 方应用程序收集的音频数据来自 audioFile.raw 而不是实际的麦克风本身.

Here's my scenario: An application I wrote records audio data from the microphone (using ALSA) and saves it to a file (audioFile0.raw). At some unknown point in time in the future, some unknown 3rd party application (as in, something I did not develop so I have no development control over, such as the Chromium web browser's "search by voice" feature) will use the microphone to obtain audio data. I would like the audio data that the 3rd party application is gathering to come from audioFile.raw rather than the actual microphone itself.

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

I was thinking if it were possible to change the default audio input device to an audio file, or maybe a named pipe and do something like cat audioFile0.raw > mypipe (since I don't know when another application will try to read from the microphone). Perhaps there is a more simple way of doing this?

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

I hope I provided enough detail and clarity. Please let me know if something is unclear.

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

So I figured out how to make a virtual microphone by creating the following .asoundrc file in my home directory:

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 文件,如下所示:

I then call arecord test.raw -c 1 -f S16_LE -r 16000 -t raw -D virtmic from the command line and I'm able to record the audio data that's in audioFile0.raw to test.raw.

My goal now is to replace the default device with my virtual microphone so any application accessing the microphone will read the audio data in audioFile0.raw instead of the actual microphone itself. So I edited my .asoundrc file to appear as follows:

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 中读取数据,而不是从麦克风中读取数据?

Then I called arecord test.raw -c 1 -f S16_LE -r 16000 -t raw from the command line. I then played back test.raw but it seemed to be recording from the microphone itself and not audioFile0.raw.

What am I doing wrong? How exactly do I change the default capture device so it will read the data from audioFile0.raw rather than the input from the microphone?

编辑 2: 好的,所以我在正确的轨道上.我在我的主目录中使用了相同的 .asoundrc 文件,我之前展示了我将默认设备更改为 virtmic 的地方.我需要更改文件 /usr/share/alsa/alsa.conf.d/pulse.conf 所以它看起来像这样:

EDIT 2: Okay, so I was on the right track. I'm using the same .asoundrc file in my home directory that I showed earlier where I changed the default device to be the virtmic. I needed to change the file /usr/share/alsa/alsa.conf.d/pulse.conf so it looks like this:

# 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 的应用程序的默认设置,而是使用我的虚拟麦克风作为默认设置.这可能不是最好的解决方案,但它有效.

The only thing I did was comment out the line "/usr/share/alsa/pulse-alsa.conf" and replaced it with "/home/charles/.asoundrc" so the pulseaudio plugin isn't the default for applications using ALSA, but rather use my virtual mic as the default. This may not be the best solution, but it works.

当我执行 arecord test.raw -t raw -c 1 -f S16_LE -r 16000 时,这有效.它从 audiofile0.raw 而不是麦克风获取数据!我使用命令 lsof/dev/snd/* 来查看在 arecord 命令运行时究竟是什么访问了音频设备.输出如下:

This worked when I did arecord test.raw -t raw -c 1 -f S16_LE -r 16000. It got the data from audiofile0.raw instead of the microphone! I used the command lsof /dev/snd/* to see what exactly was accessing the audio device while the arecord command was running. The output was as follows:

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/* 来查看究竟是什么访问了音频设备.

I then tried using Chromium browser's "search by voice" feature and saw that I couldn't get it to record from audioFile0.raw. I then used lsof /dev/snd/* to see what exactly was accessing the audio device.

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.

I see that they all have the same PID, 2044. They are all using the pulseaudio daemon, not going through ALSA.

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

My Question: How do I get pulseaudio to use my virtual microphone by default so all applications that go through pulseaudio for audio input will instead get the audio data from my file rather than the microphone?

推荐答案

经过许多艰苦的时间,我终于得到了一些可以接受的工作.我取消了我对 ALSA 所做的一切(因为默认情况下 ALSA 使用 PulseAudio,我最初覆盖了它).我创建了一个简单的 bash 脚本 install_virtmic.sh 来创建一个虚拟麦克风"供 PulseAudio 和 PulseAudio 客户端使用:

After many painstaking hours, I finally got something acceptable working. I undid everything I did with ALSA (since the default is for ALSA to use PulseAudio instead, which I initially overrode). I created a simple bash script install_virtmic.sh to create a "virtual microphone" for PulseAudio to use as well as PulseAudio clients:

#!/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 用于撤消安装脚本所做的一切:

A quick script uninstall_virtmic.sh for undoing everything done by the install script:

#!/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 文件变得非常大),但是现在就可以了.

I then fired up Chromium and clicked the microphone to use its voice search feature and it worked! I also tried with arecord test.raw -t raw -f S16_LE -c 1 -r 16000 and it worked too! It isn't perfect, because I keep writing to the named pipe virtmic in an infinite loop in the script (which quickly made my test.raw file insanely large), but it will do for now.

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

Please feel free to let me know if anyone out there finds a better solution!

这篇关于Linux管道音频文件到麦克风输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆