4

我目前正试图播放一个具有在自定义NSURLProtocol子类中定义的自定义方案的URL。最初我使用MPMoviePlayerController试图实现这一点,但在遇到问题并检查堆栈溢出后,我发现MPMoviePlayerController没有按预期处理NSURLProtocol子类。使用MPMovieController或AVFoundation可以使用NSURLProtocol的子类播放视频?

How to play movie with a URL using a custom NSURLProtocol?

因此,我决定看看AVFoundation框架,但是,似乎这也似乎并没有工作。我只想知道这是可能的,还是我想穿过墙壁?

使用AVFoundation,我使用的方法如下所示。可能值得一提的是,这对于在互联网上托管的视频使用标准URL时有效,但不适用于自定义NSURLProtocol。

// this doesn't work 
//AVPlayer *player = [[AVPlayer alloc] initWithURL:[NSURL urlWithString:@"custom URL scheme"]]; 
// this works 
AVPlayer *player = [[AVPlayer alloc] initWithURL:[NSURL urlWithString:@"some url to video on remote server"]]; 

AVPlayerLayer *layer = [AVAVPlayerLayer playerLayerWithPlayer:player]; 
// configure the layer 
[self.view.layer addSublayer:layer]; 

[player play]; 

从定义的NSURLProtocol子类中播放需要做什么不同吗?

+1

嗨塔兹,你管理,使其工作? – 2013-04-16 08:12:02

+1

嘿Geraud,不,我从来没有设法得到这个工作。看来AVFoundation也不支持NSURLProtocol子类。 – Taz 2013-04-23 16:15:58

回答

5

最近,我设法让NSURLProtocol与MPMoviePlayerController一起工作。这主要是有用的,因为MPMoviePlayerController只接受一个NSURL,所以它不让我们传递cookie或标头(用于验证)。使用NSURLProtocol允许。我想我会在这里为社区分享一些代码。

基本上,通过使用NSURLProtocol,我们可以拦截MPMoviePlayerController和流式传输请求之间的通信,沿途注入cookie,或者可能将该流保存为离线,或将其替换为cat视频等。为此,你需要创建一个新的类我伸出NSURLProtocol:

MyURLProtocol.h:

#import <Foundation/Foundation.h> 

@interface MyURLProtocol : NSURLProtocol 
+ (void) register; 
+ (void) injectURL:(NSString*) urlString cookie:(NSString*)cookie; 
@end 

MyURLProtocol.m:

#import "MyURLProtocol.h" 

@interface MyURLProtocol() <NSURLConnectionDelegate> { 
    NSMutableURLRequest* myRequest; 
    NSURLConnection * connection; 
} 
@end 

static NSString* injectedURL = nil; 
static NSString* myCookie = nil; 

@implementation MyURLProtocol 
// register the class to intercept all HTTP calls 
+ (void) register 
{ 
    [NSURLProtocol registerClass:[self class]]; 
} 

// public static function to call when injecting a cookie 
+ (void) injectURL:(NSString*) urlString cookie:(NSString*)cookie 
{ 
    injectedURL = urlString; 
    myCookie = cookie; 
} 

// decide whether or not the call should be intercepted 
+ (BOOL)canInitWithRequest:(NSURLRequest *)request { 
    if([[[request allHTTPHeaderFields] objectForKey:@"BANANA"] isEqualToString:@"DELICIOUS"]) 
    { 
     return NO; 
    } 
    return [[[request URL] absoluteString] isEqualToString:injectedURL]; 
} 

// required (don't know what this means) 
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { 
    return request; 
} 

// intercept the request and handle it yourself 
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client { 

    if (self = [super initWithRequest:request cachedResponse:cachedResponse client:client]) { 
     myRequest = request.mutableCopy; 
     [myRequest setValue:@"DELICIOUS" forHTTPHeaderField:@"BANANA"]; // add your own signature to the request 
    } 
    return self; 
} 

// load the request 
- (void)startLoading { 
    // inject your cookie 
    [myRequest setValue:myCookie forHTTPHeaderField:@"Cookie"]; 
    connection = [[NSURLConnection alloc] initWithRequest:myRequest delegate:self]; 
} 

// overload didReceive data 
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [[self client] URLProtocol:self didLoadData:data]; 
} 

// overload didReceiveResponse 
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response { 
    [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:[myRequest cachePolicy]]; 
} 

// overload didFinishLoading 
- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    [[self client] URLProtocolDidFinishLoading:self]; 
} 

// overload didFail 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    [[self client] URLProtocol:self didFailWithError:error]; 
} 

// handle load cancelation 
- (void)stopLoading { 
    [connection cancel]; 
} 

@end 

用法:

[MyURLProtocol register]; 
[MyURLProtocol injectURL:@"http://server/your-video-url.mp4" cookie:@"mycookie=123"]; 
MPMoviePlayerController* moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:@"http://server/your-video-url.mp4"]; 
[moviePlayer play]; 
+0

您是否可以播放视频?有没有演示? – 2014-08-13 12:18:06

+1

我也这么做。它适用于模拟器,但不适用于设备。我使用iOS 8.1,xcode 6.1进行测试。你有没有得到它在设备上工作 – sahara108 2014-12-08 04:09:42

+0

它适用于流媒体的MP3/M4A,但MP4的视频捕获与iOS不加载 – malex 2015-02-27 23:11:18