《AV Foundation 开发秘籍》读书笔记

本文章是小编阅读这本书的一些摘录和笔记
希望自己能尽快读完,持续更新吧

第1章 AV Foundation 入门

1.1 AV Foundation 的含义

  • 高度依赖多线程机制
  • 充分利用多核硬件优势并大量使用block和Grand Central Dispatch(GCD)机制将复杂的计算进程放在后台线程运行。

1.2 AV Foundation 的适用范围

  1. Core Audio 推荐阅读《Leaning Core Audio》
  2. Core Video 数字视频所提供的管道模式,为相对的Core Media提供图片缓存和缓存池支持
  3. Core Media 低层级媒体管道的一部分,提供针对音频样本是视频帧处理所需的低层级数据类型和接口
  4. Core Animation 在视频编辑和播放过程中添加动画标题和图片效果

1.3 解析 AV Foundation

  1. 音频播放(AVAudioPlayer)和记录(AVAudioRecorder)
  2. 媒体文件检查:获取媒体资源技术参数,基于AVMetadataItem提供源数据支持
  3. 视频播放:本地或远程流,核心类AVPlayer和AVPlayerItem
  4. 媒体捕捉:摄像头捕捉核心类AVCaptureSession
  5. 媒体编辑:音视频组合、修改编辑媒体片段、修改音频参数、添加动画标题、场景切换效果
  6. 媒体处理:直接访问视频帧和音频样本(AVAssetReader和AVAssetWriter)

1.4 了解数字媒体

  • 音视频模拟信号 -> 大脑电信号
  • 模拟信号 -> 数字信号 (采样Sampling)

1.4.1 数字媒体采样

  • 时间采样:捕捉一个信号周期内的变化
  • 空间采样:可视化媒体

1.4.2 音频采样介绍

  • 频率:震动的速率或频率决定了声音的音调
  • 振幅:用来测量频率的相对强度,大致表示声音的音量
  • 电动式麦克风(dynamic microphone):膜片感受到声音震动,带动线圈震动,产生同输入信号相同振幅和频率的电流信号
  • 人类可接收到的音频范围:20Hz~20kHz
  • 线型脉冲编码调制(linear pulse-code modulation,Linear PCM, LPCM):这个过程采样或测量一个固定的音频信号,过程的周期率被称为采样率。
  • 未压缩视频存储需求举例:24位RGB色彩(R、G、B各占8位),分辨率1280×720,帧率30FPS,那么存储需求为79MB/s

1.5 数字媒体压缩

1.5.1 色彩二次抽样

  • YUV(Y-Prime-C-B-C-R)(Y'CbCr'):适用色彩(颜色)通道UV替换了像素的亮度通道Y。如果除去亮度,剩下的就是一幅灰度图片。因此如果大幅减少存储在每个像素中的颜色信息,而不至于图片的质量受损,这个减少颜色数据的过程就成为色彩二次抽样。
  • jab:这个比较难理解

1.5.2 编解码器压缩

1.5.3 视频编解码器

  1. H.264:规范是MPEG(Motion Picture Experts Group)所定义的MPEG-4的一部分。多用于消费者视频摄像头捕捉到的资源。通过帧内压缩和帧间压缩缩小视频文件的尺寸。
  2. Apple ProRes:是有损编解码器,只在OS X上可用。
  3. 此外AV Foundation还支持MPEG-1、MPEG-2、MPEG-4、H.263和DV等多种不同的视频捕捉设备的编解码器。

1.5.4 音频编解码器

  1. 高级音频编码(ACC):是H.264标准相应的音频处理方式。可在低比特率低前提下提供更高质量的音频。

1.6 容器格式

通常的文件后缀应被认为是文件的容器格式(containerformat),也是元文件格式,容器格式包含一种或更多种媒体类型的目录。

  1. QuickTime:
  2. MPEG-4:

1.7 初识 AV Foundation

使用AVSpeechSynthesizerAVSpeechUtterance实现文本语音播放

第2章 播放和录制音频

2.1 Mac和iOS的音频环境

  • 可管理的音频环境(managed audio environment)
  • 音频会话(audio session)

2.2 理解音频会话

2.2.1 音频会话分类

AV Foundation 定义了7种分类来描述应用程序所使用的音频行为:

分类 作用 是否允许混音 音频输入 音频输出
Ambient 游戏、效率应用
Solo Ambient(默认) 游戏、效率应用
Playback 音频和视频播放器 可选
Record 录音机、音频捕捉
Play and Record VoIP、语音聊天 可选
Audio Processing 离线会话和处理
Multi_Route 使用外部硬件的高级 A/V 应用程序

2.2.2 配置音频会话

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // 应用程序音频会话
    AVAudioSession *session = [AVAudioSession sharedInstance]; // 单例
    NSError *error;
    
    // 设置分类
    BOOL categoryPlayback = [session setCategory:AVAudioSessionCategoryPlayback error:&error];
    if (!categoryPlayback) {
        
    }
    
    // 最后告知音频会话激活配置
    BOOL isActive = [session setActive:YES error:&error];
    if (!isActive) {
        
    }

    return YES;
}

2.3 使用 AVAudioPlayer 播放音频

AVAudioPlayer类的实例提供了一种简单地从文本或内存中播放音频的方法。
AUAudioPlayer构建于Core Audio中的C-based Audio Queue Services的最顶层。

2.3.1 创建 AVAudioPlayer

有两种方法可以创建一个AudioPlayer,使用包含要播放音频的内存版本的NSData,或本地音频文件的NSURL

// 通过本地音频的URL创建
NSURL *audioURL = [[NSBundle mainBundle] URLForResource:@"Sheep" withExtension:@"mp3"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];

