5

現在、カスタム NSURLProtocol サブクラスで定義されたカスタム スキームを持つ URL でビデオを再生しようとしています。最初はこれを達成するために MPMoviePlayerController を使用していましたが、問題が発生してスタック オーバーフローを確認した後、MPMoviePlayerController が NSURLProtocol サブクラスを期待どおりに処理しないことがわかりました。

カスタム NSURLProtocol を使用して URL でムービーを再生するには?

その結果、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 サブクラスから再生するために行う必要がある別のことはありますか?

4

1 に答える 1

5

最近、NSURLProtocol を MPMoviePlayerController で動作させることができました。MPMoviePlayerController は NSURL のみを受け入れるため、Cookie やヘッダー (認証用) を渡すことができないため、これは主に便利です。NSURLProtocol を使用すると、それが可能になりました。ここで、コミュニティのためにいくつかのコードを一度共有したいと思いました。

基本的に、NSURLProtocol を使用することで、MPMoviePlayerController とストリーミングされたリクエストの間の通信をインターセプトして、途中で Cookie を挿入したり、ストリームをオフラインで保存したり、猫の動画などに置き換えたりすることができます...これを行うには、作成する必要があります新しいクラス My 拡張 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];
于 2014-04-24T06:04:28.050 に答える