Esempio n. 1
0
def _cat_m4a(audio_resources):
    filenames = [
        get_generated_filename(resource.blob.href, 'audio/mp4', None, resource)
        for resource in audio_resources
    ]

    # join the audio files into one
    tmpdir = mkdtemp()

    def delete_tmpdir(filename=None):
        rmtree(tmpdir, ignore_errors=True)

    output_filename = os.path.join(tmpdir, "joined_audio.m4a")
    logger.info("Joining %d m4a files" % len(filenames))
    try:
        # MP4Box can concatenate a maximum of 20 files at a time, so we call it
        # repeatedly until everything is concatenated.
        from itertools import islice
        MAX_CUMUL_OPS = 20  # as defined in gpac/applications/mp4box/main.c
        i = iter(filenames)
        while True:
            current_filenames = list(islice(i, MAX_CUMUL_OPS))
            if not current_filenames:
                break
            cmd = [
                settings.MP4BOX_PATH, output_filename, '-tmp', tmpdir, '-cat'
            ] + _join_list(current_filenames, '-cat')
            subprocess.check_call(cmd)
    except Exception:
        delete_tmpdir()
        raise
    return iterate_file_then_delete(output_filename, delete_func=delete_tmpdir)
Esempio n. 2
0
def mediacache_audio(blob_urn, mime_type, additional_args, audio):
    if additional_args:
        return None
    if blob_urn != audio.blob.href:
        return None

    if mime_type == audio.blob.mime_type:
        return iter(audio.blob)

    input_suffix = '.' + mime_to_ext[audio.blob.mime_type]
    output_suffix = '.' + mime_to_ext[mime_type]
    try:
        cmd = AUDIO_CONVERSION_COMMANDS[(audio.blob.mime_type, mime_type)]
    except KeyError:
        return None # we don't support this converstion
    else:
        input_filename = iterator_to_tempfile(iter(audio.blob), suffix=input_suffix)
        try:
            tmpdir = mkdtemp()
            def delete_tmpdir(filename=None):
                rmtree(tmpdir, ignore_errors=True)
            output_filename = os.path.join(tmpdir, "audio" + output_suffix)
            logger.info("Converting %s to %s", input_filename, output_filename)
            cmd = cmd.format(input_filename=input_filename,
                             output_filename=output_filename)
            try:
                subprocess.check_call(cmd, shell=True)
            except Exception:
                delete_tmpdir()
                raise
            return iterate_file_then_delete(output_filename, delete_func=delete_tmpdir)
        finally:
            os.remove(input_filename)
Esempio n. 3
0
def _cat_m4a(audio_resources):
    filenames = [get_generated_filename(resource.blob.href, 'audio/mp4',
                                        None, resource)
                 for resource in audio_resources]

    # join the audio files into one
    tmpdir = mkdtemp()
    def delete_tmpdir(filename=None):
        rmtree(tmpdir, ignore_errors=True)
    output_filename = os.path.join(tmpdir, "joined_audio.m4a")
    logger.info("Joining %d m4a files" % len(filenames))
    try:
        # MP4Box can concatenate a maximum of 20 files at a time, so we call it
        # repeatedly until everything is concatenated.
        from itertools import islice
        MAX_CUMUL_OPS = 20  # as defined in gpac/applications/mp4box/main.c
        i = iter(filenames)
        while True:
            current_filenames = list(islice(i, MAX_CUMUL_OPS))
            if not current_filenames:
                break
            cmd = [settings.MP4BOX_PATH, output_filename, '-tmp', tmpdir, '-cat'] + _join_list(current_filenames, '-cat')
            subprocess.check_call(cmd)
    except Exception:
        delete_tmpdir()
        raise
    return iterate_file_then_delete(output_filename, delete_func=delete_tmpdir)
Esempio n. 4
0
def _cat_webm(audio_resources):
    """
    do the actual call to mkvmerge to concatenate audio files into a podcast.
    webm requires consistent vorbis codebooks in the embedded vorbis stream, if this is not the case,
    we fall back to ffmpeg to reencode the whole thing.
    (documentation about this is pretty limited, refer to mkvmerge sourcecode for details)
    """
    filenames = [get_generated_filename(resource.blob.href, 'audio/ogg',
                                        None, resource)
                 for resource in audio_resources]

    # join the audio files into one
    tmpdir = mkdtemp()
    def delete_tmpdir(filename=None):
        rmtree(tmpdir, ignore_errors=True)
    output_filename = os.path.join(tmpdir, "joined_audio.webm")
    logger.info("Joining %d ogg/vorbis files" % len(filenames))
    try:
        try:
            subprocess.check_call([settings.MKVMERGE_PATH, '-o', output_filename, '-w', '-q'] + _join_list(filenames, '+'))
        except subprocess.CalledProcessError as e:
            # webm format requires "compatible" vorbis codebooks in audio files, if not, we must reencode
            logger.info("couldn't merge files, reencoding the whole podcast")
            # there must be no space between 'concat:' and the first filename, so pass the args as a string
            files = 'concat:' + ''.join(_join_list(filenames, '|'))
            subprocess.check_call([settings.FFMPEG_PATH, '-i', files, '-y', '-aq', '3', output_filename])
    except Exception:
        delete_tmpdir()
        raise
    return iterate_file_then_delete(output_filename, delete_func=delete_tmpdir)
