ios 開發(fā)視頻在線播放

iOS9之前使用MediaPlayer來(lái)進(jìn)行視頻的播放,iOS9之后系統(tǒng)推薦使用AVFoundation框架實(shí)現(xiàn)視頻的播放,兩者的使用都是比較簡(jiǎn)單,但是之前使用MediaPlayer播放的時(shí)候好像沒能實(shí)現(xiàn)跟優(yōu)酷視頻(或者其他視頻)一樣全屏。
1澳淑、首先定義AVPlayer、AVPlayerLayer插佛、AVPlayerItem并初始化杠巡,定義一個(gè)UIView,用于存儲(chǔ)AVPlayerLayer

@property (strong, nonatomic) AVPlayer *avPlayer;
@property (strong, nonatomic) AVPlayerLayer *avPlayerLayer;
@property (strong, nonatomic) AVPlayerItem *playerItem;
@property (strong, nonatomic) UIView *imageView;
    // 初始化player 和playerLayer
    self.avPlayer = [[AVPlayer alloc]init];
    self.avPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:self.avPlayer];
    self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200.0)];
    self.imageView.userInteractionEnabled = YES;
    self.imageView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:self.imageView];
    
    // imageView上添加playerLayer
    [self.imageView.layer addSublayer:self.avPlayerLayer];
    self.avPlayerLayer.frame = self.imageView.bounds;
    
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
    self.playerItem = [AVPlayerItem playerItemWithURL:url];
    [self.avPlayer replaceCurrentItemWithPlayerItem:self.playerItem];

播放API

[self.avPlayer play];

暫停API

[self.avPlayer pause];

重播API

[self.avPlayer replaceCurrentItemWithPlayerItem:self.playerItem];

以上代碼基本上可以實(shí)現(xiàn)視頻播放了朗涩,但是例如優(yōu)酷播放視頻里還有進(jìn)度條顯示之類的忽孽,類似下面的效果。

09807006-51E7-4FB7-B7F8-591AA7B92061.png

2谢床、其他控件定義

@property (strong, nonatomic) UIView *showTime;
@property (strong, nonatomic) UIButton *buttonFull;
@property (strong, nonatomic) UIView *maskView;
@property (strong, nonatomic) UIButton *replayBtn;
@property (strong, nonatomic) UILabel *timeLabel;
@property (strong, nonatomic) UILabel *allTimeLabel;
@property (strong, nonatomic) UISlider *slider;
@property (strong, nonatomic) NSTimer *progressTimer;
@property (strong, nonatomic) UIButton *playOrPauseBtn;

3兄一、實(shí)現(xiàn)進(jìn)度條效果
一下實(shí)現(xiàn)進(jìn)度條頁(yè)面的主要代碼

- (UIView *)showTime{
    if (_showTime == nil) {
        _showTime = [[UIView alloc] init];
        _showTime.backgroundColor = [UIColor colorWithWhite:1 alpha:0.0];
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button setImage:[UIImage imageNamed:@"full_play_btn_hl"] forState:UIControlStateNormal];
        button.frame = CGRectMake(10, 5, 30, 30);
        [button setImage:[UIImage imageNamed:@"full_pause_btn"] forState:UIControlStateSelected];
        [button addTarget:self action:@selector(player:) forControlEvents:UIControlEventTouchUpInside];
        [_showTime addSubview:button];
        _playOrPauseBtn = button;
        
        UIButton *buttonFull = [UIButton buttonWithType:UIButtonTypeCustom];
        [buttonFull setImage:[UIImage imageNamed:@"mini_launchFullScreen_btn_hl"] forState:UIControlStateNormal];
        [buttonFull setImage:[UIImage imageNamed:@"full_minimize_btn_hl"] forState:UIControlStateSelected];
        [buttonFull addTarget:self action:@selector(fullScreen:) forControlEvents:UIControlEventTouchUpInside];
        [_showTime addSubview:buttonFull];
        _buttonFull = buttonFull;
        
        _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(button.frame) + 10.0, 0, 40.0, 40.0)];
        _timeLabel.textColor = [UIColor whiteColor];
        _timeLabel.font = [UIFont systemFontOfSize:14.0];
        [_showTime addSubview:_timeLabel];
        
        _allTimeLabel = [[UILabel alloc] init];
        _allTimeLabel.textColor = [UIColor whiteColor];
        _allTimeLabel.font = [UIFont systemFontOfSize:14.0];
        [_showTime addSubview:_allTimeLabel];
        
        _slider = [[UISlider alloc] init];
        _slider.tintColor = [UIColor redColor];
        [_slider setThumbImage:[UIImage imageNamed:@"thumbImage"] forState:UIControlStateNormal];
        [_slider addTarget:self action:@selector(touchDownSlider:) forControlEvents:UIControlEventTouchDown];
        [_slider addTarget:self action:@selector(valueChangedSlider:) forControlEvents:UIControlEventValueChanged];
        [_slider addTarget:self action:@selector(touchUpInside:) forControlEvents:UIControlEventTouchUpInside];
        [_showTime addSubview:_slider];
        
        [self setShowTimeFrame];
    }
    return _showTime;
}

