5

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 を同期的に完全にダウンロードする必要があり、これは明らかに望ましくありません。これを回避する方法はありますか?

ありがとう。

編集

実際には、パスの拡張子は関係ないようです。Content-Type が HTTP ヘッダーに設定されていないだけです。それでも、後者のコードは機能し、前者は機能しません。サーバーにアクセスせずにこれを修正する方法を知っている人はいますか?

編集 2

誰?これに関する情報がどこにも見つからず、Google は苛立たしいことに、ほとんどのクエリでこのページを上位の結果として表示するようになりました...

4

4 に答える 4

0

weichsel の最初の解決策がハックだと思った場合は、次の方法を気に入るはずです。

あなたが決定したように、犯人はContent-Typeヘッダーです。内部でObjective -C を使用していた場合、これは、選択したカテゴリでQTKit.frameworkオーバーライドするのは簡単なことです。-[NSHTTPURLResponse allHeaderFields]ただし、QTKit.framework(良くも悪くも)Core Foundation(およびCore Services)を内部で使用しています。これらは両方とも C ベースのフレームワークであり、C で関数をオーバーライドする洗練された方法はありません。

とはいえ、方法ありますが、きれいなものではありません。関数の介入はApple によって文書化されていますが、他の文書と比較して少し遅れているようです。

本質的に、次の行に沿って何かが必要です。

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);
    }
}

Content-Typeすべての HTTP リクエストがオーディオ ファイルであると判断されたときにアプリケーションが奇妙で素晴らしい方法で壊れないように、フィールドの処理に関して、アプリケーションに固有のロジックを追加することをお勧めします。

于 2010-12-14T07:25:46.137 に答える
0

このようなインスタンスを作成するだけです...

QTMovie *aPlayer  = [QTMovie movieWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
                                                 fileUrl, QTMovieURLAttribute,
                                                 [NSNumber numberWithBool:YES], QTMovieOpenForPlaybackAttribute,
                                                 /*[NSNumber numberWithBool:YES], QTMovieOpenAsyncOKAttribute,*/
                                                 nil] error:error];
于 2012-05-25T13:08:18.943 に答える
0

に置き換えhttp://てみてくださいicy://

于 2010-12-27T20:05:50.443 に答える
0

2 つのアイデア。(最初のものは少しハックです):
欠落しているコンテンツ タイプを回避するには、欠落しているヘッダー フィールドを補う小さな Cocoa Web サーバーを埋め込み、その「プロキシ」を介して NSURL をルーティングすることができます。

いくつかの Cocoa http サーバーの実装:

2 つ目は、下位レベルのフレームワーク (QTKit から AudioToolbox へ) に切り替えることです。
より多くのコードが必要になりますが、AudioToolbox を使用して mp3 をストリーミングする方法に関する非常に優れたリソースがいくつかあります。
例: http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html

個人的には、2番目のオプションを使用します。AudioToolbox は QTKit ほど単純ではありませんが、問題に対する明確な解決策を提供します。また、iOS と Mac OS の両方で利用できるので、多くの情報を見つけることができます。

更新:
別の初期化子を使用しようとしましたか? 例えば

+ (id)movieWithAttributes:(NSDictionary *)attributes error:(NSError **)errorPtr

キーの URL を挿入できます。QTMovieURLAttributeおそらく、そのディクショナリに他の属性を指定することで、不足しているコンテンツ タイプを補うことができます。このオープン ソース プロジェクトには、同様のことを達成するためのメソッドを含む QTMovie カテゴリがあります: http://vidnik.googlecode.com/svn-history/r63/trunk/Source/Categories/QTMovie+Async.m

于 2010-12-12T12:40:25.367 に答える