diff --git a/beetsplug/echonest.py b/beetsplug/echonest.py index 6403c7b64..481ba26fd 100644 --- a/beetsplug/echonest.py +++ b/beetsplug/echonest.py @@ -36,6 +36,7 @@ RETRY_INTERVAL = 10 DEVNULL = open(os.devnull, 'wb') ALLOWED_FORMATS = ('MP3', 'OGG', 'AAC') +UPLOAD_MAX_SIZE = 50 * 1024 * 1024 # The attributes we can import and where to store them in beets fields. ATTRIBUTES = { @@ -111,6 +112,7 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): 'codegen': None, 'upload': True, 'convert': True, + 'truncate': True, }) self.config.add(ATTRIBUTES) @@ -310,6 +312,36 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): ) return dest + def truncate(self, item): + """Truncates an item to a size less than UPLOAD_MAX_SIZE.""" + fd, dest = tempfile.mkstemp(u'.ogg') + os.close(fd) + source = item.path + + log.info(u'echonest: truncating {0} to {1}'.format( + util.displayable_path(source), + util.displayable_path(dest), + )) + + command = u'ffmpeg -t 300 -i $source -y -acodec copy $dest' + opts = [] + for arg in command.split(): + arg = arg.encode('utf-8') + opts.append(Template(arg).substitute(source=source, dest=dest)) + + # Run the command. + try: + util.command_output(opts) + except (OSError, subprocess.CalledProcessError) as exc: + log.debug(u'echonest: truncate failed: {0}'.format(exc)) + util.remove(dest) + return + + log.info(u'echonest: truncate encoding {0}'.format( + util.displayable_path(source)) + ) + return dest + def analyze(self, item): """Upload the item to the EchoNest for analysis. May require to convert the item to a supported media format. @@ -326,6 +358,15 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): else: return + if os.stat(item.path).st_size > UPLOAD_MAX_SIZE: + if config['echonest']['truncate']: + source = self.convert(item) + if not source: + log.debug(u'echonest: failed to truncate file') + return + else: + return + # Upload the audio file. log.info(u'echonest: uploading file, please be patient') track = self._echofun(pyechonest.track.track_from_filename, diff --git a/docs/changelog.rst b/docs/changelog.rst index 00d633850..7bd6552a7 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -16,7 +16,7 @@ New stuff: * :doc:`/plugins/lyrics`: Lyrics should now be found for more songs. Searching is now sensitive to featured artists and parenthesized title suffixes. When a song has multiple titles, lyrics from all the named songs are now - concatenated. Thanks to Fabrice Laporte and Paul Phillips. + concatenated. Thanks to Fabrice Laporte and Paul Phillips. * Add support for `initial_key` as field in the library and tag for media files. When the user sets this field with ``beet modify initial_key=Am`` the media files will reflect this in their tags. The @@ -28,6 +28,8 @@ New stuff: Fixes: +* :doc:`/plugins/echonest`: Truncate files larger than 50MB before uploading for + analysis. * :doc:`/plugins/fetchart`: Fix a crash when the server does not specify a content type. Thanks to Lee Reinhardt. * :doc:`/plugins/convert`: The ``--keep-new`` flag now works correctly diff --git a/docs/plugins/echonest.rst b/docs/plugins/echonest.rst index b1d7e8240..0c2481d3a 100644 --- a/docs/plugins/echonest.rst +++ b/docs/plugins/echonest.rst @@ -71,13 +71,21 @@ can not be identified by other means. If you don't want that, disable the echonest: upload: no -The Echo Nest server only supports a limited range of file formats. The -``plugin`` automatically converts unsupported files to ``ogg``. If you don't -want that, disable the ``convert`` config option like so:: +The Echo Nest server only supports a limited range of file formats. The plugin +automatically converts unsupported files to ``ogg``. If you don't want that, +disable the ``convert`` config option like so:: echonest: convert: no +The Echo Nest server does not allow uploading of files with sizes greater than +50MB. The plugin automatically truncates large files to their first 5 +minutes. If you don't want that, disable the ``truncate`` config option like +so:: + + echonest: + truncate: no + To enable fingerprinting, you'll need to tell the plugin where to find the Echoprint or ENMFP codegen binary. Use the ``codegen`` key under the ``echonest`` section like so::