原文: http://www.raywenderlich.com/64623/make-narrated-book-using-avspeechsynthesizer-ios-7

随着 PageViewController 的引入,苹果让开发者们制作图书类app 更加轻松。不幸的是,对于生活在朝九晚五繁忙节奏中的人们来说,阅读也是一件奢侈的事情。为什么你不能在读一本小说的同时做其他事情呢?

在 Siri 刚开始出现的时候,苹果曾经用复杂的动态文本阅读将开发者拒之门外,但当iOS7 发布的时候,苹果终于放开了这扇大门。

在本教程中,你将制作一本故事书。这本书的每一页都会在显示文字的同时朗读文字中的内容。有声的阅读将让你的 app 在 iTunes 中显得与众不同,同时还保护了视力。有声书尤其受广播听众的喜爱,因为它允许人们在锻炼、烹饪或工作的同时进行“阅读”。

当你制作自己的有声书时, 你将学习到:

  • 如何使用 AVSpeechSynthesizer 和 AVSpeechUtterance 让 iOS 设备朗读文本
  • How to make this synthesized speech sound more natural by modifying AVSpeechUtterance properties like pitch and rate.
  • 如何修改 AVSpeechUtterance 属性例如 pitch 和 rate,使合成的语音更自然

AVSpeechSynthesizer当然比不上真人语音,但它对于你将要开发的 app 来说,相对容易一些。

注意:关于如何用 Sprite Kit 开发iPad儿童书籍,请参考Tammy Coron 的教程: How to Create an Interactive Children’s Book for the iPad

开始:AVSpeechSynthesizer

首先,请下载 初始项目。进入NarratedBookUsingAVSpeechStarter 目录,双击 NarratedBookUsingAVSpeech.xcodeproj 以打开初始项目。

Build & run 。你将在模拟器中看到:

书的内容是关于松鼠的童谣。虽然不是亚马逊买得最火的读物,但对于本教程来说足够了。向左滑动进行向后翻页,向右滑动则返回前一页。噢,它已经拥有了基本的“书”的功能,真是不错的开始。

理解机制

注意:教程的最后,会留给你几个习题。接下来一节将包括示例项目的一些内容,以便你能独立完成这些习题。如果你对这部分内容不感兴趣,请跳到下一节。

初始项目包括两个类:

1. Models: 用于存放书籍的内容,它是page 的集合。
2. Presentation: 将 models 展现到屏幕并响应用户动作(例如滑动手势)。

在你制作自己的图书时,理解这两个类的工作机制是很有必要的。打开RWTBook.h:

@interface RWTBook : NSObject

//1

@property (nonatomic, copy, readonly) NSArray *pages;

//2

+ (instancetype)bookWithPages:(NSArray*)pages;

//3

+ (instancetype)testBook;

@end

  1. pages 属性存放了 Page 对象的数组,每个 Page对象代表图书中的每一页。
  2. bookWithPages: 方法是一个初始化 Book 的方法,它用指定的 page 对象数组为参数,返回一个 book 对象。
  3. testBook 创建 Book 对象,用于测试。在开始加入和读取你自己的图书内容之前,就先使用 testBook 创建一个简单的 Book 吧。

RWTPage.h声明如下:

//1

extern NSString* const RWTPageAttributesKeyUtterances;

extern NSString* const RWTPageAttributesKeyBackgroundImage;

@interface RWTPage : NSObject

//2

@property (nonatomic, strong, readonly) NSString *displayText;

@property (nonatomic, strong, readonly) UIImage *backgroundImage;

//3 + (instancetype)pageWithAttributes:(NSDictionary*)attributes;

@end

  1. 常量用于从字典中检索页。RWTPageAttributesKeyUtterances常量可以检索出page 对象中的文本,RWTPageAttributesKeyBackgroundImage则用于检索 page 对象所用的背景图片。
  2. displayText 属性用于存储 page 的文本,backgroundImage 属性用于存储 page 的背景图片。
  3. pageWithAttributes:用指定的 NSDictionary 创建一个 page 实例。

RWTPageViewController.m声明如下:

#pragma mark - Class Extension

// 1

@interface RWTPageViewController ()

@property (nonatomic, strong) RWTBook *book;

@property (nonatomic, assign) NSUInteger currentPageIndex;

@end

@implementation RWTPageViewController

#pragma mark - Lifecycle

// 2

- (void)viewDidLoad {

[super viewDidLoad];

[self setupBook:[RWTBook testBook]];

UISwipeGestureRecognizer *swipeNext = [[UISwipeGestureRecognizer alloc]                                           initWithTarget:self                                                   action:@selector(gotoNextPage)];

swipeNext.direction = UISwipeGestureRecognizerDirectionLeft;   [self.view addGestureRecognizer:swipeNext];

UISwipeGestureRecognizer *swipePrevious = [[UISwipeGestureRecognizer alloc]                                               initWithTarget:self                                                       action:@selector(gotoPreviousPage)];

swipePrevious.direction = UISwipeGestureRecognizerDirectionRight;

[self.view addGestureRecognizer:swipePrevious];

}

#pragma mark - Private

// 3

- (RWTPage*)currentPage {

return [self.book.pages objectAtIndex:self.currentPageIndex];

}

// 4

- (void)setupBook:(RWTBook*)newBook {

self.book = newBook;

self.currentPageIndex = 0;

[self setupForCurrentPage];

}

// 5

- (void)setupForCurrentPage {

self.pageTextLabel.text = [self currentPage].displayText;

self.pageImageView.image = [self currentPage].backgroundImage;

}

// 6

- (void)gotoNextPage {

if ([self.book.pages count] == 0 ||

self.currentPageIndex == [self.book.pages count] - 1) {

return;

}

self.currentPageIndex += 1;

[self setupForCurrentPage];

}

// 7

- (void)gotoPreviousPage {

if (self.currentPageIndex == 0) {

return;

}

self.currentPageIndex -= 1;

[self setupForCurrentPage];

}

@end

以上代码说明如下:

  1. book 属性保存了当前的 RWTBook 对象,currentPageIndex属性保存了 RWTBook 对象的当前页索引。
  2. 当视图加载完毕,设置要显示的 page,并添加滑动手势的识别器以便用户能通过手势进行翻页。
  3. 返回当前页的 RWTPage 对象。
  4. 设置 book 属性并将当前页置为第一页。
  5. 设置当前页的显示内容。
  6. 查找下一页,如果该页存在,则将下一页设置为当前页。该方法由 swipeNext 手势识别器调用。
  7. 查找上一页,如果该页存在,则将上一页设置为当前页。该方法由 swipePrevious 手势识别器调用。

播放和停止!

这是一个很要命的问题。

打开RWTPageViewController.m,在#import "RWTPage.h" 下面加入:

@import AVFoundation;

iOS 语音功能由 AVFoundation 框架提供,你必须导入这个框架。

提示: @import会导入并连接 AVFoundation 框架。关于 iOS7 中 @import 及相关的 O-C 语言新特性,请参考这篇文章What’sNew in Objective-C and Foundation in iOS 7。

在 currentPageIndex 属性声明之下加入:

@property (nonatomic, strong) AVSpeechSynthesizer *synthesizer;

synthesizer 对象将用于朗读每一页中的文字。

可以将 ViewController 中定义的AVSpeechSynthesizer 对象想象成一个会说话的人。而 AVSpeechUtterance 则可以想象成一张小纸条,把纸条递给这个人,则他就会念出纸条上的字。

注意:一个 AVSpeechUtterance 可能是一个单词,比如“Whisky”,或者是一个完整的语句,比如“Whisky,frisky,hippidityhop”。

在 RWTPageViewController.m 的最后加入以下方法:

#pragma mark - Speech Management

- (void)speakNextUtterance {

AVSpeechUtterance *nextUtterance = [[AVSpeechUtterance alloc]                                        initWithString:[self currentPage].displayText];

[self.synthesizer speakUtterance:nextUtterance];

}

创建了一个 utterance 对象,然后告诉 synthesizer 去念出它。

然后实现这个方法:

- (void)startSpeaking {

if (!self.synthesizer) {

self.synthesizer = [[AVSpeechSynthesizer alloc] init];

}

[self speakNextUtterance];

}

这个方法负责初始化 synthesizer 属性(如果它未初始化的话)。然后调用speakNextUtterance 方法,开始朗读。

在 viewDidLoad 、gotoNextPage  和 gotoPreviousPage 方法的最后加上这行:

[self startSpeaking];

这样,当书一打开,或者用户前后翻页的时候,朗读就会开始。

Build & run,你会听到AVSpeechSynthesizer 发出的天籁之音。

注意:如果你什么也没听到,请检查 Mac 或者 iOS 设备的音量设置(看你是在什么地方运行这个 app 的)。你可以尝试着进行翻页看是不是能播放语音。

提示:如果你是在模拟器上运行程序, 可能控制台会输出一堆莫名其妙的错误信息。这只会在模拟器上出现,使用设备时则不会打印这些错误。

如果你听到了语音播放,请再次 Build & Run。这次,在第一页内容播放完之前,尝试向左滑动(向后翻页)。发现了什么?

synthesizer 只会在第一页念完之后才开始念下一页。这不是用户想要的结果,他们会想让第一页停止播放而第二页立即开始。这点小瑕疵对于一页内容比较短的童谣来说不成问题,但试想一下,如果每页的内容都很长的话会是什么效果……

如何使用 iOS 7 的 AVSpeechSynthesizer 制作有声书(1)相关推荐

  1. 智能有声书_有声小说全套资料_SSM_PPT_演示视频

    软件需求规约 1. 简介 1.1 目的 本文档目的在于提供关于智能有声书系统的功能需求的详述以及系统性能参数的说明. 1.2 开发语言及工具 组号 06 项目名称 智能有声书 编程语言 JavaScr ...

  2. 有声书制作是什么?有声书和电子书的区别是什么?

    有声书制作是什么? 有声书制作是一种个人或多人依据文稿并借着不同的声音表情和录音格式所录制的作品,常见的有声书制作格式有录音带.CD.数位档(例如MP3). 有声书制作一词约在1980年代出现,意味着 ...

  3. 大众都在用FLBOOK平台制作有声朗读电子书

    先看一段视频: QQ录屏20230719102543 怎么样?效果是不是很nice,不仅缓解疲劳,节约用眼.节省时间,还能增添很多乐趣! 想知道怎么制作吗? 我有一个方法可以供大家见解,FLBOOK大 ...

  4. 墙裂安利!用腾讯云AI语音合成打造自己的第一本有声书

    现代生活中,我们不可避免会遇到很多碎片时间,等公交.倒地铁.排核酸.买早点等等.这些时间累积起来,无疑是一笔很大的个人资源,而想利用这部分时间,听显然是最好的方式. 国内云计算语音合成服务已经非常成熟 ...

  5. [Android] 我的听书 一款安卓听书小说软件 清新无广告 离线缓存 最好的有声书播放器

    发一个无广告的听书app,有离线缓存功能,书源还可以自行手动勾选,软件自带的书源就有几十种可供选择,另外其他一些播放高级功能也都能在设置中找到,具体大家自行测试吧, 独特功能说明(最好的有声书播放器) ...

  6. audible 有声书_如何在iPhone或iPad上购买Kindle或Audible书

    audible 有声书 If you've ever tried to buy a book from the Kindle or Audible app on your iPhone or iPad ...

  7. 为什么人们爱听有声书?

    今日导读 都说"一千个人心中就有一千个哈姆雷特",那么试问,在音频对白中听到的哈姆雷特,相比在舞台上.荧幕上看到的哈姆雷特,哪一种给你留下的印象会更深刻呢?单纯的听觉享受和多维的视 ...

  8. 百度路书 信息显示_学会用地图制作路书,分分钟从小白变成自驾游达人

    原创文章,欢迎点评! 很多想要开车自驾游的朋友,由于自己不会做行程规划和安排,或总是感觉自己做的行程规划.安排不是很精准,不能很清晰的规划出自己每天该走多远的路?途中在景点游玩的时间应该是多少?什么时 ...

  9. 不可描述⁄( ⁄•⁄ω⁄•⁄ )⁄!亚马逊用机器学习找有声书中情色片段

    安妮 编译整理 量子位 出品 | 公众号 QbitAI 醉翁之意不在酒("∇") 你得承认,有的时候看言情小说不是因为里面的情节有多赞,也不是因为它的文学价值很高,而是因为里面有一 ...

  10. 爬虫结合批量下载评书、有声书、戏曲等的使用教程

    为了教妈妈如何给姥爷下载唱戏机评书歌曲 出了一份图解教程如下 1.打开ht网.(此爬虫专用网站) 2.在网站上选择喜欢的内容记住他的id号码(下图举例)图片中id号为9774 3.以家里电脑为例,进入 ...

最新文章

  1. JAVA基础——最简单的多重循环程序
  2. 汇编中的length(返回利用dup定义的数组中的元素个数,即重复操作符dup前的count值)
  3. LVS(MASTER---NAT)
  4. http1.0 http1.1 http2 之间的区别
  5. 获取指定日期所属年份的第一天日期或最后一天日期
  6. PHP header发送各种类型文件及设置文件下载名
  7. linux下 java 压缩文件夹,java压缩文件夹linux下乱码问题
  8. 天天都在用的 Nginx,可你知道如何用一个反向代理实现多个不同类型的后端网站访问吗?...
  9. activiti工作流简介
  10. java输入、输出流的简单入门
  11. python如何调用dll库中的函数_Python调用DLL动态库函数读写CPU卡
  12. python 面试真题
  13. 2020 年 9 月程序员平均工资 14469 元,你拖后腿了没?
  14. openGauss社区成立QA SIG
  15. ZZM区块链全球区块文化娱乐相结合的新型网站源码
  16. 群晖NAS中对Gitlab配置邮箱发送消息_以163邮箱为例
  17. leetcode 714. 买卖股票的时机含手续费 python
  18. 数学建模-数学规划模型
  19. Linux虚拟机添加快照,Linux系统下kvm虚拟化(六)创建快照、恢复快照和删除快照...
  20. 去除word转pdf时的图片黑边

热门文章

  1. 五.java入门【循环语句】
  2. portraiture2022插件安装使用教程
  3. 【MATLAB】数值运算 ( 数值运算示例 | 三角函数 | 指数运算 | 对数运算 | 常用的数学公式对应函数 )
  4. 程序员为什么单身?细数程序员“六宗罪”
  5. 『IT视界』 [原创评论]揪出"程序员"身上的"六宗罪"
  6. 转:echarts图表x,y轴的设置
  7. OSChina 周一乱弹 —— 这片城市都会属于你,而你属于我
  8. 【.Net码农】ListT 类
  9. 计算机教室如何防火,校园防火及火灾逃生自救安全常识
  10. 数据结构与算法课设:基于交通路线的规划系统