2010-01-03 37 views
27

Tôi đang cố gắng để nhúng một yếu tố âm thanh HTML5 trỏ đến dữ liệu MP3 hoặc OGG phục vụ bởi một file PHP. Khi tôi xem trang trong Safari, các điều khiển xuất hiện, nhưng giao diện người dùng nói "Phát trực tiếp". Khi tôi nhấp vào phát, âm thanh sẽ bắt đầu như mong đợi. Tuy nhiên, khi nó kết thúc, tôi không thể bắt đầu chơi lại bằng cách nhấp vào phát. Ngay cả khi sử dụng API JS trên phần tử âm thanh và thiết lập currentTime thành 0 không thành công với một ngoại lệ lỗi chỉ mục.HTML5 <audio> Safari sống phát sóng vs không

tôi nghi ngờ các tiêu đề từ các tập lệnh PHP là những vấn đề, đặc biệt là thiếu chiều dài nội dung. Nhưng đó không phải là trường hợp. Tiêu đề phản hồi bao gồm Nội dung phù hợp để chỉ ra âm thanh có kích thước hữu hạn. Hơn nữa, mọi thứ hoạt động như mong đợi trong Firefox 3.5+. Tôi có thể nhấp vào phát trên phần tử âm thanh nhiều lần để nghe phát lại âm thanh.

Nếu tôi loại bỏ các script PHP từ phương trình và phục vụ lên một bản sao tĩnh của tập tin MP3, mọi thứ hoạt động tốt trong Safari.

Điều này có nghĩa là đối xử với Safari URL src âm thanh với tham số truy vấn khác biệt so với các URL không có chúng? Bất cứ ai có may mắn nhận được điều này để làm việc?

trang ví dụ đơn giản của tôi là:

<!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> 

HTTP Headers từ PHP kịch bản:

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 Headers từ truy cập tập tin trực tiếp:

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 

tôi đã cố gắng cứng mã hóa Chấp nhận-Ranges tiêu đề vào kịch bản quá, nhưng không có may mắn.

+0

Tôi không chắc liệu bạn có được thông báo về chỉnh sửa hay không, nhưng tôi đã chỉnh sửa câu trả lời của mình để bao gồm trường hợp kiểm tra phù hợp với tôi và dường như phù hợp với những gì bạn đang làm. Bạn có thể kiểm tra xem trường hợp thử nghiệm của tôi có hoạt động cho bạn không? –

Trả lời

31

Bạn có thể gửi các tiêu đề được gửi bởi máy chủ cả có và không có kịch bản PHP? Tôi tự hỏi nếu kịch bản PHP đang gửi một khác nhau Content-Type hơn phục vụ các tập tin bình thường. Bạn cũng cần phải chỉ định thuộc tính type trên các yếu tố source, do đó trình duyệt không phải tải xuống cả hai clip để xác định xem nó có thể phát chúng hay không.

Tôi không thể tạo lại sự cố của bạn. Tôi đã cố gắng tạo lại sự cố trong Safari 4.0.4 và WebKit hiện tại hàng đêm, với following test page. Tôi chỉ đơn giản là sử dụng mod_rewrite để gửi đến các định dạng khác nhau dựa trên một tham số thay vì PHP, nhưng tôi không nghĩ rằng nên tạo sự khác biệt, trừ khi bằng cách nào đó PHP đang sửa đổi tệp.

<!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> 

Bạn có thể thử ví dụ của tôi và cho tôi biết nếu nó phù hợp với bạn không?

chỉnh sửa Ah. Sau khi poking xung quanh nó nhiều hơn một chút, có vẻ như vấn đề là do một cách kỳ lạ mà các yếu tố <audio> trong Safari cư xử trong cố gắng để xác định kích thước của nội dung.

Dưới đây là một đoạn trích từ gói chụp Safari khi gặp phải phần tử <audio> trỏ đến tệp được phân phối trực tiếp từ Apache. Như bạn có thể thấy, trước tiên, nó cố gắng tìm nạp hai byte đầu tiên của phương tiện, có lẽ vì vậy nó có thể nhận được một Content-Length back, và có thể các header khác. Sau đó nó cố gắng tìm kiếm toàn bộ. Sau đó, không thể giải thích, nó cố gắng lấy lại hai byte đầu tiên một lần nữa, nhưng chuyển các tiêu đề bộ nhớ đệm thích hợp để nhận được phản hồi "304 không được sửa đổi".Và cuối cùng, vẫn không thể giải thích, nó lấy lại 3440 byte cuối cùng của tập tin trên một lần nữa. Nó thực hiện tất cả những điều này trong các kết nối TCP riêng biệt, bổ sung thêm chi phí đáng kể, ngoài việc nạp dữ liệu một vài lần.

 
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:12:48 GMT 
Server: Apache 
Last-Modified: 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 

