Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 如何使用强制(MP3)类型从URL播放QTMovie文件?_Objective C_Cocoa_Mp3_Qtkit_Progressive Download - Fatal编程技术网

Objective c 如何使用强制(MP3)类型从URL播放QTMovie文件?

Objective c 如何使用强制(MP3)类型从URL播放QTMovie文件?,objective-c,cocoa,mp3,qtkit,progressive-download,Objective C,Cocoa,Mp3,Qtkit,Progressive Download,我正在使用QTKit逐步从URL下载并播放MP3。根据,这是我应该用来实现以下目标的代码: NSURL *mp3URL = [NSURL URLWithString:@"http://foo.com/bar.mp3"]; NSError *error = nil; QTMovie *sound = [[QTMovie alloc] initWithURL:mp3URL error:&error]; [sound play]; 这是可行的,并且完全符合我的要求——M

我正在使用QTKit逐步从URL下载并播放MP3。根据,这是我应该用来实现以下目标的代码:

NSURL *mp3URL = [NSURL URLWithString:@"http://foo.com/bar.mp3"];

NSError *error = nil;
QTMovie *sound = [[QTMovie alloc] initWithURL:mp3URL error:&error];
[sound play];
这是可行的,并且完全符合我的要求——MP3 URL被延迟下载并立即开始播放。但是,如果URL没有“.mp3”路径扩展名,则会失败:

NSURL *mp3URL = [NSURL URLWithString:@"http://foo.com/bar"];

NSError *error = nil;
QTMovie *sound = [[QTMovie alloc] initWithURL:mp3URL error:&error];
[sound play];
未给出错误,未引发异常;声音的持续时间刚刚设置为零,什么也不播放

我发现解决此问题的唯一方法是通过手动加载数据并使用QTDataReference强制类型:

NSURL *mp3URL = [NSURL URLWithString:@"http://foo.com/bar"];
NSData *mp3Data = [NSData dataWithContentsOfURL:mp3URL];

QTDataReference *dataReference = 
    [QTDataReference dataReferenceWithReferenceToData:mp3Data
                                                 name:@"bar.mp3"
                                             MIMEType:nil];
NSError *error = nil;
QTMovie *sound = [[QTMovie alloc] initWithDataReference:dataReference error:&error];
[sound play];
然而,这迫使我在开始播放之前完全同步下载所有MP3,这显然是不可取的。这有什么办法吗

谢谢

编辑 实际上,路径扩展似乎与此无关;HTTP头中没有设置内容类型。即便如此,后一种代码仍然有效,而前一种代码则不然。有人知道一种不用访问服务器就能解决这个问题的方法吗

编辑2 有人吗?我在任何地方都找不到这方面的信息,令人沮丧的是,谷歌现在将此页面显示为我大多数查询的最佳结果…

两个想法。(第一个有点老套):
为了解决缺少的内容类型,您可以嵌入一个小型Cocoa Web服务器来补充缺少的头字段,并通过该“代理”路由NSURL

一些http服务器实现:

第二个是,切换到较低级别的框架(从QTKit到AudioToolbox)。
您需要更多的代码,但关于如何使用AudioToolbox流式播放mp3,有一些非常好的资源。
例如。:

就我个人而言,我会选择第二种选择。AudioToolbox不像QTKit那么简单,但它为您的问题提供了一个干净的解决方案。它在iOS和Mac操作系统上都可用,所以你会发现很多信息

更新:
您是否尝试使用其他初始值设定项?e、 g

+ (id)movieWithAttributes:(NSDictionary *)attributes error:(NSError **)errorPtr
您可以为key
qtmovieurldattribute
插入URL,也可以通过在该字典中提供其他属性来补偿缺少的内容类型。 此开源项目有一个QTMovie类别,其中包含完成类似任务的方法:

如果你认为第一个解决方案是黑客的,你会喜欢这个:

罪魁祸首是
内容类型
标题,正如您所确定的。如果
QTKit.framework
在内部使用Objective-C,那么用您选择的类别覆盖
-[NSHTTPURLResponse allHeaderFields]
将是一件小事。但是, QtKIT.Frase(更好或更坏)在内部使用核心基础(和核心服务)。这些都是基于C的框架,在C中没有优雅的方法重写函数

也就是说,有一种方法,只是不漂亮。功能插入甚至由苹果公司提供,但与他们文档的其余部分相比,似乎有点落后于时代

从本质上讲,您希望得到以下几点:

typedef struct interpose_s {
    void *new_func;
    void *orig_func;
} interpose_t;

CFStringRef myCFHTTPMessageCopyHeaderFieldValue (
                                                 CFHTTPMessageRef message,
                                                 CFStringRef headerField
                                                 );

static const interpose_t interposers[] __attribute__ ((section("__DATA, __interpose"))) = {
    { (void *)myCFHTTPMessageCopyHeaderFieldValue, (void *)CFHTTPMessageCopyHeaderFieldValue }
};

CFStringRef myCFHTTPMessageCopyHeaderFieldValue (
                                                 CFHTTPMessageRef message,
                                                 CFStringRef headerField
                                                 ) {
    if (CFStringCompare(headerField, CFSTR("Content-Type"), 0) == kCFCompareEqualTo) {
        return CFSTR("audio/x-mpeg");
    } else {
        return CFHTTPMessageCopyHeaderFieldValue(message, headerField);
    }
}

您可能希望在处理
内容类型字段方面为应用程序添加特定的逻辑,以免当每个HTTP请求都被确定为音频文件时,应用程序以奇怪的方式崩溃。

尝试将
HTTP://
替换为
icy://
只需创建一个这样的实例

QTMovie *aPlayer  = [QTMovie movieWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                 fileUrl, QTMovieURLAttribute,
                                                 [NSNumber numberWithBool:YES], QTMovieOpenForPlaybackAttribute,
                                                 /*[NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,*/
                                                 nil] error:error];

AddioStuffER看起来很有前途,但不幸的是,它似乎不适用于我的用例,因为我经常收到一个“无法配置的网络读流”后暂停,然后在MP3的中间播放。(因此,我正在寻找渐进式下载器而不是拖缆。)此外,“AudioToolbox并不像QTKit那么简单“有点轻描淡写,不是吗?核心音频经常被引用为最重要的音频,我敢肯定这是最容易被微妙地滥用的音频之一。由于我所做的工作相对简单,我更愿意将繁重的工作留给“做得对”的更高级别API来完成。”。是的,核心音频很难,我完全理解您首先查看高级API。我用另一个想法更新了我的原始答案。(虽然没有测试。您可以发布一些有问题的URL吗?)感谢您的帮助和进一步建议;但不幸的是,我得到了相同的结果。下面是一个“坏”URL的示例: