公開URLで入手できるMP3ファイルを再生しているアプリケーションがあります。残念ながら、サーバーはストリーミングをサポートしていませんが、Androidはユーザーエクスペリエンスをかなり受け入れます。Android JellyBeanネットワークメディアの問題
JellyBeanを除くすべてのプラットフォームで問題なく動作します。 MP3を要求するとき、JBはRange-Headerを10回要求する。 10回目の試みの後でさえ、それは古い振る舞いに戻っているようです。 Looks like this already reported issue。
もう1つ見つけたSO thread推奨ソリューションは、Tranfer-Encoding:chunkedヘッダーを使用することをお勧めします。しかし、すぐ下には、これがうまくいかないというコメントがあります。
現時点では、私は上記のレスポンスヘッダーを提供することは何もできませんが、私がそれを実行できるようになるまで、私はクライアント側で代替手段を探すことを考えました。 (それでも、0からContent-Length-1までのインデックスを含むContent-Rangeのみを返すことができます。例Content-Range:0-3123456/3123457バイト)。
私は何をしようとしたことにより、擬似ストリーミングクライアント側でを実装することです:
- はMP3への入力ストリームを開きます。
- JLayerを使用して受信バイトをデコードします。私はthis linkでデコードを見つけました。
- デコードされた配列バイトを既に再生可能なstream_mode AudioTrackに送信します。私は時間のチャンクで復号バイトを要求してい
public byte[] decode(InputStream inputStream, int startMs, int maxMs) throws IOException { ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024); float totalMs = 0; boolean seeking = true; try { Bitstream bitstream = new Bitstream(inputStream); Decoder decoder = new Decoder(); boolean done = false; while (!done) { Header frameHeader = bitstream.readFrame(); if (frameHeader == null) { done = true; } else { totalMs += frameHeader.ms_per_frame(); if (totalMs >= startMs) { seeking = false; } if (!seeking) { // logger.debug("Handling header: " + frameHeader.layer_string()); SampleBuffer output = (SampleBuffer) decoder.decodeFrame(frameHeader, bitstream); if (output.getSampleFrequency() != 44100 || output.getChannelCount() != 2) { throw new IllegalArgumentException("mono or non-44100 MP3 not supported"); } short[] pcm = output.getBuffer(); for (short s : pcm) { outStream.write(s & 0xff); outStream.write((s >> 8) & 0xff); } } if (totalMs >= (startMs + maxMs)) { done = true; } } bitstream.closeFrame(); } return outStream.toByteArray(); } catch (BitstreamException e) { throw new IOException("Bitstream error: " + e); } catch (DecoderException e) { throw new IOException("Decoder error: " + e); } }
:始まるそれは入力ストリームを受信するよう
復号化を行うコードの部分が見つけることができ、私はそれを変更しました(5000、1000)、(6000、1000)、(7000、1000)、などの次のバイト配列を要求しています。 。
デコードが速く、別のスレッドで実行され、デコードされたバイト配列が利用可能になると、ブロックキューを使用して別のスレッドで再生中のAudioTrackに書き込みます。
問題は、チャンクがトラック内で連続していないためです(各チャンクは連続していますが、AudioTrackに追加すると不自然な再生になります)。
締めくくりには:
- あなたはこのJellyBean問題にぶつかっている場合は、どのようにあなたがそれを解決しましたか?
- 私のアプローチを試した人は、上記のコードで何が間違っていますか?これがあなたが使用したソリューションであれば、残りのコードを公開することができます。
ありがとう!
答えてくれてありがとう...私が必要としていたプロジェクトではこのアプローチに従いたいとは思っていませんが、いつか私は余裕を持っています。オープンな質問がまだ残っています(JellyBeanを除くすべてのプラットフォームでうまくいきます)MP3をリクエストすると、JBはRange-Headerを10回要求します.10回目の試行の後でのみ、古い動作に戻ります。 )これにぶつかったら、どうやってこれを修正しましたか?それはサーバー側からのものか、それともクライアント側のものでしたか? – gunar
この行にコードを含めることができますか: "MP3を要求するとき、JBはRange-Headerを10回要求します.10回目の試行の後でさえ、以前の動作に戻っているようです。 – Matt
JBossでRange-Headerをリクエストするためのコードを追加していないので、[添付のAndroidの問題](https://code.google.com/p/android/issues/detail?id=35790)をご覧ください。それはすべてそれに関連しています。 – gunar