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,retain) AVPlayer *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,retain) NSURL *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(1, 1)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
IOS流媒体播放的更多相关文章
- iOS中 流媒体播放和下载 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 iOS中关于流媒体的简介:介于下载本地播放与实时流媒体之间的一种播放形式,下载本地播放必须全部将文件下载完成后才能播 ...
- m4a文件在iOS上的流媒体播放
Date: 2016-03-23 Title: m4a文件在iOS上的流媒体播放 Tags: m4a, mp4, iOS, Android URL: m4a-streaming-play-on-mob ...
- 寒城攻略:Listo 教你用Swift 语言编写 IOS 平台流媒体播放器
先展示播放器效果: 依然继承 Listo 本人的强迫症,还是从最初到完毕完整的写一个攻略来记录一下,这里声明 Listo 本人也是看了非常多的戴维营攻略才总结分享给大家这一篇攻略的. 首先,Lis ...
- EasyPlayer iOS开源流媒体播放器中AAC解码PCM问题
本文转自EasyDarwin开源团队成员Penggy的博客:http://www.jianshu.com/p/feeb107b6657 最近遇到在 iOS 平台上实时播放 AAC 音频数据流, 一开始 ...
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...
- ios项目里扒出来的json文件
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...
- Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)
下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...
- IOS多媒体
概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像 ...
- 《转》iOS音频视频初级开发
代码改变世界 Posts - 73, Articles - 0, Comments - 1539 Cnblogs Dashboard Logout HOME CONTACT GALLERY RSS ...
随机推荐
- 2014-07-30 MVC框架中对SQL Server数据库的访问
今天是在吾索实习的第16天.我自己主要学习了基于MVC框架的系统的开发时,对SQL Server数据库的相关访问.其步骤如下: 第一步,在Models文件夹中创建一个类,并命名为Movies.cs,如 ...
- IMS 相关名词解释
IMS: IMS(IP Multimedia Subsystem)是IP多媒体系统,是一种全新的多媒体业务形式,它能够满足现在的终端客户更新颖.更多样化多媒体业务的需求. RCS:Rich Commu ...
- UVA 11636 - Hello World! 水
水题,贪心,dp都随意 /* author:jxy lang:C/C++ university:China,Xidian University **If you need to reprint,ple ...
- Kafka小记
kafka简介 kafka是由LinkedIn开发,主要是用来处理Linkedin的大面积活跃数据流处理(activity stream). 此类的数据经常用来反映网站的一些有用的信息,比如PV,页 ...
- 2016-05-I
2016 年上半年软件设计师上午真题 1. VLIW 是( )的简称.A.复杂指令系统计算机 B.超大规模集成电路C.单指令流多数据流 D.超长指令字 2.主存与 Cache 的地址映射方式中,( ) ...
- hdu1547之BFS
Bubble Shooter Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- [Javascript] Safe Nested Object Inspection
A common problem when dealing with some kinds of data is that not every object has the same nested s ...
- RPC 实现
PC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Servic ...
- Python - SQLAlchemy之连表操作
ORM的两种创建方式 数据库优先:指的是先创建数据库,包括表和字段的建立,然后根据数据库生成ORM的代码,它是先创建数据库,再创建相关程序代码 代码优先:就是先写代码,然后根据代码去生成数据库结构. ...
- Cretiria查询应用(二)
1.条件查询,动态查询 public void conditionQuery(){ Session session=null; try { session=HibernateUtil.currentS ...