当前位置: 首页 > news >正文

IOS流媒体播放

 

IOS流媒体播放

1. 这里的流媒体地址是指服务端那边已经调好格式的可以在ios上播放的视频流。

下面提供几个视频流的地址:

NSString *linkStr = 

http://61.160.227.6/rtencode_m3u8?bl=/f4v/61/140783661.h264_2.f4v&t=8&em=1&se=c629000050724fef&k=8bb5b375af9ab17fa859074fb394455fcd7505",

@"http://61.160.230.12/rtencode_m3u8?bl=/f4v/85/140698785.h264_2.f4v&t=8&em=1&se=b245000050723fb4&k=0dfa39da8293f0684c6cd84fb395905fcd7505",

@"http://58.215.144.42/rtencode_m3u8?bl=/f4v/46/140739646.h264_1.f4v&t=8&em=1&se=751300005072e2d8&k=8d77cf2355c3bf817f6e364fb396005fcd7505“

 @"http://ocj2.smgbb.cn/ocj1/ocj1.m3u8"

 @"http://ocj2.smgbb.cn/ocj2/ocj2.m3u8"

 

2.播放视频

  CustomPlayerView.h 文件

 

  #import <UIKit/UIKit.h>

  #import <AVFoundation/AVFoundation.h>

 

  @interface CustomPlayerView : UIView

  @property(nonatomic,retainAVPlayer *player;

  @end

  CustomPlayerView.m 文件

  #import "CustomPlayerView.h"

 

  @implementation CustomPlayerView

  +(Class)layerClass{

      return [AVPlayerLayer class];

  }

 

  -(AVPlayer*)player{

      return [(AVPlayerLayer*)[self layer]  player];

  }

 

  -(void)setPlayer:(AVPlayer *)thePlayer{

      return [(AVPlayerLayer*)[self layer]  setPlayer:thePlayer];

  }

  @end

 

  CustomMoviePlayerController.h 文件

  #import <UIKit/UIKit.h>

  #import "CustomPlayerView.h"

  #import "MBProgressHUD.h"

 

  @interface CustomMoviePlayerController : UIViewController<UIPopoverControllerDelegate>{

      IBOutlet CustomPlayerView *moviePlayeView;

      IBOutlet UIButton *playButton;

      IBOutlet UISlider *movieProgressSlider;

      //视频的总时间

      CGFloat totalMovieDuration;

      IBOutlet UILabel *currentTimeLabel;

      IBOutlet UILabel *totalTimeLabel;

      MBProgressHUD *loadingView;

  }

  @property(nonatomic,retainNSURL *movieURL;

  -(IBAction)doneClick:(id)sender;

  -(IBAction)playClick:(id)sender;

  -(IBAction)movieProgressDragged:(id)sender;

  @end

CustomMoviePlayerController.m文件

//

//  CustomMoviePlayerController.m

//  VideoStreamDemo2

//

   

                 

 

#import "CustomMoviePlayerController.h"

 

@interfaceCustomMoviePlayerController()

-(void)initPlayer;

-(void)monitorMovieProgress;

-(NSString*)convertMovieTimeToText:(CGFloat)time;

-(void)initMoviewPreview;

-(CustomPlayerView*)previewViewCreate:(CGFloat)xOffsetInSlider;

@end

 

@implementation CustomMoviePlayerController

@synthesize movieURL;

#pragma mark - View lifecycle

 

- (void)viewDidLoad

{

    [superviewDidLoad];

    // Do any additional setup after loading the view from its nib.

    loadingView = [[MBProgressHUDalloc]initWithView:self.view];

    loadingView.labelText = @"正在加载...";

    [self.view  addSubview:loadingView];

    [self  initPlayer];

    [self  monitorMovieProgress];

    [self   initMoviewPreview];

 

}

 

- (void)dealloc {

    [movieURL release];

    [loadingViewrelease];

    //释放对视频播放完成的监测

    [[NSNotificationCenterdefaultCenter]removeObserver:selfname:AVPlayerItemDidPlayToEndTimeNotificationobject:moviePlayeView.player.currentItem];

    //释放掉对playItem的观察

    [moviePlayeView.player.currentItemremoveObserver:self

                                           forKeyPath:@"status" 

                                              context:nil];

    [moviePlayeViewrelease];

    [super dealloc];

}

 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

{

    // Return YES for supported orientations

    return interfaceOrientation!=UIInterfaceOrientationPortraitUpsideDown;

}

 

-(void)initPlayer{

    //显示loadingView

    [loadingView  show:YES];

    //使用playerItem获取视频的信息,当前播放时间,总时间等

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:movieURL];

    //player是视频播放的控制器,可以用来快进播放,暂停等

    AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];

    [moviePlayeView setPlayer:player];

    [moviePlayeView.player  play];

    //计算视频总时间

    CMTime totalTime = playerItem.duration;

    //因为slider的值是小数,要转成float,当前时间和总时间相除才能得到小数,因为5/10=0

    totalMovieDuration = (CGFloat)totalTime.value/totalTime.timescale;

    //NSLog(@"totalMovieDuration:%f",totalMovieDuration);

    //在totalTimeLabel上显示总时间

    totalTimeLabel.text = [selfconvertMovieTimeToText:totalMovieDuration];

    

    //检测视频加载状态,加载完成隐藏loadingView

    [moviePlayeView.player.currentItemaddObserver:self

                                        forKeyPath:@"status" 

                                           options:NSKeyValueObservingOptionNew

                                           context:nil];

    //添加视频播放完成的notifation

    [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(moviePlayDidEnd:)name:AVPlayerItemDidPlayToEndTimeNotificationobject:moviePlayeView.player.currentItem];

}

 

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

