畅谈<您的iOS应用>。Yandex报告

iOS中的语音识别和文本转语音的标准库提供了许多可能性。从报告中沃尔科夫·罗马您将学习如何教您的应用程序以最少的代码发音文本并自定义语音行为。Roma回顾了语音识别API,其局限性和功能,识别请求的生命周期以及离线模式下的工作方法。UX示例,现有错误的解决方法以及使用音频会话的功能正在等待您的光临。





-大家好,我叫Roman Volkov。今天,我们将讨论如何教您的移动应用程序与用户进行通信。



在开始之前,请简要介绍一下我。在开发iOS之前,我曾参与银行业集成系统的开发和石油业分析系统的开发。我直接了解PCI DSS标准是什么,例如,工程师如何仅根据温度数据了解钻井过程中井中发生的情况。



自2016年以来,我一直在进行iOS开发。我既有自由职业者的经验,也有远程工作的经验,有参与多家初创公司启动的经验。我还为劳斯莱斯(Rolls Royce)做了品牌申请。



在2018年,我加入了Prisma团队,开发了Prisma应用程序,并参与了Lensa Photo Editor的开发和发布。在2019年,我移居到Yandex作为iOS开发人员。自2020年以来,我一直领导Yandex.Translator移动开发小组。翻译器应用程序不再仅仅是用于处理文本的应用程序。我们有很多很酷的功能,例如照片翻译,对话模式,语音输入,语音代理等等。



刚开始深入探讨在iOS中使用声音的主题时,我没有发现任何紧凑的资料可以包括处理音频会话,合成,语音识别。这就是为什么我决定进行这次演讲。







它将分为四个部分。首先,我们将讨论什么是音频会话,如何正确使用它,以及它如何影响应用程序的操作。接下来,让我们继续进行语音合成。让我们考虑一下如何在电话上以几行代码向他人语音文本。接下来,我们将切换到语音识别。最后,让我们看看如何在离线模式下向用户提供所有这些功能以及它具有什么功能。







使用语音代理和语音识别有很多选择。我最喜欢的是将其他人的音频消息转换为文本。我很高兴,例如,Yandex。Messenger团队提供了这样的功能。希望其他使者也能赶上家做。



我们正在顺利进行报告的第一部分,即AVAudioSession。







音频会话是我们的应用程序和操作系统之间的一层。更确切地说,在您的应用程序和用于处理声音的硬件之间:扬声器和麦克风。在iOS,watchOS和tvOS上,每个应用程序都有一个预先配置的默认音频会话。此预设因一个操作系统而异。



专门讲iOS,默认情况下,音频会话支持音频播放,但禁止任何录音。如果将静音模式的开关设置为“静音”模式,则应用程序内的所有声音绝对会被静音。第三,锁定设备会阻止应用程序内的所有声音播放。







设置音频会话包括三点:这是类别,模式和其他选项的选择。我们将分别研究每个要点。



让我们从类别开始。类别是音频会话基本行为的一组设置。类别是一组参数,这些参数允许操作系统尽可能地匹配该类别的名称。因此,Apple建议为您的应用程序选择一个尽可能接近可用类别的类别。 iOS 13当前提供六个类别。还有第七类,但已被标记为已弃用,不应使用。



在本演讲中,我们将研究三个类别:回放,记录和playAndRecord。此模式允许您补充设置类别的功能,因为某些模式仅适用于某些类别。







例如,在幻灯片上您会看到moviePlayback模式,并且只能将其设置为Playback类别。



设置moviePlayback模式可以使音频会话自动提高内置扬声器和耳机的播放音质。在本次演讲中,我们将仅使用“默认”模式。但我想指出的是,如果您使用不兼容的类别和模式对,则将使用默认模式。







第三个是选项,音频会话的指向设置。例如,您可以自定义应用程序中的音频与其他应用程序中的音频混合的方式,设置正确停用音频会话,以便其他应用程序可以知道您的应用程序已完成音频的使用。







首先,我们来看一下设置播放类别,即播放。这是仅音频类别之一。如果已设置,则音频会话的激活会中断其他播放音频,例如来自其他应用程序的音频。



即使将静音开关设置为静音,音频也将播放也很重要。



