开发笔记(音视频)

目录

一、音频

1.音频播放
2.录音
3.讯飞语音的使用

二、视频

1.视频播放
2.视频开发

一、音频

1.音频播放

iOS开发中的音频播放大致分为两类:一种是短音频(通常称为音效,时长不超过30s),一种是长音频(通常称为音乐)。前者通常可以通过AudioToolbox.framework进行操作(由一系列C语言的函数构成),后者要使用AVFoundation.framework(用Objective-C封装好的一系列的类)。 播放音效(短音频)通常打包成.caf、.aif和.wav格式。下面为大家封装了一段播放音频的代码,由于音频播放的AudioToolBox底层都是C函数,所以使用了函数指针,不熟悉的可以翻翻之前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;
    // 在系统中创建一个音效对象并获得其唯一ID
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(fileUrl), &soundID);
    // 注册在播放完之后执行的回调函数
    // 第二个和第三个参数跟循环播放有关
    // 第五个参数是指向传给回调函数的数据的指针
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, callback, NULL);
    // 播放音效
    AudioServicesPlaySystemSound(soundID);
    // 播放音效并震动
    // AudioServicesPlayAlertSound(soundID);
}

播放音乐可以使用AVAudioPlayer类:

 NSBundle *bundle = [NSBundle mainBundle];
    NSString *path = [bundle pathForResource:@"后会无期" 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可以实现录音功能。

代码如下:

 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.讯飞语音的使用

在移动应用中使用语音识别功能后,原来需要键盘输入的地方可以直接使用语音进行输入,从而解放用户的双手提供更好的用户体验。目前讯飞MSC在中文语音识别中用得较多,下面就以讯飞语音识别为例讲解如何实现语音搜索功能。可以在讯飞开放平台的SDK下载中心下载讯飞提供的语音听写功能,当然需要注册账号并获得使用SDK的APPID,下载后的文件夹中包含了文档、库文件和样例程序,可以直接阅读文档或参考样例程序来实现自己的语音搜索功能。创建项目后,需要向项目中加入讯飞的库文件以及它依赖的其他库文件,可以在下图所示的位置进行添加,需要添加的库文件也如下图所示,其他的库文件可以通过Xcode的自动链接器自动加入。

可以对讯飞提供的SDK进行二次封装,使其变成更容易使用的API(只用一行代码就可以使用它的功能),代码如下所示:

上面的代码在讯飞提供的样例程序中可以找到,无需自行编写,但是可以对其中的一些参数进行设置,例如language(语种)、vadEos(语音结束后的超时点)、vadBos(语音开始前的超时点)、speechTimeout(语音长度达到多少时间超时)等。

.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]]; 
        //设置听写模式 
        [rView setParameter:@"iat" forKey:[IFlySpeechConstant IFLY_DOMAIN]]; 
        rView.delegate = self;
        IATConfig *instance = [IATConfig sharedInstance]; 
        //设置最长录音时间 
        [rView setParameter:instance.speechTimeout forKey:[IFlySpeechConstant SPEECH_TIMEOUT]]; 
        //设置后端点 
        [rView setParameter:instance.vadEos forKey:  [IFlySpeechConstant VAD_EOS]]; 
        //设置前端点 
        [rView setParameter:instance.vadBos forKey:[IFlySpeechConstant VAD_BOS]];  
        //设置采样率,推荐使用16K 
        [rView setParameter:instance.sampleRate forKey:[IFlySpeechConstant SAMPLE_RATE]]; 
        if ([instance.language isEqualToString:[IATConfig chinese]]) { 
            //设置语言 
            [rView setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]]; 
            //设置方言
            [rView setParameter:instance.accent forKey:[IFlySpeechConstant ACCENT]];
         } else if ([instance.language isEqualToString:[IATConfig english]]) { 
            //设置语言 
            [rView setParameter:instance.language forKey:[IFlySpeechConstant LANGUAGE]]; 
         } 
         //设置是否返回标点符号 
        [rView setParameter:instance.dot forKey:[IFlySpeechConstant ASR_PTT]];
     } 
     // 绑定语音识别完成后做回调的Block  
     self.voiceHandler = handler; 
     [rView start];
}

// 语音识别完成的回调
- (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); 
    }
}

// 语音识别出错的回调方法
- (void)onError: (IFlySpeechError *) error { 
     if (error.errorCode) {
         NSLog(@"%@", error); 
     }
}

// 从JSON格式的数据中提取语音数据(该方法可以在官方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

到此为止,我们已经封装好了自己的API,要使用它非常简单,代码如下所示:

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

@end
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
   // 将自己申请的APPID通过IFlySpeechUtility工具类进行注册 
   [IFlySpeechUtility createUtility:@"appid=自己申请的APPID"];    
   return YES;
}
@end

举例 - 下面完成了一个非常简单的应用来使用我们封装好的语音识别功能:

运行效果如下图所示,点击OK按钮开始进行语音识别,完成后将识别的内容输入文本框中:

我们可以对搜索栏中的书签按钮进行定制,在点击通过调用我们封装好的代码后产生语音识别的视图,然后将识别的结果填入搜索栏中:

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

// 点击书签按钮的回调方法
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
     [[CDVoice sharedInstance] voiceToTextString:^(NSString *str) { 
        mySearchBar.text = str;
        [mySearchBar becomeFirstResponder];
     }];
}

二、视频

1.视频播放

Demo代码如图
效果如图

2.视频开发

相关链接:https://pan.baidu.com/s/16Hn_8ryr6F9AquCHD7hKhg 提取码: fjni
ZSPlayerDemo:https://github.com/wuyubeichen/ZSPlayerDemo

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容