同步两个音频文件
Sync two audio files
我有 2 个音频文件:
- correct.wav(时长3:07)
- 在correct.wav(持续时间3:10)
它们几乎相同,但生成的声音字体不同。
问题:第二个文件晚了几秒
如何将第二个文件与第一个文件同步?也许有一些bash软件可以检测到第一个声音中是否出现第一个响亮的声音并将correct.wav与incorrect.wav进行比较,缩短incorrect.wav文件的结尾。
我知道我可以手动完成,但我需要为很多文件自动解决。
这是我找到的近似解:
1) 用于检测声音同步以使用此 Python 脚本 - https://github.com/jeorgen/align-videos-by-sound 但它并不完美,未检测到 100%。
2) 将 sox 用于 cutting/trimming/comparing/detecting 声音持续时间(代码提取):
length1ok=$(sox correct.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##p')
length2ok=$(sox incorrect.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##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的回答:
这是我为您的代码得到的结果:
这是我需要的结果:
这是一种解决方案:
- 使用
ffmpeg
找到每个文件中的前导沉默
- 如果新文件有较长的前导静默,trim与
sox
的区别
- 如果新文件的前导静默较短,则用
sox
填充开头
- Trim 新文件与原文件长度相同
sox
Bash 脚本:
FILEONE=
FILETWO=
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 "> ... padding "
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 "< ... trimming "
sox $FILETWO $BASE.trim.wav trim $DIFF
fi
length1=$(sox $FILEONE -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##p')
length2=$(sox $BASE.trim.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##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
我有 2 个音频文件:
- correct.wav(时长3:07)
- 在correct.wav(持续时间3:10)
它们几乎相同,但生成的声音字体不同。
问题:第二个文件晚了几秒
如何将第二个文件与第一个文件同步?也许有一些bash软件可以检测到第一个声音中是否出现第一个响亮的声音并将correct.wav与incorrect.wav进行比较,缩短incorrect.wav文件的结尾。
我知道我可以手动完成,但我需要为很多文件自动解决。
这是我找到的近似解:
1) 用于检测声音同步以使用此 Python 脚本 - https://github.com/jeorgen/align-videos-by-sound 但它并不完美,未检测到 100%。
2) 将 sox 用于 cutting/trimming/comparing/detecting 声音持续时间(代码提取):
length1ok=$(sox correct.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##p')
length2ok=$(sox incorrect.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##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的回答: 这是我为您的代码得到的结果:
这是我需要的结果:
这是一种解决方案:
- 使用
ffmpeg
找到每个文件中的前导沉默 - 如果新文件有较长的前导静默,trim与
sox
的区别 - 如果新文件的前导静默较短,则用
sox
填充开头
- Trim 新文件与原文件长度相同
sox
Bash 脚本:
FILEONE=
FILETWO=
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 "> ... padding "
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 "< ... trimming "
sox $FILETWO $BASE.trim.wav trim $DIFF
fi
length1=$(sox $FILEONE -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##p')
length2=$(sox $BASE.trim.wav -n stat 2>&1 | sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$##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