Repository: ytdl-org/youtube-dl

Issue:
Merge issues due to outdated avconv
After switching to `-f bestvideo+bestaudio/best` as default format selection strategy we receive some bugreports caused by outdated avconv (e.g. #5659 #5595) (and probably ffmpeg). It would probably be reasonable to tweak format selection logic a bit, e.g. enable `-f bestvideo+beastaudio/best` only if merger version is new enough (capable of actual merging) and fallback to `-f best` otherwise.

I did some investigations with [original Windows builds](http://builds.libav.org/windows/release-gpl/) and here are the results.

**Test video:** http://www.youtube.com/watch?v=ScMOyURq9os

**Test formats:**

| format code | extension | type | codec |
| --- | --- | --- | --- |
| 278 | webm | video only | vp9 |
| 249 | webm | audio only | opus |
| 160 | mp4 | video only | h264 |
| 140 | m4a | audio only | aac |

**Results:**

| video | audio | merge output | avconv 9.18 | avconv 10.6 | avconv 11.3 |
| --- | --- | --- | --- | --- | --- |
| 160 | 140 | mp4 | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 278 | 249 | webm | :x: | :x: | :heavy_check_mark: |
| 278 | 249 | mkv | :x: | :heavy_check_mark: | :heavy_check_mark: |
| 160 | 249 | mkv | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
| 278 | 140 | mkv | :x: | :heavy_check_mark: | :heavy_check_mark: |

With libav 0.8.17 it's even [worse](https://github.com/rg3/youtube-dl/issues/5595).

So, we can for example:
- fallback to `-f best` if avconv is older than 10 and if avconv is 10 - force merge output format to mkv if `bestvideo+bestaudio` turns out to be webm+webm.
- fallback to `-f best` if avconv is older than 11.



Discussion:
It's a good idea.

> if avconv is 10 - force merge output format to mkv if bestvideo+bestaudio turns out to be webm+webm

I would prefer to avoid this option, it would make the code more complicated. I consider libav not being able to merge them into webm their bug and we shouldn't handle it specially; the user should either update libav or manually choose the output format.
Since 10 supports the other combinations, I think it's better to use `bestvideo+bestaudio/best`.

On 10.6 everything works the same except webm output, could it be caused by the configuration/libraries used?

Forgot to mention, tests were (yet) performed on Windows only with original builds from [here](http://builds.libav.org/windows/release-gpl/) that ship all the necessary libs. So I doubt some misconfiguration/libs can affect the results.

I encountered the same problem after updating youtube-dl . It looks to me as if the option `f - best` is no longer the default - this should be checked (and corrected in that case).

Former youtube-dl appeared to download the best available mp4 (audio+video) by default, but now it downloads audio and video separately and then tries to merge the two using `avconv` (but `avconv` is not working on my machine, which is a different problem).

> Forgot to mention, tests were (yet) performed on Windows only with original builds from here that ship all the necessary libs. So I doubt some misconfiguration/libs can affect the results.

Ok. Maybe it's caused because they added [the native Opus decoder in version 11](https://git.libav.org/?p=libav.git;a=blob;f=Changelog;hb=refs/tags/v11.3#l95) and the [VP9 in 10](https://git.libav.org/?p=libav.git;a=blob;f=Changelog;hb=refs/tags/v10.6#l169).
Since version 10 works with other formats I would use `-f bestvideo+bestaudio/best` and don't automatically merge to mkv if it's `webm+webm`.

@Wikinaut youtube-dl now uses `-f bestvideo+bestaudio/best` if ffmpeg/avconv is installed, because it gives better quality. If you want to keep the old behaviour read the last two paragraphs [in the FORMAT SELECTION section](https://github.com/rg3/youtube-dl/blob/50b901306406d5c37f31880860e2a4dbb5e0a165/README.md#format-selection).

@jaimeMF thank you for swift reply and for the pointer to the detailed explanation in the FORMAT SELECTION readme, which I did not read when having this problem. The youtube-dl issue is solved for me, thanks. Also, the information about a way to set `-f best` as the default in the configuration file, is a useful tip.

(The problem (on my computer) which brought up that problem is a problem with avconv and some libraries which are by some way not compatible with my current ffmpeg version. I have to fix this, too. No answer needed.)


Resolving patch:
diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py
--- a/youtube_dl/YoutubeDL.py
+++ b/youtube_dl/YoutubeDL.py
@@ -1086,9 +1086,10 @@ def process_video_result(self, info_dict, download=True):
         if req_format is None:
             req_format_list = []
             if (self.params.get('outtmpl', DEFAULT_OUTTMPL) != '-'
-                    and info_dict['extractor'] in ['youtube', 'ted']
-                    and FFmpegMergerPP(self).available):
-                req_format_list.append('bestvideo+bestaudio')
+                    and info_dict['extractor'] in ['youtube', 'ted']):
+                merger = FFmpegMergerPP(self)
+                if merger.available and merger.can_merge():
+                    req_format_list.append('bestvideo+bestaudio')
             req_format_list.append('best')
             req_format = '/'.join(req_format_list)
         formats_to_download = []
diff --git a/youtube_dl/postprocessor/ffmpeg.py b/youtube_dl/postprocessor/ffmpeg.py
--- a/youtube_dl/postprocessor/ffmpeg.py
+++ b/youtube_dl/postprocessor/ffmpeg.py
@@ -591,6 +591,23 @@ def run(self, info):
         os.rename(encodeFilename(temp_filename), encodeFilename(filename))
         return info['__files_to_merge'], info
 
+    def can_merge(self):
+        # TODO: figure out merge-capable ffmpeg version
+        if self.basename != 'avconv':
+            return True
+
+        required_version = '10-0'
+        if is_outdated_version(
+                self._versions[self.basename], required_version):
+            warning = ('Your copy of %s is outdated and unable to properly mux separate video and audio files, '
+                       'youtube-dl will download single file media. '
+                       'Update %s to version %s or newer to fix this.') % (
+                           self.basename, self.basename, required_version)
+            if self._downloader:
+                self._downloader.report_warning(warning)
+            return False
+        return True
+
 
 class FFmpegFixupStretchedPP(FFmpegPostProcessor):
     def run(self, info):


Test patch: