简单地音频播放 AVPlayer 供参考

这个博客展示了如何使用AVPlayer来实现音频的缓冲播放,包括设置观察者、监听播放状态、处理播放结束等关键步骤,但未能找到直接的缓冲播放方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想把音频播放做成 缓冲一些便开始播放 没有找到相关方法 有知道的朋友希望能给予指教

//

#import "AVPlayerViewController.h"


@interface AVPlayerViewController ()

{

    id timeObserve;

    NSTimer *playTimer;

}

@property (nonatomic,strong)AVPlayer *player;

@property (nonatomic,strong)AVPlayerItem *playeritem;

//@property (nonatomic, assign) BOOL isPlaying;

@property (nonatomic,strong)UISlider *sliderProgress;

@property (nonatomic,strong)UIProgressView *playerProgress;

@property (nonatomic,strong)UIImageView *backView;

@property (nonatomic,strong)UIImageView *revolveView;

@property (nonatomic,strong)UILabel *nowTimeLabel;

@property (nonatomic,strong)UILabel *totalTimeLabel;

@property (nonatomic,strong)UIButton *playButton;

@property (nonatomic,assign)BOOL play;

@property (nonatomic,assign)CGFloat playheadTime;

@property (nonatomic,assign)CGFloat totalTime;

@end


@implementation AVPlayerViewController

- (void)dealloc{

    [self.playeritemremoveObserver:self forKeyPath:@"status" context:nil];

    [self.playeritemremoveObserver:self forKeyPath:@"loadedTimeRanges" context:nil];

    [[NSNotificationCenterdefaultCenter]removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.playeritem];

    [[NSNotificationCenterdefaultCenter] removeObserver:self];

    [self.playerremoveTimeObserver:timeObserve];

}

- (void)backAction{

    [self.playerpause];

    [playTimerinvalidate];

    playTimer =nil;

    [self.navigationControllerpopViewControllerAnimated:YES];

}

