開(kāi)發(fā)筆記(音視頻)

目錄

一、音頻

1.音頻播放
2.錄音
3.訊飛語(yǔ)音的使用

二标沪、視頻

1.視頻播放
2.視頻開(kāi)發(fā)

一苞轿、音頻

1.音頻播放

iOS開(kāi)發(fā)中的音頻播放大致分為兩類(lèi):一種是短音頻(通常稱(chēng)為音效逗物,時(shí)長(zhǎng)不超過(guò)30s),一種是長(zhǎng)音頻(通常稱(chēng)為音樂(lè))瑟俭。前者通臭嶙浚可以通過(guò)AudioToolbox.framework進(jìn)行操作(由一系列C語(yǔ)言的函數(shù)構(gòu)成)摆寄,后者要使用AVFoundation.framework(用Objective-C封裝好的一系列的類(lèi))失暴。?播放音效(短音頻)通常打包成.caf、.aif和.wav格式微饥。下面為大家封裝了一段播放音頻的代碼,由于音頻播放的AudioToolBox底層都是C函數(shù)欠橘,所以使用了函數(shù)指針矩肩,不熟悉的可以翻翻之前C的東西

- (void)playSoundEffect:(NSString *)name withCallback:(void (*)(SystemSoundID, void *)) callback {
    NSString *audioFile = [[NSBundle mainBundle] pathForResource:name ofType:nil];
    NSURL *fileUrl = [NSURL fileURLWithPath:audioFile];

    SystemSoundID soundID;
    // 在系統(tǒng)中創(chuàng)建一個(gè)音效對(duì)象并獲得其唯一ID
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(fileUrl), &soundID);
    // 注冊(cè)在播放完之后執(zhí)行的回調(diào)函數(shù)
    // 第二個(gè)和第三個(gè)參數(shù)跟循環(huán)播放有關(guān)
    // 第五個(gè)參數(shù)是指向傳給回調(diào)函數(shù)的數(shù)據(jù)的指針
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, callback, NULL);
    // 播放音效
    AudioServicesPlaySystemSound(soundID);
    // 播放音效并震動(dòng)
    // AudioServicesPlayAlertSound(soundID);
}

播放音樂(lè)可以使用AVAudioPlayer類(lèi):

 NSBundle *bundle = [NSBundle mainBundle];
    NSString *path = [bundle pathForResource:@"后會(huì)無(wú)期" ofType:@"mp3"];
    NSURL *url = [NSURL fileURLWithPath:path];
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    self.player.volume = 5;
    self.player.delegate = self;
    [self.player prepareToPlay];
    [self.player play];

Demo代碼如下:

2.錄音

使用AVAudioRecorder可以實(shí)現(xiàn)錄音功能肃续。

代碼如下:

 NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
            [NSNumber numberWithInt:AVAudioQualityLow], AVEncoderAudioQualityKey,
            [NSNumber numberWithInt:16], AVEncoderBitRateKey,
            [NSNumber numberWithInt:2],AVNumberOfChannelsKey,
            [NSNumber numberWithFloat:44100.0],AVSampleRateKey,
            nil
    ];
    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/record.caf", [[NSBundle mainBundle] resourcePath]]];
    self.recorder = [[AVAudioRecorder alloc] initWithURL:url settings:dict error:nil];
    [self.recorder prepareToRecord];

Demo代碼如下:

3.訊飛語(yǔ)音的使用

在移動(dòng)應(yīng)用中使用語(yǔ)音識(shí)別功能后叉袍,原來(lái)需要鍵盤(pán)輸入的地方可以直接使用語(yǔ)音進(jìn)行輸入刽酱,從而解放用戶(hù)的雙手提供更好的用戶(hù)體驗(yàn)喳逛。目前訊飛MSC在中文語(yǔ)音識(shí)別中用得較多,下面就以訊飛語(yǔ)音識(shí)別為例講解如何實(shí)現(xiàn)語(yǔ)音搜索功能棵里。可以在訊飛開(kāi)放平臺(tái)的SDK下載中心下載訊飛提供的語(yǔ)音聽(tīng)寫(xiě)功能殿怜,當(dāng)然需要注冊(cè)賬號(hào)并獲得使用SDK的APPID转唉,下載后的文件夾中包含了文檔稳捆、庫(kù)文件和樣例程序赠法,可以直接閱讀文檔或參考樣例程序來(lái)實(shí)現(xiàn)自己的語(yǔ)音搜索功能乔夯。創(chuàng)建項(xiàng)目后砖织,需要向項(xiàng)目中加入訊飛的庫(kù)文件以及它依賴(lài)的其他庫(kù)文件末荐,可以在下圖所示的位置進(jìn)行添加侧纯,需要添加的庫(kù)文件也如下圖所示,其他的庫(kù)文件可以通過(guò)Xcode的自動(dòng)鏈接器自動(dòng)加入眶熬。

