《AV Foundation 開發(fā)秘籍》讀書筆記

本文章是小編閱讀這本書的一些摘錄和筆記
希望自己能盡快讀完膘魄,持續(xù)更新吧

第1章 AV Foundation 入門

1.1 AV Foundation 的含義

  • 高度依賴多線程機制
  • 充分利用多核硬件優(yōu)勢并大量使用block和Grand Central Dispatch(GCD)機制將復雜的計算進程放在后臺線程運行赠叼。

1.2 AV Foundation 的適用范圍

  1. Core Audio 推薦閱讀《Leaning Core Audio》
  2. Core Video 數(shù)字視頻所提供的管道模式奶浦,為相對的Core Media提供圖片緩存和緩存池支持
  3. Core Media 低層級媒體管道的一部分尼荆,提供針對音頻樣本是視頻幀處理所需的低層級數(shù)據(jù)類型和接口
  4. Core Animation 在視頻編輯和播放過程中添加動畫標題和圖片效果

1.3 解析 AV Foundation

  1. 音頻播放(AVAudioPlayer)和記錄(AVAudioRecorder)
  2. 媒體文件檢查:獲取媒體資源技術(shù)參數(shù)际长,基于AVMetadataItem提供源數(shù)據(jù)支持
  3. 視頻播放:本地或遠程流想帅,核心類AVPlayer和AVPlayerItem
  4. 媒體捕捉:攝像頭捕捉核心類AVCaptureSession
  5. 媒體編輯:音視頻組合、修改編輯媒體片段队丝、修改音頻參數(shù)、添加動畫標題欲鹏、場景切換效果
  6. 媒體處理:直接訪問視頻幀和音頻樣本(AVAssetReader和AVAssetWriter)

1.4 了解數(shù)字媒體

  • 音視頻模擬信號 -> 大腦電信號
  • 模擬信號 -> 數(shù)字信號 (采樣Sampling)

1.4.1 數(shù)字媒體采樣

  • 時間采樣:捕捉一個信號周期內(nèi)的變化
  • 空間采樣:可視化媒體

1.4.2 音頻采樣介紹

  • 頻率:震動的速率或頻率決定了聲音的音調(diào)
  • 振幅:用來測量頻率的相對強度机久,大致表示聲音的音量
  • 電動式麥克風(dynamic microphone):膜片感受到聲音震動,帶動線圈震動赔嚎,產(chǎn)生同輸入信號相同振幅和頻率的電流信號
  • 人類可接收到的音頻范圍:20Hz~20kHz
  • 線型脈沖編碼調(diào)制(linear pulse-code modulation膘盖,Linear PCM, LPCM):這個過程采樣或測量一個固定的音頻信號,過程的周期率被稱為采樣率尤误。
  • 未壓縮視頻存儲需求舉例:24位RGB色彩(R侠畔、G、B各占8位)损晤,分辨率1280×720软棺,幀率30FPS,那么存儲需求為79MB/s

1.5 數(shù)字媒體壓縮

1.5.1 色彩二次抽樣

  • YUV(Y-Prime-C-B-C-R)(Y'CbCr'):適用色彩(顏色)通道UV替換了像素的亮度通道Y尤勋。如果除去亮度喘落,剩下的就是一幅灰度圖片。因此如果大幅減少存儲在每個像素中的顏色信息最冰,而不至于圖片的質(zhì)量受損瘦棋,這個減少顏色數(shù)據(jù)的過程就成為色彩二次抽樣。
  • jab:這個比較難理解

1.5.2 編解碼器壓縮

1.5.3 視頻編解碼器

  1. H.264:規(guī)范是MPEG(Motion Picture Experts Group)所定義的MPEG-4的一部分暖哨。多用于消費者視頻攝像頭捕捉到的資源赌朋。通過幀內(nèi)壓縮和幀間壓縮縮小視頻文件的尺寸。
  2. Apple ProRes:是有損編解碼器鹿蜀,只在OS X上可用箕慧。
  3. 此外AV Foundation還支持MPEG-1、MPEG-2茴恰、MPEG-4颠焦、H.263和DV等多種不同的視頻捕捉設備的編解碼器。

1.5.4 音頻編解碼器

  1. 高級音頻編碼(ACC):是H.264標準相應的音頻處理方式往枣》ネィ可在低比特率低前提下提供更高質(zhì)量的音頻。

1.6 容器格式

通常的文件后綴應被認為是文件的容器格式(containerformat)分冈,也是元文件格式圾另,容器格式包含一種或更多種媒體類型的目錄。

  1. QuickTime:
  2. MPEG-4:

1.7 初識 AV Foundation

使用AVSpeechSynthesizerAVSpeechUtterance實現(xiàn)文本語音播放

第2章 播放和錄制音頻

