web-dev-qa-db-ja.com

HTML5 <audio> Safariライブブロードキャストvsnot

PHPファイルによって提供されるMP3またはOGGデータを指すHTML5オーディオ要素を埋め込もうとしています。Safariでページを表示すると、コントロールが表示されますが、UIに「ライブブロードキャスト」と表示されます。 。 "再生をクリックすると、オーディオは期待どおりに開始されます。ただし、終了すると、再生をクリックしても再生を再開できません。オーディオ要素でJS APIを使用し、currentTimeを0に設定しても、インデックスエラーで失敗します。例外。

PHPスクリプトのヘッダーが問題であり、特にコンテンツの長さが欠落しているのではないかと思いました。しかし、そうではありません。応答ヘッダーには、オーディオのサイズが有限であることを示す適切なContent-Lengthが含まれています。さらに、Firefox 3.5以降ではすべてが期待どおりに機能します。オーディオ要素の[再生]を複数回クリックして、サウンドの再生を聞くことができます。

方程式からPHPスクリプトを削除し、MP3ファイルの静的コピーを提供すると、Safariではすべてが正常に機能します。

これは、Safariがクエリパラメータを持つオーディオsrc URLを、クエリパラメータを持たないURLとは異なる方法で処理していることを意味しますか?誰かがこれを機能させる運がありますか?

私の簡単なサンプルページは次のとおりです。

<!DOCTYPE html>
<html>
  <head></head>
  <body>
    <audio controls autobuffer>
      <source src="say.php?text=this%20is%20a%20test&format=.ogg" />
      <source src="say.php?text=this%20is%20a%20test&format=.mp3" />
    </audio>
  </body>
</html>

PHPスクリプトからのHTTPヘッダー:

HTTP/1.x 200 OK
Date: Sun, 03 Jan 2010 15:39:34 GMT
Server: Apache
X-Powered-By: PHP/5.2.10
Content-Length: 8993
Keep-Alive: timeout=2, max=98
Connection: Keep-Alive
Content-Type: audio/mpeg

直接ファイルアクセスからのHTTPヘッダー:

HTTP/1.x 200 OK
Date: Sun, 03 Jan 2010 20:06:59 GMT
Server: Apache
Last-Modified: Sun, 03 Jan 2010 03:20:02 GMT
Etag: "a404b-c3f-47c3a14937c80"
Accept-Ranges: bytes
Content-Length: 8993
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: audio/mpeg

Accept-Rangesヘッダーもスクリプトにハードコーディングしようとしましたが、うまくいきませんでした。

34
Peter Parente

PHPスクリプトの有無にかかわらず、サーバーから送信されたヘッダーを投稿できますか?PHPスクリプトは、提供するものとは異なるContent-Typeを送信しているのではないかと思います。通常のファイル。

type要素にsource属性を指定することもお勧めします。これにより、ブラウザーは両方のクリップをダウンロードして、再生できるかどうかを判断する必要がなくなります。

私はあなたの問題を再現することはできません。 次のテストページ を使用して、Safari4.0.4と現在のWebKitで毎晩問題を再現しようとしました。私は単にmod_rewriteを使用して、PHPの代わりにパラメーターに基づいてさまざまな形式にディスパッチしていますが、何らかの理由でPHPがファイルを変更していない限り、違いはないと思います。

<!DOCTYPE html>
<title>Auido test</title>
<audio controls autobuffer>
  <source src="gnossienne-no-1?foo=bar&format=.mp4">
  <source src="gnossienne-no-1?foo=bar&format=.ogg">
</audio>

私の例を試してみて、それがうまくいくかどうか教えていただけますか?

編集ああ。もう少し調べてみると、Safariの<audio>要素がコンテンツのサイズを決定しようとする奇妙な方法が原因であるように見えます。

これは、Apacheから直接提供されるファイルを指す<audio>要素に遭遇したときのSafariのパケットキャプチャからの抜粋です。ご覧のとおり、最初にメディアの最初の2バイトをフェッチしようとします。これは、おそらくContent-Lengthと、場合によっては他のヘッダーを取得できるようにするためです。次に、すべてをフェッチしようとします。次に、不可解なことに、最初の2バイトを再度フェッチしようとしますが、適切なキャッシュヘッダーを渡して、「304NotModified」応答を取得します。そして最後に、それでも不可解なことに、ファイルの最後の3440バイトをもう一度フェッチします。これらすべてを別々のTCP接続で実行します。これにより、データを数回フェッチするオーバーヘッドに加えて、かなりのオーバーヘッドが追加されます。

 GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1 