该类别还有一个在后台状态播放的选项,但是为此,您的应用程序必须启用“音频”,“ AirPlay”和“画中画”功能。



考虑幻灯片上可见的两个选项。第一个是mixWithOthers。如果使用此选项激活音频会话,则应用程序内部的声音播放将与当前播放的声音(例如音乐)以一个音量级别混合。但是,如果您希望声音在音量上胜过当前播放,则可以使用duckOthers选项。它可以降低在后台播放的声音的音量,并在应用程序内部的声音播放完毕后将其返回。



例如,可以在导航应用程序中观察到这一点:对于路线公告,您正在收听的内容将被静音,播放公告,然后所有内容返回其原始状态。







让我们考虑设置音频会话以从麦克风识别的选项。在应用程序中与此类别的音频会话处于活动状态时,“记录”类别会使所有正在播放的音频静音。录音无法使系统声音(例如呼叫,警报)静音-通常,优先级较高的标准声音。



您还可以添加选项allowBluetoothA2DP,这使您可以使用AirPods之类的耳机来记录来自麦克风的声音并在其中播放声音。对此有一个较旧的选项,听起来就像allowBluetooth,但会大大降低声音质量。



我们曾经使用旧的选项,并且用户抱怨他们对应用程序内播放和录制的声音的质量不满意。我们更改了选项,一切都变得更好了。



如果要同时使用语音识别和语音合成,请使用playAndRecord类别。然后,在激活的音频会话中,您可以使用声音的录制和回放。



notifyOthersOnDeactivation选项应单独考虑。在激活音频会话的方法中使用它。为什么这么重要?







如果使用此选项停用了音频会话,则其他应用程序将接收带有AVAudioSessionInterruptionTypeEnded参数的AVAudioSessionInterruptionNotification标识,该参数的音频会话中断已结束,并且他们可以继续使用音频,该音频在被中断之前就已开始。



如果您在不带mixWithOthers选项的应用程序中使用播放类别,则可能出现这种情况,因为否则您将不会中断另一个应用程序的声音,您的音频将仅与另一个应用程序混合。



使用此选项并正确处理修改,可以使您在使用应用程序时为用户提供舒适的用户体验。







在幻灯片上,您可以看到一个示例,该示例说明如何正确处理有关您的应用程序在音频会话中被另一个应用程序中断的通知,以及中断结束时的情况。也就是说,我们订阅某种通知,并且可能订阅两种通知:中断刚开始时和中断结束时。



在第一种情况下,您可以保存状态,在第二种情况下,您可以继续播放被另一个应用程序打断的声音。



这是一个可能如何工作的示例:



该视频将从该示例显示的那一刻开始播放,



在此示例中,音乐是在另一个应用程序(即VLC)中播放的,然后我开始在我们的应用程序中播放声音。音乐被打断,正在播放合成语音,然后音乐自动恢复播放。



我想指出的是,并不是所有的应用程序在声音中断时都能正确处理这种情况。例如,某些流行的即时通讯工具无法恢复音频播放。







让我们总结一下。我们已经分析了音频会话的原理。我们研究了根据您的应用程序要求配置音频会话的可能性,并学习了如何方便地为用户激活和停用音频会话。



继续。语音合成。







幻灯片显示了语音合成过程中涉及的类的图。主要类别为AVSpeechSynthesiser,AVSpeechUtterance和AVSpeechSynthesisVoice及其设置。



另外,我注意到有一个AVSpeechSynthesizerDelegate,它使您可以接收有关整个请求生命周期的通知。由于文本的声音正在播放声音,因此前面讨论的AVAudioSession在这里将是隐式的依赖项。



您可以在不设置音频会话的情况下请求识别,但是对于任何生产应用程序,了解如何设置它都是很重要的。我们之前谈到了这一点。







如何快速发出语音合成请求的最简短示例。您需要创建AVSpeechUtterance类的对象,在其中指定要说的文本,所需的语音和语言。如果在创建语音时未指定语言区域设置,则将使用手机的默认区域设置。但是在下一张幻灯片中,我们将讨论声音的选择以及如何使用它们。



接下来,创建AVSpeechSynthesizer类的对象,并调用语音方法。所有。之后,文本将被合成并播放,您将听到结果。



但是实际上,这仅仅是开始。语音合成还有更多的可能性,我们现在将讨论。







