/// <summary> /// 获取章节语音 /// </summary> /// <param name="chapter">章节</param> /// <param name="setCurrentChapter">是否将其设置为当前章节</param> /// <param name="synthesizer">语音合成器</param> /// <returns></returns> public async Task <MediaPlaybackItem> GetChapterVoiceAsync(Chapter chapter, bool setCurrentChapter = false, SpeechSynthesizer synthesizer = null) { if (Chapters.Count == 0) { throw new InvalidCastException("Chapter not loaded"); } else if (chapter == null || !Chapters.Contains(chapter)) { throw new ArgumentException("The chapter is not in current book"); } // 将章节转化为语音合成流需要时间和额外的系统资源,不宜生成超量的文本 string content = GetReadText(chapter); if (content.Length > SpeechMaxLength) { throw new Exception("The chapter detail text length is too large"); } if (CurrentChapter != chapter) { LoadChapter(chapter); } // 控件原本是按需加载页面,但考虑到用户会对生成的语音流进行进度调整,所以在生成合成语音时会将当前章节未渲染的部分全部渲染 _readerView.RenderAllOverflows(); bool isTempSyn = false; if (synthesizer == null) { synthesizer = new SpeechSynthesizer(); isTempSyn = true; } synthesizer.Options.IncludeSentenceBoundaryMetadata = true; synthesizer.Options.IncludeWordBoundaryMetadata = true; var stream = await synthesizer.SynthesizeTextToStreamAsync(content); _tempSpeechStream = stream; MediaSource source = MediaSource.CreateFromStream(stream, stream.ContentType); if (isTempSyn) { synthesizer.Dispose(); } var playback = new MediaPlaybackItem(source); RegisterForWordBoundaryEvents(playback); return(playback); }