This file describe how to install the TimeSide python package from source.
-1. Install dependencies
-=======================
-
-TimeSide needs some other python modules to run.
-See README for the full dependency list.
-
-The following methods explain how to install all dependencies on a Debian based system
-and espacially on Debian Squeeze 6.0 (stable). Is it now considered you have install this system correctly.
-
-Become root. In a terminal or console, run::
-
- $ su
+INSTALL
+=======
-Write your root password.
-Note : you can paste the full command but without the shell character '$'.
-Then::
+TimeSide needs some other python modules to run. The following methods explain how to install all dependencies on a Debian based system like Debian, Ubuntu, etc.. On Fedora and Red-Hat you might replace 'apt-get by 'yum', on Gentoo by 'emerge', or any other package manager you like::
- $ aptitude update
- $ aptitude install python python-gobject gobject-introspection python-setuptools python-xml python-mutagen \
- python-imaging python-numpy python-scipy python-gst0.10 gstreamer0.10-plugins-base gir1.0-gstreamer-0.10 \
- gstreamer0.10-fluendo-mp3 gstreamer0.10-plugins-good gstreamer0.10-plugins-bad
+ $ sudo apt-get update
+ $ sudo apt-get install python python-pip python-setuptools python-gobject \
+ python-gst0.10 gstreamer0.10-plugins-base gir1.0-gstreamer-0.10 \
+ gstreamer0.10-plugins-good gstreamer0.10-plugins-bad \
+ gobject-introspection
-Add Debian multimedia repository to the apt sources.list and install Gstreamer MP3 modules::
-
- $ echo "deb deb http://www.debian-multimedia.org stable main" | tee -a /etc/apt/sources.list
- $ aptitude update
- $ aptitude install gstreamer0.10-fluendo-mp3 gstreamer0.10-lame
-
-
-2. Install TimeSide
-===================
-
-Go into the module directory and then install::
-
- $ cd timeside
- $ python setup.py install
+ $ sudo pip install timeside
-Or, directly from python package directory::
+To get non-free MP3, MP4 or AAC decoding and encoding features, add Debian Multimedia repository and install the modules::
- $ sudo pip install timeside
+ $ echo "deb http://www.deb-multimedia.org stable main non-free" | sudo tee -a /etc/apt/sources.list
+ $ sudo apt-get update
+ $ apt-get install gstreamer0.10-lame gstreamer0.10-plugins-really-bad
3. Use TimeSide
TimeSide : open and fast web audio components
==============================================
-TimeSide is a set of client and server side components for audio-enabling web sites and applications.
+TimeSide is a set of python components enabling easy audio processing, transcoding, imaging and streaming. Its simple architecture and high-level API have been design to process serial pipelines
-It includes a powerful DHTML-based interactive player, with support for time-marking.
-The server side components provide generic APIs for easy transcoding, metadata embedding,
-sound visualization and audio analysis.
+It includes a powerfull HTM5 interactive player which can be embedded in any web application to provide fancy waveforms, various analyzer results, synced time metadata display during playback and remote indexing.
+
+The engine (server side) is fully written in Python, the player (client side) in HTML, CSS and JavaScript.
News
=====
* bugfixes
-Platforms
-=========
+Dive in
+========
-TimeSide is intended to work on all Unix / Linux platforms.
-MacOS X and Windows versions will soon be explorated.
+Define some processors::
-It is mostly written in Python and JavaScript / CSS / HTML
+ >>> import timeside
+ >>> decoder = timeside.decoder.FileDecoder('source.wav')
+ >>> grapher = timeside.grapher.Waveform()
+ >>> analyzer = timeside.analyzer.MaxLevel()
+ >>> encoder = timeside.encoder.Mp3Encoder('output.mp3')
+then, the *magic* pipeline::
-Install and usage
-==================
+ >>> (decoder | grapher | analyzer | encoder).run()
-See INSTALL.rst
+get the results::
+ >>> grapher.render(output='image.png')
+ >>> print 'Level:', analyzer.result()
-Dependencies
-============
+finally see image.png and play output.mp3 ;)
- * python (>= 2.4)
- * python-xml
- * python-mutagen
- * python-imaging (>= 1.1.6)
- * python-numpy
- * python-setuptools
- * python-gst0.10
- * gstreamer0.10-plugins-base,
- * gstreamer0.10-plugins-fluendo-mp3
- * gstreamer0.10-plugins-good
+More examples
+=============
-Provides
-==========
+ * http://code.google.com/p/timeside/
+ * http://code.google.com/p/timeside/wiki/PythonApi
+ * https://github.com/yomguy/TimeSide/tree/master/scripts/batch/
+ * http://archives.crem-cnrs.fr/items/CNRSMH_I_1956_002_001_01/ (player embedded in a Telemeta session)
- * SoundManager 2 >= 2.91 (http://www.schillmania.com/projects/soundmanager2)
- * jQuery => 1.2.6 (http://www.jquery.com)
- * jsGraphics => 3.03 (http://www.walterzorn.com/jsgraphics/jsgraphics_e.htm)
+Related projects
+=================
-High level process example
-===========================
+TimeSide has emerged in 2010 from the `Telemeta project <http://telemeta.org>`_ which develop a free and open-source web audio CMS.
-For example::
+The time decoder depends on the `GStreamer framework<http://gstreamer.freedesktop.org/>`_.
- >>> import timeside
- >>> decoder = timeside.decoder.FileDecoder('source.wav')
- >>> grapher = timeside.grapher.Waveform()
- >>> analyzer = timeside.analyzer.MaxLevel()
- >>> encoder = timeside.encoder.Mp3Encoder('output.mp3')
- >>> (decoder | grapher | analyzer | encoder).run()
- >>> grapher.render(output='image.png')
- >>> print 'Level:', analyzer.result()
+APIs
+====
-UI Integration
-===============
+Engine API : http://code.google.com/p/timeside/source/browse/trunk/timeside/api.py
-See TimeSide UI integration guide: http://code.google.com/p/timeside/wiki/UiGuide
+Player API and guide : http://code.google.com/p/timeside/wiki/UiGuide
-More examples
-==============
+Platforms
+=========
- * http://code.google.com/p/timeside/
- * http://archives.crem-cnrs.fr/items/CNRSMH_I_1956_002_001_01/
- * http://demo.telemeta.org (login: demo , pass: demo)
+The TimeSide engine is intended to work on all Unix / Linux platforms, but MacOS X and Windows versions will soon be explorated.
+The player should work on any modern HTML5 enabled browser. Flash is needed for MP3 if the browser doesn't support it.
-Related projects
-=================
-Telemeta : open web audio CMS (http://telemeta.org)
+Install
+=======
+TimeSide needs some other python modules to run. The following methods explain how to install all dependencies on a Debian based system like Debian, Ubuntu, etc.. On Fedora and Red-Hat you might replace 'apt-get by 'yum', on Gentoo by 'emerge', or any other package manager you like::
-Copyrights
-==========
+ $ sudo apt-get update
+ $ sudo apt-get install python python-pip python-setuptools python-gobject \
+ python-gst0.10 gstreamer0.10-plugins-base gir1.0-gstreamer-0.10 \
+ gstreamer0.10-plugins-good gstreamer0.10-plugins-bad \
+ gobject-introspection
+
+ $ sudo pip install timeside
+
+To get non-free MP3, MP4 or AAC decoding and encoding features, add Debian Multimedia repository and install the modules::
+
+ $ echo "deb http://www.deb-multimedia.org stable main non-free" | sudo tee -a /etc/apt/sources.list
+ $ sudo apt-get update
+ $ apt-get install gstreamer0.10-lame gstreamer0.10-plugins-really-bad
+
+
+Batching
+=========
+
+TimeSide provides ts-waveforms : a waveform redering batch script.
+
+Usage::
+
+ $ ts-waveforms /path/to/media_dir /path/to/img_dir
+
+Please use absolute paths. For example::
+
+ $ ts-waveforms /home/$user/music/mp3/ /home/$USER/images/
+
+To change the color scheme or the size of the waveforms, edit the script from the source and change the variables of the GrapherScheme object::
-Copyright (c) 2006, 2011 Parisson SARL. All rights reserved.
-Copyright (c) 2006, 2010 Samalyse SARL.
-Copyright (c) 2010, 2012, Paul Brossier.
+ $ git clone git://github.com/yomguy/TimeSide.git
+ $ cd timeside/scripts/
+ $ vi ts-waveforms
+ $ ./ts-waveforms /home/$user/music/mp3/ /home/$USER/images/
+
+
+Packages included
+=================
+
+ * SoundManager 2 >= 2.91 (http://www.schillmania.com/projects/soundmanager2)
+ * jQuery => 1.2.6 (http://www.jquery.com)
+ * jsGraphics => 3.03 (http://www.walterzorn.com/jsgraphics/jsgraphics_e.htm)
License
See LICENSE for more details.
-Contact and Informations
-========================
+Development
+===========
+
+ * http://code.google.com/p/timeside/
+ * https://github.com/yomguy/TimeSide
+
+
+Copyrights
+==========
+
+ * Copyright (c) 2006, 2012 Parisson SARL
+ * Copyright (c) 2006, 2012 Guillaume Pellerin
+ * Copyright (c) 2010, 2012 Paul Brossier
+ * Copyright (c) 2006, 2010 Samalyse SARL
+
-See http://code.google.com/p/timeside/
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+version = '0.4'
+
+import os
+import sys
+import time
+import datetime
+import timeside
+from logger import Logger
+import Queue
+from threading import Thread
+from cache import Cache
+from django.core.management import setup_environ
+from django.core.files.base import ContentFile
+
+
+class GrapherScheme:
+
+ def __init__(self):
+ self.color = 255
+ self.color_scheme = {
+ 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
+ (self.color,self.color,self.color)
+# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
+ ],
+ 'spectrogram': [
+ (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
+ ]}
+
+ # Grapher id
+ self.id = 'waveform_awdio'
+
+ # Width of the image
+ self.width = 1800
+
+ # Height of the image
+ self.height = 233
+
+ # Background color
+ self.bg_color = None
+
+ # Force computation. By default, the class doesn't overwrite existing image files.
+ self.force = False
+
+ # Nb of threads
+ # FIXME: memory leak for > 1 !
+ self.threads = 1
+
+
+class TelemetaPreprocessImport(object):
+
+ def __init__(self, media_dir, dest_dir, log_file):
+ self.root_dir = media_dir
+ self.dest_dir = dest_dir
+ self.threads = 1
+ self.logger = Logger(log_file)
+ self.counter = 0
+ self.force = 0
+ self.cache = Cache(self.dest_dir)
+
+ self.scheme = GrapherScheme()
+ self.width = self.scheme.width
+ self.height = self.scheme.height
+ self.bg_color = self.scheme.bg_color
+ self.color_scheme = self.scheme.color_scheme
+ self.force = self.scheme.force
+ self.threads = self.scheme.threads
+ self.logger = Logger(log_file)
+ self.counter = 0
+
+ self.analyzers = timeside.core.processors(timeside.api.IAnalyzer)
+ self.grapher = timeside.grapher.WaveformAwdio(width=self.width,
+ height=self.height,
+ bg_color=self.bg_color,
+ color_scheme=self.color_scheme)
+
+ self.media_list = self.get_media_list()
+ if not os.path.exists(self.dest_dir):
+ os.makedirs(self.dest_dir)
+
+ def get_media_list(self):
+ media_list = []
+ for root, dirs, files in os.walk(self.root_dir):
+ if root:
+ for file in files:
+ if file[0] != '.':
+ ext = file.split('.')[-1]
+ media_list.append(root+os.sep+file)
+ return media_list
+
+ def process(self):
+ for media in self.media_list:
+ filename = media.split(os.sep)[-1]
+ name, ext = os.path.splitext(filename)
+ size = str(self.width) + '_' + str(self.height)
+ image = self.dest_dir + os.sep + name + '.' + self.scheme.id + '.' + size + '.png'
+ xml = name + '.xml'
+
+ if not self.cache.exists(image) or not self.cache.exists(xml):
+ mess = 'Processing ' + media
+ self.logger.write_info(mess)
+ decoder = timeside.decoder.FileDecoder(media)
+ pipe = decoder | self.grapher
+ analyzers = []
+ analyzers_sub = []
+ for analyzer in self.analyzers:
+ subpipe = analyzer()
+ analyzers_sub.append(subpipe)
+ pipe = pipe | subpipe
+ pipe.run()
+
+ mess = 'Rendering ' + image
+ self.logger.write_info(mess)
+ self.grapher.render(output=image)
+
+ mess = 'Frames / Pixel = ' + str(self.grapher.graph.samples_per_pixel)
+ self.logger.write_info(mess)
+
+ for analyzer in analyzers_sub:
+ value = analyzer.result()
+ if analyzer.id() == 'duration':
+ value = datetime.timedelta(0,value)
+ analyzers.append({'name':analyzer.name(),
+ 'id':analyzer.id(),
+ 'unit':analyzer.unit(),
+ 'value':str(value)})
+
+ self.cache.write_analyzer_xml(analyzers, xml)
+
+ filename = name
+ data = name.split('.')
+ date = data[0]
+ collection_name = data[1]
+ other = ''
+ if len(data) > 2:
+ other = '.'.join(data[2:])
+
+ item = telemeta.models.media.MediaItem.objects.filter(code=filename)
+ collections = telemeta.models.media.MediaCollection.objects.filter(code=collection_name)
+
+ if not collections:
+ c = telemeta.models.media.MediaCollection(code=collection_name)
+ c.title = collection_name
+ c.save()
+ msg = 'added'
+ self.logger.write_info(collection_name, msg)
+ collection = c
+ else:
+ collection = collections[0]
+
+ if not item:
+ item = telemeta.models.media.MediaItem(collection=collection, code=filename)
+ item.title = filename
+ item.file = self.media_dir + os.sep + media
+ item.save()
+ msg = 'added item : ' + filename
+ self.logger.write_info(collection_name, msg)
+
+
+
+if __name__ == '__main__':
+ if len(sys.argv) <= 2:
+ print """
+ Usage : python telemeta_preprocess_batch.py /path/to/project /path/to/media_dir /path/to/dest_dir /path/to/log
+
+ Dependencies : timeside, python, python-numpy, python-gst0.10, gstreamer0.10-plugins-base
+ See http://code.google.com/p/timeside/ for more information.
+ """
+ else:
+ project_dir = sys.argv[-2]
+ log_file = sys.argv[-1]
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ media_dir = settings.MEDIA_ROOT
+ data_dir = settings.TELEMETA_DATA_CACHE_DIR
+ print media_dir, data_dir
+ t = TelemetaPreprocessImport(media_dir, data_dir, log_file)
+ t.process()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+# for python2.5
+
+version = '0.5'
+
+
+import os
+import sys
+import time
+import shutil
+import datetime
+import timeside
+
+# soon with python2.6
+#from multiprocessing import Process
+
+from django.core.management import setup_environ
+from django.core.files.base import ContentFile
+import cgi
+fs = cgi.FieldStorage()
+
+
+orig_media_dir = '/mnt/awdiomusic/musicbase'
+project_dir = '/mnt/awdio'
+log_file = project_dir + '/logs/process.log'
+sys.path.append('/home/awdio/apps/telemeta-awdio')
+
+
+class GrapherScheme:
+
+ def __init__(self):
+ self.color = 255
+ self.color_scheme = {
+ 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
+ (self.color,self.color,self.color)
+# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
+ ],
+ 'spectrogram': [
+ (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
+ ]}
+
+ # Grapher id
+ self.id = 'waveform_awdio'
+
+ # Width of the image
+ self.width = 1800
+
+ # Height of the image
+ self.height = 233
+
+ # Background color
+ self.bg_color = None
+
+ # Force computation. By default, the class doesn't overwrite existing image files.
+ self.force = False
+
+ # Nb of threads
+ # FIXME: memory leak for > 1 !
+ self.threads = 1
+
+
+class TelemetaPreprocessImport(object):
+
+ def __init__(self, root_dir, dest_dir, log_file):
+ from telemeta.cache import TelemetaCache as Cache
+ from telemeta.util.logger import Logger
+ self.media_item_dir = 'items'
+ self.root_dir = root_dir + 'items'
+ self.dest_dir = dest_dir
+ self.threads = 1
+ self.logger = Logger(log_file)
+ self.counter = 0
+ self.force = 0
+ self.cache = Cache(self.dest_dir)
+
+ self.scheme = GrapherScheme()
+ self.width = self.scheme.width
+ self.height = self.scheme.height
+ self.bg_color = self.scheme.bg_color
+ self.color_scheme = self.scheme.color_scheme
+ self.force = self.scheme.force
+ self.threads = self.scheme.threads
+ self.logger = Logger(log_file)
+ self.counter = 0
+ self.collection_name = 'awdio'
+ self.collection = self.set_collection(self.collection_name)
+
+ self.analyzers = timeside.core.processors(timeside.api.IAnalyzer)
+ self.grapher = timeside.grapher.WaveformAwdio(width=self.width,
+ height=self.height,
+ bg_color=self.bg_color,
+ color_scheme=self.color_scheme)
+
+
+ def set_collection(self, collection_name):
+ import telemeta.models
+ collections = telemeta.models.media.MediaCollection.objects.filter(code=collection_name)
+ if not collections:
+ c = telemeta.models.media.MediaCollection(code=collection_name)
+ c.title = collection_name
+ c.save()
+ msg = 'added'
+ self.logger.logger.info(collection_name, msg)
+ collection = c
+ else:
+ collection = collections[0]
+ return collection
+
+ def process(self):
+ import telemeta.models
+ keys = fs.keys()
+ if keys[0] == 'file':
+ filename = fs['file'].value
+ media_orig = orig_media_dir + os.sep + filename
+ media = self.root_dir + os.sep + filename
+
+ if not os.path.exists(media):
+ shutil.copy(media_orig, media)
+ os.system('chmod 644 ' + media)
+
+ name, ext = os.path.splitext(filename)
+ size = str(self.width) + '_' + str(self.height)
+ image_name = name + '.' + self.scheme.id + '.' + size + '.png'
+ image = self.dest_dir + os.sep + image_name
+ xml = name + '.xml'
+
+ if not self.cache.exists(image_name) or not self.cache.exists(xml):
+ mess = 'Processing ' + media
+ self.logger.logger.info(mess)
+
+ print "Content-type: text/plain\n"
+ print mess
+ decoder = timeside.decoder.FileDecoder(media)
+ pipe = decoder | self.grapher
+ analyzers = []
+ analyzers_sub = []
+ for analyzer in self.analyzers:
+ subpipe = analyzer()
+ analyzers_sub.append(subpipe)
+ pipe = pipe | subpipe
+ pipe.run()
+
+ mess = 'Rendering ' + image
+ self.logger.logger.info(mess)
+ self.grapher.render(output=image)
+
+ mess = 'Frames / Pixel = ' + str(self.grapher.graph.samples_per_pixel)
+ self.logger.logger.info(mess)
+
+ for analyzer in analyzers_sub:
+ value = analyzer.result()
+ if analyzer.id() == 'duration':
+ value = datetime.timedelta(0,value)
+ analyzers.append({'name':analyzer.name(),
+ 'id':analyzer.id(),
+ 'unit':analyzer.unit(),
+ 'value':str(value)})
+
+ self.cache.write_analyzer_xml(analyzers, xml)
+
+ item = telemeta.models.media.MediaItem.objects.filter(code=name)
+
+ if not item:
+ item = telemeta.models.media.MediaItem(collection=self.collection, code=name)
+ item.title = name
+ item.file = self.media_item_dir + os.sep + filename
+ item.save()
+ msg = 'added item : ' + filename
+ self.logger.logger.info(self.collection_name, msg)
+
+ pipe = 0
+ decoder = 0
+
+ print "OK"
+
+ #except:
+ #pipe = 0
+ #decoder = 0
+ #mess = 'Could NOT process : ' + media
+ #self.logger.logger.error(mess)
+ #print mess
+
+ else:
+ mess = "Nothing to do with file : " + media
+ self.logger.logger.info(mess)
+ print "Content-type: text/plain\n"
+ print mess
+
+ else:
+ print "Content-type: text/plain\n"
+ print "No file given !"
+
+
+if __name__ == '__main__':
+ sys.path.append(project_dir)
+ import settings
+ setup_environ(settings)
+ media_dir = settings.MEDIA_ROOT
+ data_dir = settings.TELEMETA_DATA_CACHE_DIR
+ t = TelemetaPreprocessImport(media_dir, data_dir, log_file)
+ t.process()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+version = '0.3'
+
+import os
+import sys
+import time
+import timeside
+from logger import Logger
+import Queue
+from threading import Thread
+
+class GrapherScheme:
+
+ def __init__(self):
+ self.color = 255
+ self.color_scheme = {
+ 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
+ (self.color,self.color,self.color)
+# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
+ ],
+ 'spectrogram': [
+ (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
+ ]}
+
+ # Grapher id
+ self.id = 'waveform_awdio'
+
+ # Width of the image
+ self.width = 1800
+
+ # Height of the image
+ self.height = 233
+
+ # Background color
+ self.bg_color = None
+
+ # Force computation. By default, the class doesn't overwrite existing image files.
+ self.force = False
+
+ # Nb of threads
+ # FIXME: memory leak for > 1 !
+ self.threads = 1
+
+
+class Media2Waveform(object):
+
+ def __init__(self, media_dir, img_dir, log_file):
+ self.root_dir = os.path.join(os.path.dirname(__file__), media_dir)
+ self.img_dir = os.path.join(os.path.dirname(__file__), img_dir)
+ self.scheme = GrapherScheme()
+ self.width = self.scheme.width
+ self.height = self.scheme.height
+ self.bg_color = self.scheme.bg_color
+ self.color_scheme = self.scheme.color_scheme
+ self.force = self.scheme.force
+ self.threads = self.scheme.threads
+ self.logger = Logger(log_file)
+ self.counter = 0
+
+ self.media_list = self.get_media_list()
+ if not os.path.exists(self.img_dir):
+ os.makedirs(self.img_dir)
+ self.path_dict = self.get_path_dict()
+
+ def get_media_list(self):
+ media_list = []
+ for root, dirs, files in os.walk(self.root_dir):
+ if root:
+ for file in files:
+ if file[0] != '.':
+ ext = file.split('.')[-1]
+ media_list.append(root+os.sep+file)
+ return media_list
+
+ def get_path_dict(self):
+ path_dict = {}
+ for media in self.media_list:
+ filename = media.split(os.sep)[-1]
+ name, ext = os.path.splitext(filename)
+ size = str(self.width) + '_' + str(self.height)
+ image = self.img_dir + os.sep + name + '.' + self.scheme.id + '.' + size + '.png'
+ if not os.path.exists(image) or self.force:
+ path_dict[media] = image
+ return path_dict
+
+ def process(self):
+ q = Queue.Queue()
+ for i in range(0, self.threads):
+ worker = Thread(target=Worker, args=(self.width, self.height, self.bg_color, self.color_scheme, q, self.logger))
+ worker.setDaemon(True)
+ worker.start()
+
+ mess = str(self.threads) + ' thread(s) started'
+ self.logger.write_info(mess)
+
+ for media, image in self.path_dict.iteritems():
+ q.put((media, image))
+ q.join()
+
+
+def Worker(width, height, bg_color, color_scheme, q, logger):
+ while True:
+ media, image = q.get()
+ mess = 'Processing ' + media
+ logger.write_info(mess)
+ decoder = timeside.decoder.FileDecoder(media)
+ grapher = timeside.grapher.WaveformAwdio(width=width, height=height, bg_color=bg_color, color_scheme=color_scheme)
+ (decoder | grapher).run()
+ mess = 'Rendering ' + image
+ logger.write_info(mess)
+ grapher.render(output=image)
+ mess = 'Frames / Pixel = ' + str(grapher.graph.samples_per_pixel)
+ logger.write_info(mess)
+ grapher.release()
+ q.task_done()
+
+if __name__ == '__main__':
+ if len(sys.argv) <= 2:
+ print """
+ Usage : python waveform_batch /path/to/media_dir /path/to/img_dir
+
+ Dependencies : timeside, python, python-numpy, python-gst0.10, gstreamer0.10-plugins-base
+ See http://code.google.com/p/timeside/ for more information.
+ """
+ else:
+ media_dir = sys.argv[-3]
+ img_dir = sys.argv[-2]
+ log_file = sys.argv[-1]
+ m = Media2Waveform(media_dir, img_dir, log_file)
+ m.process()
--- /dev/null
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
+
+# This file is part of TimeSide.
+
+# TimeSide is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+
+# TimeSide is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+version = '0.2'
+
+import os
+import sys
+import timeside
+
+
+class GrapherScheme:
+
+ def __init__(self):
+
+ self.color_scheme = {
+ 'waveform': [
+ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
+ (30,144,255), (30,144,255), (30,144,255), (30,144,255)
+ ],
+ 'spectrogram': [
+ (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2),
+ (90,180,100), (224,224,44), (255,60,30), (255,255,255)
+ ]}
+
+ # Width of the image
+ self.width = 925
+
+ # Height of the image
+ self.height = 67
+
+ # Background color
+ self.bg_color = (-1, -1, -1, -1)
+
+ # Force computation. By default, the class doesn't overwrite existing image files.
+ self.force = True
+
+
+class Media2Waveform(object):
+
+ def __init__(self, media_dir, img_dir):
+ self.root_dir = os.path.join(os.path.dirname(__file__), media_dir)
+ self.img_dir = os.path.join(os.path.dirname(__file__), img_dir)
+ self.scheme = GrapherScheme()
+ self.width = self.scheme.width
+ self.height = self.scheme.height
+ self.bg_color = self.scheme.bg_color
+ self.color_scheme = self.scheme.color_scheme
+ self.force = self.scheme.force
+
+ self.media_list = self.get_media_list()
+ if not os.path.exists(self.img_dir):
+ os.makedirs(self.img_dir)
+ self.path_dict = self.get_path_dict()
+
+ def get_media_list(self):
+ media_list = []
+ for root, dirs, files in os.walk(self.root_dir):
+ if root:
+ for file in files:
+ ext = file.split('.')[-1]
+ if not file[0] == '.':
+ media_list.append(root+os.sep+file)
+ return media_list
+
+ def get_path_dict(self):
+ path_dict = {}
+ for media in self.media_list:
+ filename = media.split(os.sep)[-1]
+ name, ext = os.path.splitext(filename)
+ path_dict[media] = self.img_dir + os.sep + filename.replace('.', '_') + '.png'
+ return path_dict
+
+ def process(self):
+ waveform = timeside.grapher.Waveform(width=self.width, height=self.height,
+ bg_color=self.bg_color, color_scheme=self.color_scheme)
+ for source, image in self.path_dict.iteritems():
+ if not os.path.exists(image) or self.force:
+ print 'Processing ', source
+ audio = os.path.join(os.path.dirname(__file__), source)
+ decoder = timeside.decoder.FileDecoder(audio)
+ duration = decoder.duration
+ (decoder | waveform).run()
+ img_name = os.path.split(image)[1]
+ image = os.path.split(image)[0]+os.sep+os.path.splitext(img_name)[0] + '_' +\
+ '_'.join([str(self.width), str(self.height),
+ str(int(duration))])+os.path.splitext(img_name)[1]
+ waveform.graph.filename = image
+ print 'Rendering ', waveform.graph.filename
+ #print 'frames per pixel = ', waveform.graph.samples_per_pixel
+ waveform.render(output=image)
+
+
+if __name__ == '__main__':
+ if len(sys.argv) <= 1:
+ print """
+ TimeSide simple waveform generator
+
+ Usage : python waveform_batch.py /path/to/media_dir /path/to/img_dir
+
+ Dependencies : timeside, python, python-numpy, python-gst0.10, gstreamer0.10-plugins-base
+ See http://code.google.com/p/timeside/ for more information.
+ """
+ else:
+ media_dir = sys.argv[-2]
+ img_dir = sys.argv[-1]
+ m = Media2Waveform(media_dir, img_dir)
+ m.process()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
-import os
CLASSIFIERS = [
'Intended Audience :: Science/Research',
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-version = '0.4'
-
-import os
-import sys
-import time
-import datetime
-import timeside
-from logger import Logger
-import Queue
-from threading import Thread
-from cache import Cache
-from django.core.management import setup_environ
-from django.core.files.base import ContentFile
-
-
-class GrapherScheme:
-
- def __init__(self):
- self.color = 255
- self.color_scheme = {
- 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
- (self.color,self.color,self.color)
-# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
- ],
- 'spectrogram': [
- (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
- ]}
-
- # Grapher id
- self.id = 'waveform_awdio'
-
- # Width of the image
- self.width = 1800
-
- # Height of the image
- self.height = 233
-
- # Background color
- self.bg_color = None
-
- # Force computation. By default, the class doesn't overwrite existing image files.
- self.force = False
-
- # Nb of threads
- # FIXME: memory leak for > 1 !
- self.threads = 1
-
-
-class TelemetaPreprocessImport(object):
-
- def __init__(self, media_dir, dest_dir, log_file):
- self.root_dir = media_dir
- self.dest_dir = dest_dir
- self.threads = 1
- self.logger = Logger(log_file)
- self.counter = 0
- self.force = 0
- self.cache = Cache(self.dest_dir)
-
- self.scheme = GrapherScheme()
- self.width = self.scheme.width
- self.height = self.scheme.height
- self.bg_color = self.scheme.bg_color
- self.color_scheme = self.scheme.color_scheme
- self.force = self.scheme.force
- self.threads = self.scheme.threads
- self.logger = Logger(log_file)
- self.counter = 0
-
- self.analyzers = timeside.core.processors(timeside.api.IAnalyzer)
- self.grapher = timeside.grapher.WaveformAwdio(width=self.width,
- height=self.height,
- bg_color=self.bg_color,
- color_scheme=self.color_scheme)
-
- self.media_list = self.get_media_list()
- if not os.path.exists(self.dest_dir):
- os.makedirs(self.dest_dir)
-
- def get_media_list(self):
- media_list = []
- for root, dirs, files in os.walk(self.root_dir):
- if root:
- for file in files:
- if file[0] != '.':
- ext = file.split('.')[-1]
- media_list.append(root+os.sep+file)
- return media_list
-
- def process(self):
- for media in self.media_list:
- filename = media.split(os.sep)[-1]
- name, ext = os.path.splitext(filename)
- size = str(self.width) + '_' + str(self.height)
- image = self.dest_dir + os.sep + name + '.' + self.scheme.id + '.' + size + '.png'
- xml = name + '.xml'
-
- if not self.cache.exists(image) or not self.cache.exists(xml):
- mess = 'Processing ' + media
- self.logger.write_info(mess)
- decoder = timeside.decoder.FileDecoder(media)
- pipe = decoder | self.grapher
- analyzers = []
- analyzers_sub = []
- for analyzer in self.analyzers:
- subpipe = analyzer()
- analyzers_sub.append(subpipe)
- pipe = pipe | subpipe
- pipe.run()
-
- mess = 'Rendering ' + image
- self.logger.write_info(mess)
- self.grapher.render(output=image)
-
- mess = 'Frames / Pixel = ' + str(self.grapher.graph.samples_per_pixel)
- self.logger.write_info(mess)
-
- for analyzer in analyzers_sub:
- value = analyzer.result()
- if analyzer.id() == 'duration':
- value = datetime.timedelta(0,value)
- analyzers.append({'name':analyzer.name(),
- 'id':analyzer.id(),
- 'unit':analyzer.unit(),
- 'value':str(value)})
-
- self.cache.write_analyzer_xml(analyzers, xml)
-
- filename = name
- data = name.split('.')
- date = data[0]
- collection_name = data[1]
- other = ''
- if len(data) > 2:
- other = '.'.join(data[2:])
-
- item = telemeta.models.media.MediaItem.objects.filter(code=filename)
- collections = telemeta.models.media.MediaCollection.objects.filter(code=collection_name)
-
- if not collections:
- c = telemeta.models.media.MediaCollection(code=collection_name)
- c.title = collection_name
- c.save()
- msg = 'added'
- self.logger.write_info(collection_name, msg)
- collection = c
- else:
- collection = collections[0]
-
- if not item:
- item = telemeta.models.media.MediaItem(collection=collection, code=filename)
- item.title = filename
- item.file = self.media_dir + os.sep + media
- item.save()
- msg = 'added item : ' + filename
- self.logger.write_info(collection_name, msg)
-
-
-
-if __name__ == '__main__':
- if len(sys.argv) <= 2:
- print """
- Usage : python telemeta_preprocess_batch.py /path/to/project /path/to/media_dir /path/to/dest_dir /path/to/log
-
- Dependencies : timeside, python, python-numpy, python-gst0.10, gstreamer0.10-plugins-base
- See http://code.google.com/p/timeside/ for more information.
- """
- else:
- project_dir = sys.argv[-2]
- log_file = sys.argv[-1]
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- media_dir = settings.MEDIA_ROOT
- data_dir = settings.TELEMETA_DATA_CACHE_DIR
- print media_dir, data_dir
- t = TelemetaPreprocessImport(media_dir, data_dir, log_file)
- t.process()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-# for python2.5
-
-version = '0.5'
-
-
-import os
-import sys
-import time
-import shutil
-import datetime
-import timeside
-
-# soon with python2.6
-#from multiprocessing import Process
-
-from django.core.management import setup_environ
-from django.core.files.base import ContentFile
-import cgi
-fs = cgi.FieldStorage()
-
-
-orig_media_dir = '/mnt/awdiomusic/musicbase'
-project_dir = '/mnt/awdio'
-log_file = project_dir + '/logs/process.log'
-sys.path.append('/home/awdio/apps/telemeta-awdio')
-
-
-class GrapherScheme:
-
- def __init__(self):
- self.color = 255
- self.color_scheme = {
- 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
- (self.color,self.color,self.color)
-# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
- ],
- 'spectrogram': [
- (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
- ]}
-
- # Grapher id
- self.id = 'waveform_awdio'
-
- # Width of the image
- self.width = 1800
-
- # Height of the image
- self.height = 233
-
- # Background color
- self.bg_color = None
-
- # Force computation. By default, the class doesn't overwrite existing image files.
- self.force = False
-
- # Nb of threads
- # FIXME: memory leak for > 1 !
- self.threads = 1
-
-
-class TelemetaPreprocessImport(object):
-
- def __init__(self, root_dir, dest_dir, log_file):
- from telemeta.cache import TelemetaCache as Cache
- from telemeta.util.logger import Logger
- self.media_item_dir = 'items'
- self.root_dir = root_dir + 'items'
- self.dest_dir = dest_dir
- self.threads = 1
- self.logger = Logger(log_file)
- self.counter = 0
- self.force = 0
- self.cache = Cache(self.dest_dir)
-
- self.scheme = GrapherScheme()
- self.width = self.scheme.width
- self.height = self.scheme.height
- self.bg_color = self.scheme.bg_color
- self.color_scheme = self.scheme.color_scheme
- self.force = self.scheme.force
- self.threads = self.scheme.threads
- self.logger = Logger(log_file)
- self.counter = 0
- self.collection_name = 'awdio'
- self.collection = self.set_collection(self.collection_name)
-
- self.analyzers = timeside.core.processors(timeside.api.IAnalyzer)
- self.grapher = timeside.grapher.WaveformAwdio(width=self.width,
- height=self.height,
- bg_color=self.bg_color,
- color_scheme=self.color_scheme)
-
-
- def set_collection(self, collection_name):
- import telemeta.models
- collections = telemeta.models.media.MediaCollection.objects.filter(code=collection_name)
- if not collections:
- c = telemeta.models.media.MediaCollection(code=collection_name)
- c.title = collection_name
- c.save()
- msg = 'added'
- self.logger.logger.info(collection_name, msg)
- collection = c
- else:
- collection = collections[0]
- return collection
-
- def process(self):
- import telemeta.models
- keys = fs.keys()
- if keys[0] == 'file':
- filename = fs['file'].value
- media_orig = orig_media_dir + os.sep + filename
- media = self.root_dir + os.sep + filename
-
- if not os.path.exists(media):
- shutil.copy(media_orig, media)
- os.system('chmod 644 ' + media)
-
- name, ext = os.path.splitext(filename)
- size = str(self.width) + '_' + str(self.height)
- image_name = name + '.' + self.scheme.id + '.' + size + '.png'
- image = self.dest_dir + os.sep + image_name
- xml = name + '.xml'
-
- if not self.cache.exists(image_name) or not self.cache.exists(xml):
- mess = 'Processing ' + media
- self.logger.logger.info(mess)
-
- print "Content-type: text/plain\n"
- print mess
- decoder = timeside.decoder.FileDecoder(media)
- pipe = decoder | self.grapher
- analyzers = []
- analyzers_sub = []
- for analyzer in self.analyzers:
- subpipe = analyzer()
- analyzers_sub.append(subpipe)
- pipe = pipe | subpipe
- pipe.run()
-
- mess = 'Rendering ' + image
- self.logger.logger.info(mess)
- self.grapher.render(output=image)
-
- mess = 'Frames / Pixel = ' + str(self.grapher.graph.samples_per_pixel)
- self.logger.logger.info(mess)
-
- for analyzer in analyzers_sub:
- value = analyzer.result()
- if analyzer.id() == 'duration':
- value = datetime.timedelta(0,value)
- analyzers.append({'name':analyzer.name(),
- 'id':analyzer.id(),
- 'unit':analyzer.unit(),
- 'value':str(value)})
-
- self.cache.write_analyzer_xml(analyzers, xml)
-
- item = telemeta.models.media.MediaItem.objects.filter(code=name)
-
- if not item:
- item = telemeta.models.media.MediaItem(collection=self.collection, code=name)
- item.title = name
- item.file = self.media_item_dir + os.sep + filename
- item.save()
- msg = 'added item : ' + filename
- self.logger.logger.info(self.collection_name, msg)
-
- pipe = 0
- decoder = 0
-
- print "OK"
-
- #except:
- #pipe = 0
- #decoder = 0
- #mess = 'Could NOT process : ' + media
- #self.logger.logger.error(mess)
- #print mess
-
- else:
- mess = "Nothing to do with file : " + media
- self.logger.logger.info(mess)
- print "Content-type: text/plain\n"
- print mess
-
- else:
- print "Content-type: text/plain\n"
- print "No file given !"
-
-
-if __name__ == '__main__':
- sys.path.append(project_dir)
- import settings
- setup_environ(settings)
- media_dir = settings.MEDIA_ROOT
- data_dir = settings.TELEMETA_DATA_CACHE_DIR
- t = TelemetaPreprocessImport(media_dir, data_dir, log_file)
- t.process()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-version = '0.2'
-
-import os
-import sys
-import timeside
-
-
-class GrapherScheme:
-
- def __init__(self):
-
- self.color_scheme = {
- 'waveform': [
- # Four (R,G,B) tuples for three main color channels for the spectral centroid method
- (30,144,255), (30,144,255), (30,144,255), (30,144,255)
- ],
- 'spectrogram': [
- (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2),
- (90,180,100), (224,224,44), (255,60,30), (255,255,255)
- ]}
-
- # Width of the image
- self.width = 925
-
- # Height of the image
- self.height = 67
-
- # Background color
- self.bg_color = (-1, -1, -1, -1)
-
- # Force computation. By default, the class doesn't overwrite existing image files.
- self.force = True
-
-
-class Media2Waveform(object):
-
- def __init__(self, media_dir, img_dir):
- self.root_dir = os.path.join(os.path.dirname(__file__), media_dir)
- self.img_dir = os.path.join(os.path.dirname(__file__), img_dir)
- self.scheme = GrapherScheme()
- self.width = self.scheme.width
- self.height = self.scheme.height
- self.bg_color = self.scheme.bg_color
- self.color_scheme = self.scheme.color_scheme
- self.force = self.scheme.force
-
- self.media_list = self.get_media_list()
- if not os.path.exists(self.img_dir):
- os.makedirs(self.img_dir)
- self.path_dict = self.get_path_dict()
-
- def get_media_list(self):
- media_list = []
- for root, dirs, files in os.walk(self.root_dir):
- if root:
- for file in files:
- ext = file.split('.')[-1]
- if not file[0] == '.':
- media_list.append(root+os.sep+file)
- return media_list
-
- def get_path_dict(self):
- path_dict = {}
- for media in self.media_list:
- filename = media.split(os.sep)[-1]
- name, ext = os.path.splitext(filename)
- path_dict[media] = self.img_dir + os.sep + filename.replace('.', '_') + '.png'
- return path_dict
-
- def process(self):
- waveform = timeside.grapher.Waveform(width=self.width, height=self.height,
- bg_color=self.bg_color, color_scheme=self.color_scheme)
- for source, image in self.path_dict.iteritems():
- if not os.path.exists(image) or self.force:
- print 'Processing ', source
- audio = os.path.join(os.path.dirname(__file__), source)
- decoder = timeside.decoder.FileDecoder(audio)
- duration = decoder.duration
- (decoder | waveform).run()
- img_name = os.path.split(image)[1]
- image = os.path.split(image)[0]+os.sep+os.path.splitext(img_name)[0] + '_' +\
- '_'.join([str(self.width), str(self.height),
- str(int(duration))])+os.path.splitext(img_name)[1]
- waveform.graph.filename = image
- print 'Rendering ', waveform.graph.filename
- #print 'frames per pixel = ', waveform.graph.samples_per_pixel
- waveform.render(output=image)
-
-
-if __name__ == '__main__':
- if len(sys.argv) <= 1:
- print """
- TimeSide simple waveform generator
-
- Usage : python waveform_batch.py /path/to/media_dir /path/to/img_dir
-
- Dependencies : timeside, python, python-numpy, python-gst0.10, gstreamer0.10-plugins-base
- See http://code.google.com/p/timeside/ for more information.
- """
- else:
- media_dir = sys.argv[-2]
- img_dir = sys.argv[-1]
- m = Media2Waveform(media_dir, img_dir)
- m.process()
+++ /dev/null
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2009-2010 Guillaume Pellerin <yomguy@parisson.com>
-
-# This file is part of TimeSide.
-
-# TimeSide is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-
-# TimeSide is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with TimeSide. If not, see <http://www.gnu.org/licenses/>.
-
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-version = '0.3'
-
-import os
-import sys
-import time
-import timeside
-from logger import Logger
-import Queue
-from threading import Thread
-
-class GrapherScheme:
-
- def __init__(self):
- self.color = 255
- self.color_scheme = {
- 'waveform': [ # Four (R,G,B) tuples for three main color channels for the spectral centroid method
- (self.color,self.color,self.color)
-# (0, 0, 0), (0, 0, 0), (0, 0, 0), (0,0,0)
- ],
- 'spectrogram': [
- (0, 0, 0), (58/4,68/4,65/4), (80/2,100/2,153/2), (90,180,100), (224,224,44), (255,60,30), (255,255,255)
- ]}
-
- # Grapher id
- self.id = 'waveform_awdio'
-
- # Width of the image
- self.width = 1800
-
- # Height of the image
- self.height = 233
-
- # Background color
- self.bg_color = None
-
- # Force computation. By default, the class doesn't overwrite existing image files.
- self.force = False
-
- # Nb of threads
- # FIXME: memory leak for > 1 !
- self.threads = 1
-
-
-class Media2Waveform(object):
-
- def __init__(self, media_dir, img_dir, log_file):
- self.root_dir = os.path.join(os.path.dirname(__file__), media_dir)
- self.img_dir = os.path.join(os.path.dirname(__file__), img_dir)
- self.scheme = GrapherScheme()
- self.width = self.scheme.width
- self.height = self.scheme.height
- self.bg_color = self.scheme.bg_color
- self.color_scheme = self.scheme.color_scheme
- self.force = self.scheme.force
- self.threads = self.scheme.threads
- self.logger = Logger(log_file)
- self.counter = 0
-
- self.media_list = self.get_media_list()
- if not os.path.exists(self.img_dir):
- os.makedirs(self.img_dir)
- self.path_dict = self.get_path_dict()
-
- def get_media_list(self):
- media_list = []
- for root, dirs, files in os.walk(self.root_dir):
- if root:
- for file in files:
- if file[0] != '.':
- ext = file.split('.')[-1]
- media_list.append(root+os.sep+file)
- return media_list
-
- def get_path_dict(self):
- path_dict = {}
- for media in self.media_list:
- filename = media.split(os.sep)[-1]
- name, ext = os.path.splitext(filename)
- size = str(self.width) + '_' + str(self.height)
- image = self.img_dir + os.sep + name + '.' + self.scheme.id + '.' + size + '.png'
- if not os.path.exists(image) or self.force:
- path_dict[media] = image
- return path_dict
-
- def process(self):
- q = Queue.Queue()
- for i in range(0, self.threads):
- worker = Thread(target=Worker, args=(self.width, self.height, self.bg_color, self.color_scheme, q, self.logger))
- worker.setDaemon(True)
- worker.start()
-
- mess = str(self.threads) + ' thread(s) started'
- self.logger.write_info(mess)
-
- for media, image in self.path_dict.iteritems():
- q.put((media, image))
- q.join()
-
-
-def Worker(width, height, bg_color, color_scheme, q, logger):
- while True:
- media, image = q.get()
- mess = 'Processing ' + media
- logger.write_info(mess)
- decoder = timeside.decoder.FileDecoder(media)
- grapher = timeside.grapher.WaveformAwdio(width=width, height=height, bg_color=bg_color, color_scheme=color_scheme)
- (decoder | grapher).run()
- mess = 'Rendering ' + image
- logger.write_info(mess)
- grapher.render(output=image)
- mess = 'Frames / Pixel = ' + str(grapher.graph.samples_per_pixel)
- logger.write_info(mess)
- grapher.release()
- q.task_done()
-
-if __name__ == '__main__':
- if len(sys.argv) <= 2:
- print """
- Usage : python waveform_batch /path/to/media_dir /path/to/img_dir
-
- Dependencies : timeside, python, python-numpy, python-gst0.10, gstreamer0.10-plugins-base
- See http://code.google.com/p/timeside/ for more information.
- """
- else:
- media_dir = sys.argv[-3]
- img_dir = sys.argv[-2]
- log_file = sys.argv[-1]
- m = Media2Waveform(media_dir, img_dir, log_file)
- m.process()