2.1 Mac和iOS的音頻環(huán)境

  • 可管理的音頻環(huán)境(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類的實例提供了一種簡單地從文本或內(nèi)存中播放音頻的方法扰路。
AUAudioPlayer構(gòu)建于Core Audio中的C-based Audio Queue Services的最頂層尤溜。

2.3.1 創(chuàng)建 AVAudioPlayer

有兩種方法可以創(chuàng)建一個AudioPlayer,使用包含要播放音頻的內(nèi)存版本的NSData汗唱,或本地音頻文件的NSURL宫莱。

// 通過本地音頻的URL創(chuàng)建
NSURL *audioURL = [[NSBundle mainBundle] URLForResource:@"Sheep" withExtension:@"mp3"];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];

// 如果返回一個有效的播放實例,建議開發(fā)者調(diào)用其prepareToPlay方法哩罪,
// 這樣做會取得需要的音頻硬件并預加載Audio Queue的緩沖區(qū)
// 調(diào)用prepareToPlay這個動作是可選的授霸,當調(diào)用play方法時會隱形激活,不過在創(chuàng)建時準備播放器可以降低調(diào)用play方法和聽到聲音輸出之間的延時
if (audioPlayer) {
    [audioPlayer prepareToPlay];
}

// 播放音頻
[audioPlayer play];

2.3.3 對播放進行控制

pause和stop方法對異同點:

  • 相同:都可以暫停/停止當前播放的音頻际插,下一時間調(diào)用play方法碘耳,音頻都會繼續(xù)播放;
  • 不同:這兩個方法最主要的卻別在底層處理上腹鹉。調(diào)用stop方法會撤銷調(diào)用prepareToPlay時所做的設置藏畅,而調(diào)用pause方法則不會敷硅。

2.4 創(chuàng)建 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 - 處理中斷通知
// 注意這里的參數(shù)不是NSNotificationCenter绞蹦,而是推送過來的NSNotification
- (void)handleInterruption:(NSNotification *)notification {
    
    NSDictionary *info = notification.userInfo;
    
    // 中斷類型(枚舉)
    AVAudioSessionInterruptionType interruptionType = [[info objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
    switch (interruptionType) {
        case AVAudioSessionInterruptionTypeBegan: // 中斷開始
        {
            [self stop]; // 調(diào)用stop方法并不能停止播放力奋,只能更新內(nèi)部狀態(tài)
            if (self.delegate) {
                [self.delegate playbackStoped];
            }
        }
            break;
        case AVAudioSessionInterruptionTypeEnded: // 中斷結(jié)束
        {
            // 中斷結(jié)束后,恢復音樂播放
            // 音頻會話是否已經(jīng)重新激活幽七、是否可以再次播放(只有中斷結(jié)束才有這個options)
            AVAudioSessionInterruptionOptions options = [[info objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
            if (options == AVAudioSessionInterruptionOptionShouldResume) {
                [self play];
                if (self.delegate) {
                    [self.delegate playbackBegan];
                }
            }
        }
            break;
        default:
            break;
    }
}

因為控制器參與處理頁面,所以寫個協(xié)議,設置委托來進行更新界面

@protocol THPlayerControllerDelegate <NSObject>

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

@end

2.7 對線路改變的響應

iOS設備上添加或移除音頻輸入披蕉、輸出線路時妖爷,會發(fā)生線路改變。有多重原因會導致線路的變化驶鹉,比如用戶插入耳機或斷開USB麥克風绩蜻。當這些事件發(fā)生時,音頻會根據(jù)情況改變輸入或輸出線路室埋,同時AVAudioSession會廣播一個描述該變化的通知給所有相關(guān)的偵聽器办绝。為了遵循Apple的Human Interface Guidelines(HIG)的相關(guān)定義,應用程序應該成為這些相關(guān)偵聽器中的一員姚淆。

注冊線路變化通知

// 注冊線路通知
[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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腌逢,一起剝皮案震驚了整個濱河市降淮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌搏讶,老刑警劉巖佳鳖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纳本,死亡現(xiàn)場離奇詭異,居然都是意外死亡腋颠,警方通過查閱死者的電腦和手機繁成,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淑玫,“玉大人巾腕,你說我怎么就攤上這事⌒踺铮” “怎么了尊搬?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長土涝。 經(jīng)常有香客問我佛寿,道長,這世上最難降的妖魔是什么但壮? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任冀泻,我火速辦了婚禮,結(jié)果婚禮上蜡饵,老公的妹妹穿的比我還像新娘弹渔。我一直安慰自己,他們只是感情好溯祸,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布肢专。 她就那樣靜靜地躺著,像睡著了一般焦辅。 火紅的嫁衣襯著肌膚如雪博杖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天筷登,我揣著相機與錄音剃根,去河邊找鬼。 笑死仆抵,一個胖子當著我的面吹牛跟继,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镣丑,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼舔糖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了莺匠?” 一聲冷哼從身側(cè)響起金吗,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后摇庙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旱物,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年卫袒,在試婚紗的時候發(fā)現(xiàn)自己被綠了宵呛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡夕凝,死狀恐怖宝穗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情码秉,我是刑警寧澤逮矛,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站转砖,受9級特大地震影響须鼎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜府蔗,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一晋控、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧礁竞,春花似錦糖荒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜘矢。三九已至狂男,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間品腹,已是汗流浹背岖食。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舞吭,地道東北人泡垃。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像羡鸥,于是被迫代替她去往敵國和親蔑穴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容