小朋友觉得单个英语音频文件太长了,重听一句话,要手动拉来拉去,太费体力;做个小工具自用,按静音把音频文件切分为多个文件,对于规规矩矩朗读的音频可以比较准确的切分,基本够用了。
#!/bin/bash
#王道元
g_NOISE=-40dB #噪声容忍值,单位为dB,默认为-60dB
g_DURATION=0.40 #duration, d:设置静音时长,默认为2s; 根据不同情况设置有0.4,1.0等
g_START_AD=0.25 #上次静音结束位置往前调整值 秒
g_TIME_AD=0.5 #截取时长调整值 秒
split_audio(){
#split_audio mp3file 上个静音结束时间 当前静音开始时间 序号 分割文件存储目录
lfile=$1
llast_end=$2
lcur_start=$3
lind=$4
ldstdir=$5
lbase=`echo ${lfile%%.*}` #取文件名 Book1-001.mp3之Book1-001
ltype=`echo ${lfile#*.}` #取后缀 mp3
ldst=$ldstdir"/"$lbase"_"$lind"."$ltype #/abcw/Book1-001_1000.mp3
# echo " "$1" "$2" "$3" "$ldst
# ss = END_1 - Delta, t = START_2 - END_1 + Delta +Delta
lss=$(printf "%.5f" `echo "scale=5; $llast_end - $g_START_AD" | bc`)
lt=$(printf "%.5f" `echo "scale=5; $lcur_start - $llast_end + $g_TIME_AD" | bc`)
echo "ffmpeg -i $lfile -ss $lss -t $lt $ldst -hide_banner -y"
ffmpeg -i $lfile -ss $lss -t $lt $ldst -hide_banner -y -f null - 2> /dev/null
}
gen_silence_log(){
lfile=$1
llog=$2
echo "ffmpeg -i $lfile -af silencedetect=noise=$g_NOISE:d=$g_DURATION -hide_banner -f null - 2> $llog"
ffmpeg -i $lfile -af silencedetect=noise=$g_NOISE:d=$g_DURATION -hide_banner -f null - 2> $llog
# cp $llog $PWD/"origlog"
sed -i '/^\s*$/d' $llog
sed -i '/^[^\[].*$/d' $llog #删除非[开头行
sed -i '/^\[[^s].*$/d' $llog #删除非[s开头行
sed -i 's/\[s.*\]//g' $llog #删除[silencedetect *]
sed -i 's/|.*//g' $llog #删除 | 及之后内容
sed -i 's/[[:space:]]//g' $llog #删除所有空格
sed -i 's/silence_//g' $llog
# cp $llog $PWD/"fmtlog"
}
parse_log(){
lfile=$1
llog=$2
ldstdir=$3
let lind=1000 #分割后文件起始序号,1开头确保相同宽度
let llast_end=-1 #上一个end为-1, 则为本文件第一个静音段,此段start忽略
# while read -r lline; do #使用while read 会导致读取行错误
for lline in `cat $llog`; do
echo "TimsStamp Line:"$lline
lname=`echo ${lline%%:*}` #silence_start: 82.62 取silence_start或end
lvalue=`echo ${lline#*:}` #silence_start: 82.62 取82.62
echo "NAME:"$lname" VALUE: "$lvalue
if [ "start" == $lname ] ; then
if [ -1 != $llast_end ] ; then
lcur_start=$lvalue
echo "split_audio $lfile $llast_end $lcur_start $lind $ldstdir"
split_audio $lfile $llast_end $lcur_start $lind $ldstdir
#split_audio mp3 上个静音结束时间 当前静音开始时间 序号 分割文件存储目录
let lind++
sleep 1
fi
else
llast_end=$lvalue
fi
done
# done < $llog
}
for file in `ls *.mp3`
do
echo $file
lbase=`echo ${file%%.*}` #取文件名前缀 Book1-001
ldstdir=$lbase"d" #文件截分后保存目录
ldstlog=$ldstdir"/vol"
echo "lbase:" $lbase " ldstdir: " $ldstdir " ldstlog: " $ldstlog
rm -rf $ldstdir
mkdir $ldstdir
gen_silence_log $file $ldstlog
parse_log $file $ldstlog $ldstdir
rm -f $ldstlog
done