cleanup imports and syntax warnings
This commit is contained in:
parent
7fdae917cf
commit
2d5f924891
46 changed files with 452 additions and 517 deletions
|
|
@ -6,6 +6,7 @@ from django.contrib import admin
|
|||
from forms import FileAdminForm, InstanceAdminForm
|
||||
import models
|
||||
|
||||
|
||||
class FileAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name', 'video_codec']
|
||||
list_display = ['available', 'is_main', '__unicode__', 'itemId']
|
||||
|
|
@ -18,9 +19,9 @@ class FileAdmin(admin.ModelAdmin):
|
|||
|
||||
admin.site.register(models.File, FileAdmin)
|
||||
|
||||
|
||||
class InstanceAdmin(admin.ModelAdmin):
|
||||
search_fields = ['name', 'folder', 'volume__name']
|
||||
form = InstanceAdminForm
|
||||
|
||||
admin.site.register(models.Instance, InstanceAdmin)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,33 +3,31 @@
|
|||
from __future__ import division, with_statement
|
||||
|
||||
import os
|
||||
from os.path import abspath, join, dirname, exists
|
||||
from os.path import exists
|
||||
|
||||
import fractions
|
||||
import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import re
|
||||
import math
|
||||
from glob import glob
|
||||
|
||||
import numpy as np
|
||||
import Image
|
||||
import ox
|
||||
from ox.utils import json
|
||||
|
||||
|
||||
img_extension='jpg'
|
||||
|
||||
FFMPEG2THEORA = 'ffmpeg2theora'
|
||||
|
||||
|
||||
class AspectRatio(fractions.Fraction):
|
||||
|
||||
def __new__(cls, numerator, denominator=None):
|
||||
if not denominator:
|
||||
ratio = map(int, numerator.split(':'))
|
||||
if len(ratio) == 1: ratio.append(1)
|
||||
if len(ratio) == 1:
|
||||
ratio.append(1)
|
||||
numerator = ratio[0]
|
||||
denominator = ratio[1]
|
||||
#if its close enough to the common aspect ratios rather use that
|
||||
|
|
@ -45,6 +43,7 @@ class AspectRatio(fractions.Fraction):
|
|||
def ratio(self):
|
||||
return "%d:%d" % (self.numerator, self.denominator)
|
||||
|
||||
|
||||
def stream(video, target, profile, info):
|
||||
if not os.path.exists(target):
|
||||
fdir = os.path.dirname(target)
|
||||
|
|
@ -118,8 +117,8 @@ def stream(video, target, profile, info):
|
|||
bpp = 0.17
|
||||
fps = AspectRatio(info['video'][0]['framerate'])
|
||||
|
||||
width = int(dar * height)
|
||||
width += width % 2
|
||||
width = int(dar * height)
|
||||
width += width % 2
|
||||
|
||||
bitrate = height*width*fps*bpp/1000
|
||||
aspect = dar.ratio
|
||||
|
|
@ -184,7 +183,7 @@ def stream(video, target, profile, info):
|
|||
'-me_range', '16',
|
||||
'-g', '250', #FIXME: should this be related to fps?
|
||||
'-keyint_min', '25', #FIXME: should this be related to fps?
|
||||
'-sc_threshold','40',
|
||||
'-sc_threshold', '40',
|
||||
'-i_qfactor', '0.71',
|
||||
'-qmin', '10', '-qmax', '51',
|
||||
'-qdiff', '4'
|
||||
|
|
@ -200,19 +199,20 @@ def stream(video, target, profile, info):
|
|||
if format == 'mp4':
|
||||
cmd += ["%s.mp4"%target]
|
||||
else:
|
||||
cmd += ['-f','webm', target]
|
||||
cmd += ['-f', 'webm', target]
|
||||
|
||||
print cmd
|
||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
p.communicate()
|
||||
if format == 'mp4':
|
||||
cmd = ['qt-faststart', "%s.mp4"%target, target]
|
||||
cmd = ['qt-faststart', "%s.mp4"%target, target]
|
||||
print cmd
|
||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
p.communicate()
|
||||
os.unlink("%s.mp4"%target)
|
||||
return True
|
||||
|
||||
|
||||
def run_command(cmd, timeout=10):
|
||||
#print cmd
|
||||
p = subprocess.Popen(cmd, stdout=open('/dev/null', 'w'), stderr=subprocess.STDOUT)
|
||||
|
|
@ -226,6 +226,7 @@ def run_command(cmd, timeout=10):
|
|||
killedpid, stat = os.waitpid(p.pid, os.WNOHANG)
|
||||
return p.returncode
|
||||
|
||||
|
||||
def frame(videoFile, frame, position, width=128, redo=False):
|
||||
'''
|
||||
params:
|
||||
|
|
@ -243,6 +244,7 @@ def frame(videoFile, frame, position, width=128, redo=False):
|
|||
cmd = ['oxframe', '-i', videoFile, '-o', frame, '-p', str(position), '-x', str(width)]
|
||||
run_command(cmd)
|
||||
|
||||
|
||||
def resize_image(image_source, image_output, width=None, size=None):
|
||||
if exists(image_source):
|
||||
source = Image.open(image_source).convert('RGB')
|
||||
|
|
@ -257,7 +259,7 @@ def resize_image(image_source, image_output, width=None, size=None):
|
|||
height = size
|
||||
width = int(height * (float(source_width) / source_height))
|
||||
width = width - width % 2
|
||||
|
||||
|
||||
else:
|
||||
height = int(width / (float(source_width) / source_height))
|
||||
height = height - height % 2
|
||||
|
|
@ -269,12 +271,13 @@ def resize_image(image_source, image_output, width=None, size=None):
|
|||
output = source.resize((width, height), resize_method)
|
||||
output.save(image_output)
|
||||
|
||||
|
||||
def timeline(video, prefix):
|
||||
cmd = ['oxtimeline', '-i', video, '-o', prefix]
|
||||
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
p.wait()
|
||||
|
||||
#stats based on timeline images
|
||||
|
||||
def average_color(prefix):
|
||||
height = 64
|
||||
width = 1500
|
||||
|
|
@ -294,10 +297,12 @@ def average_color(prefix):
|
|||
color += p
|
||||
return list(map(float, color))
|
||||
|
||||
|
||||
def get_distance(rgb0, rgb1):
|
||||
dst = math.sqrt(pow(rgb0[0] - rgb1[0], 2) + pow(rgb0[0] - rgb1[0], 2) + pow(rgb0[0] - rgb1[0], 2))
|
||||
return dst / math.sqrt(3 * pow(255, 2))
|
||||
|
||||
|
||||
def cuts(prefix):
|
||||
cuts = []
|
||||
fps = 25
|
||||
|
|
@ -324,6 +329,7 @@ def cuts(prefix):
|
|||
cuts.append(frame / fps)
|
||||
return cuts
|
||||
|
||||
|
||||
def divide(num, by):
|
||||
# >>> divide(100, 3)
|
||||
# [33, 33, 34]
|
||||
|
|
@ -334,9 +340,10 @@ def divide(num, by):
|
|||
arr.append(div + (i > by - 1 - mod))
|
||||
return arr
|
||||
|
||||
|
||||
def timeline_strip(item, cuts, info, prefix):
|
||||
_debug = False
|
||||
duration = info['duration']
|
||||
duration = info['duration']
|
||||
video_height = info['video'][0]['height']
|
||||
video_width = info['video'][0]['width']
|
||||
video_ratio = video_width / video_height
|
||||
|
|
@ -392,6 +399,7 @@ def timeline_strip(item, cuts, info, prefix):
|
|||
print 'writing', timeline_file
|
||||
timeline_image.save(timeline_file)
|
||||
|
||||
|
||||
def chop(video, start, end):
|
||||
t = end - start
|
||||
tmp = tempfile.mkdtemp()
|
||||
|
|
@ -401,7 +409,7 @@ def chop(video, start, end):
|
|||
'-y',
|
||||
'-i', video,
|
||||
'-ss', '%.3f'%start,
|
||||
'-t','%.3f'%t,
|
||||
'-t', '%.3f'%t,
|
||||
'-vcodec', 'copy',
|
||||
'-acodec', 'copy',
|
||||
'-f', 'webm',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from ajax_filtered_fields.forms import AjaxManyToManyField, ForeignKeyByLetter
|
||||
from ajax_filtered_fields.forms import ForeignKeyByLetter
|
||||
from django.conf import settings
|
||||
from django import forms
|
||||
|
||||
|
|
@ -10,6 +10,8 @@ ajax_filtered_js = (
|
|||
settings.STATIC_URL + 'js/jquery/jquery.js',
|
||||
settings.STATIC_URL + 'js/ajax_filtered_fields.js',
|
||||
)
|
||||
|
||||
|
||||
class FileAdminForm(forms.ModelForm):
|
||||
item = ForeignKeyByLetter(models.Item, field_name='itemId')
|
||||
|
||||
|
|
@ -28,4 +30,3 @@ class InstanceAdminForm(forms.ModelForm):
|
|||
|
||||
class Media:
|
||||
js = ajax_filtered_js
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from __future__ import division
|
||||
from datetime import datetime
|
||||
|
||||
import os.path
|
||||
import random
|
||||
import re
|
||||
import time
|
||||
|
||||
from django.db import models
|
||||
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 ox.django import fields
|
||||
import ox
|
||||
from ox import stripTags
|
||||
from ox.normalize import canonicalTitle, canonicalName
|
||||
from firefogg import Firefogg
|
||||
from ox.normalize import canonicalTitle
|
||||
import chardet
|
||||
|
||||
from item import utils
|
||||
from item.models import Item
|
||||
|
||||
import extract
|
||||
|
||||
|
||||
class File(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
|
@ -37,7 +29,7 @@ class File(models.Model):
|
|||
item = models.ForeignKey(Item, related_name='files')
|
||||
|
||||
name = models.CharField(max_length=2048, default="") # canoncial path/file
|
||||
sort_name = models.CharField(max_length=2048, default="") # sort path/file name
|
||||
sort_name = models.CharField(max_length=2048, default="") # sort name
|
||||
|
||||
part = models.CharField(default="", max_length=255)
|
||||
version = models.CharField(default="", max_length=255) # sort path/file name
|
||||
|
|
@ -146,13 +138,14 @@ class File(models.Model):
|
|||
return None
|
||||
|
||||
def srt(self):
|
||||
|
||||
def _detectEncoding(fp):
|
||||
bomDict={ # bytepattern : name
|
||||
(0x00, 0x00, 0xFE, 0xFF) : "utf_32_be",
|
||||
(0xFF, 0xFE, 0x00, 0x00) : "utf_32_le",
|
||||
(0xFE, 0xFF, None, None) : "utf_16_be",
|
||||
(0xFF, 0xFE, None, None) : "utf_16_le",
|
||||
(0xEF, 0xBB, 0xBF, None) : "utf_8",
|
||||
bomDict={ # bytepattern : name
|
||||
(0x00, 0x00, 0xFE, 0xFF): "utf_32_be",
|
||||
(0xFF, 0xFE, 0x00, 0x00): "utf_32_le",
|
||||
(0xFE, 0xFF, None, None): "utf_16_be",
|
||||
(0xFF, 0xFE, None, None): "utf_16_le",
|
||||
(0xEF, 0xBB, 0xBF, None): "utf_8",
|
||||
}
|
||||
|
||||
# go to beginning of file and get the first 4 bytes
|
||||
|
|
@ -162,15 +155,15 @@ class File(models.Model):
|
|||
|
||||
# try bom detection using 4 bytes, 3 bytes, or 2 bytes
|
||||
bomDetection = bomDict.get((byte1, byte2, byte3, byte4))
|
||||
if not bomDetection :
|
||||
if not bomDetection:
|
||||
bomDetection = bomDict.get((byte1, byte2, byte3, None))
|
||||
if not bomDetection :
|
||||
if not bomDetection:
|
||||
bomDetection = bomDict.get((byte1, byte2, None, None))
|
||||
|
||||
## if BOM detected, we're done :-)
|
||||
fp.seek(oldFP)
|
||||
if bomDetection :
|
||||
return bomDetection
|
||||
if bomDetection:
|
||||
return bomDetection
|
||||
|
||||
encoding = 'latin-1'
|
||||
#more character detecting magick using http://chardet.feedparser.org/
|
||||
|
|
@ -221,7 +214,9 @@ class File(models.Model):
|
|||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Volume(models.Model):
|
||||
|
||||
class Meta:
|
||||
unique_together = ("user", "name")
|
||||
|
||||
|
|
@ -234,7 +229,9 @@ class Volume(models.Model):
|
|||
def __unicode__(self):
|
||||
return u"%s's %s"% (self.user, self.name)
|
||||
|
||||
|
||||
class Instance(models.Model):
|
||||
|
||||
class Meta:
|
||||
unique_together = ("name", "folder", "volume")
|
||||
|
||||
|
|
@ -258,12 +255,15 @@ class Instance(models.Model):
|
|||
def itemId(self):
|
||||
return File.objects.get(oshash=self.oshash).itemId
|
||||
|
||||
|
||||
def frame_path(frame, name):
|
||||
ext = os.path.splitext(name)[-1]
|
||||
name = "%s%s" % (frame.position, ext)
|
||||
return frame.file.path(name)
|
||||
|
||||
|
||||
class Frame(models.Model):
|
||||
|
||||
class Meta:
|
||||
unique_together = ("file", "position")
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
|
@ -282,5 +282,3 @@ class Frame(models.Model):
|
|||
|
||||
def __unicode__(self):
|
||||
return u'%s at %s' % (self.file, self.position)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# vi:si:et:sw=4:sts=4:ts=4
|
||||
from datetime import timedelta
|
||||
import os
|
||||
import re
|
||||
|
||||
from celery.decorators import task, periodic_task
|
||||
from celery.decorators import task
|
||||
|
||||
from item.utils import oxid, parse_path
|
||||
from item.utils import parse_path
|
||||
from item.models import get_item
|
||||
import item.tasks
|
||||
|
||||
import models
|
||||
|
||||
|
||||
@task(ignore_resulsts=True, queue='default')
|
||||
def update_files(user, volume, files):
|
||||
user = models.User.objects.get(username=user)
|
||||
|
|
@ -33,9 +31,9 @@ def update_files(user, volume, files):
|
|||
|
||||
same_folder = models.Instance.objects.filter(folder=folder, volume=volume)
|
||||
if same_folder.count() > 0:
|
||||
item = same_folder[0].file.item
|
||||
i = same_folder[0].file.item
|
||||
else:
|
||||
item = None
|
||||
i = None
|
||||
|
||||
path = os.path.join(folder, name)
|
||||
|
||||
|
|
@ -48,7 +46,7 @@ def update_files(user, volume, files):
|
|||
setattr(instance, key, f[key])
|
||||
updated=True
|
||||
if updated:
|
||||
instance.save()
|
||||
instance.save()
|
||||
else:
|
||||
#look if oshash is known
|
||||
file_objects = models.File.objects.filter(oshash=oshash)
|
||||
|
|
@ -56,13 +54,13 @@ def update_files(user, volume, files):
|
|||
file_object = file_objects[0]
|
||||
#new oshash, add to database
|
||||
else:
|
||||
if not item:
|
||||
if not i:
|
||||
item_info = parse_path(folder)
|
||||
item = get_item(item_info)
|
||||
i = get_item(item_info)
|
||||
file_object = models.File()
|
||||
file_object.oshash = oshash
|
||||
file_object.name = name
|
||||
file_object.item = item
|
||||
file_object.item = i
|
||||
file_object.save()
|
||||
instance = models.Instance()
|
||||
instance.volume = volume
|
||||
|
|
@ -74,4 +72,3 @@ def update_files(user, volume, files):
|
|||
#remove deleted files
|
||||
#FIXME: can this have any bad consequences? i.e. on the selction of used item files.
|
||||
models.Instance.objects.filter(volume=volume).exclude(file__oshash__in=all_files).delete()
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ Replace these with more appropriate tests for your application.
|
|||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
|
|
@ -20,4 +22,3 @@ Another way to test that 1 + 1 is equal to 2.
|
|||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,29 +2,18 @@
|
|||
# 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 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, Sum
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, get_list_or_404, redirect
|
||||
from django.template import RequestContext
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.conf import settings
|
||||
|
||||
from ox.utils import json
|
||||
from ox.django.decorators import login_required_json
|
||||
from ox.django.shortcuts import render_to_json_response, get_object_or_404_json, json_response
|
||||
from ox.django.http import HttpFileResponse
|
||||
from ox.django.views import task_status
|
||||
import ox
|
||||
|
||||
from item.utils import oxid, parse_path
|
||||
from item.utils import parse_path
|
||||
from item.models import get_item
|
||||
import item.tasks
|
||||
from api.actions import actions
|
||||
|
|
@ -47,6 +36,7 @@ def removeVolume(request):
|
|||
return render_to_json_response(response)
|
||||
actions.register(removeVolume)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def update(request):
|
||||
'''
|
||||
|
|
@ -111,12 +101,14 @@ def update(request):
|
|||
return render_to_json_response(response)
|
||||
actions.register(update)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def encodingProfile(request):
|
||||
response = json_response({'profile': settings.VIDEO_PROFILE})
|
||||
return render_to_json_response(response)
|
||||
actions.register(encodingProfile)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def upload(request):
|
||||
'''
|
||||
|
|
@ -157,11 +149,13 @@ def upload(request):
|
|||
return render_to_json_response(response)
|
||||
actions.register(upload)
|
||||
|
||||
|
||||
class VideoChunkForm(forms.Form):
|
||||
chunk = forms.FileField()
|
||||
chunkId = forms.IntegerField(required=False)
|
||||
done = forms.IntegerField(required=False)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def firefogg_upload(request):
|
||||
profile = request.GET['profile']
|
||||
|
|
@ -189,7 +183,7 @@ def firefogg_upload(request):
|
|||
#FIXME: this fails badly if rabbitmq goes down
|
||||
try:
|
||||
t = item.tasks.update_streams.delay((f.item.itemId))
|
||||
data['resultUrl'] = t.task_id
|
||||
response['resultUrl'] = t.task_id
|
||||
except:
|
||||
pass
|
||||
response['result'] = 1
|
||||
|
|
@ -213,6 +207,7 @@ def firefogg_upload(request):
|
|||
response = json_response(status=400, text='this request requires POST')
|
||||
return render_to_json_response(response)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def taskStatus(request):
|
||||
#FIXME: should check if user has permissions to get status
|
||||
|
|
@ -223,6 +218,7 @@ def taskStatus(request):
|
|||
return render_to_json_response(response)
|
||||
actions.register(taskStatus)
|
||||
|
||||
|
||||
@login_required_json
|
||||
def editFile(request):
|
||||
'''
|
||||
|
|
@ -257,6 +253,7 @@ def editFile(request):
|
|||
return render_to_json_response(response)
|
||||
actions.register(editFile)
|
||||
|
||||
|
||||
def lookup_file(request, oshash):
|
||||
f = get_object_or_404(models.File, oshash=oshash)
|
||||
return redirect(f.item.get_absolute_url())
|
||||
|
|
@ -270,34 +267,34 @@ def fileInfo(request):
|
|||
'data': {imdbId:string }}
|
||||
'''
|
||||
if 'data' in request.POST:
|
||||
oshash = json.loads(request.POST['data'])
|
||||
elif 'oshash' in request.GET:
|
||||
oshash = request.GET['oshash']
|
||||
oshash = json.loads(request.POST['data'])
|
||||
elif 'oshash' in request.GET:
|
||||
oshash = request.GET['oshash']
|
||||
f = models.ItemFile.objects.get(oshash=oshash)
|
||||
response = {'data': f.json()}
|
||||
return render_to_json_response(response)
|
||||
actions.register(fileInfo)
|
||||
|
||||
def subtitles(request):
|
||||
'''
|
||||
param data
|
||||
oshash string
|
||||
language string
|
||||
subtitle string
|
||||
return
|
||||
if no language is provided:
|
||||
{data: {languages: array}}
|
||||
if language is set:
|
||||
{data: {subtitle: string}}
|
||||
if subtitle is set:
|
||||
saves subtitle for given language
|
||||
'''
|
||||
'''
|
||||
param data
|
||||
oshash string
|
||||
language string
|
||||
subtitle string
|
||||
return
|
||||
if no language is provided:
|
||||
{data: {languages: array}}
|
||||
if language is set:
|
||||
{data: {subtitle: string}}
|
||||
if subtitle is set:
|
||||
saves subtitle for given language
|
||||
'''
|
||||
if 'data' in request.POST:
|
||||
data = json.loads(request.POST['data'])
|
||||
oshash = data['oshash']
|
||||
language = data.get('language', None)
|
||||
srt = data.get('subtitle', None)
|
||||
if srt:
|
||||
data = json.loads(request.POST['data'])
|
||||
oshash = data['oshash']
|
||||
language = data.get('language', None)
|
||||
srt = data.get('subtitle', None)
|
||||
if srt:
|
||||
user = request.user
|
||||
sub = models.Subtitles.objects.get_or_create(user, oshash, language)
|
||||
sub.srt = srt
|
||||
|
|
@ -307,8 +304,8 @@ def subtitles(request):
|
|||
if language:
|
||||
q = models.Subtitles.objects.filter(item_file__oshash=oshash, language=language)
|
||||
if q.count() > 0:
|
||||
response['data']['subtitle'] = q[0].srt
|
||||
return render_to_json_response(response)
|
||||
response['data']['subtitle'] = q[0].srt
|
||||
return render_to_json_response(response)
|
||||
l = models.Subtitles.objects.filter(item_file__oshash=oshash).values('language')
|
||||
response['data']['languages'] = [f['language'] for f in l]
|
||||
return render_to_json_response(response)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue