这次我有一个逻辑问题。希望有人帮助我。使用`NSSpeechSynthesizer'你可以设置速率,即每分钟235个单词,每分钟100个单词等等......
我发现通常使用每个单词5个字符的标准化单词长度计算每分钟单词的平均值,计算空格和符号。
我需要使用预先选定的持续时间自动细分曲目中的长文本,比方说每曲目15分钟。
我们如何计算每个“拆分”到语音引擎的正确字符数?
我的解决方案如下:
// duration is the number of minutes per track
numberOfWordsPerTrack = [rateSlider floatValue] * duration;
splits = [[NSMutableArray alloc] init];
finished = NO;
NSUInteger position = 0;
while( !finished ) {
NSRange range;
// the idea is: I take 5*numberOfWordsPerTrack characters
// until the text allows me to select them
range = NSMakeRange( position, 5*numberOfWordsPerTrack );
if( range.location+range.length > mainTextView.string.length ) {
// If there are not another full character track we get
// the tail of the remaining text
finished = YES;
range = NSMakeRange( position, mainTextView.string.length-position );
}
// Here we get the track and add it to the split list
if( range.location+range.length <= mainTextView.string.length ) {
currentSplit = [mainTextView.string substringWithRange:range];
[splits addObject:currentSplit];
}
position += range.length;
}
此解决方案的问题是轨道持续时间不正确。它与期望值相差不大,但它不对。例如,每分钟使用235个单词,持续时间为50分钟,每首歌曲有40分钟。如果我每首曲目设置120分钟,我每小时1小时:39米......依此类推......
您认为逻辑错误在哪里?
JanX2回复后的编辑
好吧,虽然我随意地想到了以下的小说,你可以告诉我你在实现之前对此有何看法,因为我的代码并没有轻微改变
如果我使用speechSynthesizer:willSpeakWord:ofString:
代理成员,我可以经常测试.aiff文件大小,即在说出下一个单词(真实单词,未标准化)之前。因为我们知道这些文件由合成器创建的Hz,比特和通道,并且因为我们知道它们没有被压缩,所以我们可以猜测轨道的当前长度。
此解决方案的最大缺点可能是连续磁盘访问,这会极大地降低性能。
您怎么看?
答案 0 :(得分:1)
我只能猜测,但你使用的启发式将包括“无声”角色。为什么不尝试补偿测量误差?您似乎有一个非常线性的错误,因此您可以将其纳入计算:
40/50 = 80%
99/120 = 82.5%
所以你的错误大约是17.5-20%。只需将上面计算的时间乘以0.8或0.825就可以了。这很粗糙,但您已经在使用启发式。
BTW:你可能应该考虑使用-enumerateSubstringsInRange:options:usingBlock:
来实现句子粒度而不是任意的单词分割。
使用“-speechSynthesizer:willSpeakWord:ofString:”会导致更大的问题:根据我的经验,它可能与几百毫秒到几秒钟内写入的文件中的位置不同步。当与Nuance声音一起使用时,说下一个单词似乎有问题。