//    NSLog(@"keyPath:%@,object:%@",keyPath,NSStringFromClass([object class]));

    if ([keyPath isEqualToString:@"status"]) {

        AVPlayerItem *playerItem = (AVPlayerItem*)object;

        if (playerItem.status==AVPlayerStatusReadyToPlay) {

            //视频加载完成,隐藏loadingView

            [loadingView hide:YES];

        }

    }

}

 

-(NSString*)convertMovieTimeToText:(CGFloat)time{

    //把秒数转换成文字

    if (time<60.f) {

        return [NSString stringWithFormat:@"%.0f",time];

    }else{

        return [NSString stringWithFormat:@"%.2f",time/60];

    }

}

 

-(void)monitorMovieProgress{

    //使用movieProgressSlider反应视频播放的进度

    //第一个参数反应了检测的频率

    [moviePlayeView.playeraddPeriodicTimeObserverForInterval:CMTimeMake(11)queue:NULLusingBlock:^(CMTime time){

        //获取当前时间

        CMTime currentTime = moviePlayeView.player.currentItem.currentTime;

        //转成秒数

        CGFloat currentPlayTime = (CGFloat)currentTime.value/currentTime.timescale;

        movieProgressSlider.value = currentPlayTime/totalMovieDuration;

        //用label显示当前播放的秒数

        //判断秒数是否满一分钟,如果不满一分钟显示秒,如果满一分钟,显示分钟

        currentTimeLabel.text = [self convertMovieTimeToText:currentPlayTime];

        //NSLog(@"currentTimeLabel.text:%@",currentTimeLabel.text);

    }];

}

 

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

    //视频播放完成,回退到视频列表页面

    [self doneClick:nil];

}

 

-(IBAction)doneClick:(id)sender{

    //停止播放,不然页面dimiss了以后,还有播放的声音

    [moviePlayeView.playerpause];

    [selfdismissModalViewControllerAnimated:YES];

}

 

-(IBAction)playClick:(id)sender{

    //播放暂停控制,进入页面就开始播放视频,然后播放按钮的文字是暂停

    //点击一下播放视频停止,按钮文字变成播放

    //判断是播放还是暂停状态

    if ([[playButtontitleForState:UIControlStateNormal]isEqualToString:@"暂停"]) {

        //从播放状态进入暂停

        [moviePlayeView.playerpause];

        [playButtonsetTitle:@"播放"forState:UIControlStateNormal];

    }else{

        //从暂停状态进入播放

        [moviePlayeView.playerplay];

        [playButtonsetTitle:@"暂停"forState:UIControlStateNormal];

    }

}

 

-(IBAction)movieProgressDragged:(id)sender{

    //拖动改变视频播放进度

    //计算出拖动的当前秒数

    NSInteger dragedSeconds = floorf(totalMovieDuration*movieProgressSlider.value);

    NSLog(@"dragedSeconds:%d",dragedSeconds);

    //转换成CMTime才能给player来控制播放进度

    CMTime dragedCMTime = CMTimeMake(dragedSeconds, 1);

    [moviePlayeView.playerpause];

    [moviePlayeView.player seekToTime:dragedCMTime completionHandler:^(BOOL finish){

        [moviePlayeView.playerplay];

    }];

}

 

//长按手势

-(void)initMoviewPreview{

    UILongPressGestureRecognizer *longPress =          [[UILongPressGestureRecognizeralloc]initWithTarget:selfaction:@selector(progessSliderLongPress:)];

    [movieProgressSlideraddGestureRecognizer:longPress];

    [longPress release];

}

 

-(void)progessSliderLongPress:(UILongPressGestureRecognizer*)theLong{

    //因为长按手势的方法最少会被调用两次,所以为了不重复弹出popOver进行判断,只调用一次弹出popOver

    if (theLong.state==UIGestureRecognizerStateBegan) {

        //长按以后弹出popView在长按的位置

        CGPoint touchPoint = [theLong locationInView:self.view];

        //只能显示在进度条上方

        CGRect popOverFrame = CGRectMake(touchPoint.x-100, movieProgressSlider.frame.origin.y, 200, 150);

        UIViewController *previewMovieController = [[UIViewController alloc]init];

        //通过长按手势在slider的位置,计算视频预览的时间

        CGPoint touchPointInSlider = [theLong locationInView:movieProgressSlider];

        CustomPlayerView *previewView = [self previewViewCreate:touchPointInSlider.x];

        

        previewMovieController.view.backgroundColor = [UIColor whiteColor];

                previewMovieController.view = previewView;

        UIPopoverController *popoverController = [[UIPopoverControlleralloc]initWithContentViewController:previewMovieController];

        //更改popover的contentSize

        popoverController.delegate = self;

        popoverController.popoverContentSize = CGSizeMake(200, 150);

        //箭头向下,指向进度条

        [popoverController presentPopoverFromRect:popOverFrameinView:self.viewpermittedArrowDirections:UIPopoverArrowDirectionDownanimated:YES];

        //播放视频

        [previewView.player play];

        [previewMovieController release];

        //不能在这里使用release和autorelease,因为popOver正在使用,release会导致crash

        //[popoverController release];

    }

}

 

//为了使调用视频预览的代码更清晰,把创建playerView的代码和创建popover的分开

-(CustomPlayerView*)previewViewCreate:(CGFloat)xOffsetInSlider{

    //        NSLog(@"touchPoint:%@,touchPointInSlider:%@",NSStringFromCGPoint(touchPoint),NSStringFromCGPoint(touchPointInSlider));

    //把touchPointInSlider。x除以slider的宽度可以计算出预览的进度

    CGFloat previewValue = xOffsetInSlider/movieProgressSlider.bounds.size.width;

    //如果长按在进度条的中间,那么previewValue就是0。5,乘以视频的总时间,就知道了视频预览的时间

    NSInteger previewSeconds = floorf(previewValue*totalMovieDuration);

    //秒数舍弃小数部分,转换成cmTime

    CMTime previewCMTime = CMTimeMake(previewSeconds, 1);

    //初始化视频预览的view

    CustomPlayerView *previewView = [[CustomPlayerView alloc]initWithFrame:CGRectMake(0, 0, 200, 150)];

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:movieURL];

    //跳到视频预览的时间

    [playerItem seekToTime:previewCMTime];

    //player是视频播放的控制器,可以用来快进播放,暂停等

    AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];

    [previewView setPlayer:player];

    return [previewView autorelease];

}

 

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{

    //popOver已经使用完毕,release是可以的

    [popoverController release];

}

@end

 

转载于:https://www.cnblogs.com/iOS-mt/p/4325202.html

相关文章:

  • 云安全概述与发展趋势
  • Android存储访问及目录
  • 单任务现象
  • Houdini中总结Volume Lattice的方法
  • 添加树莓派python程序自启动的方法
  • 开源Math.NET基础数学类库使用(01)综合介绍
  • webapi返回json字符串
  • Hash小结
  • css 清除浮动样式
  • linux shadow破解
  • 大学生如何看待校园考勤
  • Android中ListView结合CheckBox判断选中项
  • 常用Linux命令
  • ETCD 安装及使用
  • Server.MapPath和Request.PhysicalApplicationPath的异同
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • express如何解决request entity too large问题
  • HTML5新特性总结
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • Intervention/image 图片处理扩展包的安装和使用
  • iOS | NSProxy
  • JavaScript实现分页效果
  • Java超时控制的实现
  • Java基本数据类型之Number
  • java小心机(3)| 浅析finalize()
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Netty 4.1 源代码学习:线程模型
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • vue自定义指令实现v-tap插件
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 什么是Javascript函数节流?
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 我从编程教室毕业
  • 延迟脚本的方式
  • nb
  • ​Spring Boot 分片上传文件
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #WEB前端(HTML属性)
  • (2020)Java后端开发----(面试题和笔试题)
  • (SpringBoot)第二章:Spring创建和使用
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • .Net CoreRabbitMQ消息存储可靠机制
  • .NET DataGridView数据绑定说明
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .net framework profiles /.net framework 配置
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET Reactor简单使用教程
  • .Net的DataSet直接与SQL2005交互
  • .sh 的运行
  • @ConfigurationProperties注解对数据的自动封装
  • @property @synthesize @dynamic 及相关属性作用探究
  • [C#]无法获取源 https://api.nuge t.org/v3-index存储签名信息解决方法