Пример #1
0
    def transcode(self, quality=None):
        if not quality:
            quality = self.audio_config['quality']

        if self._skip_processing('webm_audio', quality=quality):
            return

        progress_callback = ProgressCallback(self.entry)
        webm_audio_tmp = os.path.join(
            self.workbench.dir, self.name_builder.fill('{basename}{ext}'))

        self.transcoder.transcode(self.process_filename,
                                  webm_audio_tmp,
                                  quality=quality,
                                  progress_callback=progress_callback)

        self.transcoder.discover(webm_audio_tmp)

        self._keep_best()

        _log.debug('Saving medium...')
        store_public(self.entry, 'webm_audio', webm_audio_tmp,
                     self.name_builder.fill('{basename}.medium.webm'))

        self.entry.set_file_metadata('webm_audio', **{'quality': quality})
Пример #2
0
    def transcode(self, medium_size=None, vp8_quality=None, vp8_threads=None,
                  vorbis_quality=None):
        progress_callback = ProgressCallback(self.entry)
        tmp_dst = os.path.join(self.workbench.dir,
                               self.name_builder.fill('{basename}.medium.webm'))

        if not medium_size:
            medium_size = (
                mgg.global_config['media:medium']['max_width'],
                mgg.global_config['media:medium']['max_height'])
        if not vp8_quality:
            vp8_quality = self.video_config['vp8_quality']
        if not vp8_threads:
            vp8_threads = self.video_config['vp8_threads']
        if not vorbis_quality:
            vorbis_quality = self.video_config['vorbis_quality']

        file_metadata = {'medium_size': medium_size,
                         'vp8_threads': vp8_threads,
                         'vp8_quality': vp8_quality,
                         'vorbis_quality': vorbis_quality}

        if self._skip_processing('webm_video', **file_metadata):
            return

        # Extract metadata and keep a record of it
        metadata = self.transcoder.discover(self.process_filename)
        store_metadata(self.entry, metadata)

        # Figure out whether or not we need to transcode this video or
        # if we can skip it
        if skip_transcode(metadata, medium_size):
            _log.debug('Skipping transcoding')

            dst_dimensions = metadata['videowidth'], metadata['videoheight']

            # If there is an original and transcoded, delete the transcoded
            # since it must be of lower quality then the original
            if self.entry.media_files.get('original') and \
               self.entry.media_files.get('webm_video'):
                self.entry.media_files['webm_video'].delete()

        else:
            self.transcoder.transcode(self.process_filename, tmp_dst,
                                      vp8_quality=vp8_quality,
                                      vp8_threads=vp8_threads,
                                      vorbis_quality=vorbis_quality,
                                      progress_callback=progress_callback,
                                      dimensions=tuple(medium_size))

            dst_dimensions = self.transcoder.dst_data.videowidth,\
                self.transcoder.dst_data.videoheight

            self._keep_best()

            # Push transcoded video to public storage
            _log.debug('Saving medium...')
            store_public(self.entry, 'webm_video', tmp_dst,
                         self.name_builder.fill('{basename}.medium.webm'))
            _log.debug('Saved medium')

            self.entry.set_file_metadata('webm_video', **file_metadata)

            self.did_transcode = True

        # Save the width and height of the transcoded video
        self.entry.media_data_init(
            width=dst_dimensions[0],
            height=dst_dimensions[1])
