Мониторинг аудио линии

Мне нужно контролировать мой аудио линейный в linux, а в случае воспроизведения звука звук должен записываться и сохраняться в файл. Совместимо с тем, как motion отслеживает видеопоток.

Можно ли это сделать с помощью bash? что-то вроде:

#!/bin/bash

# audio device
device=/dev/audio-line-in

# below this threshold audio will not be recorded.
noise_threshold=10

# folder where recordings are stored
storage_folder=~/recordings

# run indefenitly, until Ctrl-C is pressed
while true; do
   # noise_level() represents a function to determine
   # the noise level from device
   if noise_level( $device ) > $noise_threshold; then
     # stream from device to file, can be encoded to mp3 later.
     cat $device > $storage_folder/$(date +%FT%T).raw         
   fi;
done;

EDIT: поток, который я хочу получить от этой программы,

 a. when noise > threshold, start recording  
 b. stop recording when noise < threshold for 10 seconds
 c. save recorded piece to separate file

Ответ 1

SoX - это швейцарский армейский нож для обработки звука. Вы можете использовать его для анализа записей. Единственный недостаток следующих решений:

  • Вам нужно разделить записи на блоки фиксированного размера.
  • Вы можете потерять время записи (из-за убийства/анализа/перезапуска записей).

Таким образом, дальнейшие усовершенствования могут анализировать асинхронность, хотя это усложнит задание.

#!/bin/bash 

record_interval=5
noise_threshold=3
storage_folder=~/recordings

exec 2>/dev/null        # no default  error output
while true; do 
    rec out.wav &
    sleep $record_interval
    kill -KILL %1
    max_level="$(sox  out.wav -n stats -s 16 2>&1|awk '/^Max\ level/ {print int($3)}')"
    if [ $max_level -gt $noise_threshold ];then 
    mv out.wav ${storage_folder}/recording-$(date +%FT%T).wav;
    else 
    rm out.wav
    fi
done

Update:

В следующем решении используется fifo как результат из rec. Используя split на этом канале, чтобы получить куски, не должно быть потерь времени записи:

#!/bin/bash 

noise_threshold=3
storage_folder=~/recordings
raw_folder=~/recordings/tmp
split_folder=~/recordings/split
sox_raw_options="-t raw -r 48k -e signed -b 16"
split_size=1048576 # 1M

mkdir -p ${raw_folder} ${split_folder}

test -a ${raw_folder}/in.raw ||  mkfifo ${raw_folder}/in.raw

# start recording and spliting in background
rec ${sox_raw_options} - >${raw_folder}/in.raw 2>/dev/null &
split -b ${split_size} - <${raw_folder}/in.raw ${split_folder}/piece &


while true; do 
    # check each finished raw file
    for raw in $(find ${split_folder} -size ${split_size}c);do 
    max_level="$(sox $sox_raw_options  ${raw} -n stats -s 16 2>&1|awk '/^Max\ level/ {print int($3)}')"
    if [ $max_level -gt $noise_threshold ];then 
        sox ${sox_raw_options} ${raw} ${storage_folder}/recording-$(date +%FT%T).wav;
    fi
    rm ${raw}
    done
    sleep 1
done1

Ответ 2

Здесь еще лучше,

sox -t alsa default ./recording.flac silence 1 0.1 5% 1 1.0 5%

Он создает звуковой файл, только когда есть звук, и отключает тишину. Так что никаких пробелов и долгого молчания, как и выше!

Ответ 3

Вот эскиз того, как улучшить решение J & uuml; rgen: он просто двойной буферизации, поэтому, пока вы анализируете один файл, вы уже начали запись следующего. Я предполагаю, что этот трюк уменьшит пробелы до порядка 100 миллисекунд, но вам нужно будет сделать некоторые эксперименты, чтобы узнать.

Полностью непроверенный!

#!/bin/bash 

record_interval=5
noise_threshold=3
storage_folder=~/recordings

exec 2>/dev/null        # no default  error output

function maybe_save { # out.wav date
    max_level="$(sox "$1" -n stats -s 16 2>&1|
                 awk '/^Max\ level/ {print int($3)}')"
    if [ $max_level -gt $noise_threshold ]; then 
      mv "$1" ${storage_folder}/recording-"$2"
    else 
      rm "$1"
    fi
}

i=0
while true; do 
    this=out$i.wav
    rec $this &
    pid=$?
    if [ $i -gt 9 ]; then i=0; else i=$(expr $i + 1); fi
    archive=$(date +%FT%T).wav;
    sleep $record_interval
    kill -TERM $pid
    maybe_save $this $archive &
done

Ключ в том, что в тот момент, когда вы убиваете процесс записи, вы запускаете анализ в фоновом режиме, а затем выполняете еще одну поездку вокруг цикла для записи следующего фрагмента. Действительно, сначала нужно запустить следующий процесс записи, затем провести анализ, но сделает поток управления немного уродливым. Сначала я буду измерять, какие виды скипов вы получаете.

Ответ 4

rec -c CHANNELS -r RATE -b BITS -n OUTPUT.AUDIOTYPE noisered NOISEREDUCTION.noise-profile silence 1 5 1% 1 1t 1%

Это будет непрерывно контролировать вход микрофона по умолчанию, пока не будет слышен звук, превышающий 1% от уменьшенного профиля фонового шума, затем выведите файл AUDIOTYPE (mp4, flac, wav, raw и т.д.) в RATE hz, БИТЫ, КАНАЛЫ. Запись прекратится после 1 секунды молчания, как измерено на уровне 1% от уровня шума. Выходной файл будет очищен от фонового шума (в основном).

Теперь, если кто-то может просто сказать мне, как определить, что запись прекратилась программно, я могу сделать ее полезной для непрерывного мониторинга распознавания голоса.