[ffmpeg] Warn if ffmpeg/avconv version is too old (Fixes #4026)
This commit is contained in:
		
							parent
							
								
									d28b517154
								
							
						
					
					
						commit
						488447455d
					
				| @ -1026,7 +1026,7 @@ class YoutubeDL(object): | |||||||
|                         downloaded = [] |                         downloaded = [] | ||||||
|                         success = True |                         success = True | ||||||
|                         merger = FFmpegMergerPP(self, not self.params.get('keepvideo')) |                         merger = FFmpegMergerPP(self, not self.params.get('keepvideo')) | ||||||
|                         if not merger._get_executable(): |                         if not merger._executable: | ||||||
|                             postprocessors = [] |                             postprocessors = [] | ||||||
|                             self.report_warning('You have requested multiple ' |                             self.report_warning('You have requested multiple ' | ||||||
|                                 'formats but ffmpeg or avconv are not installed.' |                                 'formats but ffmpeg or avconv are not installed.' | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ from ..utils import ( | |||||||
|     compat_subprocess_get_DEVNULL, |     compat_subprocess_get_DEVNULL, | ||||||
|     encodeArgument, |     encodeArgument, | ||||||
|     encodeFilename, |     encodeFilename, | ||||||
|  |     is_outdated_version, | ||||||
|     PostProcessingError, |     PostProcessingError, | ||||||
|     prepend_extension, |     prepend_extension, | ||||||
|     shell_quote, |     shell_quote, | ||||||
| @ -41,17 +42,29 @@ class FFmpegPostProcessorError(PostProcessingError): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class FFmpegPostProcessor(PostProcessor): | class FFmpegPostProcessor(PostProcessor): | ||||||
|     def __init__(self, downloader=None, deletetempfiles=False): |     def __init__(self, downloader, deletetempfiles=False): | ||||||
|         PostProcessor.__init__(self, downloader) |         PostProcessor.__init__(self, downloader) | ||||||
|         self._versions = self.get_versions() |         self._versions = self.get_versions() | ||||||
|         self._deletetempfiles = deletetempfiles |         self._deletetempfiles = deletetempfiles | ||||||
| 
 | 
 | ||||||
|  |     def check_version(self): | ||||||
|  |         if not self._executable: | ||||||
|  |             raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.') | ||||||
|  | 
 | ||||||
|  |         REQUIRED_VERSION = '1.0' | ||||||
|  |         if is_outdated_version( | ||||||
|  |                 self._versions[self._executable], REQUIRED_VERSION): | ||||||
|  |             warning = u'Your copy of %s is outdated, update %s to version %s or newer if you encounter any errors.' % ( | ||||||
|  |                 self._executable, self._executable, REQUIRED_VERSION) | ||||||
|  |             self._downloader.report_warning(warning) | ||||||
|  | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def get_versions(): |     def get_versions(): | ||||||
|         programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe'] |         programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe'] | ||||||
|         return dict((program, get_version(program)) for program in programs) |         return dict((program, get_version(program)) for program in programs) | ||||||
| 
 | 
 | ||||||
|     def _get_executable(self): |     @property | ||||||
|  |     def _executable(self): | ||||||
|         if self._downloader.params.get('prefer_ffmpeg', False): |         if self._downloader.params.get('prefer_ffmpeg', False): | ||||||
|             prefs = ('ffmpeg', 'avconv') |             prefs = ('ffmpeg', 'avconv') | ||||||
|         else: |         else: | ||||||
| @ -62,16 +75,15 @@ class FFmpegPostProcessor(PostProcessor): | |||||||
|         return None |         return None | ||||||
| 
 | 
 | ||||||
|     def _uses_avconv(self): |     def _uses_avconv(self): | ||||||
|         return self._get_executable() == 'avconv' |         return self._executable == 'avconv' | ||||||
| 
 | 
 | ||||||
|     def run_ffmpeg_multiple_files(self, input_paths, out_path, opts): |     def run_ffmpeg_multiple_files(self, input_paths, out_path, opts): | ||||||
|         if not self._get_executable(): |         self.check_version() | ||||||
|             raise FFmpegPostProcessorError(u'ffmpeg or avconv not found. Please install one.') |  | ||||||
| 
 | 
 | ||||||
|         files_cmd = [] |         files_cmd = [] | ||||||
|         for path in input_paths: |         for path in input_paths: | ||||||
|             files_cmd.extend(['-i', encodeFilename(path, True)]) |             files_cmd.extend(['-i', encodeFilename(path, True)]) | ||||||
|         cmd = ([self._get_executable(), '-y'] + files_cmd |         cmd = ([self._executable, '-y'] + files_cmd | ||||||
|                + [encodeArgument(o) for o in opts] + |                + [encodeArgument(o) for o in opts] + | ||||||
|                [encodeFilename(self._ffmpeg_filename_argument(out_path), True)]) |                [encodeFilename(self._ffmpeg_filename_argument(out_path), True)]) | ||||||
| 
 | 
 | ||||||
| @ -204,14 +216,14 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): | |||||||
|             if self._nopostoverwrites and os.path.exists(encodeFilename(new_path)): |             if self._nopostoverwrites and os.path.exists(encodeFilename(new_path)): | ||||||
|                 self._downloader.to_screen(u'[youtube] Post-process file %s exists, skipping' % new_path) |                 self._downloader.to_screen(u'[youtube] Post-process file %s exists, skipping' % new_path) | ||||||
|             else: |             else: | ||||||
|                 self._downloader.to_screen(u'[' + self._get_executable() + '] Destination: ' + new_path) |                 self._downloader.to_screen(u'[' + self._executable + '] Destination: ' + new_path) | ||||||
|                 self.run_ffmpeg(path, new_path, acodec, more_opts) |                 self.run_ffmpeg(path, new_path, acodec, more_opts) | ||||||
|         except: |         except: | ||||||
|             etype,e,tb = sys.exc_info() |             etype,e,tb = sys.exc_info() | ||||||
|             if isinstance(e, AudioConversionError): |             if isinstance(e, AudioConversionError): | ||||||
|                 msg = u'audio conversion failed: ' + e.msg |                 msg = u'audio conversion failed: ' + e.msg | ||||||
|             else: |             else: | ||||||
|                 msg = u'error running ' + self._get_executable() |                 msg = u'error running ' + self._executable | ||||||
|             raise PostProcessingError(msg) |             raise PostProcessingError(msg) | ||||||
| 
 | 
 | ||||||
|         # Try to update the date time for extracted audio file. |         # Try to update the date time for extracted audio file. | ||||||
|  | |||||||
| @ -1723,3 +1723,16 @@ def limit_length(s, length): | |||||||
|     if len(s) > length: |     if len(s) > length: | ||||||
|         return s[:length - len(ELLIPSES)] + ELLIPSES |         return s[:length - len(ELLIPSES)] + ELLIPSES | ||||||
|     return s |     return s | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def version_tuple(v): | ||||||
|  |     return [int(e) for e in v.split('.')] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def is_outdated_version(version, limit, assume_new=True): | ||||||
|  |     if not version: | ||||||
|  |         return not assume_new | ||||||
|  |     try: | ||||||
|  |         return version_tuple(version) < version_tuple(limit) | ||||||
|  |     except ValueError: | ||||||
|  |         return not assume_new | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user