监听音频线路

时间:2010-04-10 11:16:45

标签: linux bash audio audio-recording

我需要在linux中监听音频 line-in ,如果播放音频,必须录制声音并保存到文件中。与 motion 监控视频Feed的方式类似。

是否可以使用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;

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

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

4 个答案:

答案 0 :(得分:5)

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

  1. 您需要将录制内容拆分为固定大小的块
  2. 您可能会丢失录制时间(由于杀死/分析/重新开始录制)
  3. 因此,进一步的改进可能是分析异步,尽管这会使工作复杂化。

    #!/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
    

答案 1 :(得分:2)

这是一个更好的一个;

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

只有在有声音的情况下才会生成音频文件,并切断静音。所以没有差距,没有像上面那样的长时间沉默!

答案 2 :(得分:0)

以下是如何改进Jü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

关键是,当您终止录制过程的那一刻,您在后台启动分析,然后绕循环再次行程以记录下一个片段。 你真的应该首先启动下一个录制过程,然后是分析,但那样做 将使控制流程更加丑陋。我先测量一下你会看到什么样的跳过。

答案 3 :(得分:0)

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

这将持续监听默认麦克风输入,直到听到声音超过背景噪音降低曲线的1%,然后在RATE hz输出AUDIOTYPE文件(mp4,flac,wav,raw等), BITS,CHANNELS。在1%的噪声降低水平下测量,静音1秒后录音将停止。输出文件将被清除背景噪音(主要是)。

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