iOS - 使用AVPlayer播放音频、视频

最近有个项目需要自定义播放器界面,要求能调节声音、和播放进度并显示播放时间,效果图如下:

iOS - 使用AVPlayer播放音频、视频_第1张图片


开始准备用AVAudioPlayer,但是不好控制播放进度,最后使用了AVPlayer ;同时也学习到了怎么自定义UISlider


需要引入的framework:  AVFoundation.framework  、MediaPlayer.framework  、CoreMedia.framework


首先我定义了一个xib文件:



类的.h文件

#import 
#import  
#import 
#import 

@interface AudioPlayerView : UIView 
{ 
    __weak IBOutlet UILabel *timeLabel;
    __weak IBOutlet UISlider *processSlider;
    __weak IBOutlet UISlider *volumeSlider;
    __weak IBOutlet UIButton *startOrStopButton;
    
    float totalDuration;
    float currentDuration; 
    
    BOOL isPlay; //是否正在播放
    id mTimeObserver;
}
 
@property (nonatomic , strong) AVPlayer *mediaPlayer;

- (void)setAudioName:(NSString *)name;
- (void)dismissFromSuperview;
- (IBAction)startOrStopButtonAction:(id)sender;  

@end

.m文件

/*
 1、添加播放器()
 AudioPlayerView *audioView = [[[NSBundle mainBundle] loadNibNamed:@"AudioPlayerView" owner:self options:nil] objectAtIndex:0];
 [self.view addSubview:audioView];
 [audioView setAudioName:@"demo.mp3"];
 2、移除播放器
 [audioView dismissFromSuperview];
 audioView = nil;
*/

#import "AudioPlayerView.h"

#define animationDuration  0.3

@implementation AudioPlayerView
@synthesize mediaPlayer = _mediaPlayer; 

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
} 

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if(self){
        //your corder
        currentDuration = 0;
        totalDuration = 0; 
    }
    return self;
}

- (void)willMoveToSuperview:(UIView *)newSuperview
{
    if(newSuperview){    //视图将要出现时的动画
        CGRect audioFrame = self.frame;
        audioFrame.origin.y = newSuperview.bounds.size.height;
        self.frame = audioFrame;
        audioFrame.origin.y = newSuperview.bounds.size.height-self.bounds.size.height;
        [UIView animateWithDuration:animationDuration animations:^{
            self.frame = audioFrame;
        }];
    } 
}

- (void)dismissFromSuperview
{
    [self stopAVPlayer]; 
    CGRect audioFrame = self.frame;
    audioFrame.origin.y = self.frame.size.height+self.frame.origin.y;
    [UIView animateWithDuration:animationDuration animations:^{
        self.frame = audioFrame;
    } completion:^(BOOL finished){
        [self removeFromSuperview]; 
    }];
}

- (void)setAudioName:(NSString *)name
{
    NSFileManager *fileManage = [NSFileManager defaultManager];
    if(![fileManage fileExistsAtPath:PathOfFileNamed(name)]){
        [self performSelector:@selector(showAlertViewWithMessage:) withObject:@"语音文件不存在" afterDelay:.5];
        return ;
    } 
    
    NSURL *audioURL = [NSURL fileURLWithPath:PathOfFileNamed(name)];
    
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:audioURL options:nil];
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:urlAsset];; 
    self.mediaPlayer = [AVPlayer playerWithPlayerItem:playerItem]; 
    [self initProcessSliderTimer];
    
    ALog(@"totalDuration %f",totalDuration);
    CMTime totalTime = playerItem.duration;  //获取音频的总时间
    totalDuration = (CGFloat)totalTime.value/totalTime.timescale;  
    [self initTimelabel]; 
    [self performSelector:@selector(startOrStopButtonAction:) withObject:startOrStopButton afterDelay:animationDuration];

    //播放视频时使用