ホスト:ephemera.continuation.org 
範囲:bytes = 0-1 
接続:閉じる
ユーザーエージェント:Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540 
承認:*/* 
 Accept-Encoding:identity 
 Cookie:[編集済み] 
 
 HTTP/1.1206部分コンテンツ
日付:2010年1月5日火曜日02:12 :48 GMT 
サーバー:Apache 
最終変更日:2010年1月5日火曜日02:02:08 GMT 
 ETag: "b2a80ad-11f6-47c6139aaa800" 
 Accept-Ranges:bytes 
 Content-Length:2 
 Content-Range:bytes 0-1/4598 
 Connection:close 
 Content-Type:audio/mpeg 
 
#2バイトのデータ
 
 GET/stackoverflow/audio-test/say-noid3?foo = bar&format = .mp3 HTTP/1.1 
ホスト:ephemera.continuation.org 
範囲:bytes = 0-4597 
接続:close 
ユーザーエージェント:Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540 
承認:*/* 
承認-エンコーディング:identi ty 
 Cookie:[編集済み] 
 
 HTTP/1.1206部分コンテンツ
日付:2010年1月5日火曜日02:12:48 GMT 
サーバー:Apache 
最終変更日:2010年1月5日火曜日02:02:08 GMT 
 ETag: "b2a80ad-11f6-47c6139aaa800" 
 Accept-Ranges:bytes 
 Content-Length:4598 
 Content-Range:bytes 0-4597/4598 
 Connection:close 
 Content-Type:audio/mpeg 
 
#4598バイトのデータ
 
 GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1 
ホスト:ephemera.continuation.org 
範囲:bytes = 0-1 
接続:close 
ユーザーエージェント:Apple Mac OS X v10.6.2CoreMediav1.0.0。 10C540 
 Accept:*/* 
 Accept-Encoding:identity 
 Cookie:[編集済み] 
 If-None-Match: "b2a80ad-11f6-47c6139aaa800" 
 If-Modified-Since:Tue、05 Jan 2010 02:02:08 GMT 
 
 HTTP/1.1 304 Not Modified 
 Date:Tue、05 Jan 2010 02 :12:49 GMT 
サーバー:Apache 
接続:閉じる
 ETag: "b2 a80ad-11f6-47c6139aaa800 "
 
#no data 
 
 GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1 
ホスト:ephemera.continuation.org 
範囲:bytes = 1158-4597 
接続:close 
ユーザーエージェント:Apple = Mac OS X v10.6.2 CoreMedia v1.0.0.10C540 
 Accept:*/* 
 Accept-Encoding:identity 
 Cookie:[編集済み] 
 
 HTTP/1.1 206部分コンテンツ
日付:2010年1月5日火曜日02:12:49 GMT 
サーバー:Apache 
最終変更日:2010年1月5日火曜日02 :02:08 GMT 
 ETag: "b2a80ad-11f6-47c6139aaa800" 
 Accept-Ranges:bytes 
 Content-Length:3440 
 Content-Range:bytes 1158 -4597/4598 
接続:close 
 Content-Type:audio/mpeg 
 
#3440バイトのデータ

とにかく、PHPスクリプトの出力をどのように処理するかについてです。ここで、Safariは最初の2バイトを再度ダウンロードしようとしますが、スクリプトはRange要求を無視して戻りますどうやら、WebKitはそれを好まないので、Rangeリクエストなしで再試行します。スクリプトは完全なコンテンツを送信します。Safariはもう一度試行し、Icy-Metadataヘッダーを追加します。ストリームをダウンロードしていると考え、ストリーミングメタデータを送信したいことを示します。最終的にその出力を受け入れ、<audio>要素を再生できます。

 GET /say.php?text=this%20is%20a%20test&format=.mp3 HTTP/1.1 
ホスト:tts.mindtrove.info 
範囲:bytes = 0-1 
接続:閉じる
ユーザーエージェント:Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540 
承認:*/* 
 Accept-Encoding:identity 
 
 HTTP/1.1 200 OK 
日付:2010年1月5日火曜日02:14:28 GMT 
サーバー:Apache 
 X-Powered-By:PHP/5.2.10 
 Content-Length:4598 
 Connection:close 
 Content-Type:audio/mpeg 
 
#4598バイトのデータ
 
 GET /say.php?text=this%20is%20a%20test&format=.mp3 HTTP/1.1 
ホスト:tts .mindtrove.info 
接続:閉じる
ユーザーエージェント:Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540 
承認: */* 
 
 HTTP/1.1 200 OK 
