• 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(@"----------视频下载失败-----------");
  • 相关阅读:
    深入浅出 Java 8 Lambda 表达式
    OneAPM x 腾讯 | OneAPM 技术公开课·深圳 报名:前端性能大作战!
    第30节:Java基础-内部类
    第二十九节:Java基础知识-类,多态,Object,数组和字符串
    第二十九节:Java基础知识-类,多态,Object,数组和字符串
    第二十九节:Java基础知识-类,多态,Object,数组和字符串
    第二十八节:Java基础-进阶继承,抽象类,接口
    第二十八节:Java基础-进阶继承,抽象类,接口
    第二十八节:Java基础-进阶继承,抽象类,接口
    ES6教程-字符串,函数的参数,了解函数的arguments对象,js面向对象,设计模式-单例模式,解构赋值
  • 原文地址:https://www.cnblogs.com/apem/p/4417206.html
Copyright © 2020-2023  润新知