Commit | Line | Data |
---|---|---|
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 | ||
25e39842 | 17 | from tempfile import NamedTemporaryFile |
e9c1b938 | 18 | import logging |
93bdab9d | 19 | |
93bdab9d | 20 | from mediagoblin import mg_globals as mgg |
45ab3e07 | 21 | from mediagoblin.decorators import get_workbench |
196a5181 | 22 | from mediagoblin.processing import \ |
64712915 | 23 | create_pub_filepath, FilenameBuilder, BaseProcessingFail, ProgressCallback |
51eb0267 JW |
24 | from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ |
25 | ||
26729e02 | 26 | from . import transcoders |
1f255101 | 27 | |
8e5f9746 JW |
28 | _log = logging.getLogger(__name__) |
29 | _log.setLevel(logging.DEBUG) | |
93bdab9d JW |
30 | |
31 | ||
51eb0267 JW |
32 | class VideoTranscodingFail(BaseProcessingFail): |
33 | ''' | |
34 | Error raised if video transcoding fails | |
35 | ''' | |
36 | general_message = _(u'Video transcoding failed') | |
37 | ||
38 | ||
ec4261a4 | 39 | def sniff_handler(media_file, **kw): |
10085b77 | 40 | transcoder = transcoders.VideoTranscoder() |
4f4f2531 | 41 | data = transcoder.discover(media_file.name) |
10085b77 | 42 | |
4f4f2531 | 43 | _log.debug('Discovered: {0}'.format(data)) |
10085b77 | 44 | |
4f4f2531 JW |
45 | if not data: |
46 | _log.error('Could not discover {0}'.format( | |
10085b77 | 47 | kw.get('media'))) |
4f4f2531 | 48 | return False |
26729e02 | 49 | |
4f4f2531 JW |
50 | if data['is_video'] == True: |
51 | return True | |
26729e02 | 52 | |
ec4261a4 | 53 | return False |
93bdab9d | 54 | |
45ab3e07 SS |
55 | @get_workbench |
56 | def process_video(entry, workbench=None): | |
93bdab9d | 57 | """ |
5a34a80d JW |
58 | Process a video entry, transcode the queued media files (originals) and |
59 | create a thumbnail for the entry. | |
45ab3e07 SS |
60 | |
61 | A Workbench() represents a local tempory dir. It is automatically | |
62 | cleaned up when this function exits. | |
93bdab9d | 63 | """ |
23caf305 CAW |
64 | video_config = mgg.global_config['media_type:mediagoblin.media_types.video'] |
65 | ||
8545cfc9 | 66 | queued_filepath = entry.queued_media_file |
93bdab9d JW |
67 | queued_filename = workbench.localized_file( |
68 | mgg.queue_store, queued_filepath, | |
69 | 'source') | |
28f364bd | 70 | name_builder = FilenameBuilder(queued_filename) |
93bdab9d | 71 | |
e9c1b938 | 72 | medium_filepath = create_pub_filepath( |
28f364bd | 73 | entry, name_builder.fill('{basename}-640p.webm')) |
93bdab9d | 74 | |
e9c1b938 | 75 | thumbnail_filepath = create_pub_filepath( |
28f364bd | 76 | entry, name_builder.fill('{basename}.thumbnail.jpg')) |
93bdab9d | 77 | |
c00e18fe SS |
78 | # Create a temporary file for the video destination (cleaned up with workbench) |
79 | tmp_dst = NamedTemporaryFile(dir=workbench.dir, delete=False) | |
e9c1b938 JW |
80 | with tmp_dst: |
81 | # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square | |
64712915 | 82 | progress_callback = ProgressCallback(entry) |
10085b77 | 83 | transcoder = transcoders.VideoTranscoder() |
196a5181 JW |
84 | transcoder.transcode(queued_filename, tmp_dst.name, |
85 | vp8_quality=video_config['vp8_quality'], | |
86 | vp8_threads=video_config['vp8_threads'], | |
64712915 JW |
87 | vorbis_quality=video_config['vorbis_quality'], |
88 | progress_callback=progress_callback) | |
93bdab9d | 89 | |
c00e18fe SS |
90 | # Push transcoded video to public storage |
91 | _log.debug('Saving medium...') | |
92 | mgg.public_store.copy_local_to_storage(tmp_dst.name, medium_filepath) | |
93 | _log.debug('Saved medium') | |
e9c1b938 | 94 | |
c00e18fe | 95 | entry.media_files['webm_640'] = medium_filepath |
e9c1b938 | 96 | |
c00e18fe SS |
97 | # Save the width and height of the transcoded video |
98 | entry.media_data_init( | |
99 | width=transcoder.dst_data.videowidth, | |
100 | height=transcoder.dst_data.videoheight) | |
93bdab9d | 101 | |
c00e18fe SS |
102 | # Temporary file for the video thumbnail (cleaned up with workbench) |
103 | tmp_thumb = NamedTemporaryFile(dir=workbench.dir, suffix='.jpg', delete=False) | |
93bdab9d | 104 | |
e9c1b938 JW |
105 | with tmp_thumb: |
106 | # Create a thumbnail.jpg that fits in a 180x180 square | |
e4a1b6d2 JW |
107 | transcoders.VideoThumbnailerMarkII( |
108 | queued_filename, | |
109 | tmp_thumb.name, | |
110 | 180) | |
1f255101 | 111 | |
c00e18fe SS |
112 | # Push the thumbnail to public storage |
113 | _log.debug('Saving thumbnail...') | |
114 | mgg.public_store.copy_local_to_storage(tmp_thumb.name, thumbnail_filepath) | |
115 | entry.media_files['thumb'] = thumbnail_filepath | |
93bdab9d | 116 | |
23caf305 CAW |
117 | if video_config['keep_original']: |
118 | # Push original file to public storage | |
c00e18fe SS |
119 | _log.debug('Saving original...') |
120 | original_filepath = create_pub_filepath(entry, queued_filepath[-1]) | |
121 | mgg.public_store.copy_local_to_storage(queued_filename, original_filepath) | |
122 | entry.media_files['original'] = original_filepath | |
93bdab9d | 123 | |
e9c1b938 | 124 | mgg.queue_store.delete_file(queued_filepath) |