kaldi中文文档
脚本说明
cmd.sh(配置运行方式,以及内存使用大小,使用gpu数量)
#export train_cmd="queue.pl --mem 2G"
#export decode_cmd="queue.pl --mem 4G"
#export mkgraph_cmd="queue.pl --mem 8G"
export train_cmd=run.pl
export decode_cmd="run.pl --mem 4G"
export mkgraph_cmd="run.pl --mem 8G"
export cuda_cmd="run.pl --gpu 1"
download_and_untar.sh(下载数据集,并且解压)
remove_archive=false
if [ "$1" == --remove-archive ]; then
remove_archive=true
shift
fi
'''
$1表示传进来的参数,如果是--remove-archive则设置在解压完成后移除压缩包
Shell编程中Shift的用法
位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。
非常有用的 Unix 命令:shift。我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当 Shell 程序不知道其个数时,可以把所有参数一起赋值给变量$*。若用户要求 Shell 在不知道位置变量个数的情况下,还能逐个的把参数一一处理,也就是在 $1 后为 $2,在 $2 后面为 $3 等。在 shift 命令执行前变量 $1 的值在 shift 命令执行后就不可用了
示例如下:
#测试 shift 命令(x_shift.sh)
until [ $# -eq 0 ]
do
echo "第一个参数为: $1 参数个数为: $#"
shift
done
执行以上程序x_shift.sh:
$./x_shift.sh 1 2 3 4
结果显示如下:
第一个参数为: 1 参数个数为: 4
第一个参数为: 2 参数个数为: 3
第一个参数为: 3 参数个数为: 2
第一个参数为: 4 参数个数为: 1
从上可知 shift 命令每执行一次,变量的个数($#)减一,而变量值提前一位,下面代码用 until 和 shift 命令计算所有命令行参数的和。'''
#local/download_and_untar.sh $data $data_url data_aishell || exit 1;
这里的 a || b是一个逻辑符号,代表着如果a执行失败则执行b。
如何知道上一条linux命令是否成功执行。
是看变量$?的值,如果为0代表成功执行。
这里的exit 1终止当前进程并且将$?设置为1。表示不成功执行。
$data 是aishell在本机的位置,既可以新建一个空目录来下载,也可以指定到已经下好的路径,
aishell 分为resource_aishell和data_aishell两部分来下载,
脚本会通过检查每一个部分下是否有.complete文件来判断当前部分是否下载完全。
如果没有才会到指定网址下载
#local/download_and_untar.sh $data $data_url resource_aishell || exit 1;
下载数据集和字典相关东西
path.sh相关路径定义
export KALDI_ROOT=`pwd`/../../..
[ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ROOT/tools/env.sh
export PATH=$PWD/utils/:$KALDI_ROOT/tools/openfst/bin:$PWD:$PATH
[ ! -f $KALDI_ROOT/tools/config/common_path.sh ] && echo >&2 "The standard file $KALDI_ROOT/tools/config/common_path.sh is not present -> Exit!" && exit 1
. $KALDI_ROOT/tools/config/common_path.sh
export LC_ALL=C
"""
export用法
当使用export来导出一个变量时,当前shell就会将此变量放到“导出变量列表”中,一旦在某个时刻需要建立子shell时,就会将这个导出变量列表拷贝一份给子shell,这样子shell也就有所应当的看到了这些被导出的变量了。
(为了能让10岁以前小朋友看懂,更形象的说:从前有个母亲叫shell,shell她手里攥着“导出变量列表”和“局部变量列表”两件宝贝,当 shell生育了小孩(名叫子shell)的时候,她就把“导出变量列表”这件宝贝复制一份,交给她的孩子,而shell手里的另一件宝贝“局部变量列 表”则不会交给小孩)
在子shell是无法改变父shell中的“导出变量列表”中变量的值的。子shell只能修改自己手里的那份“导出变量列表”中变量的值
子shell是无法改变父shell中的“导出变量列表”中变量的值的。
变量一旦被导出,对所有后续执行的子shell,该变量都是导出变量。
关于export -p:
可以执行export -p来查看当前shell的导出变量列表。这其中一定是包括了从父shell继承来的导出变量列表。
全文总结:
1 没有导出的变量是局部变量,子shell是看不到的。
2 导出变量列表被复制给子shell,子shell可以修改和存取它,但是这种修改父shell看不到。
3 导出变量列表的上述特性对于直接产生的子shell生效,对于由子shell产生的后继子shell也是如此。
4 export可以在变量赋值之后用,也可以在变量赋值之前用。"""
local/aishell_prepare_dict.sh $data/resource_aishell || exit 1;
这个脚本的功能主要是将resource_aishell
下的lexicon.txt
复制到data/local/dict
中。并且提取出nonsilence_phones.txt
、optional_silence.txt
、silence_phones.txt
和extra_questions.txt
。用到了很多awk和perl的脚本。
local/aishell_data_prep.sh $data/data_aishell/wav $data/data_aishell/transcript || exit 1;(数据准备)
$data/data_aishell/wav
目录下放着的是音频文件。其中有两级目录speaker/filename.wav
。 $data/data_aishell/transcript
目录下放着的是aishell_transcript_v0.8.txt
文字翻录。 这个shell脚本的功能是将$data/data_aishell/wav
下的 train
,test
,dev
分别建立索引。并且建立Kaldi能够理解的语料格式
aishell_audio_dir=$1 #$1为audio地址
aishell_text=$2/aishell_transcript_v0.8.txt
train_dir=data/local/train
dev_dir=data/local/dev
test_dir=data/local/test
tmp_dir=data/local/tmp
#在data中建立三个文件夹train,dev,test
mkdir -p $train_dir
mkdir -p $dev_dir
mkdir -p $test_dir
mkdir -p $tmp_dir
# data directory check
if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then
echo "Error: $0 requires two directory arguments"
exit 1;
fi
#在音频目录下查找,以wav结尾的文件放入wav.flist目录
find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist
统计数据集条数,判断是否缺失
n=`cat $tmp_dir/wav.flist | wc -l`
将tmp.flist 中的音频根据是否包含wav/train 等相关字段写入到对应的train||dev||test 的wav.flist中 wav.flist就是生成文件的路径
grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1;
grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1;
grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1;
rm -r $tmp_dir #删除临时文件
#分别在train,dev,test目录中的wav.flist找出音频id到utt.list,音频id对应说话人(utt2spk)到utt2spk文件中,使用paste 将音频id 音频地址wav.flist对应输出到wav.scp_all中
.pl是perl脚本文件,
utils/filter_scp.pl -f 1 $dir/utt.list $dir/utt2spk_all | sort -u > $dir/utt2spk
将说话人和utt2spk_all对齐,排序好dao utt2spk
总之 utt2spk是排序好的,all是没有排序号的
# Transcriptions preparation
for dir in $train_dir $dev_dir $test_dir; do
echo Preparing $dir transcriptions
sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list
sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{i=NF-1;printf("%s %s\n",$NF,$i)}' > $dir/utt2spk_all
paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all
utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt
awk '{print $1}' $dir/transcripts.txt > $dir/utt.list
utils/filter_scp.pl -f 1 $dir/utt.list $dir/utt2spk_all | sort -u > $dir/utt2spk
utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp
sort -u $dir/transcripts.txt > $dir/text
utils/utt2spk_to_spk2utt.pl $dir/utt2spk > $dir/spk2utt
done