diff options
| author | Jaime Marquínez Ferrándiz <jaimemf93@gmail.com> | 2013-01-11 20:50:49 +0100 | 
|---|---|---|
| committer | Jaime Marquínez Ferrándiz <jaimemf93@gmail.com> | 2013-01-11 20:50:49 +0100 | 
| commit | 67d0c25eab1c425d22549a5d3437380a7740aec1 (patch) | |
| tree | bacf9abee85e327135e1be3ead583c8596d818a4 | |
| parent | 09f9552b409abba063de011a879e9fa94bf6f027 (diff) | |
Add a PostProcessor for converting video format
| -rw-r--r-- | youtube_dl/PostProcessor.py | 75 | ||||
| -rw-r--r-- | youtube_dl/__init__.py | 3 | 
2 files changed, 57 insertions, 21 deletions
diff --git a/youtube_dl/PostProcessor.py b/youtube_dl/PostProcessor.py index 79a0d7928..3d1093731 100644 --- a/youtube_dl/PostProcessor.py +++ b/youtube_dl/PostProcessor.py @@ -57,19 +57,17 @@ class PostProcessor(object):          """          return information # by default, do nothing +class FFmpegPostProcessorError(BaseException): +    def __init__(self, message): +        self.message = message +  class AudioConversionError(BaseException):      def __init__(self, message):          self.message = message -class FFmpegExtractAudioPP(PostProcessor): -    def __init__(self, downloader=None, preferredcodec=None, preferredquality=None, keepvideo=False, nopostoverwrites=False): +class FFmpegPostProcessor(PostProcessor): +    def __init__(self,downloader=None):          PostProcessor.__init__(self, downloader) -        if preferredcodec is None: -            preferredcodec = 'best' -        self._preferredcodec = preferredcodec -        self._preferredquality = preferredquality -        self._keepvideo = keepvideo -        self._nopostoverwrites = nopostoverwrites          self._exes = self.detect_executables()      @staticmethod @@ -83,6 +81,34 @@ class FFmpegExtractAudioPP(PostProcessor):          programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe']          return dict((program, executable(program)) for program in programs) +    def run_ffmpeg(self, path, out_path, opts): +        if not self._exes['ffmpeg'] and not self._exes['avconv']: +            raise FFmpegPostProcessorError('ffmpeg or avconv not found. Please install one.') +        cmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y', '-i', encodeFilename(path)] +               + opts + +               [encodeFilename(self._ffmpeg_filename_argument(out_path))]) +        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) +        stdout,stderr = p.communicate() +        if p.returncode != 0: +            msg = stderr.strip().split('\n')[-1] +            raise FFmpegPostProcessorError(msg) + +    def _ffmpeg_filename_argument(self, fn): +        # ffmpeg broke --, see https://ffmpeg.org/trac/ffmpeg/ticket/2127 for details +        if fn.startswith(u'-'): +            return u'./' + fn +        return fn + +class FFmpegExtractAudioPP(FFmpegPostProcessor): +    def __init__(self, downloader=None, preferredcodec=None, preferredquality=None, keepvideo=False, nopostoverwrites=False): +        FFmpegPostProcessor.__init__(self, downloader) +        if preferredcodec is None: +            preferredcodec = 'best' +        self._preferredcodec = preferredcodec +        self._preferredquality = preferredquality +        self._keepvideo = keepvideo +        self._nopostoverwrites = nopostoverwrites +      def get_audio_codec(self, path):          if not self._exes['ffprobe'] and not self._exes['avprobe']: return None          try: @@ -108,14 +134,11 @@ class FFmpegExtractAudioPP(PostProcessor):              acodec_opts = []          else:              acodec_opts = ['-acodec', codec] -        cmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y', '-i', encodeFilename(path), '-vn'] -               + acodec_opts + more_opts + -               [encodeFilename(self._ffmpeg_filename_argument(out_path))]) -        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) -        stdout,stderr = p.communicate() -        if p.returncode != 0: -            msg = stderr.strip().split('\n')[-1] -            raise AudioConversionError(msg) +        opts = ['-vn'] + acodec_opts + more_opts +        try: +            FFmpegPostProcessor.run_ffmpeg(self, path, out_path, opts) +        except FFmpegPostProcessorError as err: +            raise AudioConversionError(err.message)      def run(self, information):          path = information['filepath'] @@ -203,9 +226,19 @@ class FFmpegExtractAudioPP(PostProcessor):          information['filepath'] = new_path          return information -    def _ffmpeg_filename_argument(self, fn): -        # ffmpeg broke --, see https://ffmpeg.org/trac/ffmpeg/ticket/2127 for details -        if fn.startswith(u'-'): -            return u'./' + fn -        return fn +class FFmpegVideoConvertor(FFmpegPostProcessor): +    def __init__(self, downloader=None,preferedformat=None): +        FFmpegPostProcessor.__init__(self,downloader) +        self._preferedformat=preferedformat +    def run(self, information): +        path = information['filepath'] +        prefix, sep, ext = path.rpartition(u'.') +        outpath = prefix + sep + self._preferedformat +        if not self._preferedformat or information['format'] == self._preferedformat: +            return information +        self._downloader.to_screen(u'['+'ffmpeg'+'] Converting video from %s to %s, Destination: ' % (information['format'], self._preferedformat) +outpath) +        self.run_ffmpeg(path, outpath, []) +        information['filepath'] = outpath +        information['format'] = self._preferedformat +        return information diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index d7ab0f086..0d9053db3 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -455,6 +455,9 @@ def _real_main():      if opts.extractaudio:          fd.add_post_processor(FFmpegExtractAudioPP(preferredcodec=opts.audioformat, preferredquality=opts.audioquality, keepvideo=opts.keepvideo, nopostoverwrites=opts.nopostoverwrites)) +    if opts.format: +        fd.add_post_processor(FFmpegVideoConvertor(preferedformat=opts.format)) +      # Update version      if opts.update_self:          update_self(fd.to_screen, opts.verbose, sys.argv[0])  | 
