播放本地m3u8流媒体

本文介绍如何在iOS应用中实现本地播放m3u8流媒体。通过CocoaHTTPServer搭建本地服务器,将m3u8文件及.ts片段下载到服务器根目录,然后使用M3U8Parser框架解析m3u8文件并下载.ts文件。最后,通过MPMoviePlayerViewController播放本地m3u8文件。


要播放m3u8流媒体

搭建本地服务器:
1. 使用CocoaHTTPServer 生产服务器,指定某文件夹为服务器根目录;
2.启动指定端口的服务器;
3.HTTPServer 为 单例对象的属性,否则服务器启动完就会关闭,用单例就可以将HTTPServer对象放到静态栈里面;

下载m3u8文件:
1.用get请求将 xxxx.m3u8文件下载到服务器根目录下的一个文件夹中;
2.使用M3U8Parser框架解析 http://xxxxx/xxxx.m3u8文件
3.根据解析结果,将m3u8文件里面的.ts文件下载到与xxxx.m3u8文件同一目录下
4.下载.ts文件时使用 get请求,将 http://xxxxx/xxxx.m3u8的http://xxxxx/aaa.ts下载

播放m3u8文件
1.简单点的可以使用 MPMoviePlayerViewController 播放 根服务器下的xxxx.m3u8文件
   
代码:

注:pod ‘M3U8Parser'
       pod ‘CocoaHTTPServer'

HTTPServerManager.h
#import <Foundation/Foundation.h>
#import
<HTTPServer.h>
@interface HTTPServerManager : NSObject
{
   
HTTPServer *httpServer;
}
+ (
instancetype )shareInstance;

- (
void )startHTTPServer;

- (HTTPServer *)returnHTTPServer;
@end

////////////////////////////////////
HTTPServerManager.m
#import "HTTPServerManager.h"

@implementation HTTPServerManager
+ (
instancetype )shareInstance
{
   
static HTTPServerManager *manager;
   
static dispatch_once_t once;
   
if (!manager) {
       
dispatch_once (&once, ^{
          
            manager = [[
HTTPServerManager alloc ] init ];
           
        });
    }
   
   
return manager;
}

- (
NSString *)webRoot
{
   
NSString *web = [ NSHomeDirectory () stringByAppendingPathComponent : @"Documents/web" ];
   
   
NSFileManager *fm = [ NSFileManager defaultManager ];
   
   
if (![fm fileExistsAtPath :web]) {
        [fm
createDirectoryAtPath :web withIntermediateDirectories : YES attributes : nil error : nil ];
       
NSLog ( @" 服务器艮目录是 :%@" ,web);
       
    }
   
   
return web;
}

- (
void )startHTTPServer
{
   
httpServer = [[ HTTPServer alloc ] init ];
    [
httpServer setType : @"_http._tcp." ];
    [
httpServer setPort : 30000 ];
    [
httpServer setDocumentRoot :[ self webRoot ]];
   
   
NSError *error;
   
if ([ httpServer start :&error]) {
       
       
NSLog ( @"HttpServer is started, port is :%hu" ,[ httpServer listeningPort ]);
       
NSLog ( @" 服务器请求地址是 :http://127.0.0.1:30000" );
       
    }
else {
       
       
NSLog ( @"%@" ,error. description );
    }
}

- (
HTTPServer *)returnHTTPServer
{
   
if ( httpServer == nil ) {
        [
self startHTTPServer ];
    }
   
return httpServer ;
}
@end

/////////////////////////////////////////
PlayM3U8ViewController.h

#import <UIKit/UIKit.h>

@interface PlayM3U8ViewController : UIViewController

@end

////////////////////////////
PlayM3U8ViewController.m

#import "PlayM3U8ViewController.h"
#import
<MediaPlayer/MediaPlayer.h>
#import
<AVFoundation/AVFoundation.h>
#import
<AVKit/AVKit.h>
#define KURL @
"http://127.0.0.1:30000/a/output.m3u8"
@interface PlayM3U8ViewController ()

@end

@implementation PlayM3U8ViewController

- (
void )viewDidLoad {
    [
super viewDidLoad ];
   
   
self . view . backgroundColor = [ UIColor whiteColor ];
   
   
NSURL *localM3U8Url = [ NSURL URLWithString : @"http://127.0.0.1:30000/a/output.m3u8" ];
   
MPMoviePlayerViewController *mpc = [[ MPMoviePlayerViewController alloc ] initWithContentURL :localM3U8Url];
    [
self presentViewController :mpc animated : YES completion :^{
    }];
   
}
@end

///////////////////////////////////////
M3u8DownloadManager.h
#import <Foundation/Foundation.h>

@interface M3u8DownloadManager : NSObject

/*
 * 1.
搭建服务器 - 创建文件夹
 * 2.
下载 m3u8 文件
 * 3.解析下载A:m3u8文件
 * 4.根据A:m3u8文件列表下载.ts文件
 * 5. .ts 文件按 m3u8 文件列表组合或拼接
 * 6. .ts 文件保存到与A :m3u8 同一目录下
 */

// 根据文件路径下载 .ts 文件 以及 创建 m3u8 列表
- (
void )downloadM3u8WithFile:( NSString *)URL;
@end

///////////////////////////////////////
M3u8DownloadManager.m

//
//  M3u8DownloadManager.m
//  DownloadM3u8
//
//

#import "M3u8DownloadManager.h"
#import
"URLConnectionGet.h"

