2012年5月27日 星期日

[html5]在伺服器端怎麼支援 video 這個標籤

今天遇到的是,如果網頁中有個 video 標籤,伺服器該怎麼辦?一般人也許不會想到這個問題,而我卻遇到了。原因是我自己有寫一個小小 http server 的程式,只是為了要接收幾個按鈕,查詢並執行 ffmpeg 程式幫忙轉檔。小事情就自己動手了。所以,這種事情當然就要自己來處理囉。

從來自 chrome 的 request 之 headers 裡,有看到一個 range: 0- 這個,經過查詢(我當然還是查給人看的,而不是給超人看的文章),這個是通知伺服器說,從檔案的位置 0 開始給,結束位置隨便。感覺很隨便?其實是為了彈性。如此,伺服器該怎麼回應呢?

在 response 裡,要回覆的有

  1. Accept-Ranges: bytes
  2. Content-Range: xxx-ooo/sss

第一個是告訴瀏覽器說,我接受,而且是用 byte 當計算。 (有人說的,官方文件我真的看不懂,太像是給編譯器看的。) 而第二個就是告訴瀏覽器,從位置 xxx 開始(位置是從 0 開始算),到第 ooo 結束。整個檔案的大小是 sss。

舉例來說,一個 256 bytes 的小檔案,一次全部傳送完,Content-Range,就是 0-255/256。如果像大影片檔,就最好是一點一點的傳送,而就沒辦法一次全傳送了。

另外一個重點是回應碼,不是 200,而是 206 (參考),這樣瀏覽器才會再送一次 request 來要求其他的部份。像我提供 mp4 檔案的話,瀏覽器很聰明的先要了前面的部份之後,接下來要求最後的部份,據說是要影片的描述。有支援這種 partial content 的伺服器,大檔案傳送時應該很好用。

除了支援 range 之外,只要把 Content-Type 換成 video/mp4,chrome 就可以看影片。可以拉著時間軸跳到任意時間觀看。

程式的部份長這樣(我是用 python 寫):

self.send_response( 206 )
self.send_header( "Accept-Ranges", 'bytes' )
self.send_header( "Content-Type", 'video/mp4' )
self.send_header( "Content-Range", 'bytes %s-%s/%s' % (offset, end, size) )
self.log_message( 'bytes %s-%s/%s' % (offset, end, size))
self.end_headers()
f = open(src,'rb')
f.seek(offset, os.SEEK_SET )
self.wfile.write( f.read(block) )
f.close()
self.wfile.close()

沒有留言:

張貼留言