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)
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))
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)
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
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