Merge remote-tracking branch 'joar/media-fixes'
[mediagoblin.git] / mediagoblin / media_types / video / processing.py
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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
17 import tempfile
18 import logging
19
20 from mediagoblin import mg_globals as mgg
21 from mediagoblin.processing import \
22 create_pub_filepath, FilenameBuilder
23 from . import transcoders
24
25 _log = logging.getLogger(__name__)
26 _log.setLevel(logging.DEBUG)
27
28
29 def sniff_handler(media_file, **kw):
30 transcoder = transcoders.VideoTranscoder()
31 data = transcoder.discover(media_file.name)
32
33 _log.debug('Discovered: {0}'.format(data))
34
35 if not data:
36 _log.error('Could not discover {0}'.format(
37 kw.get('media')))
38 return False
39
40 if data['is_video'] == True:
41 return True
42
43 return False
44
45
46 def process_video(entry):
47 """
48 Process a video entry, transcode the queued media files (originals) and
49 create a thumbnail for the entry.
50 """
51 video_config = mgg.global_config['media_type:mediagoblin.media_types.video']
52
53 workbench = mgg.workbench_manager.create_workbench()
54
55 queued_filepath = entry.queued_media_file
56 queued_filename = workbench.localized_file(
57 mgg.queue_store, queued_filepath,
58 'source')
59 name_builder = FilenameBuilder(queued_filename)
60
61 medium_filepath = create_pub_filepath(
62 entry, name_builder.fill('{basename}-640p.webm'))
63
64 thumbnail_filepath = create_pub_filepath(
65 entry, name_builder.fill('{basename}.thumbnail.jpg'))
66
67 # Create a temporary file for the video destination
68 tmp_dst = tempfile.NamedTemporaryFile()
69
70 with tmp_dst:
71 # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square
72 transcoder = transcoders.VideoTranscoder()
73 transcoder.transcode(queued_filename, tmp_dst.name,
74 vp8_quality=video_config['vp8_quality'],
75 vp8_threads=video_config['vp8_threads'],
76 vorbis_quality=video_config['vorbis_quality'])
77
78 # Push transcoded video to public storage
79 _log.debug('Saving medium...')
80 mgg.public_store.get_file(medium_filepath, 'wb').write(
81 tmp_dst.read())
82 _log.debug('Saved medium')
83
84 entry.media_files['webm_640'] = medium_filepath
85
86 # Save the width and height of the transcoded video
87 entry.media_data_init(
88 width=transcoder.dst_data.videowidth,
89 height=transcoder.dst_data.videoheight)
90
91 # Create a temporary file for the video thumbnail
92 tmp_thumb = tempfile.NamedTemporaryFile(suffix='.jpg')
93
94 with tmp_thumb:
95 # Create a thumbnail.jpg that fits in a 180x180 square
96 transcoders.VideoThumbnailer(queued_filename, tmp_thumb.name)
97
98 # Push the thumbnail to public storage
99 _log.debug('Saving thumbnail...')
100 mgg.public_store.get_file(thumbnail_filepath, 'wb').write(
101 tmp_thumb.read())
102 _log.debug('Saved thumbnail')
103
104 entry.media_files['thumb'] = thumbnail_filepath
105
106 if video_config['keep_original']:
107 # Push original file to public storage
108 queued_file = file(queued_filename, 'rb')
109
110 with queued_file:
111 original_filepath = create_pub_filepath(
112 entry,
113 queued_filepath[-1])
114
115 with mgg.public_store.get_file(original_filepath, 'wb') as \
116 original_file:
117 _log.debug('Saving original...')
118 original_file.write(queued_file.read())
119 _log.debug('Saved original')
120
121 entry.media_files['original'] = original_filepath
122
123 mgg.queue_store.delete_file(queued_filepath)
124
125 # Save the MediaEntry
126 entry.save()