It's 2012 all up in here
[mediagoblin.git] / mediagoblin / media_types / video / processing.py
CommitLineData
93bdab9d 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
93bdab9d
JW
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
93bdab9d 17import tempfile
e9c1b938 18import logging
a63b640f 19import os
93bdab9d 20
93bdab9d 21from mediagoblin import mg_globals as mgg
8e5f9746
JW
22from mediagoblin.processing import mark_entry_failed, \
23 THUMB_SIZE, MEDIUM_SIZE, create_pub_filepath
26729e02 24from . import transcoders
1f255101 25
1f255101 26logging.basicConfig()
8e5f9746
JW
27
28_log = logging.getLogger(__name__)
29_log.setLevel(logging.DEBUG)
93bdab9d
JW
30
31
32def process_video(entry):
33 """
34 Code to process a video
26729e02
JW
35
36 Much of this code is derived from the arista-transcoder script in
37 the arista PyPI package and changed to match the needs of
38 MediaGoblin
39
40 This function sets up the arista video encoder in some kind of new thread
41 and attaches callbacks to that child process, hopefully, the
42 entry-complete callback will be called when the video is done.
93bdab9d 43 """
23caf305
CAW
44 video_config = mgg.global_config['media_type:mediagoblin.media_types.video']
45
93bdab9d
JW
46 workbench = mgg.workbench_manager.create_workbench()
47
8545cfc9 48 queued_filepath = entry.queued_media_file
93bdab9d
JW
49 queued_filename = workbench.localized_file(
50 mgg.queue_store, queued_filepath,
51 'source')
52
e9c1b938 53 medium_filepath = create_pub_filepath(
a63b640f
JW
54 entry,
55 '{original}-640p.webm'.format(
56 original=os.path.splitext(
57 queued_filepath[-1])[0] # Select the
58 ))
93bdab9d 59
e9c1b938
JW
60 thumbnail_filepath = create_pub_filepath(
61 entry, 'thumbnail.jpg')
1f255101 62
93bdab9d 63
e9c1b938
JW
64 # Create a temporary file for the video destination
65 tmp_dst = tempfile.NamedTemporaryFile()
93bdab9d 66
e9c1b938
JW
67 with tmp_dst:
68 # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square
69 transcoder = transcoders.VideoTranscoder(queued_filename, tmp_dst.name)
93bdab9d 70
e9c1b938 71 # Push transcoded video to public storage
8e5f9746 72 _log.debug('Saving medium...')
e9c1b938
JW
73 mgg.public_store.get_file(medium_filepath, 'wb').write(
74 tmp_dst.read())
8e5f9746 75 _log.debug('Saved medium')
e9c1b938 76
228c4470 77 entry.media_files['webm_640'] = medium_filepath
e9c1b938
JW
78
79 # Save the width and height of the transcoded video
ddc1cae9 80 entry.media_data['video'] = {
e9c1b938
JW
81 u'width': transcoder.dst_data.videowidth,
82 u'height': transcoder.dst_data.videoheight}
93bdab9d 83
e9c1b938
JW
84 # Create a temporary file for the video thumbnail
85 tmp_thumb = tempfile.NamedTemporaryFile()
93bdab9d 86
e9c1b938
JW
87 with tmp_thumb:
88 # Create a thumbnail.jpg that fits in a 180x180 square
89 transcoders.VideoThumbnailer(queued_filename, tmp_thumb.name)
1f255101 90
e9c1b938 91 # Push the thumbnail to public storage
8e5f9746 92 _log.debug('Saving thumbnail...')
e9c1b938
JW
93 mgg.public_store.get_file(thumbnail_filepath, 'wb').write(
94 tmp_thumb.read())
8e5f9746 95 _log.debug('Saved thumbnail')
93bdab9d 96
228c4470 97 entry.media_files['thumb'] = thumbnail_filepath
93bdab9d 98
23caf305
CAW
99 if video_config['keep_original']:
100 # Push original file to public storage
101 queued_file = file(queued_filename, 'rb')
93bdab9d 102
23caf305
CAW
103 with queued_file:
104 original_filepath = create_pub_filepath(
105 entry,
106 queued_filepath[-1])
26729e02 107
23caf305
CAW
108 with mgg.public_store.get_file(original_filepath, 'wb') as \
109 original_file:
110 _log.debug('Saving original...')
111 original_file.write(queued_file.read())
112 _log.debug('Saved original')
1f255101 113
228c4470 114 entry.media_files['original'] = original_filepath
93bdab9d 115
e9c1b938
JW
116 mgg.queue_store.delete_file(queued_filepath)
117
e9c1b938
JW
118 # Save the MediaEntry
119 entry.save()