forked from escaped/django-video-encoding
/
tasks.py
93 lines (75 loc) · 2.78 KB
/
tasks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import os
import tempfile
from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.core.files import File
from .backends import get_backend
from .config import settings
from .exceptions import VideoEncodingError
from .fields import VideoField
from .models import Format
def convert_all_videos(app_label, model_name, object_pk):
"""
Automatically converts all videos of a given instance.
"""
# get instance
Model = apps.get_model(app_label=app_label, model_name=model_name)
instance = Model.objects.get(pk=object_pk)
# search for `VideoFields`
fields = instance._meta.fields
for field in fields:
if isinstance(field, VideoField):
if not getattr(instance, field.name):
# ignore empty fields
continue
# trigger conversion
fieldfile = getattr(instance, field.name)
convert_video(fieldfile)
def convert_video(fieldfile, force=False):
"""
Converts a given video file into all defined formats.
"""
instance = fieldfile.instance
field = fieldfile.field
try:
source_path = fieldfile.path
except NotImplementedError:
source_path = fieldfile.url
filename = os.path.basename(source_path)
encoding_backend = get_backend()
for options in settings.VIDEO_ENCODING_FORMATS[encoding_backend.name]:
video_format, created = Format.objects.get_or_create(
object_id=instance.pk,
content_type=ContentType.objects.get_for_model(instance),
field_name=field.name, format=options['name'])
# do not reencode if not requested
if video_format.file and not force:
continue
else:
# set progress to 0
video_format.reset_progress()
# TODO do not upscale videos
_, target_path = tempfile.mkstemp(
suffix='_{name}.{extension}'.format(**options))
try:
encoding = encoding_backend.encode(
source_path, target_path, options['params'])
while encoding:
try:
progress = next(encoding)
except StopIteration:
break
video_format.update_progress(progress)
except VideoEncodingError:
# TODO handle with more care
video_format.delete()
os.remove(target_path)
continue
# save encoded file
video_format.file.save(
'{filename}_{name}.{extension}'.format(filename=filename,
**options),
File(open(target_path, mode='rb')))
video_format.update_progress(100) # now we are ready
# remove temporary file
os.remove(target_path)