//    AVPlayerLayer * playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.mediaPlayer]; 
//    [playerLayer setFrame:CGRectMake(0, 0, 320, 280)];  
//    [self.superview.layer addSublayer:playerLayer];
}

- (void)showAlertViewWithMessage:(NSString *)message
{
    [[[UIAlertView alloc] initWithTitle:nil
                                message:message
                               delegate:self
                      cancelButtonTitle:@"确定"
                      otherButtonTitles:nil, nil] show];
}

- (void)awakeFromNib
{
    self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"audioPlayerBg.png"]];
    [self initSlider];
}

- (CMTime)playerItemDuration
{
	AVPlayerItem *playerItem = [self.mediaPlayer currentItem];
	if (playerItem.status == AVPlayerItemStatusReadyToPlay) {
		return([playerItem duration]);
	}
	return(kCMTimeInvalid);
}

-(void)initProcessSliderTimer
{
    if(!mTimeObserver){
        CMTime time = CMTimeMake(1,1);
        __weak typeof(self) weakSelf = self;
        mTimeObserver = [self.mediaPlayer addPeriodicTimeObserverForInterval:time
                                                                       queue:NULL
                                                                  usingBlock:^(CMTime time){
                                                                      [weakSelf syncProcessSlider];
                                                                  }];
    }
    
	CMTime playerDuration = [self playerItemDuration];
	if (CMTIME_IS_INVALID(playerDuration)) {
        processSlider.value = 0;
	}
}

- (void)syncProcessSlider
{
    //实时刷新播放进度条  
	CMTime playerDuration = [self playerItemDuration];
	if (CMTIME_IS_INVALID(playerDuration)) {
		processSlider.minimumValue = 0.0;
		return;
	}
	totalDuration = CMTimeGetSeconds(playerDuration);
	if (isfinite(totalDuration)){
		float minValue = [processSlider minimumValue];
		float maxValue = [processSlider maximumValue];
		currentDuration = CMTimeGetSeconds([self.mediaPlayer currentTime]);
        [self initTimelabel];
		[processSlider setValue:(maxValue - minValue) * currentDuration / totalDuration + minValue];
	}
    if (processSlider.value == 1.0) {
        [self.mediaPlayer seekToTime:kCMTimeZero];
        [startOrStopButton setImage:[UIImage imageNamed:@"audioPlayerStart.png"] forState:UIControlStateNormal];
    }
}

- (IBAction)startOrStopButtonAction:(id)sender
{ 
    if (self.mediaPlayer.rate == 1) {
        [self.mediaPlayer pause]; 
        [startOrStopButton setImage:[UIImage imageNamed:@"audioPlayerStart.png"] forState:UIControlStateNormal];
    } else {
        [self.mediaPlayer play];
         
        [startOrStopButton setImage:[UIImage imageNamed:@"audioPlayerPause.png"] forState:UIControlStateNormal]; 
        [self initProcessSliderTimer];
    }
} 


- (void)initTimelabel
{
    //更新显示的时间
    NSString *currentTime = [self formatDateWithSecond:(int)currentDuration];
    NSString *totalTime = [self formatDateWithSecond:(int)totalDuration];
    NSString *timeString = [NSString stringWithFormat:@"%@ / %@",currentTime,totalTime];
    timeLabel.text = timeString;
}
- (NSString *)formatDateWithSecond:(int)second
{
    if(!second || second<=0){
        return @"00:00";
    }
    int hour = second/(60*60);
    int minute = (second-(60*60)*hour)/60;
    second -= (60*60)*hour+minute*60;
    
    if(hour!=0){
        return [NSString stringWithFormat:@"%02i:%02i:%02i", hour, minute, second];
    }else{
        return [NSString stringWithFormat:@"%02i:%02i", minute, second];
    }
    return nil; 
}

