你可以发布服务器发送的标题有无PHP脚本?我想知道PHP脚本是否发送不同的Content-Type而不是正常提供文件。
在源元素上指定type属性也是一个好主意,因此浏览器不必下载两个剪辑以确定是否可以播放它们。
我不能重现你的问题。我试图在Safari 4.0.4中重现问题,并且当前的WebKit每晚,与following test page.我只是使用mod_rewrite分发到不同的格式,基于一个参数,而不是PHP,但我不认为应该一个区别,除非不知何故PHP正在修改文件。
Auido test你能试试我的例子,让我知道它是否适合你?
编辑啊。在稍微戳一遍它之后,似乎问题是由于< audio>的奇怪方式引起的。元素在尝试确定内容的大小时会起作用。
下面是Safari遇到< audio>时捕获的数据包的摘录。元素指向直接从Apache提供的文件。正如你可以看到,它首先尝试获取媒体的前两个字节,大概是因为它可以获得一个Content-Length,以及可能的其他头。然后它尝试获取整个事情。然后,不可能的是,它尝试再次获取前两个字节,但传递适当的缓存头以获取“304未修改”响应。最后,仍然莫名其妙地,它再次获取文件的最后3440字节。它在单独的TCP连接中执行所有这些操作,这增加了相当大的开销,以及获取数据的开销。
GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1
Host: ephemera.continuation.org
Range: bytes=0-1
Connection: close
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Accept: */*
Accept-Encoding: identity
Cookie: [redacted]
HTTP/1.1 206 Partial Content
Date: Tue,05 Jan 2010 02:12:48 GMT
Server: Apache
Last-Modified: Tue,05 Jan 2010 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 bytes of data
GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1
Host: ephemera.continuation.org
Range: bytes=0-4597
Connection: close
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Accept: */*
Accept-Encoding: identity
Cookie: [redacted]
HTTP/1.1 206 Partial Content
Date: Tue,05 Jan 2010 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 bytes of data
GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1
Host: ephemera.continuation.org
Range: bytes=0-1
Connection: close
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Accept: */*
Accept-Encoding: identity
Cookie: [redacted]
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
Server: Apache
Connection: close
ETag: "b2a80ad-11f6-47c6139aaa800"
# no data
GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1
Host: ephemera.continuation.org
Range: bytes=1158-4597
Connection: close
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Accept: */*
Accept-Encoding: identity
Cookie: [redacted]
HTTP/1.1 206 Partial Content
Date: Tue,05 Jan 2010 02:12:49 GMT
Server: Apache
Last-Modified: Tue,05 Jan 2010 02:02:08 GMT
ETag: "b2a80ad-11f6-47c6139aaa800"
Accept-Ranges: bytes
Content-Length: 3440
Content-Range: bytes 1158-4597/4598
Connection: close
Content-Type: audio/mpeg
# 3440 bytes of data
无论如何,关于它如何处理您的PHP脚本的输出。这里,Safari再次尝试下载前两个字节,但是您的脚本忽略Range请求并返回整个内容。显然,WebKit不喜欢,所以它再次尝试,没有Range请求。同样,您的脚本发送完整的内容。 Safari现在再次尝试,添加一个Icy-Metadata头,这表明它认为它正在下载一个流,并且想要发送流元数据。它最终接受其输出,并且< audio>元素可以玩。
GET /say.PHP?text=this%20is%20a%20test&format=.mp3 HTTP/1.1
Host: tts.mindtrove.info
Range: bytes=0-1
Connection: close
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Accept: */*
Accept-Encoding: identity
HTTP/1.1 200 OK
Date: Tue,05 Jan 2010 02:14:28 GMT
Server: Apache
X-Powered-By: PHP/5.2.10
Content-Length: 4598
Connection: close
Content-Type: audio/mpeg
# 4598 bytes of data
GET /say.PHP?text=this%20is%20a%20test&format=.mp3 HTTP/1.1
Host: tts.mindtrove.info
Connection: close
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Accept: */*
HTTP/1.1 200 OK
Date: Tue,05 Jan 2010 02:14:28 GMT
Server: Apache
X-Powered-By: PHP/5.2.10
Content-Length: 4598
Connection: close
Content-Type: audio/mpeg
# 4598 bytes of data
GET /say.PHP?text=this%20is%20a%20test&format=.mp3 HTTP/1.1
Host: tts.mindtrove.info
Accept: */*
User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540
Icy-Metadata: 1
Connection: close
HTTP/1.1 200 OK
Date: Tue,05 Jan 2010 02:14:28 GMT
Server: Apache
X-Powered-By: PHP/5.2.10
Content-Length: 4598
Connection: close
Content-Type: audio/mpeg
# 4598 bytes of data
总而言之,Safari(或更准确地说,QuickTime,Safari使用它来处理所有媒体和媒体下载)有一个完全困难的方法来下载媒体。在你发送数据的方式,可能是你没有响应Range请求的事实,使它认为你发送流媒体,导致它重复下载内容(虽然即使面对的服务器响应Range请求,它仍然会执行几个更多的请求,而不是它真正需要的)。
我的建议是尽量适当响应Range请求;当提供媒体时,浏览器可能会使用它们尝试最小化带宽,通过只缓冲尽可能多的,他们需要能够播放(虽然有autobuffer属性,表明你希望他们缓冲整个事情,浏览器可以忽略)。我建议使用X-Sendfile让Apache处理文件,缓存和范围请求,但你似乎是在没有安装mod_xsendfile的Dreamhost,所以你必须滚动自己的范围处理。