Esempio n. 5
0
 def __getitem__(self, key):
     try:
         return self.__cache[key]
     except Exception:
         data_iterator = self.__backing_store[key]
         # Cache it
         tmpfile = iterator_to_tempfile(data_iterator)
         self.__attempt_cache_save(key, tmpfile)
         return iterate_file_then_delete(tmpfile)
Esempio n. 6
0
 def __getitem__(self, key):
     for i, backend in enumerate(self.__backends):
         try:
             data_iterator = backend[key]
         except KeyError:
             pass
         else:
             if self.collect_resources and i > 0:
                 # Save a copy to the primary backend
                 tmpfile = iterator_to_tempfile(data_iterator)
                 try:
                     primary_backend = self.__backends[0]
                     primary_backend.put_file(key, tmpfile)
                 except Exception:
                     pass
                 data_iterator = iterate_file_then_delete(tmpfile)
             return data_iterator
     raise KeyError(key)
Esempio n. 7
0
    def wrapped_getitem(s, key):
        data_iterator = original_getitem(s, key)
        max_resource_size = getattr(s, "max_resource_size", (20*1024*1024))
        data_iterator = check_resource_size(data_iterator, max_resource_size)

        # Calculate hash and save to temporary file
        hash_obj = hash_algorithm()
        data_iterator = calculate_hash(data_iterator, hash_obj)
        tmpfile = iterator_to_tempfile(data_iterator)

        # Verify hash
        try:
            digest = hash_encode(hash_obj.digest())
            if key != "urn:%s:%s" % (hash_name, digest):
                raise "URN given does not match content." # valueerror
        except:
            os.remove(tmpfile)
            raise

        return iterate_file_then_delete(tmpfile)
Esempio n. 8
0
def _cat_webm(audio_resources):
    """
    do the actual call to mkvmerge to concatenate audio files into a podcast.
    webm requires consistent vorbis codebooks in the embedded vorbis stream, if this is not the case,
    we fall back to ffmpeg to reencode the whole thing.
    (documentation about this is pretty limited, refer to mkvmerge sourcecode for details)
    """
    filenames = [
        get_generated_filename(resource.blob.href, 'audio/ogg', None, resource)
        for resource in audio_resources
    ]

    # join the audio files into one
    tmpdir = mkdtemp()

    def delete_tmpdir(filename=None):
        rmtree(tmpdir, ignore_errors=True)

    output_filename = os.path.join(tmpdir, "joined_audio.webm")
    logger.info("Joining %d ogg/vorbis files" % len(filenames))
    try:
        try:
            subprocess.check_call(
                [settings.MKVMERGE_PATH, '-o', output_filename, '-w', '-q'] +
                _join_list(filenames, '+'))
        except subprocess.CalledProcessError as e:
            # webm format requires "compatible" vorbis codebooks in audio files, if not, we must reencode
            logger.info("couldn't merge files, reencoding the whole podcast")
            # there must be no space between 'concat:' and the first filename, so pass the args as a string
            files = 'concat:' + ''.join(_join_list(filenames, '|'))
            subprocess.check_call([
                settings.FFMPEG_PATH, '-i', files, '-y', '-aq', '3',
                output_filename
            ])
    except Exception:
        delete_tmpdir()
        raise
    return iterate_file_then_delete(output_filename, delete_func=delete_tmpdir)
Esempio n. 9
0
def mediacache_audio(blob_urn, mime_type, additional_args, audio):
    if additional_args:
        return None
    if blob_urn != audio.blob.href:
        return None

    if mime_type == audio.blob.mime_type:
        return iter(audio.blob)

    input_suffix = '.' + mime_to_ext[audio.blob.mime_type]
    output_suffix = '.' + mime_to_ext[mime_type]
    try:
        cmd = AUDIO_CONVERSION_COMMANDS[(audio.blob.mime_type, mime_type)]
    except KeyError:
        return None  # we don't support this converstion
    else:
        input_filename = iterator_to_tempfile(iter(audio.blob),
                                              suffix=input_suffix)
        try:
            tmpdir = mkdtemp()

            def delete_tmpdir(filename=None):
                rmtree(tmpdir, ignore_errors=True)

            output_filename = os.path.join(tmpdir, "audio" + output_suffix)
            logger.info("Converting %s to %s", input_filename, output_filename)
            cmd = cmd.format(input_filename=input_filename,
                             output_filename=output_filename)
            try:
                subprocess.check_call(cmd, shell=True)
            except Exception:
                delete_tmpdir()
                raise
            return iterate_file_then_delete(output_filename,
                                            delete_func=delete_tmpdir)
        finally:
            os.remove(input_filename)