diff options
| -rwxr-xr-x | youtube_dl/YoutubeDL.py | 29 | ||||
| -rw-r--r-- | youtube_dl/__init__.py | 1 | ||||
| -rw-r--r-- | youtube_dl/extractor/common.py | 3 | ||||
| -rw-r--r-- | youtube_dl/extractor/youtube.py | 24 | ||||
| -rw-r--r-- | youtube_dl/options.py | 7 | ||||
| -rw-r--r-- | youtube_dl/postprocessor/__init__.py | 2 | ||||
| -rw-r--r-- | youtube_dl/postprocessor/ffmpeg.py | 23 | 
7 files changed, 89 insertions, 0 deletions
| diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 61675d8ec..4cc3ec2fb 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -70,6 +70,7 @@ from .extractor import get_info_extractor, gen_extractors  from .downloader import get_suitable_downloader  from .downloader.rtmp import rtmpdump_version  from .postprocessor import ( +    FFmpegFixupStretchedPP,      FFmpegMergerPP,      FFmpegPostProcessor,      get_postprocessor, @@ -204,6 +205,12 @@ class YoutubeDL(object):                         Progress hooks are guaranteed to be called at least once                         (with status "finished") if the download is successful.      merge_output_format: Extension to use when merging formats. +    fixup:             Automatically correct known faults of the file. +                       One of: +                       - "never": do nothing +                       - "warn": only emit a warning +                       - "detect_or_warn": check whether we can do anything +                                           about it, warn otherwise      The following parameters are not used by YoutubeDL itself, they are used by @@ -924,6 +931,7 @@ class YoutubeDL(object):                                  'fps': formats_info[0].get('fps'),                                  'vcodec': formats_info[0].get('vcodec'),                                  'vbr': formats_info[0].get('vbr'), +                                'stretched_ratio': formats_info[0].get('stretched_ratio'),                                  'acodec': formats_info[1].get('acodec'),                                  'abr': formats_info[1].get('abr'),                                  'ext': output_ext, @@ -1154,6 +1162,27 @@ class YoutubeDL(object):                      return              if success: +                # Fixup content +                stretched_ratio = info_dict.get('stretched_ratio') +                if stretched_ratio is not None and stretched_ratio != 1: +                    fixup_policy = self.params.get('fixup') +                    if fixup_policy is None: +                        fixup_policy = 'detect_or_warn' +                    if fixup_policy == 'warn': +                        self.report_warning('%s: Non-uniform pixel ratio (%s)' % ( +                            info_dict['id'], stretched_ratio)) +                    elif fixup_policy == 'detect_or_warn': +                        stretched_pp = FFmpegFixupStretchedPP(self) +                        if stretched_pp.available: +                            info_dict.setdefault('__postprocessors', []) +                            info_dict['__postprocessors'].append(stretched_pp) +                        else: +                            self.report_warning( +                                '%s: Non-uniform pixel ratio (%s). Install ffmpeg or avconv to fix this automatically.' % ( +                                    info_dict['id'], stretched_ratio)) +                    else: +                        assert fixup_policy == 'ignore' +                  try:                      self.post_process(filename, info_dict)                  except (PostProcessingError) as err: diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 8e7b74466..659a92a3b 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -326,6 +326,7 @@ def _real_main(argv=None):          'extract_flat': opts.extract_flat,          'merge_output_format': opts.merge_output_format,          'postprocessors': postprocessors, +        'fixup': opts.fixup,      }      with YoutubeDL(ydl_opts) as ydl: diff --git a/youtube_dl/extractor/common.py b/youtube_dl/extractor/common.py index cd155a090..363e2000c 100644 --- a/youtube_dl/extractor/common.py +++ b/youtube_dl/extractor/common.py @@ -114,6 +114,9 @@ class InfoExtractor(object):                                   to add to the request.                      * http_post_data  Additional data to send with a POST                                   request. +                    * stretched_ratio  If given and not 1, indicates that the +                                       video's pixels are not square. +                                       width : height ratio as float.      url:            Final video URL.      ext:            Video filename extension.      format:         The video format, defaults to ext (used for --get-format) diff --git a/youtube_dl/extractor/youtube.py b/youtube_dl/extractor/youtube.py index bc18276d6..c7611a3a0 100644 --- a/youtube_dl/extractor/youtube.py +++ b/youtube_dl/extractor/youtube.py @@ -465,6 +465,20 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):                  'skip_download': 'requires avconv',              }          }, +        # Non-square pixels +        { +            'url': 'https://www.youtube.com/watch?v=_b-2C3KPAM0', +            'info_dict': { +                'id': '_b-2C3KPAM0', +                'ext': 'mp4', +                'stretched_ratio': 16 / 9., +                'upload_date': '20110310', +                'uploader_id': 'AllenMeow', +                'description': 'made by Wacom from Korea | 字幕&加油添醋 by TY\'s Allen | 感謝heylisa00cavey1001同學熱情提供梗及翻譯', +                'uploader': '孫艾倫', +                'title': '[A-made] 變態妍字幕版 太妍 我就是這樣的人', +            }, +        }      ]      def __init__(self, *args, **kwargs): @@ -1051,6 +1065,16 @@ class YoutubeIE(YoutubeBaseInfoExtractor, SubtitlesInfoExtractor):                              f['preference'] = f.get('preference', 0) - 10000                      formats.extend(dash_formats) +        # Check for malformed aspect ratio +        stretched_m = re.search( +            r'<meta\s+property="og:video:tag".*?content="yt:stretch=(?P<w>[0-9]+):(?P<h>[0-9]+)">', +            video_webpage) +        if stretched_m: +            ratio = float(stretched_m.group('w')) / float(stretched_m.group('h')) +            for f in formats: +                if f.get('vcodec') != 'none': +                    f['stretched_ratio'] = ratio +          self._sort_formats(formats)          return { diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 14006178d..e5602bb3a 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -632,6 +632,13 @@ def parseOpts(overrideArguments=None):          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( +        '--fixup', +        metavar='POLICY', dest='fixup', default='detect_or_warn', +        help='(experimental) Automatically correct known faults of the file. ' +             'One of never (do nothing), warn (only emit a warning), ' +             'detect_or_warn(check whether we can do anything about it, warn ' +             'otherwise') +    postproc.add_option(          '--prefer-avconv',          action='store_false', dest='prefer_ffmpeg',          help='Prefer avconv over ffmpeg for running the postprocessors (default)') diff --git a/youtube_dl/postprocessor/__init__.py b/youtube_dl/postprocessor/__init__.py index 7f505b58e..f8507951c 100644 --- a/youtube_dl/postprocessor/__init__.py +++ b/youtube_dl/postprocessor/__init__.py @@ -6,6 +6,7 @@ from .ffmpeg import (      FFmpegAudioFixPP,      FFmpegEmbedSubtitlePP,      FFmpegExtractAudioPP, +    FFmpegFixupStretchedPP,      FFmpegMergerPP,      FFmpegMetadataPP,      FFmpegVideoConvertorPP, @@ -24,6 +25,7 @@ __all__ = [      'FFmpegAudioFixPP',      'FFmpegEmbedSubtitlePP',      'FFmpegExtractAudioPP', +    'FFmpegFixupStretchedPP',      'FFmpegMergerPP',      'FFmpegMetadataPP',      'FFmpegPostProcessor', diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py index d1b342c7a..6e9194fa6 100644 --- a/youtube_dl/postprocessor/ffmpeg.py +++ b/youtube_dl/postprocessor/ffmpeg.py @@ -51,6 +51,10 @@ class FFmpegPostProcessor(PostProcessor):          return dict((p, get_exe_version(p, args=['-version'])) for p in programs)      @property +    def available(self): +        return self._executable is not None + +    @property      def _executable(self):          if self._downloader.params.get('prefer_ffmpeg', False):              prefs = ('ffmpeg', 'avconv') @@ -540,3 +544,22 @@ class FFmpegAudioFixPP(FFmpegPostProcessor):          os.rename(encodeFilename(temp_filename), encodeFilename(filename))          return True, info + + +class FFmpegFixupStretchedPP(FFmpegPostProcessor): +    def run(self, info): +        stretched_ratio = info.get('stretched_ratio') +        if stretched_ratio is None or stretched_ratio == 1: +            return + +        filename = info['filepath'] +        temp_filename = prepend_extension(filename, 'temp') + +        options = ['-c', 'copy', '-aspect', '%f' % stretched_ratio] +        self._downloader.to_screen('[ffmpeg] Fixing aspect ratio in "%s"' % filename) +        self.run_ffmpeg(filename, temp_filename, options) + +        os.remove(encodeFilename(filename)) +        os.rename(encodeFilename(temp_filename), encodeFilename(filename)) + +        return True, info | 
