同步两个音频文件

时间:2017-12-26 06:40:34

标签: bash audio ffmpeg signal-processing sox

我有2个音频文件:

  • correct.wav(时长3:07)
  • incorrect.wav(持续时间3:10)

2 audio files

它们几乎相同,但是使用不同的声音字体生成。

问题:第二个文件迟了几秒钟。

如何将第二个文件与第一个文件同步?也许有一些bash软件可以在第一个声音中检测到第一个响亮的声音,并将correct.wav与incorrect.wav进行比较,缩短了错误的.wav文件的结尾。

我知道我可以手动完成,但是我需要为很多文件自动化处理。

以下是我发现的近似解决方案:

1)用于检测声音同步以使用此Python脚本 - https://github.com/jeorgen/align-videos-by-sound但它并不完美,没有检测到100%。

2)使用sox进行剪切/修剪/比较/检测声音持续时间(代码提取):

length1ok=$(sox correct.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p')
length2ok=$(sox incorrect.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p')
if [[ $length1ok == $length2ok ]]; then
    echo "Everything OK: $length1ok = $length2ok"
else
    echo "Fatal error: Not the same final files"
fi

diff=$(echo "$length2 - $length1" | bc -l)
echo "difference = $diff"
echo "webm $length1 not greater than fluid2 $length2"
sox correct.wav incorrect.wav pad 0 $diff

评论UltrasoundJelly的回答: 这是我为您的代码得到的结果:

Result

这是我需要的结果:

Need result

1 个答案:

答案 0 :(得分:3)

这是一个解决方案:

  • 使用ffmpeg查找每个文件中的主要沉默
  • 如果新文件的前导静音较长,请使用sox
  • 修剪差异
  • 如果新文件的前导静音较短,请使用sox
  • 填充开头
  • 使用sox
  • 将新文件修剪为与原始文件相同的长度

Bash脚本:

FILEONE=$1
FILETWO=$2
MINSILENCE=0.1
THRESH="-50dB"
S1=$(ffmpeg -i $FILEONE -af silencedetect=noise=$THRESH:d=$MINSILENCE -f null -  2>&1 | grep silence_duration -m 1 | awk '{print $NF}')
S2=$(ffmpeg -i $FILETWO -af silencedetect=noise=$THRESH:d=$MINSILENCE -f null -  2>&1 | grep silence_duration -m 1 | awk '{print $NF}')
if [ -z "$S1" ]; then echo "no starting silence found in $FILEONE" && exit 1;fi
if [ -z "$S2" ]; then echo "no starting silence found in $FILETWO" && exit 1;fi
DIFF=$(echo "$S1-$S2"|bc)
ISNEG=$(echo $DIFF'>0'| bc -l)
DIFF=${DIFF#-}
BASE="${FILETWO%.*}"
if [ $ISNEG -eq 1 ]
then
  echo "$1>$2 ... padding $2"
  SAMPRATE=$(sox --i -r $FILETWO)
  sox -n -r $SAMPRATE -c 2 silence.wav trim 0.0 $DIFF
  sox silence.wav $FILETWO $BASE.shift.wav
  rm silence.wav
else
  echo "$1<$2 ... trimming $2"
  sox $FILETWO $BASE.trim.wav trim $DIFF
fi

length1=$(sox $FILEONE -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p')
length2=$(sox $BASE.trim.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p')

if (( $(echo "$length2 > $length1" | bc -l) )); then
    diff=$(echo "$length2 - $length1" | bc -l)
    echo "difference = $diff"
    sox $BASE.trim.wav finished.wav trim 0 -$diff
fi