Аудио-файл Linux pipe к входу микрофона

Я ищу способ подачи аудиоданных из файла в микрофон, поэтому, когда сторонние приложения (такие как arecord или функция Chromium "поиск по голосу") используют микрофон для ввода звука, они получают аудиоданные из файла вместо.

Вот мой сценарий: приложение, которое я написал, записывает аудиоданные с микрофона (используя ALSA) и сохраняет их в файл (audioFile0.raw). В какой-то неизвестный момент времени в будущем какое-то неизвестное стороннее приложение (например, что-то, что я не разрабатывал, поэтому у меня нет контроля над разработкой, например, функция "поиск по голосу" в веб-браузере Chromium) будет использовать микрофон для получить аудио данные. Я хотел бы, чтобы аудиоданные, которые собирает стороннее приложение, поступали из 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.raw в test.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 в своем домашнем каталоге, который я показал ранее, где я изменил устройство по умолчанию на виртуальное. Мне нужно было изменить файл /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.

Мой вопрос: Как заставить PuluDaudio использовать мой виртуальный микрофон по умолчанию, чтобы все приложения, использующие PuluAudio для аудиовхода, вместо этого получали аудиоданные из моего файла, а не из микрофона?

1 ответ

Решение

После многих кропотливых часов я, наконец, получил что-то приемлемое, работая. Я отменил все, что я сделал с 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 файл безумно большой), но пока подойдет.

Пожалуйста, дайте мне знать, если кто-нибудь найдет лучшее решение!

  1. Убедитесь, что у вас установлен PulseAudio Volume Control (pavucontrol). если нет, вы можете установить его, просто набрав в терминале: sudo apt install pavucontrol.

  1. Откройте PulseAudio Volume Control (pavucontrol) и перейдите на вкладку "Запись". Если у вас нет устройств, записывающих ваш микрофон, эта панель должна выглядеть пустой. Как только какое-либо приложение начнет запись или вызов Skype, на этой панели должна быть хотя бы одна запись.

  1. Выбор "Встроенный аналоговый стереозвук" является поведением по умолчанию (перенаправление вашего голоса на вывод микрофона). Вы также должны увидеть "Монитор встроенного аудио аналогового стерео". когда вы выбираете эту опцию, вывод любого приложения, которое воспроизводит звук (например, VLC), должен быть перенаправлен на микрофон вместо вашего голоса.

  2. Не забудьте изменить его обратно на "Встроенный аналоговый аудио стерео" после завершения воспроизведения звука, чтобы все вернулось к нормальному состоянию.

Другие вопросы по тегам