iOS開發 - 多媒體

來源:互聯網
上載者:User

iOS開發 - 多媒體

                                    音頻播放在iOS中音頻播放從形式上可以分為音效播放和音樂播放。前者主要指的是一些短音頻播放,通常作為點綴音頻,對於這類音頻不需要進行進度、迴圈等控制。後者指的是一些較長的音頻,通常是主音頻,對於這些音訊播放通常需要進行精確的控制。在iOS中播放兩類音頻分別使用AudioToolbox.framework和AVFoundation.framework兩個架構來完成音效和音樂播放。

一、音效

AudioToolbox.framework是一套基於C語言的架構,使用它來播放音效其本質是將短音頻註冊到系統聲音服務(System Sound Service)。System Sound Service是一種簡單、底層的聲音播放服務,使用此方法只適合播放一些很小的提示或者警告音,還可以調用系統的震動功能,但是它本身也存在著一些限制:    1.音頻播放時間不能超過30s    2.資料必須是PCM或者IMA4格式    3.音頻檔案必須打包成.caf、.aif、wav中的一種(不過需要注意的是注意這是官方文檔的說法,實際測試發現部分.mp3也可以播放)    4.不能控制播放的進度    5.調用方法後立即播放聲音    6.沒有迴圈播放和立體聲控制

二、音樂
如果播放較大的音頻或者要對音頻有精確的控制則System Sound Service可能就很難滿足實際需求了,通常這種情況會選擇使用AVFoundation.framework中的AVAudioPlayer來實現,我們可以把 AVAudioPlayer 看作是一個進階的播放器,它支援廣泛的音頻格式。

AVAudioPlayer 可以播放任意長度的音頻檔案、支援迴圈播放、可以同步播放多個音頻檔案、控制播放進度以及從音頻檔案的任意一點開始播放等,更進階的功能可以參考 AVAudioPlayer 的文檔 。要使用 AVAudioPlayer 的對象播放檔案,你只需為其指定一個音頻檔案並設定一個實現了 AVAudioPlayerDelegate 協議的 delegate 對象。

只要將 AVAudioPlayer 的 numberOfLoops 屬性設為負數,音頻檔案就會一直迴圈播放直到調用 stop 方法。

AVAudioPlayer類封裝了播放單個聲音的能力。播放器可以用NSURL或者NSData來初始化,要注意的是NSURL不可以是網路url而必須是本地檔案url,因為AVAudioPlayer不具備播放網路音訊能力。因為AVAudioPlayer只能播放一個完整的檔案,並不支援流式播放,所以必須是緩衝完才能播放。一個AVAudioPlayer只能播放一個音頻,如果你想混音你可以建立多個AVAudioPlayer執行個體,每個相當於混音板上的一個軌道,

額外進階
1.設定後台播放模式(兩個步驟缺一不可):
第一步:Required background modes
App plays audio or streams audio/video using AirPlay

第二步:設定AVAudioSession的類型為AVAudioSessionCategoryPlayback並且調用setActive::方法啟動會話AVAudioSession *audioSession=[AVAudioSession sharedInstance];[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];[audioSession setActive:YES error:nil];