可以對(duì)訊飛提供的SDK進(jìn)行二次封裝,使其變成更容易使用的API(只用一行代碼就可以使用它的功能)块请,代碼如下所示:

上面的代碼在訊飛提供的樣例程序中可以找到,無(wú)需自行編寫(xiě)墩新,但是可以對(duì)其中的一些參數(shù)進(jìn)行設(shè)置贸弥,例如language(語(yǔ)種)、vadEos(語(yǔ)音結(jié)束后的超時(shí)點(diǎn))绵疲、vadBos(語(yǔ)音開(kāi)始前的超時(shí)點(diǎn))、speechTimeout(語(yǔ)音長(zhǎng)度達(dá)到多少時(shí)間超時(shí))等臣疑。

.h文件

#import <Foundation/Foundation.h>
#import "iflyMSC/IFlyMSC.h"

typedef void(^CDVoiceHandler)(NSString *);

@interface CDVoice : NSObject <IFlyRecognizerViewDelegate> { 
IFlyRecognizerView *rView;
}

@property (nonatomic, copy) CDVoiceHandler voiceHandler;

+ (instancetype) sharedInstance;

- (void) voiceToTextString:(CDVoiceHandler) handler;

@end

.m文件

#import "CDVoice.h"
#import "IATConfig.h"

#define LEFT_FOR_RV 50#define TOP_FOR_RV 50
@implementation CDVoice

- (instancetype) init { 
    @throw [NSException exceptionWithName:@"CDVoiceException" reason:@"不允許使用初始化方法" userInfo:nil];
}

- (instancetype) initPrivate { 
   if (self = [super init]) { 
      // Do some initialization here!!!
   } return self;
}

+ (instancetype) sharedInstance { 
    static CDVoice *instance = nil;
    if (!instance) {
       instance = [[self alloc] initPrivate]; 
    } return instance;
}

- (void) voiceToTextString:(CDVoiceHandler) handler{
    if (!rView) {
        rView = [[IFlyRecognizerView alloc] initWithOrigin:CGPointMake(LEFT_FOR_RV, TOP_FOR_RV)]; 
        [rView setParameter:@"" forKey:[IFlySpeechConstant PARAMS]]; 
        //設(shè)置聽(tīng)寫(xiě)模式 
        [rView setParameter:@"iat" forKey:[IFlySpeechConstant IFLY_DOMAIN]]; 
        rView.delegate = self;
        IATConfig *instance = [IATConfig sharedInstance]; 
        //設(shè)置最長(zhǎng)錄音時(shí)間 
        [rView setParameter:instance.speechTimeout forKey:[IFlySpeechConstant SPEECH_TIMEOUT]]; 
        //設(shè)置后端點(diǎn) 
        [rView setParameter:instance.vadEos forKey:  [IFlySpeechConstant VAD_EOS]]; 
        //設(shè)置前端點(diǎn) 
        [rView setParameter:instance.vadBos forKey:[IFlySpeechConstant VAD_BOS]];  
        //設(shè)置采樣率盔憨,推薦使用16K 
        [rView setParameter:instance.sampleRate forKey:[IFlySpeechConstant SAMPLE_RATE]]; 
        if ([instance.language isEqualToString:[IATConfig chinese]]) { 
            //設(shè)置語(yǔ)言 
            [rView setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]]; 
            //設(shè)置方言
            [rView setParameter:instance.accent forKey:[IFlySpeechConstant ACCENT]];
         } else if ([instance.language isEqualToString:[IATConfig english]]) { 
            //設(shè)置語(yǔ)言 
            [rView setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]]; 
         } 
         //設(shè)置是否返回標(biāo)點(diǎn)符號(hào) 
        [rView setParameter:instance.dot forKey:[IFlySpeechConstant ASR_PTT]];
     } 
     // 綁定語(yǔ)音識(shí)別完成后做回調(diào)的Block  
     self.voiceHandler = handler; 
     [rView start];
}

// 語(yǔ)音識(shí)別完成的回調(diào)
- (void)onResult:(NSArray *)resultArray isLast:(BOOL) isLast {

    NSMutableString *result = [[NSMutableString alloc] init]; 
    NSMutableString * resultString = [[NSMutableString alloc]init]; 
    NSDictionary *dic = resultArray[0]; 
    for (NSString *key in dic) { 
         [result appendFormat:@"%@",key]; 
         NSString * resultFromJson = [self stringFromABNFJson:result];
         if (! [resultString isEqualToString:@" "]) {    
             [resultString appendString:resultFromJson];       
         } 
    } 
    if (!isLast && self.voiceHandler) {  
          self.voiceHandler(resultString); 
    }
}

// 語(yǔ)音識(shí)別出錯(cuò)的回調(diào)方法
- (void)onError: (IFlySpeechError *) error { 
     if (error.errorCode) {
         NSLog(@"%@", error); 
     }
}

