Ejemplo n.º 1
0
    def transcode(self, media_in, media_out, encoder_string=''):
        # get file locators for input/output media
        selector   = VolumeSelector()
        volume_in  = selector.backend_for(selector.scheme(media_in.private_url))()
        volume_out = selector.backend_for(selector.scheme(media_out.private_url))()

        # copy input file into output
        with volume_in.open(media_in.private_url, 'rb') as i:
            volume_out.save(media_out.private_url, i)
Ejemplo n.º 2
0
    def transcode(self, media_in, media_out, encoder_string=''):
        """
        Transcodes ``media_in`` using ffmpeg with the profile specified by ``encoder_string``
        and saves the transcoded media to the private url of ``media_out``.

        This method is asynchronous and only returns the task identifier. Current progress status
        can be obtained with the tasks api.

        .. note:: Transcoding relies on both ``ffmpeg`` and ``ffprobe`` binaries; those should be
           available by the ``PATH`` variable.
        """
        # get file locators for input/output media
        selector = VolumeSelector()
        volume = selector.backend_for(selector.scheme(media_in.private_url))()

        try:
            # try to access input file from absolute path
            input_file = volume.path(media_in.private_url)
        except NotImplementedError:
            try:
                # try to access input file from url 
                input_file = 'cache:' + volume.url(media_in.private_url)
            except NotImplementedError:
                # since we can't user neither path nor url, we'll
                # copy the input file to a local temporary file
                with volume.open(media_in.private_url) as f:
                    input_file = self._local_copy(f)

        # write the output file to a temporary file
        _, output_file = tempfile.mkstemp()

        # start ffmpeg task
        return self._start_ffmpeg_task(input_file, output_file, encoder_string, media_out)
Ejemplo n.º 3
0
    def _handle_ffmpeg_complete(self, ffmpeg_proc, output_info):
        """
        Handles the termination of a ffmpeg task.
        """
        status_code = ffmpeg_proc.poll()
        if status_code == 0:
            # copy the transcoded file to the output media's private_url
            private_url = output_info['media'].private_url
            selector = VolumeSelector()
            volume = selector.backend_for(selector.scheme(private_url))()
            try:
                os.rename(output_info['filename'], volume(private_url).path)
            except NotImplementedError:
                with open(output_info['filename'], 'rb') as f:
                    volume.save(private_url, f)
            output_info['media'].status = 'ready'
        else:
            output_info['media'].status = 'failed'
        output_info['media'].save()

        cache.set('task_ffmpeg_{0}'.format(ffmpeg_proc.pid), {
            'eta': 0,
            'progress' : 100
        })

        logger.info('ffmpeg job [%i] exited with status %i' % (ffmpeg_proc.pid, status_code))
Ejemplo n.º 4
0
    def publish(self, media, public_name):
        if media.public_url:
            raise ValueError("%(media)s is already published on %(url)s" % {
                'media': str(media),
                'url': media.public_url
            })

        selector = VolumeSelector()
        volume = selector.backend_for(selector.scheme(media.private_url))()

        try:
            private_path = volume.path(media.private_url)
            symlink = True
        except NotImplementedError:
            with volume.open(media.private_url) as f:
                private_path = self._local_copy(f)
            symlink = False

        # check that the publication path doesn't override an existing file
        publication_path = safe_join(self.root, public_name)
        if os.path.exists(publication_path):
            raise ValueError("The publication path is not available.")

        # create any intermediate directories to the publication path that do not exist
        directory = os.path.dirname(publication_path)
        if not os.path.exists(directory):
            try:
                if self.directory_permissions_mode is not None:
                    # os.makedirs applies the global umask, so we reset it,
                    # for consistency with file_permissions_mode behavior.
                    old_umask = os.umask(0)
                    try:
                        os.makedirs(directory, self.directory_permissions_mode)
                    finally:
                        os.umask(old_umask)
                else:
                    os.makedirs(directory)
            except OSError as e:
                if e.errno != errno.EEXIST:
                    raise
        if not os.path.isdir(directory):
            raise IOError("%s exists and is not a directory." % directory)

        # create a symlink or a copy to the file being published
        if symlink:
            os.symlink(private_path, publication_path)
        else:
            os.rename(private_path, publication_path)

        # compute and return publication url
        media.public_url = urljoin(self.base_url, public_name)
        media.save()
        return media.public_url
Ejemplo n.º 5
0
    def clean(self):
        # try to guess the media type if not provided
        if not self.media_type and self.private_url:
            from meho.core.volumes import VolumeSelector
            from mimetypes import guess_type

            selector = VolumeSelector()
            volume = selector.backend_for(selector.scheme(self.private_url))()
            mime, encoding = guess_type(volume.filename(self.private_url))
            if mime:
                self.media_type = mime
            if encoding:
                self.media_type += '; ' if mime else ''
                self.media_type += encoding