关于流媒体(m3u8)的播放与下载

前一段时间做了一个视频播放下载应用,抓取的是优酷的视频,虽然优酷有自己的开发平台http://open.youku.com/,但未真正的实现。所以只能靠抓取视频源,Youku的视频采取了加密+动态的获取方式,视频地址需要访问网站动态获取,而结果则还需经过解密等操作。我们的目的只解析到网站视频的m3u8地址,好在在ios 的web可以实现:

  1         // 初始化webView
  2 
  3         UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 280, 390)];
  4 
  5         [webViewsetDelegate:self];
  6 
  7         //加载网址
  8 
  9        NSURLRequest *request =[NSURLRequestrequestWithURL:url
 10 
 11                                             cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
 12 
 13                                         timeoutInterval:5.0];
 14 
 15       [webView loadRequest:request];
 16 
 17         //在UIWebViewDelegate方法中解析
 18 
 19 #pragma mark - UIWebViewDelegate Methods
 20 
 21 - (void)webViewDidStartLoad:(UIWebView *)aWebView
 22 {
 23     [indicatorView startAnimating];
 24 }
 25 
 26 - (void)webViewDidFinishLoad:(UIWebView *)aWebView
 27 {
 28     [indicatorView stopAnimating];
 29     /*
 30     NSString *lJs = @"document.documentElement.innerHTML";
 31     NSString *lHtml1 = [webView stringByEvaluatingJavaScriptFromString:lJs];
 32     NSLog(@"html内容:%@",lHtml1);
 33     
 34     // NSString *lJs2 = @"(document.getElementsByTagName(\"video\")[0]).getElementsByTagName(\"source\")[0].src";  //qiyi
 35     NSString *lJs2 = @"(document.getElementsByTagName(\"video\")[0]).src";// youku,tudou,ku6 ,souhu
 36     NSString *lm3u8 = [webView stringByEvaluatingJavaScriptFromString:lJs2];
 37     NSLog(@"video source:%@",lm3u8);
 38     */
 39     
 40     NSString  *str = nil;
 41     BOOL isYoukuTudouSource = [self isYoukuTudouSource];
 42     if (isYoukuTudouSource){
 43      
 44         str = [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('video')[0].getAttribute('src');"];
 45         if (![str isEqualToString:@""]){
 46             
 47             NSString *tempStr =str;
 48             //NSLog(@"======%@",tempStr);
 49             NSRange range = [ str rangeOfString:@"http://"];
 50             if (range.length==0){
 51                 range = [videolinkStr rangeOfString:@"youku.com"];
 52                 if (range.length>0){
 53                     str = [@"http://v.youku.com" stringByAppendingString:tempStr];
 54                 }
 55             }
 56         }
 57     }else{
 58         BOOL sourcemode = [self isSourceMode];
 59         if (sourcemode){
 60             str = [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByTagName('source')[0].getAttribute('src')"];
 61         }
 62     }    
 63     if (IfPass == NO) {//设置BOOL类型的IfPass主要目的避免重复加载获取。
 64         
 65         if (str && ![str isEqualToString:@""]) {
 66             [webView stopLoading];
 67             if ([delegate respondsToSelector:@selector(authorizeWebView:didReceiveAuthorizeCode:)])
 68             {
 69                 NSLog(@"地址信息=======%@",str);
 70                 IfPass = YES;
 71                 [delegate authorizeWebView:self didReceiveAuthorizeCode:str];
 72             }
 73         }
 74     }else if (IfPass == YES){
 75         [webView stopLoading];
 76         //NSLog(@"地址信息=======%@",str);
 77     }
 78     //NSLog(@"Web获取视频地址信息=======%@",str);
 79 }
 80 
 81 - (void)webView:(UIWebView *)aWebView didFailLoadWithError:(NSError *)error
 82 {
 83     [indicatorView stopAnimating];
 84 }
 85 
 86 - (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
 87 {
 88 
 89     return YES;
 90 }
 91 
 92 
 93 -(BOOL) isSourceMode {
 94    
 95     NSRange yinyuetai = [videolinkStr rangeOfString:@"yinyuetai.com"];
 96     NSRange iqiyi = [videolinkStr rangeOfString:@"iqiyi.com"];
 97     NSRange qq = [videolinkStr rangeOfString:@"qq.com"];
 98     return yinyuetai.length>4||iqiyi.length>4||qq.length>4;
 99 }
100 
101 - (BOOL) isYoukuTudouSource {
102 
103     NSRange youku = [videolinkStr rangeOfString:@"youku.com"];
104     NSRange tudou = [videolinkStr rangeOfString:@"tudou.com"];
105     //NSLog(@"youku length====%d===tudou length===%d",youku.length,tudou.length);
106     return youku.length>4||tudou.length>4;
107 }
View Code

 

客户端,webView加载解析会有延迟,所以这种方式不推荐。其实后台可以通过技术手段得到m3u8.接下来就是调用苹果自己的播放器播放。我单独创建了一个MyMoviePlayViewController类继承自

MPMoviePlayerViewController类,以方便我应对ios6和ios6之前版本的屏幕旋转问题。

self.myVideoUrlStr =@“视频m3u8地址”;

//这里我需要查询下视频总时间

NSURL *movieURL = [NSURL URLWithString:self.myVideoUrlStr];
        NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
        
        AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:movieURL options:opts];  // 初始化视频媒体文件
        //int minute = 0;
        int second = 0;
        second = urlAsset.duration.value / urlAsset.duration.timescale; // 获取视频总时长,单位秒

//设置播放器监听事件
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(movieFinishedCallback:)
                                                     name:MPMoviePlayerPlaybackDidFinishNotification
                                                   object:self.moviePlayer];


//初始化视频媒体文件

    MyMoviePlayViewController   *moviePalyViewController = [[MyMoviePlayViewController alloc]initWithContentURL:[NSURL URLWithString:@""]];
        
        [[moviePalyViewController view]setFrame:CGRectMake(0, 0, 320, self.view.frame.size.height*216/460)];
        moviePalyViewController.moviePlayer.view.frame =CGRectMake(0, 0, 320, 216);
        //moviePalyViewController.view.frame = CGRectMake(0, 0, 320, self.view.frame.size.height*216/460);

        [moviePalyViewController getVideoWithURL:[NSURL URLWithString:self.myVideoUrlStr]];

//视频监听调用方法。主要用来记录用户所观看的时间
- (void)movieFinishedCallback:(NSNotification*) notification {
    
    //NSLog(@"111111111视频播放完毕");
    MPMoviePlayerController *player = [notification object];
    CGFloat videotimedurationWatched;
    
    NSArray *events = player.accessLog.events;
    int count = events.count;
    //NSLog(@"events count = %d", count);
    for (int i = 0; i < count; ++i) {
        
        MPMovieAccessLogEvent *currenEvent = [events objectAtIndex:i];
        // double byts =  currenEvent.indicatedBitrate ;
         //NSLog(@"5555555==视频播放当前时间======%f",currenEvent.durationWatched);
        videotimedurationWatched = currenEvent.durationWatched;
    }

    switch (player.playbackState) {
        case MPMoviePlaybackStateStopped:{

        }
            break;
        case MPMoviePlaybackStatePlaying:{
            //NSLog(@"Playing");
        }
            break;
        case MPMoviePlaybackStatePaused:{
            
            AccountModel *tempmodel = [AccountModel shareInstance];
            tempmodel.videotimeWatched = videotimedurationWatched;
            //NSLog(@"Paused");//播放暂停,播放完毕调用
            [self dismissModalViewControllerAnimated:YES];
            return;
        }
            break;
        case MPMoviePlaybackStateInterrupted:{
            //NSLog(@"Interrupted");
        }
            break;
        case MPMoviePlaybackStateSeekingForward:{
            //NSLog(@"Forward");
        }
            break;
        case MPMoviePlaybackStateSeekingBackward:{
            //NSLog(@"Backward");
        }
            break;
        default:
            break;
    }
    
    [[NSNotificationCenter defaultCenter]
     removeObserver:self
     name:MPMoviePlayerPlaybackDidFinishNotification
     object:player];
}
View Code

 

有了在线播放功能还不够,还需要下载到本地播放,实现步骤如下:

  (1) 在线解析m3u8文件内容,把里面的ts对应连接的资源下载本地的Document文件下。

  (2) 把下载下来的资源使用本地路径重新拼接成一个新的本地m3u8文件。

  (3) 然后在开启一个http服务端,把m3u8共享成连接地址,让播放器播放。

具体实现请查看这位仁兄给的Demo,开启一个http服务端使用到了http服务端,就用CocoaHTTPServer可以把工作做好  CocoaHTTPServer小,重量轻,可嵌入HTTP服务器的Mac OS X或iOS应用程序。

有时,开发人员在他们的应用程序需要一个嵌入式HTTP服务器。也许它是一个服务器应用程序的远程监控。也许这是一个桌面应用程序使用HTTP后端的通信。它提供了:
•内置支持卓悦广播
•IPv4和IPv6支持
·异步网络,使用GCD和标准插座
•密码保护支持
•SSL/ TLS加密支持
•非常快速和高效的内存
•可扩展性(完全建立在GCD)
•重注释掉的代码
•很容易扩展
•支持WebDAV!

 下面 介绍有关视频格式的:

在线视频一般都是基于flashflv来实现的,而众所周知,iOSsafari不支持网页中的flash,但支持html5video标记。FLV视频格式:许多在线视频网站都采用此视频格式。如搜狐视频、新浪播客、六间房、56、优酷、酷6、土豆,youtube等。FLV已经成为当前视频文件的主流格式。

优酷开发了优酷通用播放器,您可以将视频嵌入到任意页面和设备中,这样视频就可以被各种终端用户观看,包括PC浏览器,iPadiPhone,较高版本Android平板和手机。优酷播放器现在只有在线播放能力,不提供播放离线文件的功能。

iOS 设备上启用 HTTP Live Streaming 非常简单,也是苹果官方推荐的方式。Adobe Flash 流媒体服务器的新版本也支持这个技术的。

有关HLS可以参考HLS直播分析与实现  ,搭建HTTP Live Streaming直播系统  

        

 

 

 

posted on 2013-06-25 17:13  一梦浮生2012  阅读(15428)  评论(0编辑  收藏  举报