serve frames and videos with X-Sendfile header
This commit is contained in:
parent
7c0e365a0a
commit
1354a1ddc5
6 changed files with 51 additions and 8 deletions
4
README
4
README
|
@ -30,3 +30,7 @@ Development:
|
|||
we are using django, http://docs.djangoproject.com/en/dev/
|
||||
communication between webserver and background tasks is done via rabbitmq
|
||||
http://github.com/ask/carrot/ for more info on the lib used to communicate
|
||||
|
||||
|
||||
Apache setup:
|
||||
sudo apt-get install libapache2-mod-wsgi libapache2-mod-xsendfile
|
||||
|
|
|
@ -8,16 +8,21 @@
|
|||
Allow from all
|
||||
</Directory>
|
||||
|
||||
Alias /.bzr /oxdb/.bzr
|
||||
Alias /static __PREFIX__/oxdb/static
|
||||
Alias /favicon.ico __PREFIX__/oxdb/static/favicon.ico
|
||||
Alias /media __PREFIX__/oxdb/media
|
||||
<Location />
|
||||
XSendFile on
|
||||
XSendFileAllowAbove on
|
||||
</Location>
|
||||
|
||||
Alias /.bzr __PREFIX__/.bzr
|
||||
Alias /static __PREFIX__/pandora/static
|
||||
Alias /favicon.ico __PREFIX__/pandora/static/favicon.ico
|
||||
Alias /media __PREFIX__/pandora/media
|
||||
Alias /admin/media __PREFIX__/src/django/django/contrib/admin/media
|
||||
Alias /static/js/jquery.js __PREFIX__/src/django/django/contrib/admin/media/js/jquery.min.js
|
||||
WSGIScriptAlias / __PREFIX__/wsgi/django.wsgi
|
||||
|
||||
WSGIDaemonProcess oxdb user=oxdb group=oxdb threads=25 python-path=__PREFIX__/lib/python2.6/site-packages/
|
||||
WSGIProcessGroup oxdb
|
||||
WSGIDaemonProcess pandora user=pandora group=pandora threads=25 python-path=__PREFIX__/lib/python2.6/site-packages/
|
||||
WSGIProcessGroup pandora
|
||||
|
||||
ServerSignature Off
|
||||
</VirtualHost>
|
||||
|
|
|
@ -10,6 +10,7 @@ from django.db.models import Q
|
|||
from django.contrib.auth.models import User
|
||||
from django.core.files.base import ContentFile
|
||||
from django.utils import simplejson as json
|
||||
from django.conf import settings
|
||||
|
||||
from oxdjango import fields
|
||||
import oxlib
|
||||
|
@ -430,6 +431,11 @@ class Movie(models.Model):
|
|||
self.get('series_title', ''), self.get('episode_title', ''),
|
||||
self.get('season', ''), self.get('episode', ''))
|
||||
|
||||
def frame(self, position, width=128):
|
||||
#FIXME: compute offset and so on
|
||||
f = self.files.all()[0]
|
||||
return f.frame(position, width)
|
||||
|
||||
def updateFind(self):
|
||||
try:
|
||||
f = self.find
|
||||
|
@ -1155,7 +1161,9 @@ class File(models.Model):
|
|||
def frame(self, position, width=128):
|
||||
videoFile = getattr(self, 'stream_%s'%settings.VIDEO_PROFILE).path
|
||||
frameFolder = os.path.join(os.path.dirname(videoFile), 'frames')
|
||||
extract.frame(videoFile, position, frameFolder, width)
|
||||
if position<= self.duration:
|
||||
return extract.frame(videoFile, position, frameFolder, width)
|
||||
return None
|
||||
|
||||
def editable(self, user):
|
||||
'''
|
||||
|
|
|
@ -6,6 +6,8 @@ from django.conf.urls.defaults import *
|
|||
|
||||
urlpatterns = patterns("backend.views",
|
||||
(r'^upload/$', 'firefogg_upload'),
|
||||
(r'^frame/(?P<id>.*)/(?P<position>.*)\.(?P<size>\d+).jpg$', 'frame'),
|
||||
(r'^stream/(?P<id>.*).(?P<quality>.*).ogv$', 'video'),
|
||||
(r'^$', 'api'),
|
||||
)
|
||||
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from __future__ import division
|
||||
import os.path
|
||||
import re
|
||||
from datetime import datetime
|
||||
from urllib2 import unquote
|
||||
import json
|
||||
import mimetypes
|
||||
|
||||
from django import forms
|
||||
from django.core.paginator import Paginator
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Q, Avg, Count
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404
|
||||
from django.template import RequestContext
|
||||
from django.conf import settings
|
||||
|
@ -23,6 +25,8 @@ except ImportError:
|
|||
|
||||
from oxdjango.decorators import login_required_json
|
||||
from oxdjango.shortcuts import render_to_json_response, get_object_or_404_json, json_response
|
||||
from oxdjango.http import HttpFileResponse
|
||||
import oxlib
|
||||
|
||||
import models
|
||||
import utils
|
||||
|
@ -630,6 +634,24 @@ def api_subtitles(request):
|
|||
l = models.Subtitles.objects.filter(movie_file__oshash=oshash).values('language')
|
||||
response['data']['languages'] = [f['language'] for f in l]
|
||||
return render_to_json_response(response)
|
||||
|
||||
def video(request, id, quality):
|
||||
movie = get_object_or_404(models.Movie, movieId=id)
|
||||
if quality not in settings.VIDEO_ENCODING:
|
||||
raise Http404
|
||||
stream = getattr(movie, 'stream_'+quality)
|
||||
response = HttpFileResponse(stream.path, content_type='video/ogg')
|
||||
#FIXME: movie needs duration field
|
||||
#response['Content-Duration'] = movie.duration
|
||||
return response
|
||||
|
||||
def frame(request, id, position, size):
|
||||
movie = get_object_or_404(models.Movie, movieId=id)
|
||||
position = oxlib.time2ms(position)/1000
|
||||
frame = movie.frame(position, int(size))
|
||||
if not frame:
|
||||
raise Http404
|
||||
return HttpFileResponse(frame, content_type='image/jpeg')
|
||||
|
||||
'''
|
||||
GET list
|
||||
|
|
|
@ -13,6 +13,8 @@ DEBUG = True
|
|||
TEMPLATE_DEBUG = DEBUG
|
||||
JSON_DEBUG = False
|
||||
|
||||
XSENDFILE = False
|
||||
|
||||
ADMINS = (
|
||||
('j', 'j@mailb.org'),
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue