要播放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;
#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 ;
@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 :^{
}];
#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 文件
@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);
}
// 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