首先,您可以设置接收声音时的速度。速度被指定为从零到一的实数。如果将rate属性设置为0到0.5,则实际比率从零到一。



如果将速率值设置在0.5到1的范围内,则速率会从1X到4X的值成比例地变化。



有关如何快速工作的示例。







在AVFoundation中,有一个常数AVSpeechUtteranceDefault,实际上是0.5,它等于音频播放的正常速度。



您还可以将速度指定为通常速度的一半,您需要将值指定为0.25。如果指定0.75,则速度将增加为正常速度的2.5倍。另外,为方便起见,还有用于最小速度和最大速度的常数。



我现在将播放一些示例:



该视频将从示例显示之时开始播放,



这是Macintosh在Apple演示文稿中首次以自己的声音讲话的示例。这就是正常的合成语音速度的一个例子。





这慢了2倍。





这快了2.5倍。



在最后几行中,我分别显示了preUtteranceDelay和postUtteranceDelay属性。这是声音开始播放之前的延迟,是声音播放完成之后的延迟。当您将您的应用程序与其他应用程序的声音混合在一起并希望音量降低一段时间后又失去效果时,使用起来很方便。然后他们等待了更多时间,直到此后另一个应用程序中的卷恢复到其原始位置。







让我们看看下一个参数-语音选择。用于语音合成的语音主要按地区,语言和质量划分。 AVFoundation提供了几种创建或获取AVSpeechSynthesisVoice对象的方法。首先是通过语音ID。每个语音都有其自己的唯一ID,可以通过访问SpeechVoice静态属性找到所有可用语音的列表。获得此属性具有一些特殊性,我们将进一步讨论它们。



值得注意的是,如果将无效标识符传递给构造函数,则构造函数将返回“ no”。



第二种选择是通过语言或区域代码来获取它。我还想指出,苹果公司说Siri声音不可用,但这不是完全正确的:我们设法获得了某些设备上Siri中使用的某些声音的ID。也许这是一个错误。



声音具有两种品质-默认和改进。对于某些声音,您可以下载改进的版本,我们将在最后一部分中讨论此问题,我们将讨论如何下载必要的声音。







如何选择特定声音的示例。第一种方式-通过特定的标识符,第二种-通过指示语言代码的行,第三种-通过特定的语言环境。



现在,我想播放两个用不同语言环境配音相同文本的示例。



该视频将在演示示例的那一刻开始播放,在



我看来,第二个选项更接近俄语发音。







性别也出现在iOS 13中。而且此属性仅在iOS 13及更高版本上可用,仅适用于在iOS 13中添加的声音。因此,“性别”设置为枚举,具有三个属性:“女”,“男”和“未指定”。



在我们的应用程序中,您可以选择文本的语音性别。对于旧的声音,我们自己列出了一份清单,并将其保留在我们的应用程序中。对于系统返回“未指定”的语音,将我们认为是男性的语音和女性的语音分开。







在iOS 13.1中,投票列表可能会在第一次调用时返回一个空列表。解决方案:您可以在一定秒数内一次重新查询整个列表。只要它回来不是空的,我们相信我们终于收到了最新的选票清单。



此错误已在后续的iOS版本中修复,但是如果您在应用程序中看到此错误,请不要感到惊讶。



我在研究文档时遇到了一个有趣的观点:有一个静态属性AVSpeechSynthesisVoiceAlexIdentifier。这是一个非常有趣的标识符,因为首先,并非所有设备都可以使用该标识符创建语音。第二,我不清楚为什么要分开放置。第三,如果您确实收到带有此标识符的语音,则该语音具有唯一且不同的类别。



同时,对框架头的研究并没有给我带来任何有用和有趣的东西。如果您知道有关此标识符的任何信息-为什么需要它,为什么它出现,请告诉我。我无法找到该问题的答案。







在这里,您可以看到一个示例,该示例说明了我们如何在界面中根据区域设置,性别来选择语音,以及如何赋予指定特定语言的语音速度的能力。







我将简要讨论基于拉丁语的转录记录符号系统。当您为语音表演提供文本时,可以在其中指定特定单词的发音。在iOS上,这是通过带有特殊键的NSAttributedString完成的。此发音的生成可直接在iOS设备的“辅助功能”部分中找到。但是对于大量用户而言,这似乎非常不便,您可以通过其他方式自动生成语音转录。



例如,这是一个英语,其中有大量的单词相关性和发音词典。







幻灯片显示了一个示例,该示例说明了如何用一种语言环境替换特定单词的发音。在这种情况下,是番茄| təˈmɑːtəʊ |。



该视频将从显示示例的那一刻开始播放,



现在已播放了将属性设置为“发音”和“不带”的选项。







总的来说,我们研究了创建语音合成请求的方法。学会用声音工作。我们研究了一种可能会遇到的错误的变通办法,并研究了语音转录以及如何使用它。







让我们继续进行语音识别。它以称为语音的框架的形式在iOS中呈现,并且可以在您的设备上直接进行语音识别。



从iOS 10开始支持大约50种语言和方言。语音识别通常需要互联网连接。但是对于某些设备和某些语言,识别可以脱机工作。我们将在我的演讲的第四部分中讨论这一点。



语音识别可从麦克风和音频文件获得。如果要使用户能够识别来自麦克风的语音,则用户必须授予两个权限的权限。第一个用于访问麦克风,第二个用于将他的语音传输到Apple服务器进行识别的事实。



不幸的是,在只能使用脱机识别的地方,不可能不请求此权限。无论如何都必须要求它。







该列表取自Apple网站。这些是可用于语音识别的语言和语言环境。但是实际上,这是标准键盘上可用于听写的语言和语言区域列表。引擎盖下的语音框架API指的是来自标准键盘的命令执行。







语音识别对于我们作为开发人员来说是免费的,但是有使用限制。第一个是每天的设备和请求的限制。第二个是应用程序的总限制。第三-您最多可以识别一分钟。唯一的例外是离线模式。您可以在其中识别长时间录制的音频消息。



苹果当然不会说出限制的具体数字,而且正如WWDC报告中写或说的那样,如果您经常遇到这些限制,您需要做好处理错误并写信给他们的准备。但是我们没有这样的问题。对于俄语,我们将SpeechKit用作语音识别引擎。而且我们的大多数用户都是说俄语的,因此我们没有遇到限制。



另外,请务必考虑隐私问题。不允许声音作用于数据-密码,信用卡数据。任何敏感或私人信息都不应被识别。







在幻灯片上,您可以看到语音识别过程中涉及的类的条件图。与合成类似,识别工作与音频熨斗一起工作,因此在这里,AVAudioSession也是一个显式依赖项。







支持。要获取一组所有受支持的语言环境,您需要访问supportedLocales页面属性。对特定语言环境的支持通常不能保证语音识别可用于该语言环境。例如,可能需要与Apple服务器的持久连接。



识别的语言环境支持与iOS键盘上的听写语言环境列表匹配。这是完整列表。为了确保可以立即处理给定的语言环境,可以使用isAvailable属性。







在iOS上的语音识别中,与合成不同,每种语言没有语言环境优先级。因此,如果我们从所有语言环境列表中选取特定语言的第一个语言环境,则可能是某些语言不是最受欢迎的语言环境。因此,对于Translator中的某些语言,我们为特定语言设置了特定语言环境的优先级。



例如,对于英语,我们使用en-US。用户首次尝试识别英语时,我们使用美国语言环境。







来自文件的识别请求。这里的一切都很简单。您需要获取并链接到文件,创建一个SFSpeechRecognizer对象,该对象指示您要使用的语言环境。检查当前是否可以识别。使用传递文件路径的结构创建SFSpeechURLRecognitionRequest。并开始识别任务。



结果,您将收到识别错误或结果。结果具有isFinal属性,这意味着该结果是最终的,可以进一步使用。







这是一个稍微复杂的示例-要求麦克风进行识别。为此,我们还需要一个AVAudioEngine对象,该对象负责处理麦克风。我们不会详细介绍其工作原理。您可以设置所需的类别-.record或.playRecord。打开音频会话。配置AudioEngine并订阅以从麦克风接收音频缓冲区。将它们添加到识别请求中,识别完成后即可退出麦克风。



值得注意的是,负责发布临时识别结果的shouldReportPartialResults属性设置为true。让我们看一下这些选项:带有和不带有shouldReportPartialResults标志的应用程序的外观。