// 從JSON格式的數(shù)據(jù)中提取語(yǔ)音數(shù)據(jù)(該方法可以在官方Demo的代碼中找到)
- (NSString *)stringFromABNFJson: (NSString *) params {
    if (!params) { 
        return nil; 
    } 
    NSMutableString *tempStr = [[NSMutableString alloc] init]; 
    NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:[params dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
    NSArray *wordArray = [resultDic objectForKey:@"ws"];
    for (int i = 0; i < [wordArray count]; i++) {  
         NSDictionary *wsDic = [wordArray objectAtIndex: i]; 
         NSArray *cwArray = [wsDic objectForKey:@"cw"]; 
         for (int j = 0; j < [cwArray count]; j++) { 
              NSDictionary *wDic = [cwArray objectAtIndex:j]; 
              NSString *str = [wDic objectForKey:@"w"]; [tempStr appendString: str]; 
         }
     } 
      return tempStr;
}
@end

到此為止讯沈,我們已經(jīng)封裝好了自己的API,要使用它非常簡(jiǎn)單,代碼如下所示:

#import "AppDelegate.h"
#import "iflyMSC/IFlyMSC.h"
@interface AppDelegate ()

@end
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
   // 將自己申請(qǐng)的APPID通過(guò)IFlySpeechUtility工具類(lèi)進(jìn)行注冊(cè) 
   [IFlySpeechUtility createUtility:@"appid=自己申請(qǐng)的APPID"];    
   return YES;
}
@end

舉例 - 下面完成了一個(gè)非常簡(jiǎn)單的應(yīng)用來(lái)使用我們封裝好的語(yǔ)音識(shí)別功能:

運(yùn)行效果如下圖所示驯用,點(diǎn)擊OK按鈕開(kāi)始進(jìn)行語(yǔ)音識(shí)別,完成后將識(shí)別的內(nèi)容輸入文本框中:

我們可以對(duì)搜索欄中的書(shū)簽按鈕進(jìn)行定制蝴乔,在點(diǎn)擊通過(guò)調(diào)用我們封裝好的代碼后產(chǎn)生語(yǔ)音識(shí)別的視圖记餐,然后將識(shí)別的結(jié)果填入搜索欄中:

- (void) customizeSearchBar { 
    mySearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 0, 40)]; 
    mySearchBar.placeholder = @"請(qǐng)輸入要查找的名字"; 
    mySearchBar.showsCancelButton = YES; 
    mySearchBar.showsBookmarkButton = YES; 
    [mySearchBar setImage:[UIImage imageNamed:@"Dudu.jpg"] forSearchBarIcon:UISearchBarIconBookmark state:UIControlStateNormal]; 
    mySearchBar.delegate = self; 
    [myTableView setTableHeaderView:mySearchBar];
}

// 點(diǎn)擊書(shū)簽按鈕的回調(diào)方法
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
     [[CDVoice sharedInstance] voiceToTextString:^(NSString *str) { 
        mySearchBar.text = str;
        [mySearchBar becomeFirstResponder];
     }];
}

二薇正、視頻

1.視頻播放

Demo代碼如圖
效果如圖

2.視頻開(kāi)發(fā)

相關(guān)鏈接:https://pan.baidu.com/s/16Hn_8ryr6F9AquCHD7hKhg 提取碼: fjni
ZSPlayerDemo:https://github.com/wuyubeichen/ZSPlayerDemo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挖腰,隨后出現(xiàn)的幾起案子雕沿,更是在濱河造成了極大的恐慌猴仑,老刑警劉巖审轮,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異疾渣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)崖飘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)榴捡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)朱浴,“玉大人吊圾,你說(shuō)我怎么就攤上這事∠钇梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵躏筏,是天一觀的道長(zhǎng)呈枉。 經(jīng)常有香客問(wèn)我趁尼,道長(zhǎng),這世上最難降的妖魔是什么猖辫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮啃憎,結(jié)果婚禮上芝囤,老公的妹妹穿的比我還像新娘。我一直安慰自己悯姊,他們只是感情好羡藐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布悯许。 她就那樣靜靜地躺著仆嗦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瘩扼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天垃僚,我揣著相機(jī)與錄音,去河邊找鬼谆棺。 笑死栽燕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纫谅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溅固,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了侍郭?” 一聲冷哼從身側(cè)響起询吴,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤亮元,失蹤者是張志新(化名)和其女友劉穎猛计,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體奉瘤,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年煮甥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片成肘。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卖局,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出双霍,到底是詐尸還是另有隱情批销,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布染坯,位于F島的核電站,受9級(jí)特大地震影響单鹿,放射性物質(zhì)發(fā)生泄漏骡技。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一布朦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧昼窗,春花似錦、人聲如沸澄惊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)肛搬。三九已至,卻和暖如春毕贼,著一層夾襖步出監(jiān)牢的瞬間温赔,已是汗流浹背鬼癣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工陶贼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留待秃,地道東北人拜秧。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像章郁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子暖庄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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