frame布局

- (void)setShowTimeFrame{
    self.showTime.frame = CGRectMake(0, self.imageView.frame.size.height-40.0, [UIScreen mainScreen].bounds.size.width, 40);
    self.buttonFull.frame = CGRectMake(_showTime.frame.size.width-30-10, 5, 30, 30);
    self.maskView.frame = self.imageView.bounds;
    self.replayBtn.center = self.maskView.center;
    self.allTimeLabel.frame = CGRectMake([UIScreen mainScreen].bounds.size.width-45-40, 0, 40.0, 40.0);
    self.slider.frame = CGRectMake(0, 0, _showTime.frame.size.width, 1);
}
- (UIView *)maskView{
    if (_maskView == nil) {
        _maskView = [[UIView alloc] init];
        _replayBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [_replayBtn setImage:[UIImage imageNamed:@"player"] forState:UIControlStateNormal];
        [_replayBtn setImage:[UIImage imageNamed:@"chongbo"] forState:UIControlStateSelected];
        [_replayBtn addTarget:self action:@selector(resetPlay:) forControlEvents:UIControlEventTouchUpInside];
        _replayBtn.bounds = CGRectMake(0, 0, 50, 50);
        [_maskView addSubview:_replayBtn];
    }
    return _maskView;
}

4、實(shí)現(xiàn)定時(shí)功能识腿,進(jìn)度條滾動(dòng)
定時(shí)器主要用于進(jìn)度條的滾動(dòng)出革,這里的NSRunLoop使用NSRunLoopCommonModes,這樣的話如果使用tableView的話渡讼,當(dāng)tableView滾動(dòng)時(shí)視頻還能繼續(xù)播放骂束。

- (NSTimer *)progressTimer{
    if (_progressTimer == nil) {
        _progressTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateProgressInfo) userInfo:nil repeats:YES];
        [[NSRunLoop mainRunLoop] addTimer:_progressTimer forMode:NSRunLoopCommonModes];
    }
    return _progressTimer;
}
/** 移除定時(shí)器 */
-(void)removeProgressTimer{
    [self.progressTimer invalidate];
    self.progressTimer = nil;
}

5、實(shí)現(xiàn)進(jìn)度條功能
開始拖動(dòng)時(shí)成箫,要移除定時(shí)監(jiān)聽器

/** slider拖動(dòng)和點(diǎn)擊事件 */
- (void)touchDownSlider:(UISlider *)sender {
    // 按下去 移除監(jiān)聽器
    [self removeProgressTimer];
}
- (void)valueChangedSlider:(UISlider *)sender {
    
    // 計(jì)算slider拖動(dòng)的點(diǎn)對(duì)應(yīng)的播放時(shí)間
    NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration) * sender.value;
    self.timeLabel.text = [self timeToStringWithTimeInterval:currentTime];
}
- (void)touchUpInside:(UISlider *)sender {
    [self progressTimer];
    //計(jì)算當(dāng)前slider拖動(dòng)對(duì)應(yīng)的播放時(shí)間
    NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration) * sender.value;
    // 播放移動(dòng)到當(dāng)前播放時(shí)間
    [self.avPlayer seekToTime:CMTimeMakeWithSeconds(currentTime, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
//    [self addShowTime];
}

6展箱、定時(shí)器方法

/** 轉(zhuǎn)換播放時(shí)間和總時(shí)間的方法 */
-(NSString *)timeToStringWithTimeInterval:(NSTimeInterval)interval;{
    NSInteger Min = interval / 60;
    NSInteger Sec = (NSInteger)interval % 60;
    NSString *intervalString = [NSString stringWithFormat:@"%02ld:%02ld",Min,Sec];
    return intervalString;
}

/** 更新slider和timeLabel */
- (void)updateProgressInfo {
    NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentTime);
    NSTimeInterval durationTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration);
    
    self.timeLabel.text = [self timeToStringWithTimeInterval:currentTime];
    self.allTimeLabel.text = [self timeToStringWithTimeInterval:durationTime];
    self.slider.value = CMTimeGetSeconds(self.avPlayer.currentTime) / CMTimeGetSeconds(self.avPlayer.currentItem.duration);
    
    
    if (self.slider.value == 1) {
        [self removeProgressTimer];
        self.replayBtn.selected = YES;
        self.maskView.hidden = NO;
        self.replayBtn.hidden = NO;
        NSLog(@"播放完了");
    }
    
}

7、播放和暫停視頻播放
這里的maskView主要是用于顯示

/** 播放暫停 */
- (void)player:(UIButton *)sender{
    
    if (sender.selected == YES) {//暫停
        [self.avPlayer pause];
        [self removeProgressTimer];
        self.maskView.hidden = NO;
        self.replayBtn.hidden = NO;
        self.replayBtn.selected = NO;
    }else{
        self.replayBtn.selected = YES;
        self.maskView.hidden = YES;
        self.replayBtn.hidden = YES;
        [self progressTimer];
        [self.avPlayer play];
    }
    sender.selected = !sender.selected;
}

8蹬昌、全屏播放
全屏播放主要是當(dāng)前控制器present到另一個(gè)控制器
新建控制器混驰,并修改控制器的方向
下面是全屏控制器,修改控制器方面的代碼

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
/** 全屏按鈕 */
- (void)fullScreen:(UIButton *)sender{
    if (sender.selected == NO) {
        [self presentViewController:self.fullVc animated:NO completion:^{
            [self.fullVc.view addSubview:self.imageView];
            self.imageView.center = self.fullVc.view.center;
            
            [UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
                self.imageView.frame = self.fullVc.view.bounds;
                [self layoutFrame];
                [self fullscreenOrNotFullScreen];
            } completion:nil];
        }];
    }else{
        [self.fullVc dismissViewControllerAnimated:NO completion:^{
            [self.view addSubview:self.imageView];
            
            [UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^{
                self.imageView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 200.0);
                [self layoutFrame];
                [self fullscreenOrNotFullScreen];
            } completion:nil];
        }];
    }
    sender.selected = !sender.selected;
}
- (void)fullscreenOrNotFullScreen{
    self.replayBtn.selected = NO;
    [self resetPlay:_replayBtn];
}


下面是非全屏播放控制器設(shè)置控制器方向

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return NO;
}

9皂贩、重新播放
視頻播放完成之后栖榨,點(diǎn)擊按鈕重新播放

/** 重新播放 */
- (void)resetPlay:(UIButton *)sender{
    if (sender.isSelected) {
        self.slider.value = 0.0;
        self.playOrPauseBtn.selected = YES;
        [self.avPlayer replaceCurrentItemWithPlayerItem:self.playerItem];
        //計(jì)算當(dāng)前slider拖動(dòng)對(duì)應(yīng)的播放時(shí)間
        NSTimeInterval currentTime = CMTimeGetSeconds(self.avPlayer.currentItem.duration) * self.slider.value;
        // 播放移動(dòng)到當(dāng)前播放時(shí)間
        [self.avPlayer seekToTime:CMTimeMakeWithSeconds(currentTime, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
    }else{
        self.playOrPauseBtn.selected = YES;
    }
    [self removeProgressTimer];
    [self.avPlayer play];
    [self progressTimer];
    sender.selected = YES;
    sender.hidden = YES;
    self.maskView.hidden = YES;
}

注意:當(dāng)最初當(dāng)前控制器的之后記得要移除監(jiān)聽器和停止播放

[self removeProgressTimer];
    [self.avPlayer pause];

目前demo在cocoaChina審核中,等審核通過(guò)會(huì)貼上網(wǎng)址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末明刷,一起剝皮案震驚了整個(gè)濱河市婴栽,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辈末,老刑警劉巖愚争,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件映皆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡准脂,警方通過(guò)查閱死者的電腦和手機(jī)劫扒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門檬洞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)狸膏,“玉大人,你說(shuō)我怎么就攤上這事添怔⊥宕粒” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵广料,是天一觀的道長(zhǎng)砾脑。 經(jīng)常有香客問我,道長(zhǎng)艾杏,這世上最難降的妖魔是什么韧衣? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮购桑,結(jié)果婚禮上畅铭,老公的妹妹穿的比我還像新娘。我一直安慰自己勃蜘,他們只是感情好硕噩,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缭贡,像睡著了一般炉擅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阳惹,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天谍失,我揣著相機(jī)與錄音,去河邊找鬼莹汤。 笑死快鱼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的体啰。 我是一名探鬼主播攒巍,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼荒勇!你這毒婦竟也來(lái)了柒莉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤沽翔,失蹤者是張志新(化名)和其女友劉穎兢孝,沒想到半個(gè)月后窿凤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跨蟹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年雳殊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窗轩。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夯秃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痢艺,到底是詐尸還是另有隱情仓洼,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布堤舒,位于F島的核電站色建,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏舌缤。R本人自食惡果不足惜箕戳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望国撵。 院中可真熱鬧陵吸,春花似錦、人聲如沸卸留。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春桥帆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谆构。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留框都,地道東北人搬素。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像魏保,于是被迫代替她去往敵國(guó)和親熬尺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容