# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import pdb
import logging
+try:
+ from PIL import Image
+except ImportError:
+ import Image
from mediagoblin.processing import BadMediaFail
+from mediagoblin.media_types.audio import audioprocessing
_log = logging.getLogger(__name__)
-CPU_COUNT = 2 # Just assuming for now
+CPU_COUNT = 2 # Just assuming for now
# IMPORT MULTIPROCESSING
try:
except ImportError:
raise Exception('gst/pygst >= 0.10 could not be imported')
+import numpy
+
+
+class AudioThumbnailer(object):
+ def __init__(self):
+ _log.info('Initializing {0}'.format(self.__class__.__name__))
+
+ def spectrogram(self, src, dst, **kw):
+ width = kw['width']
+ height = int(kw.get('height', float(width) * 0.3))
+ fft_size = kw.get('fft_size', 2048)
+ callback = kw.get('progress_callback')
+
+ processor = audioprocessing.AudioProcessor(
+ src,
+ fft_size,
+ numpy.hanning)
+
+ samples_per_pixel = processor.audio_file.nframes / float(width)
+
+ spectrogram = audioprocessing.SpectrogramImage(width, height, fft_size)
+
+ for x in range(width):
+ if callback and x % (width / 10) == 0:
+ callback((x * 100) / width)
+
+ seek_point = int(x * samples_per_pixel)
+
+ (spectral_centroid, db_spectrum) = processor.spectral_centroid(
+ seek_point)
+
+ spectrogram.draw_spectrum(x, db_spectrum)
+
+ if callback:
+ callback(100)
+
+ spectrogram.save(dst)
+
+ def thumbnail_spectrogram(self, src, dst, thumb_size):
+ '''
+ Takes a spectrogram and creates a thumbnail from it
+ '''
+ if not (type(thumb_size) == tuple and len(thumb_size) == 2):
+ raise Exception('thumb_size argument should be a tuple(width, height)')
+
+ im = Image.open(src)
+
+ im_w, im_h = [float(i) for i in im.size]
+ th_w, th_h = [float(i) for i in thumb_size]
+
+ wadsworth_position = im_w * 0.3
+
+ start_x = max((
+ wadsworth_position - ((im_h * (th_w / th_h)) / 2.0),
+ 0.0))
+
+ stop_x = start_x + (im_h * (th_w / th_h))
+
+ th = im.crop((
+ int(start_x), 0,
+ int(stop_x), int(im_h)))
+
+ if th.size[0] > th_w or th.size[1] > th_h:
+ th.thumbnail(thumb_size, Image.ANTIALIAS)
+
+ th.save(dst)
+
+
class AudioTranscoder(object):
def __init__(self):
_log.info('Initializing {0}'.format(self.__class__.__name__))
# Instantiate MainLoop
self._loop = gobject.MainLoop()
+ self._failed = None
def discover(self, src):
+ self._src_path = src
_log.info('Discovering {0}'.format(src))
self._discovery_path = src
self._loop.run() # Run MainLoop
+ if self._failed:
+ raise self._failed
+
# Once MainLoop has returned, return discovery data
- return self._discovery_data
+ return getattr(self, '_discovery_data', False)
def __on_discovered(self, data, is_media):
if not is_media:
- self.halt()
+ self._failed = BadMediaFail()
_log.error('Could not discover {0}'.format(self._src_path))
- raise BadMediaFail()
+ self.halt()
_log.debug('Discovered: {0}'.format(data.__dict__))
self.halt()
def transcode(self, src, dst, **kw):
+ _log.info('Transcoding {0} into {1}'.format(src, dst))
self._discovery_data = kw.get('data', self.discover(src))
self.__on_progress = kw.get('progress_callback')
quality = kw.get('quality', 0.3)
+ mux_string = kw.get(
+ 'mux_string',
+ 'vorbisenc quality={0} ! webmmux'.format(quality))
+
# Set up pipeline
self.pipeline = gst.parse_launch(
- 'filesrc location="{src}" ! '
+ 'filesrc location="{src}" ! '
'decodebin2 ! queue ! audiorate tolerance={tolerance} ! '
'audioconvert ! audio/x-raw-float,channels=2 ! '
- 'vorbisenc quality={quality} ! webmmux ! '
+ '{mux_string} ! '
'progressreport silent=true ! '
'filesink location="{dst}"'.format(
src=src,
tolerance=80000000,
- quality=quality,
+ mux_string=mux_string,
dst=dst))
self.bus = self.pipeline.get_bus()
data = dict(message.structure)
if self.__on_progress:
- self.__on_progress(data)
+ self.__on_progress(data.get('percent'))
_log.info('{0}% done...'.format(
data.get('percent')))
self.halt()
def halt(self):
+ if getattr(self, 'pipeline', False):
+ self.pipeline.set_state(gst.STATE_NULL)
+ del self.pipeline
_log.info('Quitting MainLoop gracefully...')
gobject.idle_add(self._loop.quit)
logging.basicConfig()
_log.setLevel(logging.INFO)
- transcoder = AudioTranscoder()
- data = transcoder.discover(sys.argv[1])
- res = transcoder.transcode(*sys.argv[1:3])
+ #transcoder = AudioTranscoder()
+ #data = transcoder.discover(sys.argv[1])
+ #res = transcoder.transcode(*sys.argv[1:3])
+
+ thumbnailer = AudioThumbnailer()
- pdb.set_trace()
+ thumbnailer.spectrogram(*sys.argv[1:], width=640)