Пример #3
0
    def transcode(self, medium_size=None, vp8_quality=None, vp8_threads=None,
                  vorbis_quality=None):
        progress_callback = ProgressCallback(self.entry)
        tmp_dst = os.path.join(self.workbench.dir, self.part_filename)

        if not medium_size:
            medium_size = (
                mgg.global_config['media:medium']['max_width'],
                mgg.global_config['media:medium']['max_height'])
        if not vp8_quality:
            vp8_quality = self.video_config['vp8_quality']
        if not vp8_threads:
            vp8_threads = self.video_config['vp8_threads']
        if not vorbis_quality:
            vorbis_quality = self.video_config['vorbis_quality']

        file_metadata = {'medium_size': medium_size,
                         'vp8_threads': vp8_threads,
                         'vp8_quality': vp8_quality,
                         'vorbis_quality': vorbis_quality}

        if self._skip_processing(self.curr_file, **file_metadata):
            return

        metadata = transcoders.discover(self.process_filename)
        orig_dst_dimensions = (metadata.get_video_streams()[0].get_width(),
                               metadata.get_video_streams()[0].get_height())

        # Figure out whether or not we need to transcode this video or
        # if we can skip it
        if skip_transcode(metadata, medium_size):
            _log.debug('Skipping transcoding')

            # If there is an original and transcoded, delete the transcoded
            # since it must be of lower quality then the original
            if self.entry.media_files.get('original') and \
               self.entry.media_files.get(self.curr_file):
                self.entry.media_files[self.curr_file].delete()

        else:
            _log.debug('Entered transcoder')
            video_config = (mgg.global_config['plugins']
                            ['mediagoblin.media_types.video'])
            num_res = len(video_config['available_resolutions'])
            default_res = video_config['default_resolution']
            self.transcoder.transcode(self.process_filename, tmp_dst,
                                      default_res, num_res,
                                      vp8_quality=vp8_quality,
                                      vp8_threads=vp8_threads,
                                      vorbis_quality=vorbis_quality,
                                      progress_callback=progress_callback,
                                      dimensions=tuple(medium_size))
            if self.transcoder.dst_data:
                # Push transcoded video to public storage
                _log.debug('Saving medium...')
                store_public(self.entry, self.curr_file, tmp_dst, self.part_filename)
                _log.debug('Saved medium')

                self.entry.set_file_metadata(self.curr_file, **file_metadata)

                self.did_transcode = True
Пример #4
0
def process_video(proc_state):
    """
    Process a video entry, transcode the queued media files (originals) and
    create a thumbnail for the entry.

    A Workbench() represents a local tempory dir. It is automatically
    cleaned up when this function exits.
    """
    entry = proc_state.entry
    workbench = proc_state.workbench
    video_config = mgg.global_config['media_type:mediagoblin.media_types.video']

    queued_filepath = entry.queued_media_file
    queued_filename = proc_state.get_queued_filename()
    name_builder = FilenameBuilder(queued_filename)

    medium_basename = name_builder.fill('{basename}-640p.webm')
    medium_filepath = create_pub_filepath(entry, medium_basename)

    thumbnail_basename = name_builder.fill('{basename}.thumbnail.jpg')
    thumbnail_filepath = create_pub_filepath(entry, thumbnail_basename)

    # Create a temporary file for the video destination (cleaned up with workbench)
    tmp_dst = os.path.join(workbench.dir, medium_basename)
    # Transcode queued file to a VP8/vorbis file that fits in a 640x640 square
    progress_callback = ProgressCallback(entry)

    dimensions = (
        mgg.global_config['media:medium']['max_width'],
        mgg.global_config['media:medium']['max_height'])

    # Extract metadata and keep a record of it
    metadata = transcoders.VideoTranscoder().discover(queued_filename)
    store_metadata(entry, metadata)

    # Figure out whether or not we need to transcode this video or
    # if we can skip it
    if skip_transcode(metadata):
        _log.debug('Skipping transcoding')

        dst_dimensions = metadata['videowidth'], metadata['videoheight']

            # Push original file to public storage
        _log.debug('Saving original...')
        proc_state.copy_original(queued_filepath[-1])

        did_transcode = False
    else:
        transcoder = transcoders.VideoTranscoder()

        transcoder.transcode(queued_filename, tmp_dst,
                vp8_quality=video_config['vp8_quality'],
                vp8_threads=video_config['vp8_threads'],
                vorbis_quality=video_config['vorbis_quality'],
                progress_callback=progress_callback,
                dimensions=dimensions)

        dst_dimensions = transcoder.dst_data.videowidth,\
            transcoder.dst_data.videoheight

        # Push transcoded video to public storage
        _log.debug('Saving medium...')
        mgg.public_store.copy_local_to_storage(tmp_dst, medium_filepath)
        _log.debug('Saved medium')

        entry.media_files['webm_640'] = medium_filepath

        did_transcode = True

    # Save the width and height of the transcoded video
    entry.media_data_init(
        width=dst_dimensions[0],
        height=dst_dimensions[1])

    # Temporary file for the video thumbnail (cleaned up with workbench)
    tmp_thumb = os.path.join(workbench.dir, thumbnail_basename)

    # Create a thumbnail.jpg that fits in a 180x180 square
    transcoders.VideoThumbnailerMarkII(
        queued_filename,
        tmp_thumb,
        180)

    # Push the thumbnail to public storage
    _log.debug('Saving thumbnail...')
    mgg.public_store.copy_local_to_storage(tmp_thumb, thumbnail_filepath)
    entry.media_files['thumb'] = thumbnail_filepath

    # save the original... but only if we did a transcoding
    # (if we skipped transcoding and just kept the original anyway as the main
    #  media, then why would we save the original twice?)
    if video_config['keep_original'] and did_transcode:
        # Push original file to public storage
        _log.debug('Saving original...')
        proc_state.copy_original(queued_filepath[-1])

    # Remove queued media file from storage and database
    proc_state.delete_queue_file()
