Linux направляет аудиофайл на вход микрофона

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

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


person cheerupcharlie    schedule 18.04.2017    source источник
comment
@CL. Поправьте меня, если я ошибаюсь, но в этом случае окажется, что приложение для записи известно (arecord test.raw -r 8000 -t raw). В моем случае я не могу контролировать, какое приложение будет обращаться к микрофону. Я хочу, чтобы любое приложение, которое будет читать с микрофона, вместо этого читало из моего файла.   -  person cheerupcharlie    schedule 18.04.2017
comment
Обратите внимание, что этот вызов arecord не указывает имя устройства и использует устройство по умолчанию. (И программа всегда может явно использовать другое имя устройства.)   -  person CL.    schedule 19.04.2017
comment
Привет @CL., Я немного пояснил свой вопрос. Теперь мне нужно изменить само устройство по умолчанию.   -  person cheerupcharlie    schedule 20.04.2017


Ответы (2)


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

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

person cheerupcharlie    schedule 21.04.2017
comment
В моем случае потоковый вывод искажается, мне кажется, что данные идут очень быстро, любая помощь ??? - person humble_wolf; 13.06.2018
comment
возиться с Alexa - я только что добавил сон 1; после кота, потому что он не успевал за всеми данными. При этом он отлично работает, спасибо. - person nayana; 30.08.2018
comment
Ты босс !!! Сэкономил мне часы возни с alsa / pulseaudio. Небольшой совет, вместо cat я использую ffmpeg вот так: ffmpeg -re -i input.mp3 -f s16le -ar 16000 -ac 1 - > /home/spiq/virtmic - person sebpiq; 13.10.2018
comment
Спасибо @sebpiq, это очень важная деталь, благодаря которой все работает гладко! - person UncleZeiv; 22.11.2018
comment
Похоже, что модуль pulseaudio-pipe-source игнорирует параметр rate, когда дело доходит до того, насколько быстро он читает данные из канала, и просто читает настолько быстро, насколько это возможно. cat будет писать так быстро, как только может, так что в итоге вы получите источник с частотой 16 кГц, который работает примерно в 1000 раз быстрее, чем должен. Необходимо ускорить запись в канал с помощью чего-то вроде ffmpeg. - person TrentP; 13.02.2021
comment
Я использую RPI в качестве гарнитуры для своего телефона, и я попробовал ваши шаги по созданию виртуального микрофона, но я не могу записывать звук на свой телефон с помощью канала на RPi. Что в этом плохого? - person Mamdouh Saeed; 21.03.2021

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

Вкладка записи

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

Вкладка записи - активна

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

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

person Mahmoud K.    schedule 10.11.2020