您是否可以发布带有和不带有PHP脚本的服务器发送的标头?我想知道PHP脚本发送的内容是否不同于Content-Type正常提供的文件。
type在
source元素上指定属性也是一个好主意,因此浏览器不必下载两个剪辑即可确定是否可以播放它们。
我无法重现您的问题。我尝试使用以下测试页面在Safari 4.0.4和当前的WebKit中每晚重新创建该问题。我只是使用mod_rewrite根据参数而不是PHP调度为不同的格式,但是我认为这不会有所作为,除非PHP以某种方式修改了该文件。
<!DOCTYPE html><title>Auido test</title><audio controls autobuffer> <source src="https://www.mshxw.com/skin/sinaskin/image/nopic.gif"> <source src="https://www.mshxw.com/skin/sinaskin/image/nopic.gif"></audio>
您可以尝试一下我的示例并让我知道它是否对您有用吗?
编辑啊。经过更多研究之后,问题似乎出
<audio>在Safari 中的元素试图确定内容大小的行为方式奇怪。
这是摘自Safari数据包捕获的摘录,其中遇到了
<audio>指向直接由Apache提供服务的文件的元素。如您所见,它首先尝试获取媒体的前两个字节,大概是这样它可以获取
Content-Length,以及其他报头。然后,它尝试获取整个内容。然后,莫名其妙地,它尝试再次获取前两个字节,但传递适当的缓存头以获取
“ 304 Not Modified”响应。最后,仍然令人费解的是,它再次重新获取文件的最后3440字节。它会在单独的TCP连接中完成所有这些操作,这不仅增加了几次获取数据的开销,还增加了相当大的开销。
GET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1Host: ephemera.continuation.orgRange: bytes=0-1Connection: closeUser-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540Accept: **Accept-Encoding: identitycookie: [redacted]HTTP/1.1 206 Partial ContentDate: Tue, 05 Jan 2010 02:12:48 GMTServer: ApacheLast-Modified: Tue, 05 Jan 2010 02:02:08 GMTETag: "b2a80ad-11f6-47c6139aaa800"Accept-Ranges: bytesContent-Length: 4598Content-Range: bytes 0-4597/4598Connection: closeContent-Type: audio/mpeg# 4598 bytes of dataGET /stackoverflow/audio-test/say-noid3?foo=bar&format=.mp3 HTTP/1.1Host: ephemera.continuation.orgRange: bytes=0-1Connection: closeUser-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540Accept: **Accept-Encoding: identitycookie: [redacted]HTTP/1.1 206 Partial ContentDate: Tue, 05 Jan 2010 02:12:49 GMTServer: ApacheLast-Modified: Tue, 05 Jan 2010 02:02:08 GMTETag: "b2a80ad-11f6-47c6139aaa800"Accept-Ranges: bytesContent-Length: 3440Content-Range: bytes 1158-4597/4598Connection: closeContent-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.1Host: tts.mindtrove.infoRange: bytes=0-1Connection: closeUser-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540Accept: **HTTP/1.1 200 OKDate: Tue, 05 Jan 2010 02:14:28 GMTServer: ApacheX-Powered-By: PHP/5.2.10Content-Length: 4598Connection: closeContent-Type: audio/mpeg# 4598 bytes of dataGET /say.php?text=this%20is%20a%20test&format=.mp3 HTTP/1.1Host: tts.mindtrove.infoAccept: */*User-Agent: Apple Mac OS X v10.6.2 CoreMedia v1.0.0.10C540Icy-metadata: 1Connection: closeHTTP/1.1 200 OKDate: Tue, 05 Jan 2010 02:14:28 GMTServer: ApacheX-Powered-By: PHP/5.2.10Content-Length: 4598Connection: closeContent-Type: audio/mpeg# 4598 bytes of data
总而言之,似乎
Safari(或更准确地说是Safari用于处理所有媒体和媒体下载的QuickTime)具有完全破坏大脑的媒体下载方法。回传数据的某种方式(可能是您未响应Range请求的事实)使其认为您正在发送流媒体,从而导致其反复下载内容(即使面对确实响应的服务器)对于一个
Range请求,它仍然执行比实际需要多的几个请求)。
我的建议是尝试适当地回应Range请求;在提供媒体内容时,浏览器可能会通过仅缓冲它们需要播放的内容来使用它们来尝试最小化带宽(尽管具有
autobuffer指示您希望它们缓冲整个内容的属性,浏览器可能忽略它)。我建议使用X-Sendfile来让Apache处理文件,缓存和范围请求的服务,但是您似乎位于
Dreamhost上(尚未
mod_xsendfile安装),因此您将不得不自己
Range处理。