Пример #5
0
def process_audio(proc_state):
    """Code to process uploaded audio. Will be run by celery.

    A Workbench() represents a local tempory dir. It is automatically
    cleaned up when this function exits.
    """
    entry = proc_state.entry
    workbench = proc_state.workbench
    audio_config = mgg.global_config[
        'media_type:mediagoblin.media_types.audio']

    queued_filepath = entry.queued_media_file
    queued_filename = workbench.localized_file(mgg.queue_store,
                                               queued_filepath, 'source')
    name_builder = FilenameBuilder(queued_filename)

    webm_audio_filepath = create_pub_filepath(
        entry, '{original}.webm'.format(
            original=os.path.splitext(queued_filepath[-1])[0]))

    if audio_config['keep_original']:
        with open(queued_filename, 'rb') as queued_file:
            original_filepath = create_pub_filepath(
                entry, name_builder.fill('{basename}{ext}'))

            with mgg.public_store.get_file(original_filepath, 'wb') as \
                    original_file:
                _log.debug('Saving original...')
                original_file.write(queued_file.read())

            entry.media_files['original'] = original_filepath

    transcoder = AudioTranscoder()

    with NamedTemporaryFile(dir=workbench.dir) as webm_audio_tmp:
        progress_callback = ProgressCallback(entry)

        transcoder.transcode(queued_filename,
                             webm_audio_tmp.name,
                             quality=audio_config['quality'],
                             progress_callback=progress_callback)

        transcoder.discover(webm_audio_tmp.name)

        _log.debug('Saving medium...')
        mgg.public_store.get_file(webm_audio_filepath,
                                  'wb').write(webm_audio_tmp.read())

        entry.media_files['webm_audio'] = webm_audio_filepath

        # entry.media_data_init(length=int(data.audiolength))

    if audio_config['create_spectrogram']:
        spectrogram_filepath = create_pub_filepath(
            entry, '{original}-spectrogram.jpg'.format(
                original=os.path.splitext(queued_filepath[-1])[0]))

        with NamedTemporaryFile(dir=workbench.dir, suffix='.ogg') as wav_tmp:
            _log.info('Creating OGG source for spectrogram')
            transcoder.transcode(
                queued_filename,
                wav_tmp.name,
                mux_string='vorbisenc quality={0} ! oggmux'.format(
                    audio_config['quality']))

            thumbnailer = AudioThumbnailer()

            with NamedTemporaryFile(dir=workbench.dir,
                                    suffix='.jpg') as spectrogram_tmp:
                thumbnailer.spectrogram(
                    wav_tmp.name,
                    spectrogram_tmp.name,
                    width=mgg.global_config['media:medium']['max_width'],
                    fft_size=audio_config['spectrogram_fft_size'])

                _log.debug('Saving spectrogram...')
                mgg.public_store.get_file(spectrogram_filepath,
                                          'wb').write(spectrogram_tmp.read())

                entry.media_files['spectrogram'] = spectrogram_filepath

                with NamedTemporaryFile(dir=workbench.dir,
                                        suffix='.jpg') as thumb_tmp:
                    thumbnailer.thumbnail_spectrogram(
                        spectrogram_tmp.name, thumb_tmp.name,
                        (mgg.global_config['media:thumb']['max_width'],
                         mgg.global_config['media:thumb']['max_height']))

                    thumb_filepath = create_pub_filepath(
                        entry, '{original}-thumbnail.jpg'.format(
                            original=os.path.splitext(queued_filepath[-1])[0]))

                    mgg.public_store.get_file(thumb_filepath,
                                              'wb').write(thumb_tmp.read())

                    entry.media_files['thumb'] = thumb_filepath
    else:
        entry.media_files['thumb'] = ['fake', 'thumb', 'path.jpg']

    # Remove queued media file from storage and database.
    # queued_filepath is in the task_id directory which should
    # be removed too, but fail if the directory is not empty to be on
    # the super-safe side.
    mgg.queue_store.delete_file(queued_filepath)  # rm file
    mgg.queue_store.delete_dir(queued_filepath[:-1])  # rm dir
    entry.queued_media_file = []