X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=youtube_dl%2Fpostprocessor%2Fffmpeg.py;h=dfae735f3cb2ca3be34311e8e88f5bbc4ec5c1af;hb=5f6a1245ffa9276c1af59b0835afeef67e2fb5b1;hp=19fc135dc356017e7a540d512f870fe9298f408b;hpb=5f82b129e085eb122b6129df36e45925f5b4546a;p=youtube-dl diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index 19fc135dc..dfae735f3 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -1,5 +1,4 @@ import os -import re import subprocess import sys import time @@ -7,11 +6,13 @@ import time from .common import AudioConversionError, PostProcessor -from ..utils import ( - check_executable, +from ..compat import ( compat_subprocess_get_DEVNULL, +) +from ..utils import ( encodeArgument, encodeFilename, + get_exe_version, is_outdated_version, PostProcessingError, prepend_extension, @@ -20,29 +21,12 @@ from ..utils import ( ) -def get_version(executable): - """ Returns the version of the specified executable, - or False if the executable is not present """ - try: - out, err = subprocess.Popen( - [executable, '-version'], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate() - except OSError: - return False - firstline = out.partition(b'\n')[0].decode('ascii', 'ignore') - m = re.search(r'version\s+([0-9._-a-zA-Z]+)', firstline) - if not m: - return u'present' - else: - return m.group(1) - - class FFmpegPostProcessorError(PostProcessingError): pass class FFmpegPostProcessor(PostProcessor): - def __init__(self, downloader, deletetempfiles=False): + def __init__(self, downloader=None, deletetempfiles=False): PostProcessor.__init__(self, downloader) self._versions = self.get_versions() self._deletetempfiles = deletetempfiles @@ -56,12 +40,13 @@ class FFmpegPostProcessor(PostProcessor): 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) + if self._downloader: + self._downloader.report_warning(warning) @staticmethod def get_versions(): programs = ['avprobe', 'avconv', 'ffmpeg', 'ffprobe'] - return dict((program, get_version(program)) for program in programs) + return dict((p, get_exe_version(p, args=['-version'])) for p in programs) @property def _executable(self): @@ -74,6 +59,17 @@ class FFmpegPostProcessor(PostProcessor): return p return None + @property + def _probe_executable(self): + if self._downloader.params.get('prefer_ffmpeg', False): + prefs = ('ffprobe', 'avprobe') + else: + prefs = ('avprobe', 'ffprobe') + for p in prefs: + if self._versions[p]: + return p + return None + def _uses_avconv(self): return self._executable == 'avconv' @@ -119,11 +115,12 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): self._nopostoverwrites = nopostoverwrites def get_audio_codec(self, path): - if not self._exes['ffprobe'] and not self._exes['avprobe']: + + if not self._probe_executable: raise PostProcessingError(u'ffprobe or avprobe not found. Please install one.') try: cmd = [ - self._exes['avprobe'] or self._exes['ffprobe'], + self._probe_executable, '-show_streams', encodeFilename(self._ffmpeg_filename_argument(path), True)] handle = subprocess.Popen(cmd, stderr=compat_subprocess_get_DEVNULL(), stdout=subprocess.PIPE) @@ -205,7 +202,7 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): extension = 'wav' more_opts += ['-f', 'wav'] - prefix, sep, ext = path.rpartition(u'.') # not os.path.splitext, since the latter does not work on unicode in all setups + prefix, sep, ext = path.rpartition(u'.') # not os.path.splitext, since the latter does not work on unicode in all setups new_path = prefix + sep + extension # If we download foo.mp3 and convert it to... foo.mp3, then don't delete foo.mp3, silly. @@ -219,7 +216,7 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): self._downloader.to_screen(u'[' + self._executable + '] Destination: ' + new_path) self.run_ffmpeg(path, new_path, acodec, more_opts) except: - etype,e,tb = sys.exc_info() + etype, e, tb = sys.exc_info() if isinstance(e, AudioConversionError): msg = u'audio conversion failed: ' + e.msg else: @@ -234,13 +231,13 @@ class FFmpegExtractAudioPP(FFmpegPostProcessor): self._downloader.report_warning(u'Cannot update utime of audio file') information['filepath'] = new_path - return self._nopostoverwrites,information + return self._nopostoverwrites, information class FFmpegVideoConvertor(FFmpegPostProcessor): - def __init__(self, downloader=None,preferedformat=None): + def __init__(self, downloader=None, preferedformat=None): super(FFmpegVideoConvertor, self).__init__(downloader) - self._preferedformat=preferedformat + self._preferedformat = preferedformat def run(self, information): path = information['filepath'] @@ -248,13 +245,13 @@ class FFmpegVideoConvertor(FFmpegPostProcessor): outpath = prefix + sep + self._preferedformat if information['ext'] == self._preferedformat: self._downloader.to_screen(u'[ffmpeg] Not converting video file %s - already is in target format %s' % (path, self._preferedformat)) - return True,information - self._downloader.to_screen(u'['+'ffmpeg'+'] Converting video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) +outpath) + return True, information + self._downloader.to_screen(u'['+'ffmpeg'+'] Converting video from %s to %s, Destination: ' % (information['ext'], self._preferedformat) + outpath) self.run_ffmpeg(path, outpath, []) information['filepath'] = outpath information['format'] = self._preferedformat information['ext'] = self._preferedformat - return False,information + return False, information class FFmpegEmbedSubtitlePP(FFmpegPostProcessor): @@ -460,7 +457,7 @@ class FFmpegEmbedSubtitlePP(FFmpegPostProcessor): self._downloader.to_screen(u'[ffmpeg] Subtitles can only be embedded in mp4 files') return True, information if not information.get('subtitles'): - self._downloader.to_screen(u'[ffmpeg] There aren\'t any subtitles to embed') + self._downloader.to_screen(u'[ffmpeg] There aren\'t any subtitles to embed') return True, information sub_langs = [key for key in information['subtitles']]