iOS語音識別和語音合成

前言

最近在做一個翻譯工具请祖,由于項(xiàng)目需要兼容 iOS 8.0订歪,所以語音識別、合成都是用的科大訊飛的肆捕。使用過程中發(fā)現(xiàn)在線轉(zhuǎn)語音不是很好刷晋,受網(wǎng)絡(luò)的影響聲音經(jīng)常斷斷續(xù)續(xù)的,而它的離線轉(zhuǎn)語音價格有太貴慎陵。而且支持的語種較少眼虱,現(xiàn)在換成系統(tǒng)自帶的語音合成、語音識別席纽。一些心得記錄一下方便需要同學(xué)查閱捏悬。

語音識別

優(yōu)點(diǎn)

  • 說話時,可以一個一個字識別润梯,科大訊飛是一段話識別一次过牙,這樣的體驗(yàn)很好甥厦,可以及時響應(yīng)到用戶;
  • 支持58種語種寇钉,其中包括一些地方方言(例如:粵語)刀疙;
  • 識別度非常高;

缺點(diǎn)

  • 只支持iOS10以上的系統(tǒng)(iOS 10以下的系統(tǒng)需要做兼容扫倡,我用的是科大訊飛)

框架主要類

#import <Foundation/Foundation.h>
#import <Speech/SFSpeechRecognitionResult.h>
#import <Speech/SFSpeechRecognitionRequest.h>
#import <Speech/SFSpeechRecognitionTask.h>
#import <Speech/SFSpeechRecognitionTaskHint.h>
#import <Speech/SFSpeechRecognizer.h>
#import <Speech/SFTranscriptionSegment.h>
#import <Speech/SFTranscription.h>

如何使用

#import "NFSpeechViewController.h"
#import <Speech/Speech.h>

@interface NFSpeechViewController ()<SFSpeechRecognitionTaskDelegate>

@property (nonatomic ,strong) SFSpeechRecognitionTask *recognitionTask;
@property (nonatomic ,strong) SFSpeechRecognizer      *speechRecognizer;
@property (nonatomic ,strong) UILabel                 *recognizerLabel;

@end

@implementation NFSpeechViewController

- (void)dealloc {
    [self.recognitionTask cancel];
    self.recognitionTask = nil;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];

    //0.0獲取權(quán)限
    //0.1在info.plist里面配置
    /*
     typedef NS_ENUM(NSInteger, SFSpeechRecognizerAuthorizationStatus) {
     SFSpeechRecognizerAuthorizationStatusNotDetermined,
     SFSpeechRecognizerAuthorizationStatusDenied,
     SFSpeechRecognizerAuthorizationStatusRestricted,
     SFSpeechRecognizerAuthorizationStatusAuthorized,
     };
     */
    [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
        switch (status) {
            case SFSpeechRecognizerAuthorizationStatusNotDetermined:
                NSLog(@"NotDetermined");
                break;
            case SFSpeechRecognizerAuthorizationStatusDenied:
                NSLog(@"Denied");
                break;
            case SFSpeechRecognizerAuthorizationStatusRestricted:
                NSLog(@"Restricted");
                break;
            case SFSpeechRecognizerAuthorizationStatusAuthorized:
                NSLog(@"Authorized");
                break;
            default:
                break;
        }
    }];

    //1.創(chuàng)建SFSpeechRecognizer識別實(shí)例
    self.speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];

    //2.創(chuàng)建識別請求
    SFSpeechURLRecognitionRequest *request = [[SFSpeechURLRecognitionRequest alloc] initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"游子吟.mp3" ofType:nil]]];

    //3.開始識別任務(wù)
    self.recognitionTask = [self recognitionTaskWithRequest1:request];
}

- (SFSpeechRecognitionTask *)recognitionTaskWithRequest0:(SFSpeechURLRecognitionRequest *)request{
    return [self.speechRecognizer recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
        if (!error) {
            NSLog(@"語音識別解析正確--%@", result.bestTranscription.formattedString);
        }else {
            NSLog(@"語音識別解析失敗--%@", error);
        }
    }];
}