日付:2010年1月5日火曜日02:14:28 GMT 
サーバー:Apache 
 X -Powered-By:PHP/5.2.10 
 Content-Length:4598 
 Connection:close 
 Content-Type:audio/mpeg 
 
 #4598バイトのデータ
 
 GET /say.php?text=this%20is%20a%20test&format=.mp3 HTTP/1.1 
ホスト:tts.mindtrove.info 
承認:* /*
User-Agent:Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540 
 Icy-Metadata:1 
接続: close 
 
 HTTP/1.1 200 OK 
日付:2010年1月5日火曜日02:14:28 GMT 
サーバー:Apache 
 X-Powered -作成者:PHP/5.2.10 
 Content-Length:4598 
 Connection:close 
 Content-Type:audio/mpeg 
 
#4598データのバイト

要約すると、Safari(より正確には、Safariがすべてのメディアとメディアのダウンロードを処理するために使用するQuickTime)は、メディアをダウンロードするための完全に頭を悩ませたアプローチを持っているようです。データを送り返す方法の何か、おそらくRangeリクエストに応答しないという事実は、ストリーミングメディアを送信していると思わせ、コンテンツを繰り返しダウンロードさせます(たとえ直面した場合でも) Rangeリクエストに応答するサーバーでは、実際に必要な数よりも多くのリクエストを実行します)。

私のアドバイスは、Rangeリクエストに適切に応答するようにすることです。メディアを提供するとき、ブラウザは、再生できるようにする必要があるだけバッファリングすることによって、帯域幅を最小化しようとする可能性があります(ただし、バッファリングすることを示すautobuffer属性があります)全体として、ブラウザはそれを無視するかもしれません)。 X-Sendfileを使用して、Apacheにファイル、キャッシュ、範囲のリクエストの処理を処理させることをお勧めしますが、mod_xsendfileがインストールされていないDreamhostを使用しているように見えるため、独自のRange処理。

35
Brian Campbell

ちなみに、PochangとChrisはどちらも、Safariでこの問題を修正するにはContent-Rangeヘッダーが必要であることは正しいですが、Chromeには、currentTimeを正しく機能させるために含める必要のある追加のヘッダーが1つ必要です。 :

header( 'Accept-Ranges: bytes');

実際にリクエストのRangeヘッダーに正しく応答する必要はなく、これを応答に含める必要があることに注意してください。

4
Brendan

古いトピックですが、2019年もまだ有効です。最終的に解決策が見つかりました...以下PHPスクリプトサンプルでは、​​Safariの「範囲」ヘッダーリクエストが考慮されます。

$bytes_total = strlen($data);
if (isset($_SERVER['HTTP_RANGE'])) {
    $byte_range = explode('-',trim(str_ireplace('bytes=','',$_SERVER['HTTP_RANGE'])));
    $byte_from = $byte_range[0];
    $byte_to = ($byte_range[1]+1);
    $data = substr($data,$byte_from,$byte_to);
    header('HTTP/1.1 206 Partial Content');
}
else {
    $byte_from = 0;
    $byte_to = $bytes_total;
}
$length = strlen($data); 
header('Content-type: '.$content_type);
header('Accept-Ranges: bytes');
header('Content-length: ' . $length);
header('Content-Range: bytes '.$byte_from.'-'.$byte_to.'/'.$bytes_total);
header('Content-Transfer-Encoding: binary');
print($data);
3
rmfm

ポチャンは正しいです。 PHP応答にContent-Rangeヘッダーを含めると、Safariが適切に動作します。また、ChromeではなくSafariで恐ろしいINDEX_SIZE_ERRなしで(media.currentTime = 0;)をシークできます。

ヘッダーのPHPコードは次のとおりです。

$len = strlen( $data );
$shortlen = $len - 1;
header( 'Content-Range: bytes 0-'.$shortlen.'/'.$len);
2
Chris Snyder

同じ問題が発生しました。重要な点はContent-Rangeヘッダーです。 mp3-output phpに追加すると、すべて正常に動作します。

2
Pochang