#import <M3U8Kit.h>
#import
<NSString+m3u8.h>

@implementation M3u8DownloadManager
{
    NSMutableString *m3u8List;
    NSString        *fileCompoment;
    NSString        *fileFolder;
    NSMutableArray  *urls;
    NSMutableArray  *names;
}

- (
id )init
{
   
self = [ super init ];
   
   
if ( self ) {
       
urls   = [[ NSMutableArray       alloc ] init ];
       
names = [[ NSMutableArray       alloc ] init ];
    }
   
   
return self ;
}


// 根据文件路径下载 .ts 文件 以及 创建 m3u8 列表
- (
void )downloadM3u8WithFile:( NSString *)URL
{
   
fileCompoment = URL. lastPathComponent ;
   
    [[[
URLConnectionGet alloc ] init ] downloadDataWithUrlString :URL finished :^( NSData *data) {
       
       
// 下载得到 m3u8 列表
       
m3u8List = [[ NSMutableString alloc ] initWithData :data encoding : NSUTF8StringEncoding ];
       
       
if ( m3u8List ) {
            [
self parser : m3u8List withURL :URL];
        }
       
    }
failed :^( NSString *errorMessage) {
       
       
NSLog ( @" 列表下载失败 " );
       
    }];
}

// 解析 m3u8 列表
//http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8
- (
void )parser:( NSString *)txt withURL:( NSString *)URL
{
   
M3U8SegmentInfoList *list = [txt m3u8SegementInfoListValueRelativeToURL :[ NSURL URLWithString :URL]];
   
   
NSLog ( @"%ld" ,list.count);
   
   
// 解析列表
   
for ( int i = 0 ; i < list.count; i++) {
       
        M3U8SegmentInfo *info = [list segmentInfoAtIndex:i];
        NSLog(
@"%@" ,info.mediaURL);
       
       
// 获取文件名
       
// 文件名
        [names addObject:info.URI];
       

       
// 整个请求地址
        NSString *pre = [URL stringByReplacingOccurrencesOfString:URL.lastPathComponent withString:
@"" ];
        NSString *tsUrl = [NSString stringWithFormat:
@"%@%@" ,pre,info.URI];
        [urls addObject:tsUrl];
    }
   
   
// 创建一个服务器下的文件名对应的文件夹
    NSArray *items = [URL.lastPathComponent componentsSeparatedByString:
@"." ];
    fileFolder = [NSString stringWithFormat:
@"%@/Documents/web/%@" ,NSHomeDirectory(),items[ 0 ]];
    NSFileManager *fm = [NSFileManager defaultManager];
    [fm createDirectoryAtPath:fileFolder withIntermediateDirectories:
YES attributes: nil error: nil ];
   
   
// 创建 m3u8 列表
    [
self createM3u8ListFile:[fileFolder copy]];
   
    NSLog(
@"%@" ,fileFolder);
   
   
// 开始下载
    [
self downloadTS:[fileFolder copy]];
}

- (
void )downloadTS:(NSString *)savePath
{
   
   
   
if (urls.count> 0 ) {
       
         [
self requestWithIndex: 0 savePath:savePath];
    }
  
}

- (
void )requestWithIndex:( int )index savePath:(NSString *)savePath
{
   
__block int blockIndex = index;
   
   
__weak NSMutableArray *weakNames = names;
   
   
__weak NSString *weakSavePath = savePath;
   
   
__weak M3u8DownloadManager *weakSelf = self ;
   
    [[URLConnectionGet alloc] downloadDataWithUrlString:urls[blockIndex] finished:^(NSData *data) {
       
        NSString *filePath = [NSString stringWithFormat:
@"%@/%@" ,weakSavePath,weakNames[blockIndex]];
       
        NSMutableData *currentData = [NSMutableData dataWithContentsOfFile:filePath];
       
       
if (currentData == nil ) {
            currentData = [[NSMutableData alloc] init];
        }
       
        [currentData appendData:data];
       
       
BOOL success = [currentData writeToFile:filePath atomically: YES ];
               
       
if (success) {
           
            blockIndex +=
1 ;
           
           
if (blockIndex < urls.count) {
               
                [weakSelf requestWithIndex:blockIndex savePath:weakSavePath];
               
            }
           
        }
       
    } failed:^(NSString *errorMessage) {
       
        NSLog(
@"%@" ,errorMessage);
       
    }];
}

// 创建 m3u8 列表
- (
void )createM3u8ListFile:(NSString *)savePath
{
   
for ( int i = 0 ; i < urls.count; i++) {
        NSString *fileName = names[i];
        NSString *URI = [NSString stringWithFormat:
@"%@/%@" ,savePath,fileName];
        [m3u8List stringByReplacingOccurrencesOfString:fileName withString:URI];
    }
   
   
// m3u8 写到文件夹
    [
self writeM3u8List];
}

- (
void )writeM3u8List
{
    NSData *data = [m3u8List dataUsingEncoding: NSUTF8StringEncoding];
    NSString *fileName = [fileCompoment componentsSeparatedByString:
@"." ][ 0 ];
    NSString *filePath = [NSString stringWithFormat:
@"%@/Documents/web/%@/%@" ,NSHomeDirectory(),fileName,fileCompoment];
   
  
BOOL is = [data writeToFile:filePath atomically: YES ];
   
    NSLog(
@"%d" ,is);
}

@end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值