Search code examples
pythonyoutube-dl

youtube-dl is not merging audio and video when embedded in Python Script


I am attempting to download the highest quality audio and video of a particular YouTube video from within a Python script.

My code is pretty straight forward:

import youtube_dl
ydl_opts = {
    'format': 'bestvideo[width>=1920]/bestvideo+bestaudio/best',
    'outtmpl': 'test.mp4',
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])

The format line was taken from this question.

The problem I'm encountering is that the downloaded result has no audio component. The video component works as expected. The console output doesn't seem to indicate that audio is downloaded either.

C:\Dev>py youtube_test.py
[youtube] BaW_jenozKc: Downloading webpage
[youtube] BaW_jenozKc: Downloading video info webpage
[youtube] BaW_jenozKc: Extracting video information
[download] Destination: test.mp4
[download] 100% of 2.11MiB in 00:00

Why am I not getting the audio component over the test video and how can I solve that?

I am running on Windows 10. I have ffmpeg installed and in my path.

C:\Dev>ffmpeg -version
ffmpeg version N-90721-g783df2eb59 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 7.3.0 (GCC)
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-bzlib --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
libavutil      56. 13.100 / 56. 13.100
libavcodec     58. 17.100 / 58. 17.100
libavformat    58. 11.101 / 58. 11.101
libavdevice    58.  2.100 / 58.  2.100
libavfilter     7. 15.100 /  7. 15.100
libswscale      5.  0.102 /  5.  0.102
libswresample   3.  0.101 /  3.  0.101
libpostproc    55.  0.100 / 55.  0.100

Solution

  • The format and output template in your code are wrong. Let's start with the format: Your specification bestvideo[width>=1920]/bestvideo+bestaudio/best says:

    1. If present and with width >= 1920, pick the best video format.
    2. Otherwise, pick the best video format, and the best audio format, and combine them.
    3. Otherwise, pick the best file with audio and video included.

    Simply remove the first term and pass in bestvideo+bestaudio/best.

    Note that the resulting file may not be mp4, so you should also use %(ext)s in the output template. In summary, use this:

    import youtube_dl
    ydl_opts = {
        'format': 'bestvideo+bestaudio/best',
        'outtmpl': 'test.%(ext)s',
    }
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc'])