该视频将从演示示例的那一刻开始播放



。在左侧的示例中,我离开了麦克风对声音的响应,直到改变音量。可以看出我在说些什么。但是直到我说完,您什么都看不到。用户花费很长时间才能得到他所指示的结果。



如果将shouldReportPartialResults设置为true并正确处理,那么用户将在讲话时看到他在说什么。这非常方便,这是执行听写操作的正确方法。







这是我们如何通过音频会话处理工作的示例。在Translator内部,我们不仅使用所编写的声音,还使用其他可以对音频会话进行处理的框架。



我们编写了一个控制器,首先,检查设置和类别是否是我们所需的设置;其次,它不会做会不断打开和关闭音频会话的事情。



甚至在开发对话模式之前,语音输入和语音代理就已经在自己打开和关闭音频会话。当我们开始使用对话模式时,事实证明,这些开-关模式会在您说出声音和发出声音之间增加额外的延迟。







对于语音识别请求,您可以指定提示-要识别的语音类型。它可以是未指定的,可以是听写,搜索或简短确认。通常,如果您的用户要说很长的话,最好使用听写。







从iOS 13开始,我们可以使用音频分析。幻灯片显示了通过识别语音可以获取的参数。也就是说,您不仅会收到用户所说的内容,而且还会收到他所说的声音。







我们将不再对此进行详细介绍。这是一个示例,说明如何通过识别的文本进行分析。







总体而言,我们研究了语音框架用于语音识别的功能,学习了如何为语音识别提供提示,并快速查看了分析功能。



最后但并非最不重要的一点:离线工作。我想谈的第一件事是用于语音合成的离线语言列表。在文档中没有任何地方提到如何显式下载语音以供脱机工作。报告和文档都说这些声音可以下载,但不能写在这里。



我搜索了系统,发现如果转到``设置'',``辅助功能''部分,然后是``口头内容''和``语音'',则首先将看到可用的语言列表。其次,通过切换到特定语言,您可以下载新的声音。



并且此列表明确匹配AVSpeechSynthesisVoice.speechVoices在应用程序内部返回的内容。这意味着您可以告诉您的用户他们可以下载他们需要离线使用文本到语音转换的语言。







用于识别的离线语言列表。在文档的任何地方都没有明确指出,但是根据不同的论坛和我们所遇到的情况来判断,这是他们可以脱机工作而无需访问Internet的语言和语言环境的列表。



应当注意,具有A9或更早版本的设备可以使用离线识别。







有趣的来了。用于语音识别的离线语言列表。与综合不同,通常没有办法为自己明确下载语言。如果将语言添加到标准键盘,则可以为其下载脱机软件包。不幸的是,这不是确定性的。让我们转到“设置”>“通用”>“键盘”>“听写”。例如,我添加了西班牙语。之后,在“听写”下会出现一个小提示,表明这些语言可能适用听写。西班牙语出现在那里。



然后,我转到了我们的应用程序,关闭了Internet,令我感到高兴的是,使用西班牙语进行了脱机识别。



不幸的是,这只能间接地受到影响,唯一的方法是将语言添加到标准键盘中。但这不能保证将下载脱机识别包。







在iOS上,即使可以使用手机,即使您可以在手机上访问Internet,也可以为设备供电并执行语音识别。



有一个supportOnDeviceRecognition属性,自iOS 13起可用。但是此属性无法正常工作,我在右下方显示了错误的屏幕截图。该错误仅在13.2中修复。该属性始终在第一个请求上返回false。根据Apple的说法,几秒钟后它将返回正确的值。



此外,此属性可以设置为false,但同时将requireOnDeviceRecognition标志设置为true可以成功进行。这意味着即使该测试标志返回false,识别也可以在设备上完全起作用。



这里可能有几种解决方案。首先,您只能在iOS 13.2上进行离线识别。其次,您可以选择一定的秒数来重新请求此属性并更新用户界面。第三,您可以忘记此属性:尝试离线识别语音,如果出现错误,只需将其显示给用户即可。







我们研究了如何显式下载脱机语音合成程序包,并找到了一种方法来尝试强制iOS下载脱机语音识别程序包。



现在您知道了如何快速将语音合成和识别添加到您的应用程序。我有一切,谢谢您的关注。



All Articles