2.處理拔出耳機後暫停功能
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];
NSDictionary *dic=notification.userInfo;
int changeReason= [dic[AVAudioSessionRouteChangeReasonKey] intValue];
if (changeReason==AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
AVAudioSessionRouteDescription *routeDescription=dic[AVAudioSessionRouteChangePreviousRouteKey];
AVAudioSessionPortDescription *portDescription= [routeDescription.outputs firstObject];
if ([portDescription.portType isEqualToString:@”Headphones”]) {
if ([self.audioPlayer isPlaying])
{
[self.audioPlayer pause];
self.timer.fireDate=[NSDate distantFuture];
}
}

配置iOS9 HTTPS&HTTP
NSAppTransportSecurity

NSAllowsArbitraryLoads
 

搖一搖demo

#import "ViewController.h"//短效音訊架構#import @interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.}-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{    NSLog(@"搖動開始");    //短效音頻播放    //建立系統聲音ID    SystemSoundID soundID;    //建立短效音頻 播放器 並且設定播放資源    NSURL * url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"shake" ofType:@"wav"]];    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);    //播放短效音訊同時加入震動效果    //kSystemSoundID_Vibrate 指的就是震動效果    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);    //播放聲音    AudioServicesPlaySystemSound(soundID);}-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{    NSLog(@"搖動結束");    //一般寫頁面跳轉}-(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{    NSLog(@"搖動取消");}音樂播放方法#pragma mark - 設定音樂播放器-(void)createAudioPlayer{    //初始化播放器    //第一種(本地) 用NSURL初始化 這裡的URL指的不是網路url 而是本地url    NSURL * url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:self.localMusicArray[_currentIndex] ofType:@"mp3"]];    NSLog(@"%@",self.localMusicArray[_currentIndex]);    _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];////    //預播放//    [_audioPlayer prepareToPlay];//    //播放//    [_audioPlayer play];    //第二種(網路) 用NSData初始化 先緩衝到本地 然後播放本地檔案//    _audioPlayer = [[AVAudioPlayer alloc ]initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:self.urlArray[_currentIndex]]] error:nil];    /**************設  置****************/    //設定代理    _audioPlayer.delegate = self;    //設定音量    _audioPlayer.volume = 0.5; //0.1-1.0之間    //設定播放迴圈次數,負數表示無限迴圈,0表示播放一次,正數是幾就播放幾次,預設播放一次    _audioPlayer.numberOfLoops = 0;    //設定開始播放的位置 單位/s    _audioPlayer.currentTime = 0; //可以指定從任意位置播放    //聲道數 唯讀屬性    /*    int channals = _audioPlayer.numberOfChannels;    //設定計數 開啟音頻計數    _audioPlayer.meteringEnabled = YES;    [_audioPlayer updateMeters];//更新音頻讀數    //擷取平均電平和峰值電平    for (int i = 0; i < channals; i++) {        //平均電平        float average = [_audioPlayer averagePowerForChannel:i];        //峰值電平        float peak = [_audioPlayer peakPowerForChannel:i];    }    //擷取播放期間    NSTimeInterval time = _audioPlayer.duration;    */    //分配播放資源,並將其添加到內部實行隊列中    [_audioPlayer prepareToPlay];    //[_audioPlayer play];}#pragma mark - 代理方法,處理播放過程中的突髮狀況-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{    NSLog(@"播放完成");    //迴圈播放,單曲迴圈...    if (flag) {        //音頻檔案在正常情況下播放完成    }else{        //說明音頻雖然播放結束了 但是資料解碼錯誤    }}-(void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{    //資料解碼錯誤}//處理音頻播放過程中被中斷的情況,ios8之前必須要實現這兩個代理方法 ios8之後系統自動處理//播放被中斷 比如突然來電或者使用者home鍵返回-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{    //如果當前現正播放則暫停    if (_audioPlayer.isPlaying) {        [_audioPlayer pause];    }}//結束中斷 返回程式-(void)audioPlayerEndInterruption:(AVAudioPlayer *)player{    [_audioPlayer play];}後台播放 開啟線控#pragma mark - 細節處理 後台播放 和開啟線控-(void)dealWithDetail{    //設定後台播放,結合修改 plist    //初始化音頻會話 多個app的音頻同時播放管理    AVAudioSession * session = [[AVAudioSession alloc] init];    //設定類型為後台播放類型    [session setCategory:AVAudioSessionCategoryPlayback error:nil];    //開啟後台播放    [session setActive:YES error:nil];    //監聽輸出裝置的狀態    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];}-(void)routeChange:(NSNotification *)noti{    //擷取監聽內容    NSDictionary * dic = noti.userInfo;    //擷取狀態改變的原因    int changeReason = [dic[AVAudioSessionRouteChangeReasonKey] intValue];    //當狀態改變原因為檢測不到輸出裝置    if (changeReason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {        //擷取狀態原因        AVAudioSessionRouteDescription * description = dic[AVAudioSessionRouteChangePreviousRouteKey];        //擷取連接埠描述        AVAudioSessionPortDescription * portDescription = [description.outputs firstObject];        //如果連接埠是耳機 並且音頻現正播放的話 就暫停播放        if([portDescription.portType isEqualToString:@"HeadPhones"]){            if (_audioPlayer.isPlaying) {                //暫停播放器                [_audioPlayer pause];                //暫停定時器                [timer setFireDate:[NSDate distantFuture]];            }        }    }}錄音demo#import "ViewController.h"#import #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width@interface ViewController (){    //記錄錄音時間    UILabel * _timeLabel ;    AVAudioRecorder * _audioRecoder;    AVPlayer * _player;}@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    [self createUI];    [self createAudioRecoder];    //定時器檢測錄音的時間長度    [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(culTime) userInfo:nil repeats:YES];}#pragma mark -定時器函數-(void)culTime{    _timeLabel.text = [NSString stringWithFormat:@"%.2f s",_audioRecoder.currentTime];}#pragma mark - 建立音頻錄製-(void)createAudioRecoder{    //設定儲存錄音檔案的路徑    NSString * path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/recoder.aac"];    NSLog(@"%@",path);    //設定錄製音訊屬性    NSDictionary * dic = @{AVFormatIDKey:@(kAudioFormatMPEG4AAC),   //音頻格式                           AVSampleRateKey:@(4000.0),   //位元速率                           AVNumberOfChannelsKey:@(2)   //聲道                           };    //初始化音頻錄製    _audioRecoder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:path] settings:dic error:nil];    //設定代理 代理的作用是檢測錄音檔案什麼時候出錯    _audioRecoder.delegate = self;    //預錄製    [_audioRecoder prepareToRecord];}#pragma mark - 建立UI- (void)createUI{    _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(150, 100, 100, 40)];    _timeLabel.backgroundColor = [UIColor redColor];    [self.view addSubview: _timeLabel];    //控制按鈕    NSArray * arr = @[@"錄音",@"暫停",@"停止",@"播放"];    for (int i = 0;  i< arr.count; i++) {        UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];        btn.frame= CGRectMake(SCREEN_WIDTH/4*i, 200, SCREEN_WIDTH/4-20, 40);        [btn setTitle:arr[i] forState:UIControlStateNormal];        [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];        btn.tag = 100+i;        [btn addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];        [self.view addSubview:btn];    }}#pragma mark - 按鈕回應程式法-(void)onClick:(UIButton *)btn{    switch (btn.tag) {        case 100:        {            [_audioRecoder record];        }            break;        case 101:        {            [_audioRecoder pause];        }            break;        case 102:        {            [_audioRecoder stop];        }            break;        case 103:        {            [self startPlay];        }            break;        default:            break;    }}#pragma mark - 播放錄音-(void)startPlay{    //初始化音頻播放器    _player = [[AVPlayer alloc] init];    //取得播放路徑    AVPlayerItem * item = [AVPlayerItem playerItemWithURL:_audioRecoder.url];    NSLog(@"%@",_audioRecoder.url);    //切換播放源    [_player replaceCurrentItemWithPlayerItem:item];    //播放    [_player play];}@end

視頻播放

一、MPMoviePlayerController

MPMoviePlayerController支援本地視頻和網路視頻播放。這個類實現了MPMediaPlayback協議,因此具備一般的播放器控制功能,例如播放、暫停、停止等。但是MPMediaPlayerController自身並不是一個完整的視圖控制器,如果要在UI中展示視頻需要將view屬性添加到介面中

二、MPMoviePlayerViewController

    其實MPMoviePlayerController如果不作為嵌入視頻來播放(例如在新聞中嵌入一個視頻),通常在播放時都是佔滿一個螢幕的,特別是在iPhone、iTouch上。因此從iOS3.2以後蘋果也在思考既然MPMoviePlayerController在使用時通常都是將其視圖view添加到另外一個視圖控制器中作為子視圖,那麼何不直接建立一個控制器視圖內部建立一個MPMoviePlayerController屬性並且預設全屏播放,開發人員在開發的時候直接使用這個視圖控制器。這個內部有一個MPMoviePlayerController的視圖控制器就是MPMoviePlayerViewController,它繼承於UIViewController。MPMoviePlayerViewController內部多了一個moviePlayer屬性和一個帶有url的初始化方法,同時它內部實現了一些作為模態視圖展示所特有的功能,例如預設是全螢幕模式展示、彈出後自動播放、作為模態視窗展示時如果點擊“Done”按鈕會自動結束模態視窗iOS9之前的實現:       //初始化播放器並且設定播放資源    //網路視頻播放        MPMoviePlayerViewController * player = [[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString:@"http://video.szzhangchu.com/1442391674615_6895658983.mp4"]];    //本地視頻播放    MPMoviePlayerViewController * player = [[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"MovieTest" ofType:@"mp4"]]];        //設定播放來源        player.moviePlayer.movieSourceType = MPMovieSourceTypeFile;        //設定全屏播放        player.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;        //播放前視頻預先處理        [player.moviePlayer prepareToPlay];        //開始播放        [player.moviePlayer play];        //推出視頻播放的控制器        [self presentViewController:player animated:YES completion:nil];iOS9之後的實現://初始化播放器AVPlayerViewController * playerVC = [[AVPlayerViewController alloc]init];//設定播放資源AVPlayer * player = [AVPlayer playerWithURL:url];playerVC.player = player;[self presentViewController:playerVC animated:YES completion:nil];

三、AVPlayer

MPMoviePlayerController足夠強大,幾乎不用寫幾行代碼就能完成一個播放器,但是正是由於它的高度封裝使得要自訂這個播放器變得很複雜,甚至是不可能完成。例如有些時候需要自訂播放器的樣式,那麼如果要使用MPMoviePlayerController就不合適了,如果要對視頻有自由的控制則可以使用AVPlayer。AVPlayer存在於AVFoundation中,它更加接近於底層,所以靈活性也更強AVPlayer本身並不能顯示視頻,而且它也不像MPMoviePlayerController有一個view屬性。如果AVPlayer要顯示必須建立一個播放器層AVPlayerLayer用於展示,播放器層繼承於CALayer,有了AVPlayerLayer之添加到控制器視圖的layer中即可。要使用AVPlayer首先瞭解一下幾個常用的類:

AVAsset:主要用於擷取多媒體資訊,是一個抽象類別,不能直接使用。
AVURLAsset:AVAsset的子類,可以根據一個URL路徑建立一個包含媒體資訊的AVURLAsset對象。
AVPlayerItem:一個媒體資源管理對象,管理者視頻的一些基本資料和狀態,一個AVPlayerItem對應著一個視頻資源

功能簡單介紹:
視頻的播放、暫停功能,這也是最基本的功能,AVPlayer對應著兩個方法play、pause來實現。但是關鍵問題是如何判斷當前視頻是否在播放,在前面的內容中無論是音頻播放器還是視頻播放器都有對應的狀態來判斷,但是AVPlayer卻沒有這樣的狀態屬性,通常情況下可以通過判斷播放器的播放速度來獲得播放狀態。如果rate為0說明是停止狀態,1是則是正常播放狀態。

到目前為止無論是MPMoviePlayerController還是AVPlayer來播放視頻都相當強大,但是它也存在著一些不可迴避的問題,那就是支援的視頻編碼格式很有限:H.264、MPEG-4,副檔名(壓縮格式):.mp4、.mov、.m4v、.m2v、.3gp、.3g2等。但是無論是MPMoviePlayerController還是AVPlayer它們都支援絕大多數音頻編碼

四、VLC視頻播放(第三方視頻整合播放)

整合步驟

1>加入libMobileVLCKit

2>加庫:ibstdc++ libiconv libbz2 Security.framework QuartzCore.framework CoreText.framework CFnetWork.framework OpenGLES.framework AudioToolbox.framework

3>修改C++編譯器為stdC++:
在[Build Setting]輸入[c++][Apple LLVM 5.1 - Languate - C++]
[C++ Standard..]選第一個[libstdc++(GNU C++ standard library)]

4>在[Build Setting][search][Search Paths][Header..]加一個路徑
開啟[libMobileVLCKit][include][MobileVLCKit]顯示簡介複製地址
把地址的前半部(包括檔案夾名稱)分改為$(SRCROOT)

5>添加標頭檔//#import “VLCMediaPlayer.h”

6>使用的檔案改為 .mm支援C++編譯

舉例視頻連結

http://video.szzhangchu.com/1442391674615_6895658983.mp4

配置iOS9
NSAppTransportSecurity

NSAllowsArbitraryLoads
 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.