NSSpeechSynthesizer和跟踪持续时间

时间:2014-08-20 22:24:20

标签: objective-c macos cocoa text-to-speech

这次我有一个逻辑问题。希望有人帮助我。使用`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,比特和通道,并且因为我们知道它们没有被压缩,所以我们可以猜测轨道的当前长度。

此解决方案的最大缺点可能是连续磁盘访问,这会极大地降低性能。

您怎么看?

1 个答案:

答案 0 :(得分:1)

我只能猜测,但你使用的启发式将包括“无声”角色。为什么不尝试补偿测量误差?您似乎有一个非常线性的错误,因此您可以将其纳入计算:

40/50 = 80%
99/120 = 82.5%

所以你的错误大约是17.5-20%。只需将上面计算的时间乘以0.8或0.825就可以了。这很粗糙,但您已经在使用启发式。

BTW:你可能应该考虑使用-enumerateSubstringsInRange:options:usingBlock:来实现句子粒度而不是任意的单词分割。

使用“-speechSynthesizer:willSpeakWord:ofString:”会导致更大的问题:根据我的经验,它可能与几百毫秒到几秒钟内写入的文件中的位置不同步。当与Nuance声音一起使用时,说下一个单词似乎有问题。