فهرست منبع

Add ‘--prefer-avconv’ and ‘--prefer-ffmpeg’ options (#2115)

Affects the ffmpeg post processors, if ‘--prefer-ffmpeg’ is given and both avconv and ffmpeg are installed, it will use ffmpeg. Otherwise it will follow the old behaviour.
Jaime Marquínez Ferrándiz 11 سال پیش
والد
کامیت
76b1bd672d
3فایلهای تغییر یافته به همراه29 افزوده شده و 12 حذف شده
  1. 4 0
      youtube_dl/YoutubeDL.py
  2. 5 0
      youtube_dl/__init__.py
  3. 20 12
      youtube_dl/postprocessor/ffmpeg.py

+ 4 - 0
youtube_dl/YoutubeDL.py

@@ -156,6 +156,10 @@ class YoutubeDL(object):
     the FileDownloader:
     nopart, updatetime, buffersize, ratelimit, min_filesize, max_filesize, test,
     noresizebuffer, retries, continuedl, noprogress, consoletitle
+
+    The following options are used by the post processors:
+    prefer_ffmpeg:     If True, use ffmpeg instead of avconv if both are available,
+                       otherwise prefer avconv.
     """
 
     params = None

+ 5 - 0
youtube_dl/__init__.py

@@ -424,6 +424,10 @@ def parseOpts(overrideArguments=None):
             help='write metadata to the video file')
     postproc.add_option('--xattrs', action='store_true', dest='xattrs', default=False,
             help='write metadata to the video file\'s xattrs (using dublin core and xdg standards)')
+    postproc.add_option('--prefer-avconv', action='store_false', dest='prefer_ffmpeg',
+        help='Prefer avconv over ffmpeg for running the postprocessors (default)')
+    postproc.add_option('--prefer-ffmpeg', action='store_true', dest='prefer_ffmpeg',
+        help='Prefer ffmpeg over avconv for running the postprocessors')
 
 
     parser.add_option_group(general)
@@ -709,6 +713,7 @@ def _real_main(argv=None):
         'socket_timeout': opts.socket_timeout,
         'bidi_workaround': opts.bidi_workaround,
         'debug_printtraffic': opts.debug_printtraffic,
+        'prefer_ffmpeg': opts.prefer_ffmpeg,
     }
 
     with YoutubeDL(ydl_opts) as ydl:

+ 20 - 12
youtube_dl/postprocessor/ffmpeg.py

@@ -31,14 +31,23 @@ class FFmpegPostProcessor(PostProcessor):
         programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe']
         return dict((program, check_executable(program, ['-version'])) for program in programs)
 
+    def _get_executable(self):
+        if self._downloader.params.get('prefer_ffmpeg', False):
+            return self._exes['ffmpeg'] or self._exes['avconv']
+        else:
+            return self._exes['avconv'] or self._exes['ffmpeg']
+
+    def _uses_avconv(self):
+        return self._get_executable() == self._exes['avconv']
+
     def run_ffmpeg_multiple_files(self, input_paths, out_path, opts):
-        if not self._exes['ffmpeg'] and not self._exes['avconv']:
+        if not self._get_executable():
             raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.')
 
         files_cmd = []
         for path in input_paths:
             files_cmd.extend(['-i', encodeFilename(path, True)])
-        cmd = ([self._exes['avconv'] or self._exes['ffmpeg'], '-y'] + files_cmd
+        cmd = ([self._get_executable(), '-y'] + files_cmd
                + opts +
                [encodeFilename(self._ffmpeg_filename_argument(out_path), True)])
 
@@ -93,8 +102,6 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor):
         return None
 
     def run_ffmpeg(self, path, out_path, codec, more_opts):
-        if not self._exes['ffmpeg'] and not self._exes['avconv']:
-            raise AudioConversionError('ffmpeg or avconv not found. Please install one.')
         if codec is None:
             acodec_opts = []
         else:
@@ -112,13 +119,14 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor):
         if filecodec is None:
             raise PostProcessingError(u'WARNING: unable to obtain file audio codec with ffprobe')
 
+        uses_avconv = self._uses_avconv()
         more_opts = []
         if self._preferredcodec == 'best' or self._preferredcodec == filecodec or (self._preferredcodec == 'm4a' and filecodec == 'aac'):
             if filecodec == 'aac' and self._preferredcodec in ['m4a', 'best']:
                 # Lossless, but in another container
                 acodec = 'copy'
                 extension = 'm4a'
-                more_opts = [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']
+                more_opts = ['-bsf:a' if uses_avconv else '-absf', 'aac_adtstoasc']
             elif filecodec in ['aac', 'mp3', 'vorbis', 'opus']:
                 # Lossless if possible
                 acodec = 'copy'
@@ -134,9 +142,9 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor):
                 more_opts = []
                 if self._preferredquality is not None:
                     if int(self._preferredquality) < 10:
-                        more_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]
+                        more_opts += ['-q:a' if uses_avconv else '-aq', self._preferredquality]
                     else:
-                        more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']
+                        more_opts += ['-b:a' if uses_avconv else '-ab', self._preferredquality + 'k']
         else:
             # We convert the audio (lossy)
             acodec = {'mp3': 'libmp3lame', 'aac': 'aac', 'm4a': 'aac', 'opus': 'opus', 'vorbis': 'libvorbis', 'wav': None}[self._preferredcodec]
@@ -145,13 +153,13 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor):
             if self._preferredquality is not None:
                 # The opus codec doesn't support the -aq option
                 if int(self._preferredquality) < 10 and extension != 'opus':
-                    more_opts += [self._exes['avconv'] and '-q:a' or '-aq', self._preferredquality]
+                    more_opts += ['-q:a' if uses_avconv else '-aq', self._preferredquality]
                 else:
-                    more_opts += [self._exes['avconv'] and '-b:a' or '-ab', self._preferredquality + 'k']
+                    more_opts += ['-b:a' if uses_avconv else '-ab', self._preferredquality + 'k']
             if self._preferredcodec == 'aac':
                 more_opts += ['-f', 'adts']
             if self._preferredcodec == 'm4a':
-                more_opts += [self._exes['avconv'] and '-bsf:a' or '-absf', 'aac_adtstoasc']
+                more_opts += ['-bsf:a' if uses_avconv else '-absf', 'aac_adtstoasc']
             if self._preferredcodec == 'vorbis':
                 extension = 'ogg'
             if self._preferredcodec == 'wav':
@@ -169,14 +177,14 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor):
             if self._nopostoverwrites and os.path.exists(encodeFilename(new_path)):
                 self._downloader.to_screen(u'[youtube] Post-process file %s exists, skipping' % new_path)
             else:
-                self._downloader.to_screen(u'[' + (self._exes['avconv'] and 'avconv' or 'ffmpeg') + '] Destination: ' + new_path)
+                self._downloader.to_screen(u'[' + self._get_executable() + '] Destination: ' + new_path)
                 self.run_ffmpeg(path, new_path, acodec, more_opts)
         except:
             etype,e,tb = sys.exc_info()
             if isinstance(e, AudioConversionError):
                 msg = u'audio conversion failed: ' + e.msg
             else:
-                msg = u'error running ' + (self._exes['avconv'] and 'avconv' or 'ffmpeg')
+                msg = u'error running ' + self._get_executable()
             raise PostProcessingError(msg)
 
         # Try to update the date time for extracted audio file.