最近在学习《AVFoundation开发秘籍》这本书,以前没有怎么接触过,学习之后瞬间感觉AVFoundation这个框架好强大,值得深入的学习。写点笔记以加强记忆和备忘。
AVFoundation入门 文本转语音 播放和录制音频音频会话分类 配置音频会话使用AVAudioPlayer播放音频 创建AVAudioPlayer对播放的控制音频中断的处理线路改变的影响使用AVAudioRecorder录制音频音频测量 资源和元数据 异步载入媒体元数据使用元数据查找元数据使用AVMetadataItemAVAssetExportSessionAVFoundation内置了文本到语音的转换功能,主要类是AVSpeechSynthesizer和AVSpeechUtterance,粗略的实现代码如下所示:
主要属性说明如下: 1. voice:指定在朗读时使用的声音 2. rate:指定在朗读时的语速,介于AVSpeechUtteranceMinimumSpeechRate 和 AVSpeechUtteranceMaximumSpeechRate之间 3. pitchMutiplier:指定朗读时的音调,一般介于0.5(低音调)和2.0(高音调)之间。 4. postUtteranceDelay:指定语音合成器在播放下一句之间的间隔,类似的可以设置preUtteranceDelay 5. volume:指定在朗读时的音量,介于0.0和1.0之间
AVFoundation定义了7种分类来描述应用程序所使用的音频行为,如下表所示:
分类作用是否允许混音音频输入音频输出Ambient游戏、效率应用程序✔︎✔︎Solo Ambient(默认)游戏、效率应用程序✔︎Playback音频和视频播放可选✔︎Record录音、音频捕捉✔︎Play and RecordVoIP、语音聊天可选✔︎✔︎Audio Processing 离线会话和处理Multi-Route使用外部硬件的高级A/V应用程序✔︎✔︎AVAudioSession提供了与应用程序音频会话交互的接口,所以开发者需要取得指向该单例的指针,通过设置合适的分类,开发者可为音频的播放指定需要的音频会话,其中定制一些行为,最后告知该音频会话激活该配置,通常只配置一次,最佳位置就是AppDelegate中的application:didFinishLaunchingWithOptions: 方法,如下所示:
有两种方法创建AVAudioPlayer,包括使用要播放音频的内存版本的NSData和本地音频文件的NSURL。在播放时最好先调用prepareToPlay方法,可降低听到声音输出之间的延时。
AVAudioPlayer包含了所有开发者期望对播放进行控制的方法,如播放play,暂停pause,停止stop,除此之外,还能设置其他一些值,如: 1. volume:修改播放器的音量,介于0.0到1.0之间 2. pan:允许使用立体声播放,介于-1.0(极左)到1.0(极右)之间,默认0.0(居中) 3. rate:调整播放器的播放速率,介于0.5(半速)到2.0(2倍速)之间 4. numberofLoops:实现音频的无缝循环,设置一个大于0的数,则播放器会循环n次,设置-1则实现无限循环
在准备为出现的中断事件采取动作前,首先需要得到中断出现的通知,注册应用程序的AVAudioSession发送的通知AVAudioSessionInterruptionNotification。
在NSNotification的userInfo中,首先通过AVAudioSessionInterruptionTypeKey的值来确定中断类型,包括AVAudioSessionInterruptionTypeBegan(中断开始) 、AVAudioSessionInterruptionTypeEnded(中断结束),当中断类型为结速时,userInfo中会包含一个AVAudioSessionInterruptionOptions值来表明音频会话是否已重新激活以及是否可以再次播放。
线路改变时,如插拔耳机时将会收到AVAudioSessionRouteChangeNotification通知,此时userInfo中会包含一个AVAudioSessionRouteChangeResonKey值,用于表示变化原因。不过需要特别注意耳机断开事件的原因为AVAudioSessionRouteChangeReasonOldDeviceUnavaliable。当有设备断开后,需要向userInfo字典提出请求,以获得其中用于描述前一个线路的AVAudioSessionRouteDescription的数组,其元素为AVAudioSessionPortDescription的实例,用于描述不同的I/O接口属性,开发者需要从中找到第一个输出接口并判断是否为耳机接口并进行处理,代码如下:
创建AVAudioRecorder实例时需要提供以下信息 1. 用于表示音频流写入文件的本地URL 2. 包含用于配置录音会话键值信息的NSDictionary 3. 用于捕捉初始化阶段各种错误的NSError
具体的初始化代码如下:
在录音时需要将AVAudioSession的分类设置为AVAudioSessionCategoryPlayAndRecord,在准备录音之前,同样的,应先调用prepareToRecord方法。
Audio Metering可让开发者读取音频的平均分贝和峰值分贝数据,并使用这些数据以可视化方式将声音的大小呈现给用户。使用方法averagePowerForChannel:和peakPowerForChannel: 均返回一个用于表示声音分贝等级的浮点值,介于0db到-160db之间。使用该功能之前,需先设置meteringEnabled属性为YES。每当需要读取值时,首先需要调用updateMeters方法才能获取最新的值。
AVFoundation中最重要的类就是AVAsset,它是一个抽象类,定义了媒体资源混合呈现的方式,将媒体资源的静态属性模块化成一个整体,它不能直接实例化,使用时应该调用assetWithURL:方法,该方法实际上是创建了一个子类AVURLAsset。
AVAsset具有多种有用的方法和属性,可提供相关资源的信息,如时长、创建日期以及元数据等等。AVAsset采用了AVAsynchronousKeyValueLoading协议,通过如下方法可实现异步载入载
-(AVKeyValueStatus)statusOfValueForKey:(NSString*)key error:(NSError**)outError; -(void)loadValuesAsynchronouslyForKeys:(NSArray*)keys completionHandler:(void(^)(void))handler;第一个方法用于查询一个给定属性的状态,若状态返回不是AVKeyValueStatusLoaded,意味着此时请求该属性可能导致程序卡顿。代码的一般写法如下所示:
请参考《AVFoundation 开发秘籍》第三章
媒体的元数据由AVMetadataItem类提供,AVAsset提供两种方法获取相关元数据,AVFoundation使用键空间作为将相关键组合在一起的方法,可以实现对AVMetadataItem集合的筛选。每个资源至少包含两个键空间。
Common键空间(AVMetadataKeySpaceCommon)用来定义所有支持的媒体类型的键,包括如曲名、歌手及插图信息等常见元素。还包含一个可以通过查询资源或曲目的commonMetadata属性,返回一个包含所有可用元数据的数组。
当我们得到一个包含元素数据项的数组时,通常希望找到所需的具体元数据值。一个特别有效的做法是使用AVMetadataItem提供的便利方法。来获取结果集并对其筛选。通用代码如下所示:
AVMetadataItem最基本的形式其实是一个封装键值对的封装器,可通过它查询key或commonKey,查询其是否存在于Common空间中。但最重要的是其value,定义为id
AVAssetExportSessione用于将AVAsset内容根据导出的预设条件进行转码,并将导出的资源写入到磁盘中。创建一个实例需要提供资源和导出预设,用于确定导出内容的质量、大小等属性。创建后,需指定outputURL输出地址,outputFileTypen导出格式,最后调用exportAsynchronouslyWithCompletionHandler:方法开始导出。通用代码如下:
