如今直播愈來愈火,儼然已經成爲了下一個紅海。做爲一個資深碼農(我只喜歡這樣稱呼本身,不喜歡別人這樣稱呼我),我必須遇上時代的潮流,開始研究視頻直播。發現視屏直播類的文章上來就講拉流、推流、採集、美顏等第三方類的使用,我是小白很不懂啊。因此我決定開始系統分享從音頻、視頻類到視頻直播的相關知識,也算溫故知新吧。我以爲去面試,說我會用第三方庫和懂第三方庫的原理,確定是面試官對後者更有興趣吧。
先從音頻講起,本篇文章主要講播放本地視頻。git
1.導入AVFoundation框架
2.工程導入一個音頻文件,向拖圖片同樣導入工程裏。
github
#import "FHAudioViewController.h" #import <AVFoundation/AVFoundation.h> #define ScreenWidth [UIScreen mainScreen].bounds.size.width #define ScreenHeight [UIScreen mainScreen].bounds.size.height @interface FHAudioViewController ()<AVAudioPlayerDelegate>{ AVAudioPlayer *_avAudioPlayer; // 播放器palyer UISlider *_pregressSlider; // 播放進度 UILabel *_pregressLabel; // 進度 UISlider *_volumeSlider; // 聲音控制 NSTimer *_timer; // 監控音頻播放進度 } @end @implementation FHAudioViewController - (void)viewDidLoad { [super viewDidLoad]; // 1.初識化UI // (1)初始化三個Button; NSArray *titleArr = @[@"播放",@"暫停",@"中止"]; for (int i = 0; i < titleArr.count; i++ ) { UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:button]; [button setFrame:CGRectMake(20 + i * 50, 130 , 60, 40)]; [button setTitle:titleArr[i] forState:UIControlStateNormal]; button.tag = i+100; [button addTarget:self action:@selector(controlAVAudioAction:) forControlEvents:UIControlEventTouchUpInside]; } // (2)初始化進度條 _pregressSlider = [[UISlider alloc] initWithFrame:CGRectMake(20, 50, ScreenWidth - 130 - 20, 20)]; [self.view addSubview: _pregressSlider]; _pregressSlider.minimumValue = 0.0f; _pregressSlider.maximumValue = 1.0f; [_pregressSlider addTarget:self action:@selector(pregressChange) forControlEvents:UIControlEventValueChanged]; _pregressLabel = [[UILabel alloc] initWithFrame:CGRectMake(ScreenWidth - 120, 50, 100, 20)]; _pregressLabel.text = @"00:00/00:00"; [self.view addSubview:_pregressLabel]; // (3)用NSTimer來監控音頻播放進度 _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(playProgress) userInfo:nil repeats:YES]; // (4)初始化音量 _volumeSlider = [[UISlider alloc] initWithFrame:CGRectMake(20, 90, ScreenWidth - 130 - 20, 20)]; [_volumeSlider addTarget:self action:@selector(volumeChange) forControlEvents:UIControlEventValueChanged]; _volumeSlider.minimumValue = 0.0f; _volumeSlider.maximumValue = 10.0f; _volumeSlider.value = 1.0f; [self.view addSubview:_volumeSlider]; UILabel *volumeLabel = [[UILabel alloc] initWithFrame:CGRectMake(ScreenWidth - 120, 90, 40, 20)]; volumeLabel.text = @"音量"; [self.view addSubview:volumeLabel]; // 2.播放本地音頻文件 // (1)從boudle路徑下讀取音頻文件 陳小春 - 獨家記憶文件名,mp3文件格式 NSString *path = [[NSBundle mainBundle] pathForResource:@"陳小春 - 獨家記憶" ofType:@"mp3"]; // (2)把音頻文件轉化成url格式 NSURL *url = [NSURL fileURLWithPath:path]; // (3)初始化音頻類 而且添加播放文件 _avAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; // (4) 設置代理 _avAudioPlayer.delegate = self; // (5) 設置初始音量大小 默認1,取值範圍 0~1 _avAudioPlayer.volume = 1; // (6)設置音樂播放次數 負數爲一直循環,直到stop,0爲一次,1爲2次,以此類推 _avAudioPlayer.numberOfLoops = 0; // (5)準備播放 [_avAudioPlayer prepareToPlay]; }
效果
面試
分析:用兩個Slider來分別表示和控制播放進程和音量。三個按鈕分別表示播放、暫停、控制。用NSTimer來每0.01秒改變一次播放進度。框架
// 音頻控制 - (void)controlAVAudioAction : (UIButton *)button { NSInteger tag = button.tag; // 播放 if (tag == 100) { [_avAudioPlayer play]; } // 暫停 if (tag == 101) { [_avAudioPlayer pause]; } // 中止 if (tag == 102) { _avAudioPlayer.currentTime = 0; [_avAudioPlayer stop]; } } // 播放進度控制 - (void)pregressChange{ _avAudioPlayer.currentTime = _pregressSlider.value * _avAudioPlayer.duration; } // 播放進度條 - (void)playProgress { // 更改當前播放時間 NSString *currentMStr = [self FormatTime:_avAudioPlayer.currentTime / 60]; NSString *currentSStr = [self FormatTime:(int)_avAudioPlayer.currentTime % 60]; NSString *durationMStr = [self FormatTime:_avAudioPlayer.duration / 60]; NSString *durationSStr = [self FormatTime:(int)_avAudioPlayer.duration % 60]; _pregressLabel.text = [NSString stringWithFormat:@"%@:%@/%@:%@",currentMStr,currentSStr,durationMStr,durationSStr]; // 播放進度條 _pregressSlider.value = _avAudioPlayer.currentTime / _avAudioPlayer.duration; } - (NSString *)FormatTime: (int)time { if (time < 10) { return [NSString stringWithFormat:@"0%d",time]; }else { return [NSString stringWithFormat:@"%d",time]; } } // 音量控制 - (void)volumeChange { _avAudioPlayer.volume = _volumeSlider.value; }
分析:我主要說一下音量,其餘的方法寫的都很清楚了。音量這個比較特殊。_avAudioPlayer.volume = 1;
這個值是百分比,設置的就是視頻播放器音量是系統音量的百分之多少。比如說系統音量是0.5,這個值設置成0.6,此時音頻播放器的音量也就是你聽到的音量至關於系統音量的0.3;這裏系統音量指:
那個中間喇叭的音量。它的取值範圍也是0~1;ide
// 獲取當前系統音量 - (float)getCurrentDeviceVolumu { float volume = [[AVAudioSession sharedInstance] outputVolume]; NSLog(@"getCurrentDeviceVolumu = %f",volume); return volume; }
// 當播放完成時執行的代理 - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { NSLog(@"audioPlayerDidFinishPlaying"); _timer = nil; [_timer invalidate]; } // 當播放發生錯誤時調用 - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error { NSLog(@"播放發生錯誤%@",error); } // 當播放器發生中斷時調用 如來電 - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player { NSLog(@"audioPlayerBeginInterruption"); // 暫停播放 用戶不暫停,系統也會幫你暫停。可是若是你暫停了,等來電結束,須要再開啓 [_avAudioPlayer pause]; } // 當中斷中止時調用 如來電結束 - (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags { NSLog(@"audioPlayerEndInterruption"); // 你能夠幫用戶開啓 也能夠什麼都不執行,讓用戶本身決定 [_avAudioPlayer play]; }
本工程將放到本人的GitUp上,歡迎下載。oop