- (void)initSlider
{
    if([[[UIDevice currentDevice] systemVersion] floatValue]>=7.0){
        CGRect proceeFrame = processSlider.frame;
        proceeFrame.origin.y = 49;
        processSlider.frame = proceeFrame;
        CGRect volumeFrame = volumeSlider.frame;
        volumeFrame.origin.y = 49;
        volumeSlider.frame = volumeFrame;
    }
    // 自定义 UISlider 的图片
    UIImage *minImage = [UIImage imageNamed:@"audioPlayerSliderMinTrack.png"];   //进度条
    UIImage *maxImage = [UIImage imageNamed:@"audioPlayerSliderMaxTrack.png"];   //滑块的底图
    UIImage *tumbImage= [UIImage imageNamed:@"audioPlayerSliderThumb.png"];      //中间的圆形控制按钮
    
    minImage=[minImage resizableImageWithCapInsets:UIEdgeInsetsMake(2, 2, 2, 2)];
    maxImage=[maxImage resizableImageWithCapInsets:UIEdgeInsetsMake(2, 2, 2, 2)];
    
    [processSlider setMinimumTrackImage:minImage forState:UIControlStateNormal];
    [processSlider setMaximumTrackImage:maxImage forState:UIControlStateNormal];
    [processSlider setThumbImage:tumbImage forState:UIControlStateNormal]; 
    processSlider.minimumValue = 0.0;
    processSlider.maximumValue = 1.0;
    processSlider.continuous = YES; 
    
    // Attach an action to slider
    [processSlider addTarget:self action:@selector(processSliderStartDragAction:)
            forControlEvents:UIControlEventTouchDown];
	[processSlider addTarget:self action:@selector(sliderValueChangedAction:)
            forControlEvents:UIControlEventValueChanged];
	[processSlider addTarget:self action:@selector(processSliderEndDragAction:)
            forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
    
    [volumeSlider setMinimumTrackImage:minImage forState:UIControlStateNormal];
    [volumeSlider setMaximumTrackImage:maxImage forState:UIControlStateNormal];
    [volumeSlider setThumbImage:tumbImage forState:UIControlStateNormal];
    volumeSlider.minimumValue = 0.0;
    volumeSlider.maximumValue = 1.0;
    volumeSlider.continuous = YES;
    volumeSlider.value = [[MPMusicPlayerController applicationMusicPlayer] volume]; //获取系统声音的值  
    [volumeSlider addTarget:self action:@selector(sliderValueChangedAction:)
            forControlEvents:UIControlEventValueChanged];
}
- (void)processSliderStartDragAction:(id)sender
{   
    if (self.mediaPlayer.rate == 1) {
        isPlay = true;
        [self.mediaPlayer pause];
    } else{
        isPlay = false;
    }
}
- (void)processSliderEndDragAction:(id)sender
{
    //调节播放进度  
    CMTime dragedCMTime = CMTimeMake(totalDuration*processSlider.value, 1);
    [self.mediaPlayer seekToTime:dragedCMTime completionHandler:^(BOOL finish){
        if(isPlay){
            [self.mediaPlayer play];
        }
    }];
}

- (void)sliderValueChangedAction:(id)sender
{
    UISlider *targetSlider = (UISlider *)sender;
    if (targetSlider == processSlider) {
        currentDuration = totalDuration*targetSlider.value;
        [self initTimelabel]; 
    }else if (targetSlider == volumeSlider){
        float volume=[[NSString stringWithFormat:@"%.1f",volumeSlider.value] floatValue];
        [[MPMusicPlayerController applicationMusicPlayer] setVolume:volume];   //设置声音  
    } 
} 


- (void)dealloc
{
    NSLog(@"AudioPlayerView  dealloc!");
    [self stopAVPlayer]; 
}

- (void)stopAVPlayer
{
    if (self.mediaPlayer.rate == 1) {
        [self.mediaPlayer pause];
    }
    self.mediaPlayer = nil;
    mTimeObserver = nil;
}

@end


最后附上实现之后的效果:

iOS - 使用AVPlayer播放音频、视频_第2张图片

你可能感兴趣的:(iOS)