現在直播越來越火,儼然已經成為了下一個紅海。作為一個資深碼農(我只喜歡這樣稱呼自己,不喜歡別人這樣稱呼我),我必須趕上時代的潮流,開始研究視頻直播。發現視屏直播類的文章上來就講拉流、推流、採集、美顏等第三方類的使用,我是小白很不懂啊。所以我決定開始系統分享從音頻、視頻類到視頻 ...
現在直播越來越火,儼然已經成為了下一個紅海。作為一個資深碼農(我只喜歡這樣稱呼自己,不喜歡別人這樣稱呼我),我必須趕上時代的潮流,開始研究視頻直播。發現視屏直播類的文章上來就講拉流、推流、採集、美顏等第三方類的使用,我是小白很不懂啊。所以我決定開始系統分享從音頻、視頻類到視頻直播的相關知識,也算溫故知新吧。我覺得去面試,說我會用第三方庫和懂第三方庫的原理,肯定是面試官對後者更有興趣吧。
先從音頻講起,本篇文章主要講播放本地視頻。
(一)準備工作
1.導入AVFoundation框架
2.工程導入一個音頻文件,向拖圖片一樣導入工程里。
#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;
// 獲取當前系統音量
- (float)getCurrentDeviceVolumu {
float volume = [[AVAudioSession sharedInstance] outputVolume]; NSLog(@"getCurrentDeviceVolumu = %f",volume);
return volume;
}
(三)AVAudioPlayerDelegate
// 當播放完成時執行的代理
- (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上,歡迎下載。