iOS開發(fā)之多媒體API
播放視頻
視頻文件介紹
視頻格式可以分為適合本地播放的本地影像視頻和適合在網(wǎng)絡(luò)中播放的網(wǎng)絡(luò)流媒體影像視頻兩大類。盡管后者在播放的穩(wěn)定性和播放畫面質(zhì)量上可能沒有前者 優(yōu)秀,但網(wǎng)絡(luò)流媒體影像視頻的廣泛傳播性使之正被廣泛應用于視頻點播、網(wǎng)絡(luò)演示、遠程教育、網(wǎng)絡(luò)視頻廣告等等互聯(lián)網(wǎng)信息服務(wù)領(lǐng)域。
適合移動設(shè)備的視頻文件
3GP,3GP是一種3G流媒體的視頻編碼格式,主要是為了配合3G網(wǎng)絡(luò)的高傳輸速度而開發(fā)的,也是目前手機中最為常見的一種視頻格式。 視頻MP4格式,除了支持MP3所具有的音樂播放功能外,還具備強大的MPEG-4視頻播放能力。
iPhone中還支持mov格式文件。
iOS播放視頻
iOS sdk為播放視頻提供了非常簡便方法,提供的MPMoviePlayerViewController類作為開發(fā)使用,在iOS4以前的版本是MPMoviePlayerController。
在iPhone開發(fā)規(guī)范中禁止使用私有API播放視頻,因此播放畫面的控制的控件都是有iPhone提供好的,我們沒有別的選擇。我們能做的:
加載URL中視頻
播放、暫停視頻
用戶控制行為和縮放模式
產(chǎn)生通知
視頻播放案例
添加 MediaPlayer.framework
MoviePlayerViewController.h
- #import <MediaPlayer/MediaPlayer.h>
- @interface MoviePlayerViewController : UIViewController {
- MPMoviePlayerViewController * moviePlayerView;
- }
- @property (nonatomic, retain) MPMoviePlayerViewController * moviePlayerView;
- -(IBAction) playMovie: (id) sender;
- - (void) playingDone;
- @end
m文件的加載和卸載方法
- - (void) viewDidLoad {
- [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(playingDone) name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
- }
- - (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [moviePlayerView release];
- [super dealloc];
- }
MPMoviePlayerViewController提供了在播放過程中的狀態(tài)改變和其它事件的通知。在viewDidLoad注冊了一個播放完成的通知,常用的通知有:
MPMoviePlayerPlaybackDidFinishNotification通知接收者播放結(jié)束。
MPMoviePlayerScalingModeDidChangeNotification改變影片的尺寸。
MPMoviePlayerContentPreloadDidFinishNotification表示預處理以及完成,準備開始播放影片。
dealloc方法中的[[NSNotificationCenter defaultCenter]
removeObserver:self];影片播放完成要注銷通知。
播放事件
- - (IBAction) playMovie: (id) sender {
- moviePlayerView = [[MPMoviePlayerViewController alloc]
- initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]
- pathForResource:@"short" ofType:@"3gp"]]];
- moviePlayerView.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
- moviePlayerView.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
- // MPMovieControlStyleNone
- //MPMovieControlStyleEmbedded
- //MPMovieControlStyleDefault
- //[movieplayer play];
- //在當前view上添加視頻的視圖
- [[[UIApplication sharedApplication] keyWindow] addSubview:moviePlayerView.view];
- }
視頻文件可以播放資源目錄、沙箱目錄和網(wǎng)絡(luò)播放。本例中我們采用資源目錄。
moviePlayerView.moviePlayer屬性是MPMoviePlayerController類型,它有的controlStyle屬性
可以控制播放行為,它的取值有:
MPMovieControlStyleFullscreen
MPMovieControlStyleNone沒有播放控件
MPMovieControlStyleEmbedded
MPMovieControlStyleDefault
MPMoviePlayerController類還有scalingMode屬性用于控制影片的尺寸,它的取值有:
MPMovieScalingModeNone原始尺寸
MPMovieScalingModeAspectFit縮放到一個填充方向
MPMovieScalingModeAspectFill填充兩邊可能會切除一部分
MPMovieScalingModeFill填充兩邊可能會改變比例
播放完成
- - (void) playingDone {
- NSLog(@"播放完成");
- [moviePlayerView.view removeFromSuperview];
- [moviePlayerView release];
- moviePlayerView = nil;
- }
playingDone 方法是在影片播放完成時候調(diào)用,這是因為我們在通知中心注冊的方法。
播放完成需要把播放視圖remove這樣才可以獲得上一個屏幕。
12.2 播放音頻
12.2.1 音頻文件介紹
有兩類主要的音頻文件格式:
無損格式,例如WAV,PCM,TTA,F(xiàn)LAC,AU,APE,TAK,WavPack(WV) ,CAF
有損格式,例如MP3,Windows Media Audio(WMA),Ogg Vorbis(OGG),AAC
移動音頻文件
作為移動設(shè)備音頻文件應該原則上比較小,一般的格式:
WAV、由于無損壓縮效果最好。
MP3、有損壓縮,文件比較小,由于去除的是人類無法感應到的聲音,效果也很好。這是目前常用格式。
AAC、壓縮比例更大,比MP3文件還要小。
CAF(Core Audio Format)是Apple專用的無損壓縮格式。
12.2.2 Core Audio
高級API,易用
System Sound API –播放短聲音、警告音等。
AVFoundation 可以播放長時間聲音,簡單易用。
低級API,能夠?qū)σ纛l有更多的控制
Audio Toolbox – 錄制、播放、音頻流有全面的控制。
OpenAL – 播放立體聲,常用于游戲。
12.2.3 System Sound API
System Sound 可以播放“短的”聲音,所謂短聲音就是5秒以內(nèi)。 不循環(huán)、沒有聲音控制、立即播放。
播放格式限制:
線性PCM 和 IMA4
.caf .aif 或 .wav
播放“短聲音”
播放“短聲音”主要就是兩個步驟:
注冊聲音
- AudioServicesCreateSystemSoundID ((CFURLRef)fileURL, &myID);
播放聲音
- AudioServicesPlaySystemSound (myID);
監(jiān)聽完成事件方法
- AudioServicesAddSystemSoundCompletion
清除播放sound ID
- SystemSoundID myID;
- AudioServicesDisposeSystemSoundID (myID);
震動
也可以通過System Sound API讓iPhone震動,但是iPod touch不能震動。
震動可以通過指定一個特殊的system sound ID—— kSystemSoundID_Vibrate實現(xiàn)。
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
#p#
實例
SystemSoundServices
添加AudioToolbox.framework框架
SystemSoundServicesViewController.h文件
- #import <UIKit/UIKit.h>
- #include <AudioToolbox/AudioToolbox.h>
- @interface SystemSoundServicesViewController : UIViewController;
- - (IBAction) playSystemSound;
- - (IBAction) vibrate;
- @end
播放事件
- - (IBAction) playSystemSound{
- NSURL* system_sound_url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"BeepGMC500" ofType:@"wav"]];
- SystemSoundID system_sound_id;
- AudioServicesCreateSystemSoundID(
- (CFURLRef)system_sound_url,
- &system_sound_id
- );
- // Register the sound completion callback.
- AudioServicesAddSystemSoundCompletion(
- system_sound_id,
- NULL, // uses the main run loop
- NULL, // uses kCFRunLoopDefaultMode
- MySoundFinishedPlayingCallback, // the name of our custom callback function
- NULL // for user data, but we don't need to do that in this case, so we just pass NULL
- );
- // Play the System Sound
- AudioServicesPlaySystemSound(system_sound_id);
- }
AudioServicesAddSystemSoundCompletion方法5個參數(shù),第一參數(shù)SystemSoundID,第二參數(shù)是是否使用循環(huán),第三個參數(shù)是循環(huán)模式,第四個參數(shù)是回調(diào)函數(shù),就是當播放完成時候回調(diào)的方法,第五個參數(shù)是為回調(diào)函數(shù)提供參數(shù)。
這里回調(diào)的方法是C語言風格的函數(shù):MySoundFinishedPlayingCallback。
回調(diào)函數(shù)
- void MySoundFinishedPlayingCallback(SystemSoundID sound_id, void* user_data){
- AudioServicesDisposeSystemSoundID(sound_id);
- }
震動方法調(diào)用
- // Vibrate on action
- - (IBAction) vibrate{
- AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
- }
12.3 播放和錄制音頻
AVFoundation控件可以實現(xiàn)一般音頻播放和錄制。
AVAudioPlayer音頻播放類,用于播放大于5秒鐘聲音,可以播放本地聲音,但是不能播放網(wǎng)絡(luò)媒體文件。能夠播放、 暫停、循環(huán)和跳過等操作。
AVAudioRecorder音頻錄制類。
實例AVAudioPlayer
添加AVFoundation.framework框架
AvplayerViewController.h文件
- #import <UIKit/UIKit.h>
- #import <AVFoundation/AVFoundation.h>
- @interface AvplayerViewController : UIViewController <AVAudioPlayerDelegate> {
- AVAudioPlayer * player;
- }
- - (IBAction) stopSong: (id) sender;
- - (IBAction) playSong: (id) sender;
- @end
AvplayerViewController.m
- #import "AvplayerViewController.h"
- @implementation AvplayerViewController
- - (IBAction) playSong: (id) sender {
- NSError *error = nil;
- player = [[AVAudioPlayer alloc] initWithContentsOfURL:
- [NSURL fileURLWithPath:[[NSBundle mainBundle]
- pathForResource:@"charleston1925_64kb" ofType:@"mp3"]] error:&error];
- player.delegate = self;
- if(error) {
- NSLog(@"%@",[error description]);
- [error release];
- }
- [player play];
- }
- - (IBAction) stopSong: (id) sender {
- [player stop];
- }
- - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
- NSLog(@"播放完成。");
- }
- - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
- NSLog(@"播放錯誤發(fā)生: %@", [error localizedDescription]);
- }
- - (void)dealloc {
- [player release];
- [super dealloc];
- }
- @end
AVAudioPlayer委托
AVAudioPlayerDelegate委托對象提供了兩個主要方法:
audioPlayerDidFinishPlaying:successfully:
audioPlayerDecodeErrorDidOccur:error:
AVAudioRecorder
新建實例:Recorder
RecorderViewController.h文件
- #import <UIKit/UIKit.h>
- #import <AVFoundation/AVFoundation.h>
- @interface RecorderViewController : UIViewController
- {
- AVAudioRecorder *recorder;
- AVAudioPlayer *player;
- UILabel *label;
- }
- @property (retain, nonatomic) AVAudioRecorder * recorder;
- @property (retain, nonatomic) AVAudioPlayer * player;
- @property (retain, nonatomic) IBOutlet UILabel *label;
- -(IBAction)recordPushed:(id)sender;
- -(IBAction)playPushed:(id)sender;
- -(IBAction)stopPushed:(id)sender;
- @end
音頻錄制方法
- -(IBAction)recordPushed:(id)sender
- {
- label.text = @"recode...";
- if([recorder isRecording])
- return;
- if([player isPlaying])
- [player stop];
- NSError *error = nil;
- [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord
- error:&error];
- [[AVAudioSession sharedInstance] setActive:YES error:&error];
AVAudioSession 是iOS提供音頻會話類,音頻會話是指定應用程序與音頻系統(tǒng)如何交互。AVAudioSession 通過指定一個音頻類別(Category)實現(xiàn)的,音頻類別(Category)描述了應用程序使用音頻的方式。下面是語句是設(shè)定音頻會話類別:
[[AVAudioSession sharedInstance]setCategory:AVAudioSessionCategoryRecord error:&error];
AVAudioSessionCategoryRecord代表只能輸入音頻,即錄制音頻了。其效果是停止其它音頻播放。
使用類別后,音頻會話要設(shè)置為“活躍的”Active,這會把后臺的任何系統(tǒng)聲音關(guān)閉。
[[AVAudioSession sharedInstance] setActive:YES error:&error];
音頻錄制方法
- NSMutableDictionary *settings = [NSMutableDictionary dictionary];
- [settings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM]
- forKey:AVFormatIDKey];
- [settings setValue:[NSNumber numberWithFloat:44100.0]
- forKey:AVSampleRateKey]; //采樣率
- [settings setValue:[NSNumber numberWithInt:1]
- forKey:AVNumberOfChannelsKey];//通道的數(shù)目
- [settings setValue:[NSNumber numberWithInt:16]
- forKey:AVLinearPCMBitDepthKey];//采樣位數(shù) 默認 16
- [settings setValue:[NSNumber numberWithBool:NO]
- forKey:AVLinearPCMIsBigEndianKey];//大端還是小端 是內(nèi)存的組織方式
- [settings setValue:[NSNumber numberWithBool:NO]
- forKey:AVLinearPCMIsFloatKey];//采樣信號是整數(shù)還是浮點數(shù)
- NSString *filePath =
- [NSString stringWithFormat:@"%@/rec_audio.caf", [self documentsDirectory]];
- NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
- //[self setRecorder:nil];
- recorder = [[AVAudioRecorder alloc]
- initWithURL:fileUrl
- settings:settings
- error:&error];
- // [recorder setMeteringEnabled:YES];
- [recorder record];
- }
-(NSString *)documentsDirectory{ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); return [paths objectAtIndex:0]; }
音頻播放方法
- -(IBAction)playPushed:(id)sender{
- label.text = @"play...";
- if([recorder isRecording])
- [recorder stop];
- if([player isPlaying])
- [player stop];
- NSString *filePath =
- [NSString stringWithFormat:@"%@/rec_audio.caf", [self documentsDirectory]];
- NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
- NSError *error = nil;
- // [self setPlayer:nil];
- [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
- error:&error];
- [[AVAudioSession sharedInstance] setActive:YES error:&error];
- player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileUrl error:&error];
- // [player setMeteringEnabled:YES];
- [player play];
- }
音頻停止方法
- -(IBAction)stopPushed:(id)sender{
- label.text = @"stop...";
- if([recorder isRecording])
- [recorder stop];
- if([player isPlaying])
- [player stop];
- }