- (void)viewDidLoad {

    [superviewDidLoad];

    // Do any additional setup after loading the view.

    self.view.backgroundColor = [UIColorwhiteColor];

    self.navigationItem.hidesBackButton = YES;

    self.navigationItem.leftBarButtonItem = [[UIBarButtonItemalloc] initWithTitle:@"back" style:UIBarButtonItemStylePlain target:self action:@selector(backAction)];

    //

    if (!_backView) {

        _backView = [[UIImageViewalloc] initWithFrame:CGRectMake(0,0, [UIScreenmainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width *9/16)];

        _backView.image = [UIImageimageNamed:@"2.52.01"];

        _backView.userInteractionEnabled =YES;

        UIBlurEffect *effect=[UIBlurEffecteffectWithStyle:UIBlurEffectStyleLight];

        UIVisualEffectView *efficview=[[UIVisualEffectViewalloc] initWithEffect:effect];

        efficview.frame=_backView.frame;

        [_backViewaddSubview:efficview];

        [self.viewaddSubview:_backView];

    }

    if (!_revolveView) {

        _revolveView = [[UIImageViewalloc] initWithFrame:CGRectMake([UIScreenmainScreen].bounds.size.width/2-75, [UIScreen mainScreen].bounds.size.width *9/16/2-75,150, 150)];

        [_revolveViewsetContentScaleFactor:[[UIScreenmainScreen] scale]];

        _revolveView.contentModeUIViewContentModeScaleAspectFill;

//        _revolveView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

        _revolveView.clipsToBounds  = YES;

        

        _revolveView.layer.cornerRadius =75;

        _revolveView.layer.masksToBounds =YES;

        _revolveView.layer.borderWidth =5;

        _revolveView.layer.borderColor = [UIColorcolorWithRed:0.13 green:0.13 blue:0.13 alpha:0.50].CGColor;

        _revolveView.image = [UIImageimageNamed:@"2.52.01"];

        [self.viewaddSubview:_revolveView];

    }

    if (!_nowTimeLabel) {

        _nowTimeLabel = [[UILabelalloc] initWithFrame:CGRectMake(50, [UIScreen mainScreen].bounds.size.width *9/16 -30, 50, 30)];

        _nowTimeLabel.text =@"00:00";

        _nowTimeLabel.textColor = [UIColordarkGrayColor];

        _nowTimeLabel.textAlignment =NSTextAlignmentCenter;

        _nowTimeLabel.font = [UIFontsystemFontOfSize:12];

        [_backViewaddSubview:_nowTimeLabel];

    }

    if (!_playerProgress) {

        _playerProgress = [[UIProgressViewalloc] initWithFrame:CGRectMake(102, [UIScreen mainScreen].bounds.size.width *9/16 -16, [UIScreenmainScreen].bounds.size.width - 200, 1)];

        //更改进度条高度

        _playerProgress.transform =CGAffineTransformMakeScale(1.0f,1.0f);

        _playerProgress.tintColor = [UIColorcolorWithRed:0.96 green:0.96 blue:0.96 alpha:1.00];

        [_backViewaddSubview:_playerProgress];

    }

    if (!_sliderProgress) {

        _sliderProgress = [[UISlideralloc] initWithFrame:CGRectMake(100, [UIScreen mainScreen].bounds.size.width *9/16 -30, [UIScreenmainScreen].bounds.size.width - 200, 30)];

        _sliderProgress.value =0.f;

        _sliderProgress.continuous =YES;

        _sliderProgress.tintColor = [UIColororangeColor];

        _sliderProgress.maximumTrackTintColor = [UIColorclearColor];

//         _sliderProgress.minimumTrackTintColor = [UIColor clearColor];

        [_backViewaddSubview:_sliderProgress];

        [_sliderProgresssetThumbImage:[UIImageimageNamed:@"sliderBall"] forState:UIControlStateNormal];

        [_sliderProgressaddTarget:self action:@selector(durationSliderTouch:) forControlEvents:UIControlEventTouchDown];

        [_sliderProgressaddTarget:self action:@selector(durationSliderTouchEnded:) forControlEvents:UIControlEventTouchUpInside];

    }

    if (!_totalTimeLabel) {

        _totalTimeLabel = [[UILabelalloc] initWithFrame:CGRectMake([UIScreenmainScreen].bounds.size.width -100, [UIScreenmainScreen].bounds.size.width *9/16 -30, 50, 30)];

        _totalTimeLabel.font = [UIFontsystemFontOfSize:12];

        _totalTimeLabel.text =@"00:00";

        _totalTimeLabel.textColor = [UIColordarkGrayColor];

        _totalTimeLabel.textAlignment =NSTextAlignmentCenter;

        [_backViewaddSubview:_totalTimeLabel];

    }

    if (!_playButton) {

        _playButton = [UIButtonbuttonWithType:UIButtonTypeCustom];

        _playButton.frame =CGRectMake(10, [UIScreenmainScreen].bounds.size.width *9/16 -50, 40,40);

          [ self.backViewaddSubview:_playButton];

        [_playButtonsetImage:[UIImageimageNamed:@"player_btn_pause_normal"] forState:UIControlStateNormal];

        self.play =YES;

        _playButton.userInteractionEnabled =NO;

        [_playButtonaddTarget:self action:@selector(playAction) forControlEvents:UIControlEventTouchUpInside];

    }

    [selfaddAppObserver];

    [selfplayerInit];

}

- (void)addAppObserver{

    [[NSNotificationCenterdefaultCenter]removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];

    [[NSNotificationCenterdefaultCenter]removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];

    // 应用从后台唤醒

    [[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];

    // 应用置于后台

    [[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(appDidEnterBackground:) name:UIApplicationWillResignActiveNotification object:nil];

}


#pragma mark 从某个时间开始播放

- (void)playFromTime:(double)time{

    if (self.player) {

        [selfseekToTime:time];

        [self.playerplay];

    }

}

#pragma mark 跳到某一播放帧

- (void)seekToTime:(double)time{

    if (time >=0) {

        CMTime timeStruct =CMTimeMake(time*1000,1000);

        [self.playerseekToTime:timeStruct

                  toleranceBefore:kCMTimeZero

                   toleranceAfter:kCMTimePositiveInfinity];

    }

}

#pragma mark 后台唤醒继续播放

- (void)appDidBecomeActive:(NSNotification *)notification{

    if (self.play ==YES) {

        [selfplayFromTime:self.playheadTime];

        [playTimersetFireDate:[NSDatedistantPast]];

    }

}

#pragma mark 进入后台停止播放

- (void)appDidEnterBackground:(NSNotification *)notification{

    if (self.play ==YES) {

        [selfpauseOnTime:self.playheadTime];

        [playTimersetFireDate:[NSDatedistantFuture]];

    }

}

- (void)pauseOnTime:(double)time{

    if (self.player) {

        [selfseekToTime:time];

        [self.player pause];

    }

}

#pragma mark 播放暂停按钮

- (void)playAction{

    if (self.play ==YES) {

        [self.playerpause];

        [playTimersetFireDate:[NSDatedistantFuture]];

        [_playButtonsetImage:[UIImageimageNamed:@"player_btn_play_highlight"] forState:UIControlStateNormal];

    }else{

        [self.playerplay];

         [playTimersetFireDate:[NSDatedistantPast]];

        [_playButtonsetImage:[UIImageimageNamed:@"player_btn_pause_normal"] forState:UIControlStateNormal];

    }

    self.play = !self.play;

}

#pragma mark 初始化播放器

- (void)playerInit{

    NSString *playstring =@"http://hls.360longyan.com/video/hls//audios/201607/20160704000214_935.mp3";

    self.playeritem = [[AVPlayerItemalloc] initWithURL:[NSURLURLWithString:playstring]];

    self.player = [[AVPlayeralloc] initWithPlayerItem:self.playeritem];

    [self.player.currentItemaddObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

    [self.player.currentItemaddObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];

    [self.player.currentItemaddObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];

    [[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(playbackFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];

}

#pragma mark 播放完成

- (void)playbackFinished:(NSNotification *)notice {

    self.play = !self.play;

    [_playButtonsetImage:[UIImageimageNamed:@"player_btn_play_highlight"] forState:UIControlStateNormal];

    self.sliderProgress.value = 0;

    self.nowTimeLabel.text = @"00:00";

    _playButton.userInteractionEnabled =YES;

    [playTimersetFireDate:[NSDatedistantFuture]];

    [self.playeritemseekToTime:kCMTimeZero];

}

- (void)click{

    self.revolveView.transform=CGAffineTransformRotate(self.revolveView.transform,0.0015);

}

#pragma mark 播放状态

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context {


    if ([keyPathisEqualToString:@"status"]) {

        if (self.player.status == AVPlayerStatusReadyToPlay) {

//            [self.player play];

            playTimer =   [NSTimerscheduledTimerWithTimeInterval:0.5/10000target:selfselector:@selector(click)userInfo:nilrepeats:YES];

            self.playButton.userInteractionEnabled = YES;

            [_playButtonsetImage:[UIImageimageNamed:@"player_btn_pause_normal"]forState:UIControlStateNormal];

            [selfaddVideoPlayTime];

        }elseif (self.player.status == AVPlayerStatusUnknown){

            NSLog(@"KVO:未知状态,此时不能播放");

        }elseif (self.player.status == AVPlayerStatusFailed){

            NSLog(@"KVO:加载失败,网络或者服务器出现问题");

        }

    }elseif ([keyPathisEqualToString:@"loadedTimeRanges"]) {

        NSTimeInterval timeInterval = [selfavailableDuration];//计算缓冲进度

        CMTime duration =self.playeritem.duration;

        CGFloat totalDuration =CMTimeGetSeconds(duration);

        [self.playerProgresssetProgress:timeInterval / totalDurationanimated:YES];


    }elseif ([keyPathisEqualToString:@"playbackBufferEmpty"]){

}

}


- (NSTimeInterval)availableDuration {

    NSArray *loadedTimeRanges = [[self.playercurrentItem] loadedTimeRanges];

    CMTimeRange timeRange = [loadedTimeRanges.firstObjectCMTimeRangeValue];//获取缓冲区域

    float startSeconds =CMTimeGetSeconds(timeRange.start);

    float durationSeconds =CMTimeGetSeconds(timeRange.duration);

    NSTimeInterval result = startSeconds + durationSeconds;//计算缓冲总进度

    return result;

}

#pragma mark 进度条开始滑动的时候先移除播放进度监听,防止进度小球回弹一下

- (void)durationSliderTouch:(UISlider *)slider{

 [self.playerremoveTimeObserver:timeObserve];

}

#pragma mark 获取播放器时间进度用于显示进度条和进度时间

- (void)addVideoPlayTime{

    __weakAVPlayerViewController *weakself =self;

    timeObserve =  [self.playeraddPeriodicTimeObserverForInterval:CMTimeMake(1,1) queue:dispatch_get_main_queue()usingBlock:^(CMTime time) {

        float current =CMTimeGetSeconds(time);

        float total =CMTimeGetSeconds(weakself.player.currentItem.duration);

        weakself.totalTime = total;

        if (current) {

            [weakself.sliderProgresssetValue:current / total animated:YES];

            weakself.playheadTime = current;

            double minutesElapsed = floor(fmod(current/60.0,60.0));

            double secondsElapsed = floor(fmod(current,60.0));

            weakself.nowTimeLabel.text = [NSStringstringWithFormat:@"%02.0f:%02.0f",minutesElapsed, secondsElapsed];

            double minutesRemaining;

            double secondsRemaining;

            minutesRemaining = floor(fmod(total/ 60.0,60.0));

            secondsRemaining = floor(fmod(total,60.0));

            weakself.totalTimeLabel.text = [NSStringstringWithFormat:@"%02.0f:%02.0f", minutesRemaining, secondsRemaining];

        }

    }];

}

#pragma mark 拖动进度条到指定位置播放,重新添加播放进度。

- (void)durationSliderTouchEnded:(UISlider *)slider{

    [selfperformSelector:@selector(addVideoPlayTime) withObject:self afterDelay:0.5];

       if (self.play) {

        // 如果之前是播放状态,那么继续播放

        [selfslidertoPlay:slider.value];

    }else{

        // 如果之前是是暂停状态,那么保持暂停

        [selfpauseOnpause:slider.value];

    }

}

#pragma mark 滑动进度条跳到指定位置,播放状态

- (void)slidertoPlay:(CGFloat)time{

        __weakAVPlayerViewController *weakself =self;

    if (time >=0) {

        CMTime timeStruct =CMTimeMake(time*self.totalTime*1000,1000);

        [self.playerseekToTime:timeStruct completionHandler:^(BOOL finished) {

            [weakself.playerplay];

            weakself.play =YES;

        }];

    }

}

#pragma mark 滑动进度条跳到指定位置,暂停状态

- (void)pauseOnpause:(CGFloat)time{

        __weakAVPlayerViewController *weakself =self;

    if (time >=0) {

        CMTime timeStruct =CMTimeMake(time*self.totalTime*1000,1000);

        [self.playerseekToTime:timeStruct completionHandler:^(BOOL finished) {

            [weakself.playerpause];

            weakself.play =NO;

        }];

    }

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


@end



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值