e59214b0b9f8e78a9d67678d80b12f56d8a37487
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
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.
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.
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/>.
20 from mediagoblin
.processing
import BadMediaFail
23 _log
= logging
.getLogger(__name__
)
25 CPU_COUNT
= 2 # Just assuming for now
27 # IMPORT MULTIPROCESSING
29 import multiprocessing
31 CPU_COUNT
= multiprocessing
.cpu_count()
32 except NotImplementedError:
33 _log
.warning('multiprocessing.cpu_count not implemented!\n'
34 'Assuming 2 CPU cores')
36 _log
.warning('Could not import multiprocessing, assuming 2 CPU cores')
41 gobject
.threads_init()
43 raise Exception('gobject could not be found')
49 # We won't settle for less. For now, this is an arbitrary limit
50 # as we have not tested with > 0.10
55 import gst
.extend
.discoverer
57 raise Exception('gst/pygst >= 0.10 could not be imported')
59 class AudioTranscoder(object):
61 _log
.info('Initializing {0}'.format(self
.__class
__.__name
__))
63 # Instantiate MainLoop
64 self
._loop
= gobject
.MainLoop()
66 def discover(self
, src
):
67 _log
.info('Discovering {0}'.format(src
))
68 self
._discovery
_path
= src
70 self
._discoverer
= gst
.extend
.discoverer
.Discoverer(
72 self
._discoverer
.connect('discovered', self
.__on
_discovered
)
73 self
._discoverer
.discover()
75 self
._loop
.run() # Run MainLoop
77 # Once MainLoop has returned, return discovery data
78 return self
._discovery
_data
80 def __on_discovered(self
, data
, is_media
):
83 _log
.error('Could not discover {0}'.format(self
._src
_path
))
86 _log
.debug('Discovered: {0}'.format(data
.__dict
__))
88 self
._discovery
_data
= data
90 # Gracefully shut down MainLoop
93 def transcode(self
, src
, dst
, **kw
):
94 self
._discovery
_data
= kw
.get('data', self
.discover(src
))
96 self
.__on
_progress
= kw
.get('progress_callback')
98 quality
= kw
.get('quality', 0.3)
101 self
.pipeline
= gst
.parse_launch(
102 'filesrc location="{src}" ! '
103 'decodebin2 ! queue ! audiorate tolerance={tolerance} ! '
104 'audioconvert ! audio/x-raw-float,channels=2 ! '
105 'vorbisenc quality={quality} ! webmmux ! '
106 'progressreport silent=true ! '
107 'filesink location="{dst}"'.format(
113 self
.bus
= self
.pipeline
.get_bus()
114 self
.bus
.add_signal_watch()
115 self
.bus
.connect('message', self
.__on
_bus
_message
)
117 self
.pipeline
.set_state(gst
.STATE_PLAYING
)
121 def __on_bus_message(self
, bus
, message
):
124 if (message
.type == gst
.MESSAGE_ELEMENT
125 and message
.structure
.get_name() == 'progress'):
126 data
= dict(message
.structure
)
128 if self
.__on
_progress
:
129 self
.__on
_progress
(data
)
131 _log
.info('{0}% done...'.format(
132 data
.get('percent')))
133 elif message
.type == gst
.MESSAGE_EOS
:
138 _log
.info('Quitting MainLoop gracefully...')
139 gobject
.idle_add(self
._loop
.quit
)
141 if __name__
== '__main__':
143 logging
.basicConfig()
144 _log
.setLevel(logging
.INFO
)
146 transcoder
= AudioTranscoder()
147 data
= transcoder
.discover(sys
.argv
[1])
148 res
= transcoder
.transcode(*sys
.argv
[1:3])