进式下载(伪流媒体)
介于下载本地播放与实时流媒体之间的一种播放形式,下载本地播放必须全部将文件下载完成后才能播放,而渐进式下载不必等到全部下载完成后再播放,它可以一边下载一边播放,在完成播放内容之后,整个文件会保存在手机上。
实时流媒体
实时流媒体是一边接收数据包一边播放,本地不保留文件副本,实时流式传输总是实时传送,可以实时实况转播,支持随机访问,用户可以快进或者快退以观看前面或后面的内容。实时流媒体传输必须保证数据包的传输速度大于文件的播放速度,否则用户看到的视频会出现暂停。当网络堵塞情况下视频质量会下降,所以要想保证视频的质量渐进式下载会更好一些。
实时流媒体协议:
rtsp(real time streaming protocol)
mms(microsoft media server protocol)
hls(http live streaming)
这里主要介绍hls,
hls(http live streaming)是苹果公司针对iphone、ipod、itouch和ipad等移动设备而开发的基于http协议的流媒体解决方案
https://developer.apple.com/streaming/
技术关键点
1.采集视频源和音频源的数据
2.对原始数据进行h264编码和aac编码
3.视频和音频数据封装为mpeg-ts包
4.hls分段生成策略及m3u8索引文件
5.http传输协议
搭建hls流媒体服务器
apache http server (苹果自带)
tomcat web server
iis(internet information services)
这里只推荐apache http server
打开终端,vi /etc/apache2/httpd.conf
在<ifmodule mime_module>下
添加两行
addtype application/x-mpegurl.m3u8
addtype video/mp2t.ts
可能你的权限不够,那就用 sudo chmod 777 /etc/apache2/httpd.conf
然后 vi /etc/apache2/httpd.conf
重启服务器
sudo apachectl restart
==============================================
或者搭建xmpp服务器 或者不搭建,从优酷获取m3u8
创建一个工程
从git中下载库:http://git.oschina.net/1213125967/hls
将库导入工程
需要引入第三方开源框架:asihttprequest,cocoahttpserver,m3u8
需要导入系统框架:libsqlite3.dylib、libz.dylib、libxml2.dylib、coretelephony.framework、systemconfiguration.framework、mobilecoreservices.framework、security.framework、cfnetwork.framework、mediaplayer.framework
在library search path 中添加 /usr/include/libxml2
添加头文件
?
1
2
3
4
<code>#import <mediaplayer/mediaplayer.h></code>
<code>#import "m3u8handler.h"</code>
<code>#import "videodownloader.h"</code>
<code>#import "httpserver.h"</code>
声明属性:
<code>@property (nonatomic, strong)httpserver * httpserver;</code>
<code>@property (nonatomic, strong)videodownloader *downloader;</code>
预先播放,毕先设置服务器
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<code>#pragma mark - 打开本地服务器</code>
<code>- (</code><code>void</code><code>)openhttpserver</code>
<code>{</code>
<code> </code><code>self.httpserver = [[httpserver alloc] init];</code>
<code> </code><code>[self.httpserver settype:@</code><code>"_http._tcp."</code><code>]; </code><code>// 设置服务类型</code>
<code> </code><code>[self.httpserver setport:12345]; </code><code>// 设置服务器端口</code>
<code> </code>
<code> </code><code>// 获取本地documents路径</code>
<code> </code><code>nsstring *pathprefix = [nssearchpathfordirectoriesindomains(nsdocumentdirectory,nsuserdomainmask,yes) objectatindex:0];</code>
<code> </code><code>// 获取本地documents路径下downloads路径</code>
<code> </code><code>nsstring *webpath = [pathprefix stringbyappendingpathcomponent:kpathdownload];</code>
<code> </code><code>nslog(@</code><code>"-------------\nsetting document root: %@\n"</code><code>, webpath);</code>
<code> </code><code>// 设置服务器路径</code>
<code> </code><code>[self.httpserver setdocumentroot:webpath];</code>
<code> </code><code>nserror *error;</code>
<code> </code><code>if</code><code>(![self.httpserver start:&error])</code>
<code> </code><code>{</code>
<code> </code><code>nslog(@</code><code>"-------------\nerror starting http server: %@\n"</code><code>, error);</code>
<code> </code><code>}</code>
<code>}</code>
搭建完成后,播放什么的,都是取决于需求
在线流媒体播放
<code> </code><code>// 优酷视频m3u8新地址格式如下:http://pl.youku.com/playlist/m3u8?vid=xnziwmde5nzi4&type=mp4</code>
<code> </code><code>// 如果上面的链接不可用,那么使用这个链接http://v.youku.com/player/getm3u8/vid/xnziwmde5nzi4/type/flv</code>
<code> </code><code>nsurl *url = [[nsurl alloc] initwithstring:@</code><code>"http://v.youku.com/player/getm3u8/vid/xnziwmde5nzi4/type/mp4"</code><code>];</code>
<code> </code><code>mpmovieplayerviewcontroller *player = [[mpmovieplayerviewcontroller alloc] initwithcontenturl:url];</code>
<code> </code><code>[self presentmovieplayerviewcontrolleranimated:player];</code>
视频下载
<code> </code><code>m3u8handler *handler = [[m3u8handler alloc] init];</code>
<code> </code><code>handler.delegate = self;</code>
<code> </code><code>// 解析m3u8视频地址</code>
<code> </code><code>[handler praseurl:[nsstring stringwithformat:@</code><code>"http://pl.youku.com/playlist/m3u8?vid=xnziwmde5nzi4&type=mp4"</code><code>]];</code>
<code> </code><code>// 开启网络指示器</code>
<code> </code><code>[[uiapplication sharedapplication] setnetworkactivityindicatorvisible:yes];</code>
播放本地视频
<code> </code><code>nsstring * playurl = [nsstring stringwithformat:@</code><code>"http://127.0.0.1:12345/xnziwmde5nzi4/movie.m3u8"</code><code>];</code>
<code> </code><code>nslog(@</code><code>"本地视频地址-----%@"</code><code>, playurl);</code>
<code> </code><code>nsstring *localdownloadspath = [pathprefix stringbyappendingpathcomponent:kpathdownload];</code>
<code> </code><code>// 获取视频本地路径</code>
<code> </code><code>nsstring *filepath = [localdownloadspath stringbyappendingpathcomponent:@</code><code>"xnziwmde5nzi4/movie.m3u8"</code><code>];</code>
<code> </code><code>nsfilemanager *filemanager = [nsfilemanager defaultmanager];</code>
<code> </code><code>// 判断视频是否缓存完成,如果完成则播放本地缓存</code>
<code> </code><code>if</code> <code>([filemanager fileexistsatpath:filepath]) {</code>
<code> </code><code>mpmovieplayerviewcontroller *playerviewcontroller =[[mpmovieplayerviewcontroller alloc]initwithcontenturl:[nsurl urlwithstring: playurl]];</code>
<code> </code><code>[self presentmovieplayerviewcontrolleranimated:playerviewcontroller];</code>
<code> </code><code>else</code><code>{</code>
<code> </code><code>uialertview *alertview = [[uialertview alloc] initwithtitle:@</code><code>"sorry"</code> <code>message:@</code><code>"当前视频未缓存"</code> <code>delegate:self cancelbuttontitle:@</code><code>"确定"</code> <code>otherbuttontitles:nil, nil];</code>
<code> </code><code>[alertview show];</code>
添加代理 <m3u8handlerdelegate,videodownloaddelegate>
24
25
26
27
28
29
30
31
32
33
34
<code>#pragma mark --------------视频解析完成----------------</code>
<code>-(</code><code>void</code><code>)prasem3u8finished:(m3u8handler*)handler</code>
<code> </code><code>handler.playlist.</code><code>uuid</code> <code>= @</code><code>"xnziwmde5nzi4"</code><code>;</code>
<code> </code><code>self.downloader = [[videodownloader alloc]initwithm3u8list:handler.playlist];</code>
<code> </code><code>[self.downloader addobserver:self forkeypath:@</code><code>"totalprogress"</code> <code>options:nskeyvalueobservingoptionnew | nskeyvalueobservingoptionold context:nil];</code>
<code> </code><code>self.downloader.delegate = self;</code>
<code> </code><code>[self.downloader startdownloadvideo];</code>
<code>-(</code><code>void</code><code>)observevalueforkeypath:(nsstring *)keypath ofobject:(id)object change:(nsdictionary *)change context:(</code><code>void</code> <code>*)context</code>
<code> </code><code>nslog(@</code><code>"下载进度 - %f"</code><code>, self.downloader.totalprogress);</code>
<code>#pragma mark --------------视频解析失败----------------</code>
<code>-(</code><code>void</code><code>)prasem3u8failed:(m3u8handler*)handler</code>
<code> </code><code>nslog(@</code><code>"视频解析失败-failed -- %@"</code><code>,handler);</code>
<code>#pragma mark --------------视频下载完成----------------</code>
<code>-(</code><code>void</code><code>)videodownloaderfinished:(videodownloader*)request</code>
<code> </code><code>[[uiapplication sharedapplication] setnetworkactivityindicatorvisible:no];</code>
<code> </code><code>[request createlocalm3u8file];</code>
<code> </code><code>nslog(@</code><code>"----------视频下载完成-------------"</code><code>);</code>
<code>#pragma mark --------------视频下载失败----------------</code>
<code>-(</code><code>void</code><code>)videodownloaderfailed:(videodownloader*)request</code>
<code> </code><code>nslog(@</code><code>"----------视频下载失败-----------"</code><code>);</code>
原文出自:http://my.oschina.net/cgshare/blog/302303