Text-to-speech on iPhone [closed]

2019-01-16 11:13发布

问题:

How difficult would it be to implement something similar to AppleScript's say "words"?
That is to say, is it just a binary link and an import, or something as messy as a libxml implementation?

Edit: My answer solves this.


  • Acapela
    • A serious ripoff
    • €250 for the SDK, and that's not including updates
  • Ivona
    • Site does not present an iOS version with the others
    • Not interested
  • VoiceText
    • Site is ugly and difficult to navigate
    • Not interested
  • OpenEars
    • Open source, a definite plus
    • By far the best offline TTS I've heard of.
  • Flite
    • Super low quality, not worth using
    • Sucks as-is. OE improved on it a lot.
  • Google TTS
    • Good, but requires a network connection
    • Not ideal

回答1:

I've looked into this and unfortunately the options are either very expensive or bad quality:

  • Acapela Good quality but expensive.
  • Ivona iOS version and price available on request.
  • VoiceText from NeoSpeech. Price available on request.
  • https://bitbucket.org/sfoster/iphone-tts/ Festival port. Bad quality.

Related to this, here is how you can use Google's online TTS (code taken from iPhone SDK - Google TTS and encoding):

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"file.mp3"];

NSString *text = @"You are one chromosome away from being a potato.";
NSString *urlString = [NSString stringWithFormat:@"http://www.translate.google.com/translate_tts?tl=en&q=%@",text];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] initWithURL:url] autorelease];
[request setValue:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1" forHTTPHeaderField:@"User-Agent"];
NSURLResponse* response = nil;
NSError* error = nil;
NSData* data = [NSURLConnection sendSynchronousRequest:request
                                     returningResponse:&response
                                                 error:&error];
[data writeToFile:path atomically:YES];

AVAudioPlayer  *player;
NSError        *err;
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) 
{    
    player = [[AVAudioPlayer alloc] initWithContentsOfURL:
              [NSURL fileURLWithPath:path] error:&err];
    player.volume = 0.4f;
    [player prepareToPlay];
    [player setNumberOfLoops:0];
    [player play];    
}

The voiceover framework from Apple is private and can only used on for accessibility. At least if you want your application approved. But if you want to use it while you decide on what system to use, here it is:

// Not App Store safe. Only available in real devices.
// See http://arstechnica.com/apple/2010/02/iphone-voiceservices-looking-under-the-hood/

#define RTLD_LAZY 0x1
#define RTLD_NOW 0x2
#define RTLD_LOCAL 0x4
#define RTLD_GLOBAL 0x8

NSObject *voiceSynthesizer;
void *voiceServices;

-(void) say:(NSString*)text {
    if (!voiceSynthesizer)
    {
        NSString *vsLocation = @"/System/Library/PrivateFrameworks/VoiceServices.framework/VoiceServices";
        voiceServices = dlopen(vsLocation.UTF8String, RTLD_LAZY);
        voiceSynthesizer = [NSClassFromString(@"VSSpeechSynthesizer") new];
    }
    [voiceSynthesizer performSelector:@selector(startSpeakingString:) withObject:text];
}


回答2:

From some question on SO (forget which one, can't find it again), I got a link to OpenEars.
For something so light, I can't really complain.

It's a bit confusing to plug in, but the documentation is all for Xcode 4. Barring user error, it won't explode a project. There are a few warnings (some of which look like they should cause a crash at runtime), but it's looking good so far.

Edit: Newest OE version is MUCH easier to install. Definitely recommended.