iOS - 使用AVPlayer播放音频、视频
来源:互联网 发布:yii2.0源码分析 编辑:程序博客网 时间:2024/05/17 22:37
最近有个项目需要自定义播放器界面,要求能调节声音、和播放进度并显示播放时间,效果图如下:
开始准备用AVAudioPlayer,但是不好控制播放进度,最后使用了AVPlayer ;同时也学习到了怎么自定义UISlider
需要引入的framework: AVFoundation.framework 、MediaPlayer.framework 、CoreMedia.framework
首先我定义了一个xib文件:
类的.h文件
#import <UIKit/UIKit.h>#import <AVFoundation/AVFoundation.h> #import <MediaPlayer/MediaPlayer.h>#import <CoreMedia/CoreMedia.h>@interface AudioPlayerView : UIView <AVAudioPlayerDelegate>{ __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播放音频、视频
- 视频(音频)播放 AVPlayer
- ios 使用AVPlayer自定义视频播放器
- ios 使用AVPlayer自定义视频播放器
- 使用AVPlayer播放视频
- iOS AVPlayer音频播放应用
- [IOS 开发] iOS音频篇:使用AVPlayer播放网络音乐
- [IOS 开发] iOS音频篇:使用AVPlayer播放网络音乐
- iOS音频篇:使用AVPlayer播放网络音乐
- iOS音频篇:使用AVPlayer播放网络音乐
- iOS音频篇:使用AVPlayer播放网络音乐
- iOS音频篇:使用AVPlayer播放网络音乐
- iOS 视频播放 MediaPlayer AVPlayer
- iOS 开发:AVPlayer播放视频
- iOS视频播放之AVPlayer
- iOS AVPlayer - swift视频播放
- 关于iOS网络音频播放的一些详解(使用AVPlayer播放网络音频)
- 视频播放AVPlayer的使用
- 程序与测试团队
- Tomcat从零开始(三)分离与完善
- 数组排序
- 多连块拼图
- 【原创】安装和使用 TPCC-MySQL 工具遇到的问题
- iOS - 使用AVPlayer播放音频、视频
- 段错误bug的调试
- SQL与NoSQL
- Linux下利用backtrace追踪函数调用堆栈以及定位段错误
- jQuery EasyUI API 中文文档 - 菜单按钮(menubutton)
- 对象的动态建立和释放
- 涉及多平台版本的中英文字符文件读写和转换
- jpbm简介
- 1521二叉树的镜像