// 如果返回一个有效的播放实例,建议开发者调用其prepareToPlay方法,
// 这样做会取得需要的音频硬件并预加载Audio Queue的缓冲区
// 调用prepareToPlay这个动作是可选的,当调用play方法时会隐形激活,不过在创建时准备播放器可以降低调用play方法和听到声音输出之间的延时
if (audioPlayer) {
    [audioPlayer prepareToPlay];
}

// 播放音频
[audioPlayer play];

2.3.3 对播放进行控制

pause和stop方法对异同点:

  • 相同:都可以暂停/停止当前播放的音频,下一时间调用play方法,音频都会继续播放;
  • 不同:这两个方法最主要的却别在底层处理上。调用stop方法会撤销调用prepareToPlay时所做的设置,而调用pause方法则不会。

2.4 创建 Audio Looper

音频混合/混音
实例:(略)

2.5 配置音频会话

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    // 音频会话设置
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *error;
    
    // 设置分类 后台播放(还需要在info.plist处添加Required background modes,并添加一项App plays audio or streams audio/video using airplay)
    if (![audioSession setCategory:AVAudioSessionCategoryPlayback error:&error]) {
        MYLog(@"音频会话分类设置错误:%@", [error localizedDescription]);
    }
    
    // 激活音频会话
    if (![audioSession setActive:YES error:&error]) {
        MYLog(@"音频会话激活失败:%@", [error localizedDescription]);
    }
    return YES;
}

2.6 处理中断事件

在控制器初始化时注册通知

// 注册中断通知
NSNotificationCenter *notif = [NSNotificationCenter defaultCenter];
[notif addObserver:self
          selector:@selector(handleInterruption:)
              name:AVAudioSessionInterruptionNotification
            object:[AVAudioSession sharedInstance]];

注册了通知中心一定要记得在销毁时移除

- (void)dealloc {
    
    // 移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

处理中断通知事件

#pragma mark - 处理中断通知
// 注意这里的参数不是NSNotificationCenter,而是推送过来的NSNotification
- (void)handleInterruption:(NSNotification *)notification {
    
    NSDictionary *info = notification.userInfo;
    
    // 中断类型(枚举)
    AVAudioSessionInterruptionType interruptionType = [[info objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    switch (interruptionType) {
        case AVAudioSessionInterruptionTypeBegan: // 中断开始
        {
            [self stop]; // 调用stop方法并不能停止播放,只能更新内部状态
            if (self.delegate) {
                [self.delegate playbackStoped];
            }
        }
            break;
        case AVAudioSessionInterruptionTypeEnded: // 中断结束
        {
            // 中断结束后,恢复音乐播放
            // 音频会话是否已经重新激活、是否可以再次播放(只有中断结束才有这个options)
            AVAudioSessionInterruptionOptions options = [[info objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
            if (options == AVAudioSessionInterruptionOptionShouldResume) {
                [self play];
                if (self.delegate) {
                    [self.delegate playbackBegan];
                }
            }
        }
            break;
        default:
            break;
    }
}

因为控制器参与处理页面,所以写个协议,设置委托来进行更新界面

@protocol THPlayerControllerDelegate 

- (void)playbackStoped;
- (void)playbackBegan;

@end

2.7 对线路改变的响应

iOS设备上添加或移除音频输入、输出线路时,会发生线路改变。有多重原因会导致线路的变化,比如用户插入耳机或断开USB麦克风。当这些事件发生时,音频会根据情况改变输入或输出线路,同时AVAudioSession会广播一个描述该变化的通知给所有相关的侦听器。为了遵循Apple的Human Interface Guidelines(HIG)的相关定义,应用程序应该成为这些相关侦听器中的一员。

注册线路变化通知

// 注册线路通知
[notif addObserver:self
          selector:@selector(handleRouteChange:)
              name:AVAudioSessionRouteChangeNotification
            object:[AVAudioSession sharedInstance]];

线路改变通知事件处理(耳机断开后停止播放)

// 线路改变通知事件处理
- (void)handleRouteChange:(NSNotification *)notification {
    
    NSDictionary *info = notification.userInfo;
    
    // 线路改变原因
    AVAudioSessionRouteChangeReason reason = [[info objectForKey:AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
    
    switch (reason) {
        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: // 旧线路不能使用
        {
            // 前一个线路的描述
            AVAudioSessionRouteDescription *previousRoute = [info objectForKey:AVAudioSessionRouteChangePreviousRouteKey];
            // 线路描述信息 输出信息
            AVAudioSessionPortDescription *previousOutput = [previousRoute.outputs firstObject];
            // (输出)类型
            NSString *portType = previousOutput.portType;
            
            // 如果之前的线路耳机(即我们要拔掉耳机时),停止播放
            if ([portType isEqualToString:AVAudioSessionPortHeadphones]) {
                [self stop];
                if (self.delegate) {
                    [self.delegate playbackStoped];
                }
            }
        }
            break;
            
        default:
            break;
    }
}

2.8 使用 AVAudioRecorder 录制音频

音频会话设置

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    // 音频会话设置
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    NSError *error;
    
    // 设置分类
    // 录音
    if (![audioSession setCategory:AVAudioSessionCategoryRecord error:&error]) {
        MYLog(@"音频会话录音分类设置错误:%@", [error localizedDescription]);
    }
    
    // 激活音频会话
    if (![audioSession setActive:YES error:&error]) {
        MYLog(@"音频会话激活失败:%@", [error localizedDescription]);
    }
    return YES;
}

你可能感兴趣的:(《AV Foundation 开发秘籍》读书笔记)