iOS 音频播放
- 本地音频文件 AVPlayer / AVAudioPlayer
- 在线音频流 AVPlayer
- iPod 歌曲 AVPlayer / AVAudioPlayer / MPMusicPlayerController
- 音效 AudioServices
iPod 音乐
- iPod 歌曲的读取
-
MPMediaPickerController
系统封装的, 包括 UI -
MPMediaLibrary + MPMediaQuery
系统封装的读取类, 不包含 UI
-
- iPod 歌曲的读取权限
- 权限相关接口: iOS 9.3+
- iPod 读取权限弹窗: iOS 9.3+ 暂时不会直接提醒弹窗权限, 在 iOS10 加入了弹窗
- 权限用途的说明文案: iOS 10+; Xcode 8+ 必须要在 info.plist 写明
NSAppleMusicUsageDescription
- 使用 MPMediaPickerController 读取
@interface MPMediaPickerController : UIViewController
@property (nonatomic, readonly) MPMediaType mediaTypes;
@property (nonatomic, weak, nullable) id delegate;
@property (nonatomic) BOOL allowsPickingMultipleItems;
@property (nonatomic) BOOL showsCloudItems;
@property (nonatomic) BOOL showsItemsWithProtectedAssets;
@property (nonatomic, copy, mullable) NSString *prompt;
@protocol MPMediaPickerControllerDelegate
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection;
- (void)mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker;
@interface MPMediaItemCollection : MPMediaEntity
@interface MPMediaItem : MPMediaEntity
-
[musicPlayer prepareToPlay]
将选中的音乐放进播放列表中- 直接调用
play
方法也可以达到将歌曲放入播放列表中的效果
- 直接调用
-
播放状态
/*** MPMusicPlaybackState ***/ MPMusicPlaybackStateStopped MPMusicPlaybackStatePlaying // 播放 MPMusicPlaybackStatePaused // 暂停 MPMusicPlaybackStateInterrupted // 中断状态 MPMusicPlaybackStateSeekingForward // 线控时播放状态 MPMusicPlaybackStateSeekingBackword // 线控时播放状态
-
播放状态的通知
MPMusicPlayerControllerPlaybackStateDidChangeNotification
播放进度
-
切歌
@interface MPMusicPlayerController (MPPlaybackControl) - (void)skipToNextItem; // 下一曲 - (void)skipToPreviousItem; // 上一曲
-
播放模式
repeatMode MPMusicRepeatModeDefault MPMusicRepeatModeNone MPMusicRepeatModeOne MPMusicRepeatModeAll shuffleMode MPMusicShuffleModeDefault MPMusicShuffleModeOff MPMusicShuffleModeSongs MPMusicShuffleModeAlbums
-
定义自己的播放模式
typedef NS_ENUM (NSUInteger, AudioPlayerMode) { AudioPlayerModeRepeat, AudioPlayerModeSingle, AudioPlayerModeRandom, } - (void)setMode:(AudioPlayerMode)mode { _mode = mode; if (mode == AudioPlayerModeRepeat) { _musicPlayer.repeatMode = MPMusicRepeatModeAll; _musicPlayer.shuffleMode = MPMusicShuffleModeOff; } else if (mode == AudioPlayerModeSingle) { _musicPlayer.repeatMode = MPMusicRepeatModeOne; _musicPlayer.shuffleMode = MPMusicShuffleModeOff; } else if (mode == AudioPlayerModeRandom) { _musicPlayer.repeatMode = MPMusicRepeatModeAll; _musicPlayer.shuffleMode = MPMusicShuffleModeSongs; } }
-
applicationMusicPlayer & systemMusicPlayer
- 都是调用系统的音乐 app 进行播放
- 不同
- applicationMusicPlayer 不会改变系统正在播放的歌曲
- systemMusicPlayer 会改变系统自动播放的歌曲, 相当于直接在系统音乐中进行播放
优势
- 接口完全封装, 使用简单
- 不关心播放模式, 播放列表的维护
- 不关心其他的问题, 例如打断
问题
- 只能播放 iPod 歌曲
- 不是自己的 app 在后台播放, 而是调用系统的音乐 app 在播放
- 进入系统选歌界面或者使用 MPMediaLibrary 歌曲会停止, 播放列表会清空
自行实现 iPod 歌曲选择
- MPMediaLibrary
类型 | 资源 | 类 |
---|---|---|
在线音频流 | 音频 URL | AVURLAsset |
本地音频文件 | 音频文件 | AVURLAsset |
iPod 歌曲 | Music.app 中的歌曲 | MPMediaItem |
-
Metadata
- 音频信息
- 歌名
- 专辑
- 歌手
- 封面图
- 音频数据 - 听到的音乐
- 音频信息
-
commonMetadata & metadata
- commonMetadata 共有格式的数据内容
- metadata 不一定通用的格式
AVPlayer
- 在线
- 本地
- iPod
AVPlayerItem
- 代表一个播放对象
- 加载状态
- 播放总时长
- 进行 seek 操作
AVQueuePlayer
初始化
- 在线歌曲不能获取 metadata, 所以对于在线歌曲就不获取 metadata
- 使用 rate 控制播放状态
- 使用在线音频的时候不能直接做立即播放
AudioSession
后台播放
- Set AudioSession Category & Active
- Set App Background Mode
- [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]
管理输入输出设备
NowPlayingCenter
录音
AudioSession
- 获取录音权限 + 填写使用理由
AVAudioSessionRecordPermission permission = [[AVAudioSession sharedInstance] recordPermission];
- set Category
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
- set Active
[[AVAudioSession sharedInstance] setActive:YES error:nil];
- 处理打断或设备更换
AVAudioRecorder
#import
NSString *const AVNumberOfChannelsKey; // 声道数
NSString *const AVSampleRateKey; // 采样率
NSString *const AVLinearPCMBitDepthKey; // 位声
NSString *const AVFormatIDKey;
/* ------ AVFormatIDKey ------
kAudioFormatLinearPCM = 'lpcm'
kAudioFormatApplelMA4 = 'ima4'
kAudioFormatMPEG4AAc = 'aac'
kAudioFormatULaw = 'ulaw'
kAudioFormatALaw = 'alaw'
kAudioFormatAppleLossless = 'alac'
*/
- PCM 文件: 最原始的未经过处理的录音文件
- 等同于: WAV
- 压缩成: AAC, MP3(有损压缩), FLAC(无损压缩), ...
- iOS 不能直接录制成 MP3 格式
NSString *filePath = [NSTemporaryDirectory() stringByAppendingFileComponent:@"tempRecord.aac"];
NSDictionary *settings = @{
AVNumberOfChannelsKey : @1,
AVSampleRateKey : @8000,
AVLinearPCMBitDepthKey : @16,
AVFormatIDKey : @(kAudioFormatMPEG4AAC)
};
NSError *error = nil;
// 生成 recorder
_recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:filePath] settings:settings error:&error];
创建文件
开始录音
- (BOOL)preparedToRecord;
- (BOOL)record;
- (BOOL)recordAtTime:(NSTimeInterval)time; // 开始时间
- (BOOL)recordForDuration:(NSTimeInterval)duration; // 录音时长
- (BOOL)recordAtTime:(NSTimeInterval)time forDuration:(NSTimeInterval)duration;
录音停止和文件操作
- (void)pause;
- (void)stop;
- (BOOL)deleteRecording;
@property BOOL recording;
@property NSURL *url;
@property NSTimeInterval currentTime; // 当前录音进行的时间
AVAudioPlayer
- 不支持播放模式
- 调整左右声道
- 调整播放器内部的音量
- 调整播放速率
- 读取播放歌曲的数据参数, 例如采样率
- 读取某个时间点的歌曲声音大小
资源类型
类型 | 资源 | 类 |
---|---|---|
在线音频流 | 音频 URL | AVURLAsset |
本地音频文件 | 音频文件 | AVURLAsset |
iPod歌曲 | Music.app中的歌曲 | MPMediaItem |
AVURLAsset �: AVAsset
/* AVAsset */
@interface AVAsset : NSObject
+ assetWithURL:(NSURL *)URL;
@property (notatomic, readonly) CMTime duration;
@property NSArray *commomMetadata;
@property NSArray *metadata;
/* AVURLAsset */
@interface AVURLAsset : AVAsset
+ URLAssetWithURL: options: ;
- initWithURL: options: ;
@property NSURL *URL;
// 继承子 AVAsset 后提供了两个初始化方法
// 提供 URL 属性的访问
// 提供 metadata 的读取
Metadata
- 音频数据 : 听到的音乐
- 音频信息 : 歌名, 专辑, 歌手, 封面 等
创建 AVURLAsset
- 三种资源转换成 AVURLAsset
// 在线音频
NSURL *audioURL = [NSURL URLWithString:@"http://xxx.com/music.mp3"];
AVURLAsset *audioAsset = [AVURLAsset assetWithURL:audioURL];
// 本地音频
NSString *filePath = [[NSBundle mainBundle] pathForResources:@"music" ofType:@"mp3"];
NSURL *fileURL = [NSURL fireURLWithPath:filePath];
AVURLAsset *fileAsset = [AVURLAsset assetWithURL:fileURL];
// iPod 音频
MPMediaQuery *query = [MPMediaQuery songsQuery];
if (query.items.count > 0) {
MPMediaItem *item = query.item[0];
AVURLAsset *iPodAsset = [AVURLAsset assetWithURL:item.assetURL];
}
AVAudioPlayer
- 初始化方法
- 尽量使用带有 fileTypeHint 的初始化方法, 并填入 hint
- 如果使用 URL 作为参数, 尽量让其带有后缀名, 例如: xxx.mp3
- 使用 URL 作为参数时只能是本地文件的 URL, 不能是网络 URL 地址
@interface AVAudioPlayer : NSObject
- initWithContentOfURL: error: ;
- initWithData: error: ;
- initWithContentOfURL: fileTypeHint: error: ; // 表示单个歌曲
- initWithData: fileTypeHint: error: ;
- fileTypeHint : 文件类型的判断, 帮助解码器判断, 使得解码不容易出错