Nhưng dù sao, về cách giao dịch với đầu ra của tập lệnh PHP của bạn. Ở đây, Safari lại cố gắng tải xuống hai byte đầu tiên, nhưng tập lệnh của bạn bỏ qua yêu cầu Range và trả về toàn bộ. Rõ ràng, WebKit không thích điều đó, và vì vậy nó cố gắng một lần nữa, mà không có yêu cầu Range. Một lần nữa, kịch bản của bạn gửi toàn bộ nội dung. Safari hiện đang thử lại một lần nữa, thêm tiêu đề Icy-Metadata, cho biết nó cho rằng nó đang tải xuống luồng và muốn gửi siêu dữ liệu trực tuyến. Cuối cùng nó chấp nhận đầu ra của nó và phần tử <audio> có thể phát.

 
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 

Nói tóm lại, có vẻ như Safari (hay chính xác hơn, QuickTime, mà Safari sử dụng để xử lý tất cả các phương tiện truyền thông và tải phương tiện truyền thông) có một cách tiếp cận hoàn toàn braindamaged truyền thông tải về. Một cái gì đó trong cách bạn gửi dữ liệu của bạn trở lại, có lẽ thực tế là bạn không đáp ứng với yêu cầu Range, làm cho nó nghĩ rằng bạn đang gửi phương tiện truyền thông, khiến nó tải xuống nội dung nhiều lần (mặc dù ngay cả khi đối mặt với một máy chủ trả lời một yêu cầu Range, nó vẫn thực hiện nhiều yêu cầu hơn so với yêu cầu thực sự).

Lời khuyên của tôi sẽ là cố gắng trả lời phù hợp với yêu cầu Range; khi cung cấp phương tiện, trình duyệt có thể sẽ sử dụng chúng để cố gắng giảm thiểu băng thông, bằng cách chỉ đệm nhiều như chúng cần để có thể phát qua (mặc dù có thuộc tính autobuffer cho biết rằng bạn muốn chúng lưu toàn bộ nội dung, trình duyệt có thể bỏ qua điều đó). Tôi khuyên bạn nên sử dụng để cho phép Apache xử lý các yêu cầu về tệp, bộ nhớ đệm và phạm vi, nhưng dường như bạn đang ở trên Dreamhost, chưa cài đặt mod_xsendfile, vì vậy bạn sẽ phải tự xử lý Range của riêng mình.

+1

Đã thêm tiêu đề vào câu hỏi gốc vì chúng không phù hợp với nhận xét. Tôi đã xác định loại ban đầu, nhưng lấy nó ra trong trường hợp nó gây ra vấn đề. Thêm chúng trở lại để đo lường tốt, nhưng không thay đổi hành vi bị hỏng trong Safari. –

+0

Ví dụ của bạn phù hợp với tôi.Vì vậy, yếu tố duy nhất có vẻ là kịch bản PHP. Hấp dẫn. Tôi đã đăng bản trình diễn mã của mình tại http://tts.mindtrove.info/test.html. Nguồn của tệp PHP được hiển thị tại http://tts.mindtrove.info/say.php.txt. Các tệp âm thanh tĩnh có tại http://tts.mindtrove.info/cache. Điều duy nhất tôi thấy trong tập lệnh PHP có thể gây rắc rối hiện nay là việc sử dụng passthru ("cat $ fn"). Nhưng với chiều dài Nội dung và lối ra cưỡng bức() ở cuối tập lệnh, tôi không chắc tại sao Safari/WebKit sẽ coi âm thanh là luồng không bao giờ kết thúc. –

+1

Trợ giúp tuyệt vời. Cảm ơn đã dành thời gian để làm việc thông qua điều này với tôi. Phát hiện của bạn có thể chín muồi cho một báo cáo lỗi, mặc dù tôi chắc chắn Apple sẽ chỉ đơn giản nói rằng kịch bản PHP cần xử lý phạm vi. Nó có thể là tốt đẹp nếu họ tài liệu nó ở đâu đó mặc dù. –

2

Tôi gặp vấn đề tương tự. Điểm mấu chốt là tiêu đề Phạm vi nội dung. Mọi thứ hoạt động tốt sau khi tôi thêm nó vào mp3-output php.

2

Pochang là chính xác. Bao gồm tiêu đề Phạm vi nội dung trong phản hồi PHP sẽ khiến Safari hoạt động đúng cách. Nó cũng cho phép tìm kiếm (media.currentTime = 0;) mà không có INDEX_SIZE_ERR đáng sợ trong Safari, mặc dù không có trong Chrome.

Các mã PHP cho tiêu đề là:

$len = strlen($data); 
$shortlen = $length - 1; 
header('Content-Range: bytes 0-'.$shortlen.'/'.$len); 
+6

Các biến ở đây chính xác là gì? ? Độ dài $ đến từ đâu? – Roozbeh15

3

Đối với hồ sơ, trong khi cả hai Pochang và Chris là chính xác những gì bạn cần header Content-Range để khắc phục vấn đề này trong Safari, Chrome yêu cầu thêm một tiêu đề phải được bao gồm để đặt currentTime hoạt động bình thường:

header('Accept-Ranges: bytes'); 

Lưu ý rằng bạn không thực sự phải trả lời chính xác cho tiêu đề Phạm vi của yêu cầu, bạn chỉ cần bao gồm điều này trong phản hồi.

+0

Cảm ơn, Brendan, đã giúp ích rất nhiều! – Hbf

Các vấn đề liên quan