Twistedで作るローカルYoutubeサーバ その2
今度は見る側。Web部分を実装する。
flvplayerは適当に見つけたJW FLV PLAYER 3.9を使う。
Web側の実装は大体
- staticファイルの参照
- 一覧ページの作成
- 詳細ページの作成
ぐらい。
staticファイルの参照
Twistedで書かれたWebサーバにはデフォルトでstaticファイルの参照用の関数がある。
twisted.webはぼろいはずのでnevowの方のstaticモジュールを使う事をおすすめする。
(renderってDefferになってなくてブロックになるのだっけ?)
server.tac
from twisted.application import service, strports from nevow import static from nevow import appserver page = web.ListPage() page.putChild('flvplayer.swf', static.File('./flvplayer.swf')) page.putChild('video', static.File(setting.repo)) site = appserver.NevowSite(page) strports.service("8081", site).setServiceParent(application)
一番親に当たるのがListPage(後述)でputChildでそれ以降にパスを設定する。
static.Fileは指定したパスをResource化してくれる。
この例では
- http://localhost:8081/はListPageの内容
- http://localhost:8081/flvplayer.swfはserver.tacと同Dirにあるflvplayer.swf
- http://localhost:8081/videoはsetting.pyで指定したvideoの保存先Dir
もちろんIndex出さなくしたりもできるけどローカルなので最小構成で。
一覧ページの作成、詳細ページの作成
せっかくなのでnevowを使いまくろう。ということでPageを使う。
from nevow import rend from nevow import loaders from nevow import accessors from nevow import inevow from twisted.python import util from twisted.python.components import registerAdapter items = [] class VideoItem(object): pass class ListPage(rend.Page): docFactory=loaders.xmlfile(util.sibpath(__file__, 'list.html')) def childFactory(self, ctx, segments): return DetailPage(segments) def data_list(self, ctx, data): return items class DetailPage(rend.Page): addSlash = True docFactory=loaders.xmlfile(util.sibpath(__file__, 'detail.html')) def __init__(self, id): self.id = id def data_id(self, ctx, data): return '/flvplayer.swf?file=/video/%s.flv' % self.id registerAdapter(accessors.ObjectContainer, VideoItem, inevow.IContainer)
ListPageは一覧、DetailPageは再生するページ。
docFactoryで対応するテンプレートを指定する。
テンプレートにはXHTML、stan、バギーなHTMLが指定できるけど今回はまじめにXHTMLを使う。
ハッカーはstanを使うといいと思う。変態的だし。
ListPageは上記のtacにも出て来たけど一番URLの親に割り当てている。
その子としてDetailPageがいる。
Twistedは割と子クラスをガンガン足してそれにURLもついていくパターン(積み上げ式)でURLを構築するケースが多いんじゃないか。
(それがいやでresolverを作ったんだけど)
childFactoryは自ページの一階層次のURLにきたときに呼ばれる。
この例ではhttp://localhost:8081/<☆>/の☆の部分をDetailPageに渡している。
htmlを見ないとわかりづらいけど☆の部分にはvideoidを渡す仕様になっていてDetailPageで実際に再生する際のvideoidをレンダリングする。
VideoItemはvideoを表すクラス。itemsには現在保持している(再生可能な)VideoItemが入っているイメージ。
ListPageはこのitemを返しているだけ。
registerAdapterを使っている理由はレンダリングする際に独自Objectを使用するため。
registerしてないとレンダリング時にうまく呼び出せない。
ながいのでこの辺で。
次はテンプレート部、XHTMLのレンダリング部分。
うくく。