Я должен контролировать свой канал звуковой частоты - в в Linux, и если аудио играется, звук должен быть зарегистрирован и сохранен в файл. Подобный тому, как движение контролирует видео канал.
Действительно ли возможно сделать это с ударом? что-то вроде:
#!/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;
Править: Поток, который я хотел бы получить из этой программы,
a. when noise > threshold, start recording
b. stop recording when noise < threshold for 10 seconds
c. save recorded piece to separate file
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
Обновление:
Следующее решение использует 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
Вот набросок того, как улучшить решение Юргена: это просто двойная буферизация, поэтому, пока вы анализируете один файл, вы уже начали запись следующего. Я предполагаю, что этот трюк сократит промежутки до 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
Суть в том, что в тот момент, когда вы прерываете процесс записи, вы запускаете анализ в фоновом режиме, а затем совершаете еще один обход цикла, чтобы записать следующий фрагмент. На самом деле вы должны сначала запустить следующий процесс записи, затем анализ, но это сделает поток управления немного уродливее. Я бы сначала измерил, чтобы увидеть, какие у вас пропуски.