zoukankan      html  css  js  c++  java
  • ios流媒体

    http://my.oschina.net/CgShare/blog/302303

    渐进式下载(伪流媒体)

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

    实时流媒体

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

    实时流媒体协议:

    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
    #import <MediaPlayer/MediaPlayer.h>
    #import "M3U8Handler.h"
    #import "VideoDownloader.h"
    #import "HTTPServer.h"

    声明属性:

    1
    2
    @property (nonatomic, strong)HTTPServer * httpServer;
    @property (nonatomic, strong)VideoDownloader *downloader;

    预先播放,毕先设置服务器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #pragma mark - 打开本地服务器
    - (void)openHttpServer
    {
        self.httpServer = [[HTTPServer alloc] init];
        [self.httpServer setType:@"_http._tcp."];  // 设置服务类型
        [self.httpServer setPort:12345]; // 设置服务器端口
         
        // 获取本地Documents路径
        NSString *pathPrefix = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
         
        // 获取本地Documents路径下downloads路径
        NSString *webPath = [pathPrefix stringByAppendingPathComponent:kPathDownload];
        NSLog(@"------------- Setting document root: %@ ", webPath);
         
        // 设置服务器路径
        [self.httpServer setDocumentRoot:webPath];
        NSError *error;
         
        if(![self.httpServer start:&error])
        {
            NSLog(@"------------- Error starting HTTP Server: %@ ", error);
        }
    }

    搭建完成后,播放什么的,都是取决于需求

    在线流媒体播放

    1
    2
    3
    4
    5
    6
        // 优酷视频m3u8新地址格式如下:http://pl.youku.com/playlist/m3u8?vid=XNzIwMDE5NzI4&type=mp4
        // 如果上面的链接不可用,那么使用这个链接http://v.youku.com/player/getM3U8/vid/XNzIwMDE5NzI4/type/flv
        NSURL *url = [[NSURL alloc] initWithString:@"http://v.youku.com/player/getM3U8/vid/XNzIwMDE5NzI4/type/mp4"];
        MPMoviePlayerViewController *player = [[MPMoviePlayerViewController alloc] initWithContentURL:url];
         
        [self presentMoviePlayerViewControllerAnimated:player];

    视频下载

    1
    2
    3
    4
    5
    6
    7
        M3U8Handler *handler = [[M3U8Handler alloc] init];
        handler.delegate = self;
        // 解析m3u8视频地址
        [handler praseUrl:[NSString stringWithFormat:@"http://pl.youku.com/playlist/m3u8?vid=XNzIwMDE5NzI4&type=mp4"]];
         
        // 开启网络指示器
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];

    播放本地视频

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
        NSString * playurl = [NSString stringWithFormat:@"http://127.0.0.1:12345/XNzIwMDE5NzI4/movie.m3u8"];
        NSLog(@"本地视频地址-----%@", playurl);
         
        // 获取本地Documents路径
        NSString *pathPrefix = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) objectAtIndex:0];
         
        // 获取本地Documents路径下downloads路径
        NSString *localDownloadsPath = [pathPrefix stringByAppendingPathComponent:kPathDownload];
         
        // 获取视频本地路径
        NSString *filePath = [localDownloadsPath stringByAppendingPathComponent:@"XNzIwMDE5NzI4/movie.m3u8"];
        NSFileManager *fileManager = [NSFileManager defaultManager];
         
        // 判断视频是否缓存完成,如果完成则播放本地缓存
        if ([fileManager fileExistsAtPath:filePath]) {
            MPMoviePlayerViewController *playerViewController =[[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL URLWithString: playurl]];
            [self presentMoviePlayerViewControllerAnimated:playerViewController];
        }
        else{
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry" message:@"当前视频未缓存" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alertView show];
        }

    添加代理 <M3U8HandlerDelegate,VideoDownloadDelegate>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #pragma mark --------------视频解析完成----------------
    -(void)praseM3U8Finished:(M3U8Handler*)handler
    {
        handler.playlist.uuid = @"XNzIwMDE5NzI4";
        self.downloader = [[VideoDownloader alloc]initWithM3U8List:handler.playlist];
        [self.downloader addObserver:self forKeyPath:@"totalprogress" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
        self.downloader.delegate = self;
        [self.downloader startDownloadVideo];
    }
     
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        NSLog(@"下载进度 - %f", self.downloader.totalprogress);
    }
     
    #pragma mark --------------视频解析失败----------------
    -(void)praseM3U8Failed:(M3U8Handler*)handler
    {
        NSLog(@"视频解析失败-failed -- %@",handler);
    }
     
    #pragma mark --------------视频下载完成----------------
    -(void)videoDownloaderFinished:(VideoDownloader*)request
    {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
        [request createLocalM3U8file];
        NSLog(@"----------视频下载完成-------------");
    }
     
    #pragma mark --------------视频下载失败----------------
    -(void)videoDownloaderFailed:(VideoDownloader*)request
    {
        NSLog(@"----------视频下载失败-----------");
  • 相关阅读:
    Leetcode 238. Product of Array Except Self
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 290. Word Pattern
    Leetcode 205. Isomorphic Strings
    Leetcode 107. Binary Tree Level Order Traversal II
    Leetcode 102. Binary Tree Level Order Traversal
    三目运算符
    简单判断案例— 分支结构的应用
    用switch判断月份的练习
    java基本打印练习《我行我素购物系统》
  • 原文地址:https://www.cnblogs.com/apem/p/4417206.html
Copyright © 2011-2022 走看看