- (SFSpeechRecognitionTask *)recognitionTaskWithRequest1:(SFSpeechURLRecognitionRequest *)request{
    return [self.speechRecognizer recognitionTaskWithRequest:request delegate:self];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark- SFSpeechRecognitionTaskDelegate

// Called when the task first detects speech in the source audio
- (void)speechRecognitionDidDetectSpeech:(SFSpeechRecognitionTask *)task {

}

// Called for all recognitions, including non-final hypothesis
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didHypothesizeTranscription:(SFTranscription *)transcription {

}

// Called only for final recognitions of utterances. No more about the utterance will be reported
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult {
    NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont systemFontOfSize:18],
                                 };

    CGRect rect = [recognitionResult.bestTranscription.formattedString boundingRectWithSize:CGSizeMake(self.view.bounds.size.width - 100, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
    self.recognizerLabel.text = recognitionResult.bestTranscription.formattedString;
    self.recognizerLabel.frame = CGRectMake(50, 120, rect.size.width, rect.size.height);
}

// Called when the task is no longer accepting new audio but may be finishing final processing
- (void)speechRecognitionTaskFinishedReadingAudio:(SFSpeechRecognitionTask *)task {

}

// Called when the task has been cancelled, either by client app, the user, or the system
- (void)speechRecognitionTaskWasCancelled:(SFSpeechRecognitionTask *)task {

}

// Called when recognition of all requested utterances is finished.
// If successfully is false, the error property of the task will contain error information
- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishSuccessfully:(BOOL)successfully {
    if (successfully) {
        NSLog(@"全部解析完畢");
    }
}

#pragma mark- getter

- (UILabel *)recognizerLabel {
    if (!_recognizerLabel) {
        _recognizerLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 120, self.view.bounds.size.width - 100, 100)];
        _recognizerLabel.numberOfLines = 0;
        _recognizerLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
        _recognizerLabel.adjustsFontForContentSizeCategory = YES;
        _recognizerLabel.textColor = [UIColor orangeColor];
        [self.view addSubview:_recognizerLabel];
    }
    return _recognizerLabel;
}

@end

上面代碼是一個簡單的列子谦秧,創(chuàng)建NFSpeechViewController的VC直接拷貝上面代碼,然后info.plist 添加用戶使用權(quán)限
Privacy - Microphone Usage Description
Privacy - Speech Recognition Usage Description
就可以使用了。

這里再重點(diǎn)說下修改本地化語言(需要識別的語言)

[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]

本地化語言的keylocaleIdentifier可以通過 [SFSpeechRecognizer supportedLocales] 獲取到镊辕,目前一共是58種油够。

for (NSLocale *lacal in [SFSpeechRecognizer supportedLocales]) {
  NSLog(@"localeIdentifier = %@,languageCode = %@, countryCode = %@",lacal.localeIdentifier,lacal.languageCode,lacal.countryCode);
}

打印日志如下:

localeIdentifier = nl-NL,languageCode = nl, countryCode = NL(荷蘭)
localeIdentifier = es-MX,languageCode = es, countryCode = MX (墨西哥)
localeIdentifier = zh-TW,languageCode = zh, countryCode = TW(中國臺灣)
localeIdentifier = fr-FR,languageCode = fr, countryCode = FR(法國)
localeIdentifier = it-IT,languageCode = it, countryCode = IT( 意大利)
localeIdentifier = vi-VN,languageCode = vi, countryCode = VN(越南)
localeIdentifier = en-ZA,languageCode = en, countryCode = ZA(南非)
localeIdentifier = ca-ES,languageCode = ca, countryCode = ES(西班牙)
localeIdentifier = es-CL,languageCode = es, countryCode = CL(智利)
localeIdentifier = ko-KR,languageCode = ko, countryCode = KR( 韓國)
localeIdentifier = ro-RO,languageCode = ro, countryCode = RO(羅馬尼亞)
localeIdentifier = fr-CH,languageCode = fr, countryCode = CH(瑞士-法語)
localeIdentifier = en-PH,languageCode = en, countryCode = PH(菲律賓)
localeIdentifier = en-CA,languageCode = en, countryCode = CA(加拿大-英語)
localeIdentifier = en-SG,languageCode = en, countryCode = SG(新加坡)
localeIdentifier = en-IN,languageCode = en, countryCode = IN(印度)
localeIdentifier = en-NZ,languageCode = en, countryCode = NZ(新西蘭)
localeIdentifier = it-CH,languageCode = it, countryCode = CH(瑞士-意大利語)
localeIdentifier = fr-CA,languageCode = fr, countryCode = CA(加拿大-法語)
localeIdentifier = da-DK,languageCode = da, countryCode = DK(丹麥)
localeIdentifier = de-AT,languageCode = de, countryCode = AT(奧地利-德語)
localeIdentifier = pt-BR,languageCode = pt, countryCode = BR(巴西-葡萄牙語)
localeIdentifier = yue-CN,languageCode = yue, countryCode = CN(中國-粵語)
localeIdentifier = zh-CN,languageCode = zh, countryCode = CN(中國-簡文)
localeIdentifier = sv-SE,languageCode = sv, countryCode = SE(瑞典-薩爾瓦多語)
localeIdentifier = es-ES,languageCode = es, countryCode = ES(西班牙-英語)
localeIdentifier = ar-SA,languageCode = ar, countryCode = SA(沙烏地阿拉伯-阿根廷語)
localeIdentifier = hu-HU,languageCode = hu, countryCode = HU(匈牙利)
localeIdentifier = fr-BE,languageCode = fr, countryCode = BE(比利時-法語)
localeIdentifier = en-GB,languageCode = en, countryCode = GB(英式英語)
localeIdentifier = ja-JP,languageCode = ja, countryCode = JP(日本)
localeIdentifier = zh-HK,languageCode = zh, countryCode = HK(中國香港-粵語)
localeIdentifier = fi-FI,languageCode = fi, countryCode = FI(芬蘭)
localeIdentifier = tr-TR,languageCode = tr, countryCode = TR(土耳其)
localeIdentifier = nb-NO,languageCode = nb, countryCode = NO(挪威)
localeIdentifier = en-ID,languageCode = en, countryCode = ID(印度尼西亞-英語)
localeIdentifier = en-SA,languageCode = en, countryCode = SA(沙烏地阿拉伯-英語)
localeIdentifier = pl-PL,languageCode = pl, countryCode = PL(波蘭)
localeIdentifier = id-ID,languageCode = id, countryCode = ID(印度尼西亞)
localeIdentifier = ms-MY,languageCode = ms, countryCode = MY(馬來西亞-蒙特塞拉特語)
localeIdentifier = el-GR,languageCode = el, countryCode = GR(希臘)
localeIdentifier = cs-CZ,languageCode = cs, countryCode = CZ(捷克共和國)
localeIdentifier = hr-HR,languageCode = hr, countryCode = HR(克羅地亞)
localeIdentifier = en-AE,languageCode = en, countryCode = AE(阿拉伯聯(lián)合酋長國-英語)
localeIdentifier = he-IL,languageCode = he, countryCode = IL(以色列)
localeIdentifier = ru-RU,languageCode = ru, countryCode = RU(俄羅斯)
localeIdentifier = de-CH,languageCode = de, countryCode = CH(瑞士-德語)
localeIdentifier = en-AU,languageCode = en, countryCode = AU(澳大利亞-英語)
localeIdentifier = de-DE,languageCode = de, countryCode = DE(德語)
localeIdentifier = nl-BE,languageCode = nl, countryCode = BE(比利時-荷蘭語)
localeIdentifier = th-TH,languageCode = th, countryCode = TH(泰國)
localeIdentifier = pt-PT,languageCode = pt, countryCode = PT(葡萄牙)
localeIdentifier = sk-SK,languageCode = sk, countryCode = SK(斯洛伐克)
localeIdentifier = en-US,languageCode = en, countryCode = US(美式英語)
localeIdentifier = en-IE,languageCode = en, countryCode = IE(愛爾蘭-英語)
localeIdentifier = es-CO,languageCode = es, countryCode = CO(哥倫比亞-西班牙語)
localeIdentifier = uk-UA,languageCode = uk, countryCode = UA(烏克蘭)
localeIdentifier = es-US,languageCode = es, countryCode = US(美國-西班牙語)

