bash 监控音频线路

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2613163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 21:56:01  来源:igfitidea点击:

Monitoring an audio line

linuxbashaudioaudio-recording

提问by Stefan

I need to monitor my audio line-inin linux, and in the event that audio is played, the sound must be recorded and saved to a file. Similiar to how motionmonitors the video feed.

我需要在 linux 中监视我的音频线路输入,并且在播放音频的情况下,必须记录声音并将其保存到文件中。类似于运动监控视频源的方式。

Is it possible to do this with bash? something along the lines of:

可以用 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: The flow I'd like to get from this program is

编辑:我想从这个程序中获得的流程是

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

采纳答案by Jürgen H?tzel

SoXis the Swiss Army knife of sound processing. You can utilize it to analyze recordings. The only shortcoming of the folowing solutions is:

SoX是声音处理的瑞士军刀。您可以利用它来分析录音。以下解决方案的唯一缺点是:

  1. You need to split up the recordings to fixed size chunks
  2. You can lose recording time (due to killing/analyzing/restarting of recordings)
  1. 您需要将录音拆分为固定大小的块
  2. 您可能会丢失录制时间(由于录制的终止/分析/重新启动)

So further improvements could be doing analyzing asynchronous, although this will complicate the job.

因此,可以进一步改进异步分析,尽管这会使工作复杂化。

#!/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()}')"
    if [ $max_level -gt $noise_threshold ];then 
    mv out.wav ${storage_folder}/recording-$(date +%FT%T).wav;
    else 
    rm out.wav
    fi
done

Update:

更新:

The following solution uses a fifo as output from rec. By using split on this pipe to get the chunks, there should be no loss of recording time:

以下解决方案使用 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()}')"
    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

回答by Rob

Here's an even better one;

这是一个更好的;

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

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

It produces an audio file, only when there is sound, and cuts out the silence. So no gaps and no long silences like the stuff above!

它仅在有声音时生成音频文件,并消除静音。所以没有像上面那样的间隙和长时间的沉默!

回答by me_

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

This will monitor the default microphone input continuously until a sound is heard that exceeds 1% of the background noise reduced profile, then output a file of AUDIOTYPE (mp4, flac, wav, raw, etc.) at the RATE hz, BITS, CHANNELS. Recording will stop after 1 second of silence as measured at 1% of noise reduced levels. The output file will be cleaned of background noise (mostly).

这将持续监视默认麦克风输入,直到听到的声音超过背景噪声降低配置文件的 1%,然后以 RATE hz、BITS、CHANNELS 输出 AUDIOTYPE(mp4、flac、wav、raw 等)文件. 在 1% 的噪音降低水平下测量的静音 1 秒后,录音将停止。输出文件将清除背景噪音(大部分)。

Now, if someone can just tell me how to determine that the recording has stopped programmatically, I can make it useful for continuous monitoring voice recognition.

现在,如果有人能告诉我如何以编程方式确定录音已停止,我可以让它对持续监控语音识别有用。

回答by Norman Ramsey

Here's a sketch of how to improve on Jürgen's solution: it's just double-buffering, so while you are analyzing one file you have already started recording the next. My guess it that this trick will reduce gaps to the order of 100 milliseconds, but you would have to do some experiments to find out.

以下是如何改进 Jürgen 解决方案的草图:它只是双缓冲,因此当您分析一个文件时,您已经开始记录下一个文件。我猜这个技巧会将差距减少到 100 毫秒的数量级,但你必须做一些实验才能找到答案。

Completely untested!

完全未经测试!

#!/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 "" -n stats -s 16 2>&1|
                 awk '/^Max\ level/ {print int()}')"
    if [ $max_level -gt $noise_threshold ]; then 
      mv "" ${storage_folder}/recording-""
    else 
      rm ""
    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

The key is that the moment you kill the recording process, you launch analysis in the background and then take another trip around the loop to record the next fragment. Really you should launch the next recording process first, then the analysis, but that will make the control flow a bit uglier. I'd measure first to see what kinds of skips you're getting.

关键是,在您终止录制过程的那一刻,您会在后台启动分析,然后再循环一次以录制下一个片段。确实,您应该先启动下一个记录过程,然后再启动分析,但这会使控制流程变得更难看。我会先测量一下,看看你得到了什么样的跳跃。