mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-30 22:25:19 +00:00 
			
		
		
		
	[ffmpeg] Framework for feature detection
Related: #1502, #1237, https://github.com/ytdl-org/youtube-dl/pull/29581
This commit is contained in:
		| @@ -232,7 +232,8 @@ def _real_main(argv=None): | ||||
|             parser.error('invalid audio format specified') | ||||
|     if opts.audioquality: | ||||
|         opts.audioquality = opts.audioquality.strip('k').strip('K') | ||||
|         if int_or_none(float_or_none(opts.audioquality)) is None:  # int_or_none prevents inf, nan | ||||
|         audioquality = int_or_none(float_or_none(opts.audioquality))  # int_or_none prevents inf, nan | ||||
|         if audioquality is None or audioquality < 0: | ||||
|             parser.error('invalid audio quality specified') | ||||
|     if opts.recodevideo is not None: | ||||
|         opts.recodevideo = opts.recodevideo.replace(' ', '') | ||||
|   | ||||
| @@ -16,7 +16,8 @@ from ..utils import ( | ||||
|     encodeArgument, | ||||
|     encodeFilename, | ||||
|     float_or_none, | ||||
|     get_exe_version, | ||||
|     _get_exe_version_output, | ||||
|     detect_exe_version, | ||||
|     is_outdated_version, | ||||
|     ISO639Utils, | ||||
|     orderedSet, | ||||
| @@ -80,10 +81,10 @@ class FFmpegPostProcessor(PostProcessor): | ||||
|  | ||||
|     def _determine_executables(self): | ||||
|         programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe'] | ||||
|         prefer_ffmpeg = True | ||||
|  | ||||
|         def get_ffmpeg_version(path): | ||||
|             ver = get_exe_version(path, args=['-version']) | ||||
|         def get_ffmpeg_version(path, prog): | ||||
|             out = _get_exe_version_output(path, ['-bsfs']) | ||||
|             ver = detect_exe_version(out) if out else False | ||||
|             if ver: | ||||
|                 regexs = [ | ||||
|                     r'(?:\d+:)?([0-9.]+)-[0-9]+ubuntu[0-9.]+$',  # Ubuntu, see [1] | ||||
| @@ -94,42 +95,46 @@ class FFmpegPostProcessor(PostProcessor): | ||||
|                     mobj = re.match(regex, ver) | ||||
|                     if mobj: | ||||
|                         ver = mobj.group(1) | ||||
|             return ver | ||||
|             self._versions[prog] = ver | ||||
|             if prog != 'ffmpeg' or not out: | ||||
|                 return | ||||
|  | ||||
|             # TODO: Feature detection | ||||
|  | ||||
|         self.basename = None | ||||
|         self.probe_basename = None | ||||
|  | ||||
|         self._paths = None | ||||
|         self._versions = None | ||||
|         if self._downloader: | ||||
|             prefer_ffmpeg = self.get_param('prefer_ffmpeg', True) | ||||
|             location = self.get_param('ffmpeg_location') | ||||
|             if location is not None: | ||||
|                 if not os.path.exists(location): | ||||
|                     self.report_warning( | ||||
|                         'ffmpeg-location %s does not exist! ' | ||||
|                         'Continuing without ffmpeg.' % (location)) | ||||
|                     self._versions = {} | ||||
|                     return | ||||
|                 elif os.path.isdir(location): | ||||
|                     dirname, basename = location, None | ||||
|                 else: | ||||
|                     basename = os.path.splitext(os.path.basename(location))[0] | ||||
|                     basename = next((p for p in programs if basename.startswith(p)), 'ffmpeg') | ||||
|                     dirname = os.path.dirname(os.path.abspath(location)) | ||||
|                     if basename in ('ffmpeg', 'ffprobe'): | ||||
|                         prefer_ffmpeg = True | ||||
|         self._features = {} | ||||
|  | ||||
|                 self._paths = dict( | ||||
|                     (p, os.path.join(dirname, p)) for p in programs) | ||||
|                 if basename: | ||||
|                     self._paths[basename] = location | ||||
|                 self._versions = dict( | ||||
|                     (p, get_ffmpeg_version(self._paths[p])) for p in programs) | ||||
|         if self._versions is None: | ||||
|             self._versions = dict( | ||||
|                 (p, get_ffmpeg_version(p)) for p in programs) | ||||
|             self._paths = dict((p, p) for p in programs) | ||||
|         prefer_ffmpeg = self.get_param('prefer_ffmpeg', True) | ||||
|         location = self.get_param('ffmpeg_location') | ||||
|         if location is None: | ||||
|             self._paths = {p: p for p in programs} | ||||
|         else: | ||||
|             if not os.path.exists(location): | ||||
|                 self.report_warning( | ||||
|                     'ffmpeg-location %s does not exist! ' | ||||
|                     'Continuing without ffmpeg.' % (location)) | ||||
|                 self._versions = {} | ||||
|                 return | ||||
|             elif os.path.isdir(location): | ||||
|                 dirname, basename = location, None | ||||
|             else: | ||||
|                 basename = os.path.splitext(os.path.basename(location))[0] | ||||
|                 basename = next((p for p in programs if basename.startswith(p)), 'ffmpeg') | ||||
|                 dirname = os.path.dirname(os.path.abspath(location)) | ||||
|                 if basename in ('ffmpeg', 'ffprobe'): | ||||
|                     prefer_ffmpeg = True | ||||
|  | ||||
|             self._paths = dict( | ||||
|                 (p, os.path.join(dirname, p)) for p in programs) | ||||
|             if basename: | ||||
|                 self._paths[basename] = location | ||||
|  | ||||
|         self._versions = {} | ||||
|         for p in programs: | ||||
|             get_ffmpeg_version(self._paths[p], p) | ||||
|  | ||||
|         if prefer_ffmpeg is False: | ||||
|             prefs = ('avconv', 'ffmpeg') | ||||
| @@ -382,7 +387,9 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): | ||||
|  | ||||
|         limits = { | ||||
|             'libmp3lame': (10, 0), | ||||
|             'aac': (0.1, 11), | ||||
|             # FFmpeg's AAC encoder does not have an upper limit for the value of -q:a. | ||||
|             # Experimentally, with values over 4, bitrate changes were minimal or non-existent | ||||
|             'aac': (0.1, 4), | ||||
|             'vorbis': (0, 10), | ||||
|             'opus': None,  # doesn't support -q:a | ||||
|             'wav': None, | ||||
|   | ||||
| @@ -4007,10 +4007,7 @@ def check_executable(exe, args=[]): | ||||
|     return exe | ||||
|  | ||||
|  | ||||
| def get_exe_version(exe, args=['--version'], | ||||
|                     version_re=None, unrecognized='present'): | ||||
|     """ Returns the version of the specified executable, | ||||
|     or False if the executable is not present """ | ||||
| def _get_exe_version_output(exe, args): | ||||
|     try: | ||||
|         # STDIN should be redirected too. On UNIX-like systems, ffmpeg triggers | ||||
|         # SIGTTOU if yt-dlp is run in the background. | ||||
| @@ -4022,7 +4019,7 @@ def get_exe_version(exe, args=['--version'], | ||||
|         return False | ||||
|     if isinstance(out, bytes):  # Python 2.x | ||||
|         out = out.decode('ascii', 'ignore') | ||||
|     return detect_exe_version(out, version_re, unrecognized) | ||||
|     return out | ||||
|  | ||||
|  | ||||
| def detect_exe_version(output, version_re=None, unrecognized='present'): | ||||
| @@ -4036,6 +4033,14 @@ def detect_exe_version(output, version_re=None, unrecognized='present'): | ||||
|         return unrecognized | ||||
|  | ||||
|  | ||||
| def get_exe_version(exe, args=['--version'], | ||||
|                     version_re=None, unrecognized='present'): | ||||
|     """ Returns the version of the specified executable, | ||||
|     or False if the executable is not present """ | ||||
|     out = _get_exe_version_output(exe, args) | ||||
|     return detect_exe_version(out, version_re, unrecognized) if out else False | ||||
|  | ||||
|  | ||||
| class LazyList(collections.abc.Sequence): | ||||
|     ''' Lazy immutable list from an iterable | ||||
|     Note that slices of a LazyList are lists and not LazyList''' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 pukkandan
					pukkandan