語音合成

優(yōu)點(diǎn)

  • 支持的30多種語種蚁袭;
  • 語速征懈、語調(diào)、音量都可以自己控制揩悄,可以自定義自己喜歡的格式卖哎;

缺點(diǎn)

  • 發(fā)音效果一般理想
  • 播音員默認(rèn)只有一個(訊飛可以選擇播音員發(fā)音效果很好)

框架主要類

#import<AVFoundation/AVSpeechSynthesis.h>

如何使用

1、初始化設(shè)置AVSpeechSynthesizer

AVSpeechSynthesizer *player  = [[AVSpeechSynthesizer alloc]init];
player.delegate = self;
self.player = player;
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc]initWithString:string];//設(shè)置語音內(nèi)容
utterance.voice  = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-TW"];//設(shè)置語言 zh-CN yue-CN
utterance.rate   = self.rate;  //設(shè)置語速
utterance.volume = self.volume;  //設(shè)置音量(0.0~1.0)默認(rèn)為1.0
utterance.pitchMultiplier = self.pitchMultiplier;  //設(shè)置語調(diào) (0.5-2.0)
utterance.postUtteranceDelay = 0; //目的是讓語音合成器播放下一語句前有短暫的暫停
[player speakUtterance:utterance];

2删性、控制部分

  • 停止
