From 5f8720353119d3fe2cce721fc8bca800b8e1d95a Mon Sep 17 00:00:00 2001 From: j <0x006A@0x2620.org> Date: Sun, 3 Jul 2011 18:21:27 +0200 Subject: [PATCH] torrent seeding --- pandora/item/models.py | 57 ++++++++++++++++++++++++++++++++++++++++++ pandora/item/urls.py | 9 +++---- pandora/item/views.py | 18 ++++++++++++- pandora/settings.py | 2 ++ 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/pandora/item/models.py b/pandora/item/models.py index 4416bf667..5dce528b1 100644 --- a/pandora/item/models.py +++ b/pandora/item/models.py @@ -9,6 +9,7 @@ from glob import glob import shutil import uuid import unicodedata +from urllib import quote from django.db import models from django.db.models import Sum @@ -17,6 +18,7 @@ from django.utils import simplejson as json from django.conf import settings from django.contrib.auth.models import User, Group from django.db.models.signals import pre_delete +from django.contrib.sites.models import Site import ox from ox.django import fields @@ -119,6 +121,9 @@ class Item(models.Model): icon = models.ImageField(default=None, blank=True, upload_to=lambda i, x: i.path("icon.jpg")) + torrent = models.FileField(default=None, blank=True, + upload_to=lambda i, x: i.path('torrent.torrent')) + #stream related fields stream_aspect = models.FloatField(default=4/3) @@ -614,6 +619,58 @@ class Item(models.Model): return videos + def make_torrent(self): + base = self.path('torrent') + base = os.path.abspath(os.path.join(settings.MEDIA_ROOT, base)) + if os.path.exists(base): + shutil.rmtree(base) + os.makedirs(base) + + base = self.path('torrent/%s' % self.get('title')) + base = os.path.abspath(os.path.join(settings.MEDIA_ROOT, base)) + size = 0 + duration = 0.0 + if len(self.main_videos()) == 1: + url = "%s/torrent/%s.webm" % (self.get_absolute_url(), + quote(self.get('title').encode('utf-8'))) + video = "%s.webm" % base + v = self.main_videos()[0] + os.symlink(v.video.path, video) + info = ox.avinfo(video) + size = info.get('size', 0) + duration = info.get('duration', 0.0) + else: + url = "%s/torrent/" % self.get_absolute_url() + part = 1 + os.makedirs(base) + for v in self.main_videos(): + video = "%s/%s.Part %d.webm" % (base, self.get('title'), part) + part += 1 + os.symlink(v.video.path, video) + info = ox.avinfo(video) + size += info.get('size', 0) + duration += info.get('duration', 0.0) + video = base + + torrent = '%s.torrent' % base + url = "http://%s%s" % (Site.objects.get_current().domain, url) + meta = { + 'target': torrent, + 'url-list': url, + } + if duration: + meta['playtime'] = ox.formatDuration(duration*1000)[:-4] + + #slightly bigger torrent file but better for streaming + piece_size_pow2 = 15 #1 mbps -> 32KB pieces + if size / duration >= 1000000: + piece_size_pow2 = 16 #2 mbps -> 64KB pieces + meta['piece_size_pow2'] = piece_size_pow2 + + ox.torrent.createTorrent(video, settings.TRACKER_URL, meta) + self.torrent.name = self.path('torrent/%s.torrent' % self.get('title')) + self.save() + def update_streams(self): files = {} for f in self.main_videos(): diff --git a/pandora/item/urls.py b/pandora/item/urls.py index bb6e2235c..d2c90f85a 100644 --- a/pandora/item/urls.py +++ b/pandora/item/urls.py @@ -6,12 +6,9 @@ from django.conf.urls.defaults import * urlpatterns = patterns("item.views", (r'^(?P[A-Z0-9].*)/frame/(?P\d+)/(?P[0-9\.,]+).jpg$', 'frame'), - (r'^(?P[A-Z0-9].*)/(?P[a-f0-9]+)/(?P.*\.webm)$', 'video'), - (r'^(?P[A-Z0-9].*)/(?P[a-f0-9]+)/(?P.*\.ogv)$', 'video'), - (r'^(?P[A-Z0-9].*)/(?P[a-f0-9]+)/(?P.*\.mp4)$', 'video'), - (r'^(?P[A-Z0-9].*)/(?P.*\.webm)$', 'video'), - (r'^(?P[A-Z0-9].*)/(?P.*\.ogv)$', 'video'), - (r'^(?P[A-Z0-9].*)/(?P.*\.mp4)$', 'video'), + (r'^(?P[A-Z0-9].*)/(?P[a-f0-9]+)/(?P.*\.(?Pwebm|ogv|mp4))$', 'video'), + (r'^(?P[A-Z0-9][A-Za-z0-9]+)/torrent/(?P.*?)$', 'torrent'), + (r'^(?P[A-Z0-9].*)/(?P.*\.(?Pwebm|ogv|mp4))$', 'video'), (r'^(?P[A-Z0-9].*)/poster\.(?P\d+)\.jpg$', 'poster'), (r'^(?P[A-Z0-9].*)/poster\.(?Plarge)\.jpg$', 'poster'), (r'^(?P[A-Z0-9].*)/poster\.jpg$', 'poster'), diff --git a/pandora/item/views.py b/pandora/item/views.py index df214b598..34cadbb8d 100644 --- a/pandora/item/views.py +++ b/pandora/item/views.py @@ -581,8 +581,24 @@ def timeline_overview(request, id, size): timeline = '%s.%s.png' %(item.timeline_prefix, size) return HttpFileResponse(timeline, content_type='image/png') +def torrent(request, id, filename=None): + item = get_object_or_404(models.Item, itemId=id) + if not item.torrent: + raise Http404 + if not filename or filename.endswith('.torrent'): + response = HttpFileResponse(item.torrent.path, + content_type='application/x-bittorrent') + filename = "%s.torrent" % item.get('title') + response['Content-Disposition'] = 'attachment; filename="%s"' % filename + return response + while filename.startswith('/'): + filename = filename[1:] + filename = filename.replace('/../', '/') + filename = item.path('torrent/%s' % filename) + filename = os.path.abspath(os.path.join(settings.MEDIA_ROOT, filename)) + return HttpFileResponse(filename) -def video(request, id, profile, oshash=None): +def video(request, id, profile, oshash=None, format=None): item = get_object_or_404(models.Item, itemId=id) if oshash: stream = get_object_or_404(item.files, oshash=oshash) diff --git a/pandora/settings.py b/pandora/settings.py index 20a68706b..ae1823c1c 100644 --- a/pandora/settings.py +++ b/pandora/settings.py @@ -172,6 +172,8 @@ DEFAULT_THEME = "classic" VIDEO_PROFILE = '96p.webm' VIDEO_DERIVATIVES = [] +TRACKER_URL="http://url2torrent.net:6970/announce" + #0xdb ''' VIDEO_PROFILE = '96p.webm'