天天看点

iOS 第三方之流媒体

进式下载(伪流媒体)

介于下载本地播放与实时流媒体之间的一种播放形式,下载本地播放必须全部将文件下载完成后才能播放,而渐进式下载不必等到全部下载完成后再播放,它可以一边下载一边播放,在完成播放内容之后,整个文件会保存在手机上。

实时流媒体

实时流媒体是一边接收数据包一边播放,本地不保留文件副本,实时流式传输总是实时传送,可以实时实况转播,支持随机访问,用户可以快进或者快退以观看前面或后面的内容。实时流媒体传输必须保证数据包的传输速度大于文件的播放速度,否则用户看到的视频会出现暂停。当网络堵塞情况下视频质量会下降,所以要想保证视频的质量渐进式下载会更好一些。

实时流媒体协议:

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 &lt;mediaplayer/mediaplayer.h&gt;</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:&amp;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&amp;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&amp;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>

添加代理 &lt;m3u8handlerdelegate,videodownloaddelegate&gt;

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