[self.player stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
  • 暫停
[self.player pauseSpeakingAtBoundary:AVSpeechBoundaryImmediate];
  • 繼續(xù)播放
 [self.player continueSpeaking];

3亏娜、代理部分

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"朗讀開始");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didPauseSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"朗讀暫停");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didContinueSpeechUtterance:(AVSpeechUtterance *)utterance{
    NSLog(@"朗讀繼續(xù)");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance{
     NSLog(@"朗讀結(jié)束");
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance{

}

設(shè)置聲音效果的方法,注意選英語則讀不了漢語蹬挺,但是漢語可以和英語混用维贺,這個我已經(jīng)試過了。但是讀起來比較生硬巴帮。

avspeech支持的語言種類包括:

"[AVSpeechSynthesisVoice 0x978a0b0] Language: th-TH",(泰國)

"[AVSpeechSynthesisVoice 0x977a450] Language: pt-BR",(巴西-葡萄牙語)

"[AVSpeechSynthesisVoice 0x977a480] Language: sk-SK",(斯洛伐克)

"[AVSpeechSynthesisVoice 0x978ad50] Language: fr-CA",(加拿大-法語)

"[AVSpeechSynthesisVoice 0x978ada0] Language: ro-RO",(羅馬尼亞)

"[AVSpeechSynthesisVoice 0x97823f0] Language: no-NO",(挪威)

"[AVSpeechSynthesisVoice 0x978e7b0] Language: fi-FI",(芬蘭)

"[AVSpeechSynthesisVoice 0x978af50] Language: pl-PL",(波蘭)

"[AVSpeechSynthesisVoice 0x978afa0] Language: de-DE",(德國)

"[AVSpeechSynthesisVoice 0x978e390] Language: nl-NL",(荷蘭)

"[AVSpeechSynthesisVoice 0x978b030] Language: id-ID",(印度尼西亞)
"[AVSpeechSynthesisVoice 0x978b080] Language: tr-TR",(土耳其)

"[AVSpeechSynthesisVoice 0x978b0d0] Language: it-IT",(意大利)

"[AVSpeechSynthesisVoice 0x978b120] Language: pt-PT",(葡萄牙)

"[AVSpeechSynthesisVoice 0x978b170] Language: fr-FR",(法國)

"[AVSpeechSynthesisVoice 0x978b1c0] Language: ru-RU",(俄羅斯)

"[AVSpeechSynthesisVoice 0x978b210] Language: es-MX",(墨西哥-西班牙語)

"[AVSpeechSynthesisVoice 0x978b2d0] Language: zh-HK",中文(香港)粵語

"[AVSpeechSynthesisVoice 0x978b320] Language: sv-SE",(瑞典-薩爾瓦多語)

"[AVSpeechSynthesisVoice 0x978b010] Language: hu-HU",(匈牙利)

"[AVSpeechSynthesisVoice 0x978b440] Language: zh-TW",中文(臺灣)

"[AVSpeechSynthesisVoice 0x978b490] Language: es-ES",(西班牙)

"[AVSpeechSynthesisVoice 0x978b4e0] Language: zh-CN",中文(普通話)

"[AVSpeechSynthesisVoice 0x978b530] Language: nl-BE",(比利時-荷蘭語)

"[AVSpeechSynthesisVoice 0x978b580] Language: en-GB",英語(英國)

"[AVSpeechSynthesisVoice 0x978b5d0] Language: ar-SA",(沙烏地阿拉伯-阿根廷語)

"[AVSpeechSynthesisVoice 0x978b620] Language: ko-KR",(韓國)

"[AVSpeechSynthesisVoice 0x978b670] Language: cs-CZ",(捷克共和國)

"[AVSpeechSynthesisVoice 0x978b6c0] Language: en-ZA",(南非-英語)

"[AVSpeechSynthesisVoice 0x978aed0] Language: en-AU",(澳大利亞-英語)

"[AVSpeechSynthesisVoice 0x978af20] Language: da-DK",(丹麥)

"[AVSpeechSynthesisVoice 0x978b810] Language: en-US",英語(美國)

"[AVSpeechSynthesisVoice 0x978b860] Language: en-IE",(愛爾蘭-英語)

"[AVSpeechSynthesisVoice 0x978b8b0] Language: hi-IN",(印度)

"[AVSpeechSynthesisVoice 0x978b900] Language: el-GR",(希臘)

"[AVSpeechSynthesisVoice 0x978b950] Language: ja-JP"(日本)

先記錄到這里溯泣,后面會再更新,上傳Demo榕茧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垃沦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子用押,更是在濱河造成了極大的恐慌肢簿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜻拨,死亡現(xiàn)場離奇詭異池充,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)缎讼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門收夸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人休涤,你說我怎么就攤上這事咱圆〉驯伲” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵序苏,是天一觀的道長手幢。 經(jīng)常有香客問我,道長忱详,這世上最難降的妖魔是什么围来? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮匈睁,結(jié)果婚禮上监透,老公的妹妹穿的比我還像新娘。我一直安慰自己航唆,他們只是感情好胀蛮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糯钙,像睡著了一般粪狼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上任岸,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天再榄,我揣著相機(jī)與錄音,去河邊找鬼享潜。 笑死困鸥,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的剑按。 我是一名探鬼主播疾就,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吕座!你這毒婦竟也來了虐译?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吴趴,失蹤者是張志新(化名)和其女友劉穎漆诽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锣枝,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厢拭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了撇叁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片供鸠。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖陨闹,靈堂內(nèi)的尸體忽然破棺而出楞捂,到底是詐尸還是另有隱情薄坏,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布寨闹,位于F島的核電站胶坠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏繁堡。R本人自食惡果不足惜沈善,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望椭蹄。 院中可真熱鬧闻牡,春花似錦、人聲如沸绳矩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽埋酬。三九已至哨啃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間写妥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工审姓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留珍特,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓魔吐,卻偏偏與公主長得像扎筒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子酬姆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容