Ios MPMoviePlayerController和基于身份验证的HLS后端服务器
我目前正在使用Ios MPMoviePlayerController和基于身份验证的HLS后端服务器,ios,mpmovieplayercontroller,http-live-streaming,Ios,Mpmovieplayercontroller,Http Live Streaming,我目前正在使用MPMoviePlayerController在iOS应用程序中提供视频。文件从需要身份验证的后端服务器流式传输。它是授权HTTP头中基于密钥的身份验证集 它过去可以完美地处理单个视频文件。现在我们正试图实现HLS自适应流媒体,我们面临着一堵墙。我目前正在使用一个自定义的NSURLProtocol子类来捕获对后端服务器的请求,并注入适当的授权头。对于HLS来说,它根本不起作用 当我们查看服务器日志时,我们清楚地看到对m3u8文件的第一个请求工作正常。然后,禁止所有后续调用(其他m3
MPMoviePlayerController
在iOS应用程序中提供视频。文件从需要身份验证的后端服务器流式传输。它是授权HTTP头中基于密钥的身份验证集
它过去可以完美地处理单个视频文件。现在我们正试图实现HLS自适应流媒体,我们面临着一堵墙。我目前正在使用一个自定义的NSURLProtocol
子类来捕获对后端服务器的请求,并注入适当的授权头。对于HLS来说,它根本不起作用
当我们查看服务器日志时,我们清楚地看到对m3u8文件的第一个请求工作正常。然后,禁止所有后续调用(其他m3u8文件和ts)。似乎MPMoviePlayerController
没有对其他文件使用nsurprotocol
。(旁注:它确实在模拟器思想上起作用,但在物理设备上不起作用,这让我觉得两者的实现方式不同)
MPMoviePlayerController实例化
URL协议拦截
任何想法、建议和解决方法?通过使用NSURL协议,您可以拦截MPMoviePlayerController和流式请求之间的通信。在此过程中注入cookies,或者可能保存流脱机视频。为此,您应该创建一个扩展NSURLProtocol的新类: 希望这对您有所帮助: GAURLProtocol.h
#import <Foundation/Foundation.h>
@interface GAURLProtocol : NSURLProtocol
+ (void) register;
+ (void) injectURL:(NSString*) urlString cookie:(NSString*)cookie;
@end
用法
[GAURLProtocol injectURL:@"http://example.com/video.mp4" cookie:@"cookie=f23r3121"];
MPMoviePlayerController * moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:@"http://example.com/video.mp4"];
[moviePlayer play];
在与苹果开发者技术支持部门核实后,我认为我想要实现的目标是不可能的(而且不受支持) 以下是回复中的引述: 您看到的NSURLProtocol等的问题是,电影播放子系统没有在您的进程中运行其HTTP请求。相反,这些请求是在单独的系统进程mediaserverd中运行的。因此,您影响播放行为的所有努力都是徒劳的
@Marc Alexandre Bérubé我可以想到以下解决方法:
在应用程序中运行代理服务器以代理所有视频URL。通过向请求中注入必要的auth头下载所有视频内容,并通过代理服务器将内容中继回媒体播放器进行渲染。这种方法可能不适用于大型视频,因为视频渲染只有在下载完整个视频后才会开始。它看起来与我所做的非常接近。。但它是在模拟器上工作,而不是在设备上(运行iOS9.2)。您能否确认它在iOS 8及以上版本的设备上以及在HLS视频上对您有效?(这与单个流文件不同)就记录而言,它与我们最终所做的非常接近。我们的服务器代理m3u8文件并注入完整的签名url以替换段条目。签名URL已过期。
#import <Foundation/Foundation.h>
@interface GAURLProtocol : NSURLProtocol
+ (void) register;
+ (void) injectURL:(NSString*) urlString cookie:(NSString*)cookie;
@end
#import "GAURLProtocol.h"
@interface GAURLProtocol() <NSURLConnectionDelegate> {
NSMutableURLRequest* myRequest;
NSURLConnection * connection;
}
@end
static NSString* injectedURL = nil;
static NSString* myCookie = nil;
@implementation GAURLProtocol
+ (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;
}
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
if([[[request allHTTPHeaderFields] objectForKey:@"Heeehey"] isEqualToString:@"Huuu"])
{
return NO;
}
return [[[request URL] absoluteString] isEqualToString:injectedURL];
}
+ (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:@"Huuu" forHTTPHeaderField:@"Heeehey"]; // 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
// register protocol
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NSURLProtocol registerClass:[GAURLProtocol class]];
return YES;
}
[GAURLProtocol injectURL:@"http://example.com/video.mp4" cookie:@"cookie=f23r3121"];
MPMoviePlayerController * moviePlayer = [[MPMoviePlayerController alloc]initWithContentURL:@"http://example.com/video.mp4"];
[moviePlayer play];