yt-dlp | A youtube-dl fork with additional features and fixes | Video Utils library

 by   yt-dlp Python Version: 2023.3.4 License: Unlicense

kandi X-RAY | yt-dlp Summary

yt-dlp is a Python library typically used in Video, Video Utils applications. yt-dlp has no bugs, it has no vulnerabilities, it has build file available, it has a Permissive License and it has medium support. You can install using 'pip install yt-dlp' or download it from GitHub, PyPI.
yt-dlp is a youtube-dl fork based on the now inactive youtube-dlc. The main focus of this project is adding new features and patches while also keeping up to date with the original project.
    Support
      Quality
        Security
          License
            Reuse
            Support
              Quality
                Security
                  License
                    Reuse

                      kandi-support Support

                        summary
                        yt-dlp has a medium active ecosystem.
                        summary
                        It has 44006 star(s) with 3618 fork(s). There are 330 watchers for this library.
                        summary
                        There were 7 major release(s) in the last 6 months.
                        summary
                        There are 895 open issues and 3745 have been closed. On average issues are closed in 14 days. There are 168 open pull requests and 0 closed requests.
                        summary
                        It has a neutral sentiment in the developer community.
                        summary
                        The latest version of yt-dlp is 2023.3.4
                        yt-dlp Support
                          Best in #Video Utils
                            Average in #Video Utils
                            yt-dlp Support
                              Best in #Video Utils
                                Average in #Video Utils

                                  kandi-Quality Quality

                                    summary
                                    yt-dlp has 0 bugs and 0 code smells.
                                    yt-dlp Quality
                                      Best in #Video Utils
                                        Average in #Video Utils
                                        yt-dlp Quality
                                          Best in #Video Utils
                                            Average in #Video Utils

                                              kandi-Security Security

                                                summary
                                                yt-dlp has no vulnerabilities reported, and its dependent libraries have no vulnerabilities reported.
                                                summary
                                                yt-dlp code analysis shows 0 unresolved vulnerabilities.
                                                summary
                                                There are 0 security hotspots that need review.
                                                yt-dlp Security
                                                  Best in #Video Utils
                                                    Average in #Video Utils
                                                    yt-dlp Security
                                                      Best in #Video Utils
                                                        Average in #Video Utils

                                                          kandi-License License

                                                            summary
                                                            yt-dlp is licensed under the Unlicense License. This license is Permissive.
                                                            summary
                                                            Permissive licenses have the least restrictions, and you can use them in most projects.
                                                            yt-dlp License
                                                              Best in #Video Utils
                                                                Average in #Video Utils
                                                                yt-dlp License
                                                                  Best in #Video Utils
                                                                    Average in #Video Utils

                                                                      kandi-Reuse Reuse

                                                                        summary
                                                                        yt-dlp releases are available to install and integrate.
                                                                        summary
                                                                        Deployable package is available in PyPI.
                                                                        summary
                                                                        Build file is available. You can build the component from source.
                                                                        summary
                                                                        Installation instructions, examples and code snippets are available.
                                                                        summary
                                                                        It has 162659 lines of code, 4842 functions and 1043 files.
                                                                        summary
                                                                        It has medium code complexity. Code complexity directly impacts maintainability of the code.
                                                                        yt-dlp Reuse
                                                                          Best in #Video Utils
                                                                            Average in #Video Utils
                                                                            yt-dlp Reuse
                                                                              Best in #Video Utils
                                                                                Average in #Video Utils
                                                                                  Top functions reviewed by kandi - BETA
                                                                                  kandi has reviewed yt-dlp and discovered the below as its top functions. This is intended to give you an instant insight into yt-dlp implemented functionality, and help decide if they suit your requirements.
                                                                                  • Create an option parser .
                                                                                    • Extract mvpd auth data .
                                                                                      • Processes info .
                                                                                        • Validate options .
                                                                                          • Parse MPD formats .
                                                                                            • Extract metadata from a video .
                                                                                              • Interpret an expression .
                                                                                                • Extract an anime entry .
                                                                                                  • Parse options .
                                                                                                    • Get information about a video .
                                                                                                      Get all kandi verified functions for this library.
                                                                                                      Get all kandi verified functions for this library.

                                                                                                      yt-dlp Key Features

                                                                                                      Based on youtube-dl 2021.12.17 commit/5add3f4 and youtube-dlc 2020.11.11-3 commit/f9401f2: You get all the features and patches of youtube-dlc in addition to the latest youtube-dl
                                                                                                      SponsorBlock Integration: You can mark/remove sponsor sections in youtube videos by utilizing the SponsorBlock API
                                                                                                      Format Sorting: The default format sorting options have been changed so that higher resolution and better codecs will be now preferred instead of simply using larger bitrate. Furthermore, you can now specify the sort order using -S. This allows for much easier format selection than what is possible by simply using --format (examples)
                                                                                                      Merged with animelover1984/youtube-dl: You get most of the features and improvements from animelover1984/youtube-dl including --write-comments, BiliBiliSearch, BilibiliChannel, Embedding thumbnail in mp4/ogg/opus, playlist infojson etc. Note that the NicoNico improvements are not available. See #31 for details.
                                                                                                      Youtube improvements: All Feeds (:ytfav, :ytwatchlater, :ytsubs, :ythistory, :ytrec) and private playlists supports downloading multiple pages of content Search (ytsearch:, ytsearchdate:), search URLs and in-channel search works Mixes supports downloading multiple pages of content Some (but not all) age-gated content can be downloaded without cookies Fix for n-sig based throttling Redirect channel's home URL automatically to /video to preserve the old behaviour 255kbps audio is extracted (if available) from youtube music when premium cookies are given Youtube music Albums, channels etc can be downloaded (except self-uploaded music) Download livestreams from the start using --live-from-start (experimental)
                                                                                                      Cookies from browser: Cookies can be automatically extracted from all major web browsers using --cookies-from-browser BROWSER[+KEYRING][:PROFILE]
                                                                                                      Split video by chapters: Videos can be split into multiple files based on chapters using --split-chapters
                                                                                                      Multi-threaded fragment downloads: Download multiple fragments of m3u8/mpd videos in parallel. Use --concurrent-fragments (-N) option to set the number of threads used
                                                                                                      Aria2c with HLS/DASH: You can use aria2c as the external downloader for DASH(mpd) and HLS(m3u8) formats
                                                                                                      New and fixed extractors: Many new extractors have been added and a lot of existing ones have been fixed. See the changelog or the list of supported sites
                                                                                                      New MSOs: Philo, Spectrum, SlingTV, Cablevision, RCN
                                                                                                      Subtitle extraction from manifests: Subtitles can be extracted from streaming media manifests. See commit/be6202f for details
                                                                                                      Multiple paths and output templates: You can give different output templates and download paths for different types of files. You can also set a temporary path where intermediary files are downloaded to using --paths (-P)
                                                                                                      Portable Configuration: Configuration files are automatically loaded from the home and root directories. See configuration for details
                                                                                                      Output template improvements: Output templates can now have date-time formatting, numeric offsets, object traversal etc. See output template for details. Even more advanced operations can also be done with the help of --parse-metadata and --replace-in-metadata
                                                                                                      Other new options: Many new options have been added such as --concat-playlist, --print, --wait-for-video, --sleep-requests, --convert-thumbnails, --write-link, --force-download-archive, --force-overwrites, --break-on-reject etc
                                                                                                      Improvements: Regex and other operators in --match-filter, multiple --postprocessor-args and --downloader-args, faster archive checking, more format selection options, merge multi-video/audio, multiple --config-locations, --exec at different stages, etc
                                                                                                      Plugins: Extractors and PostProcessors can be loaded from an external file. See plugins for details
                                                                                                      Self-updater: The releases can be updated using yt-dlp -U

                                                                                                      yt-dlp Examples and Code Snippets

                                                                                                      USAGE AND OPTIONS-Post-Processing Options:
                                                                                                      Pythondot imgLines of Code : 156dot imgLicense : Permissive (Unlicense)
                                                                                                      copy iconCopy
                                                                                                      
                                                                                                                                          -x, --extract-audio Convert video files to audio-only files (requires ffmpeg and ffprobe) --audio-format FORMAT Format to convert the audio to when -x is used. (currently supported: best (default), aac, alac, flac, m4a, mp3, opus, vorbis, wav). You can specify multiple rules using similar syntax as --remux-video --audio-quality QUALITY Specify ffmpeg audio quality to use when converting the audio with -x. Insert a value between 0 (best) and 10 (worst) for VBR or a specific bitrate like 128K (default 5) --remux-video FORMAT Remux the video into another container if necessary (currently supported: avi, flv, gif, mkv, mov, mp4, webm, aac, aiff, alac, flac, m4a, mka, mp3, ogg, opus, vorbis, wav). If target container does not support the video/audio codec, remuxing will fail. You can specify multiple rules; e.g. "aac>m4a/mov>mp4/mkv" will remux aac to m4a, mov to mp4 and anything else to mkv --recode-video FORMAT Re-encode the video into another format if necessary. The syntax and supported formats are the same as --remux-video --postprocessor-args NAME:ARGS Give these arguments to the postprocessors. Specify the postprocessor/executable name and the arguments separated by a colon ":" to give the argument to the specified postprocessor/executable. Supported PP are: Merger, ModifyChapters, SplitChapters, ExtractAudio, VideoRemuxer, VideoConvertor, Metadata, EmbedSubtitle, EmbedThumbnail, SubtitlesConvertor, ThumbnailsConvertor, FixupStretched, FixupM4a, FixupM3u8, FixupTimestamp and FixupDuration. The supported executables are: AtomicParsley, FFmpeg and FFprobe. You can also specify "PP+EXE:ARGS" to give the arguments to the specified executable only when being used by the specified postprocessor. Additionally, for ffmpeg/ffprobe, "_i"/"_o" can be appended to the prefix optionally followed by a number to pass the argument before the specified input/output file, e.g. --ppa "Merger+ffmpeg_i1:-v quiet". You can use this option multiple times to give different arguments to different postprocessors. (Alias: --ppa) -k, --keep-video Keep the intermediate video file on disk after post-processing --no-keep-video Delete the intermediate video file after post-processing (default) --post-overwrites Overwrite post-processed files (default) --no-post-overwrites Do not overwrite post-processed files --embed-subs Embed subtitles in the video (only for mp4, webm and mkv videos) --no-embed-subs Do not embed subtitles (default) --embed-thumbnail Embed thumbnail in the video as cover art --no-embed-thumbnail Do not embed thumbnail (default) --embed-metadata Embed metadata to the video file. Also embeds chapters/infojson if present unless --no-embed-chapters/--no-embed-info-json are used (Alias: --add-metadata) --no-embed-metadata Do not add metadata to file (default) (Alias: --no-add-metadata) --embed-chapters Add chapter markers to the video file (Alias: --add-chapters) --no-embed-chapters Do not add chapter markers (default) (Alias: --no-add-chapters) --embed-info-json Embed the infojson as an attachment to mkv/mka video files --no-embed-info-json Do not embed the infojson as an attachment to the video file --parse-metadata FROM:TO Parse additional metadata like title/artist from other fields; see "MODIFYING METADATA" for details --replace-in-metadata FIELDS REGEX REPLACE Replace text in a metadata field using the given regex. This option can be used multiple times --xattrs Write metadata to the video file's xattrs (using dublin core and xdg standards) --concat-playlist POLICY Concatenate videos in a playlist. One of "never", "always", or "multi_video" (default; only when the videos form a single show). All the video files must have same codecs and number of streams to be concatable. The "pl_video:" prefix can be used with "--paths" and "--output" to set the output filename for the concatenated files. See "OUTPUT TEMPLATE" for details --fixup POLICY Automatically correct known faults of the file. One of never (do nothing), warn (only emit a warning), detect_or_warn (the default; fix file if we can, warn otherwise), force (try fixing even if file already exists) --ffmpeg-location PATH Location of the ffmpeg binary; either the path to the binary or its containing directory --exec [WHEN:]CMD Execute a command, optionally prefixed with when to execute it (after_move if unspecified), separated by a ":". Supported values of "WHEN" are the same as that of --use-postprocessor. Same syntax as the output template can be used to pass any field as arguments to the command. After download, an additional field "filepath" that contains the final path of the downloaded file is also available, and if no fields are passed, %(filepath)q is appended to the end of the command. This option can be used multiple times --no-exec Remove any previously defined --exec --convert-subs FORMAT Convert the subtitles to another format (currently supported: ass, lrc, srt, vtt) (Alias: --convert-subtitles) --convert-thumbnails FORMAT Convert the thumbnails to another format (currently supported: jpg, png, webp). You can specify multiple rules using similar syntax as --remux-video --split-chapters Split video into multiple files based on internal chapters. The "chapter:" prefix can be used with "--paths" and "--output" to set the output filename for the split files. See "OUTPUT TEMPLATE" for details --no-split-chapters Do not split video based on chapters (default) --remove-chapters REGEX Remove chapters whose title matches the given regular expression. The syntax is the same as --download-sections. This option can be used multiple times --no-remove-chapters Do not remove any chapters from the file (default) --force-keyframes-at-cuts Force keyframes at cuts when downloading/splitting/removing sections. This is slow due to needing a re-encode, but the resulting video may have fewer artifacts around the cuts --no-force-keyframes-at-cuts Do not force keyframes around the chapters when cutting/splitting (default) --use-postprocessor NAME[:ARGS] The (case sensitive) name of plugin postprocessors to be enabled, and (optionally) arguments to be passed to it, separated by a colon ":". ARGS are a semicolon ";" delimited list of NAME=VALUE. The "when" argument determines when the postprocessor is invoked. It can be one of "pre_process" (after video extraction), "after_filter" (after video passes filter), "before_dl" (before each video download), "post_process" (after each video download; default), "after_move" (after moving video file to it's final locations), "after_video" (after downloading and processing all formats of a video), or "playlist" (at end of playlist). This option can be used multiple times to add different postprocessors
                                                                                                      EMBEDDING YT-DLP-Embedding examples
                                                                                                      Pythondot imgLines of Code : 140dot imgLicense : Permissive (Unlicense)
                                                                                                      copy iconCopy
                                                                                                      
                                                                                                                                          import json import yt_dlp URL = 'https://www.youtube.com/watch?v=BaW_jenozKc' # ℹ️ See help(yt_dlp.YoutubeDL) for a list of available options and public functions ydl_opts = {} with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(URL, download=False) # ℹ️ ydl.sanitize_info makes the info json-serializable print(json.dumps(ydl.sanitize_info(info)))
                                                                                                      import yt_dlp INFO_FILE = 'path/to/video.info.json' with yt_dlp.YoutubeDL() as ydl: error_code = ydl.download_with_info_file(INFO_FILE) print('Some videos failed to download' if error_code else 'All videos successfully downloaded')
                                                                                                      import yt_dlp URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] ydl_opts = { 'format': 'm4a/bestaudio/best', # ℹ️ See help(yt_dlp.postprocessor) for a list of available Postprocessors and their arguments 'postprocessors': [{ # Extract audio using ffmpeg 'key': 'FFmpegExtractAudio', 'preferredcodec': 'm4a', }] } with yt_dlp.YoutubeDL(ydl_opts) as ydl: error_code = ydl.download(URLS)
                                                                                                      import yt_dlp URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] def longer_than_a_minute(info, *, incomplete): """Download only videos longer than a minute (or with unknown duration)""" duration = info.get('duration') if duration and duration < 60: return 'The video is too short' ydl_opts = { 'match_filter': longer_than_a_minute, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: error_code = ydl.download(URLS)
                                                                                                      import yt_dlp URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] class MyLogger: def debug(self, msg): # For compatibility with youtube-dl, both debug and info are passed into debug # You can distinguish them by the prefix '[debug] ' if msg.startswith('[debug] '): pass else: self.info(msg) def info(self, msg): pass def warning(self, msg): pass def error(self, msg): print(msg) # ℹ️ See "progress_hooks" in help(yt_dlp.YoutubeDL) def my_hook(d): if d['status'] == 'finished': print('Done downloading, now post-processing ...') ydl_opts = { 'logger': MyLogger(), 'progress_hooks': [my_hook], } with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download(URLS)
                                                                                                      import yt_dlp URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] # ℹ️ See help(yt_dlp.postprocessor.PostProcessor) class MyCustomPP(yt_dlp.postprocessor.PostProcessor): def run(self, info): self.to_screen('Doing stuff') return [], info with yt_dlp.YoutubeDL() as ydl: # ℹ️ "when" can take any value in yt_dlp.utils.POSTPROCESS_WHEN ydl.add_post_processor(MyCustomPP(), when='pre_process') ydl.download(URLS)
                                                                                                      import yt_dlp URL = ['https://www.youtube.com/watch?v=BaW_jenozKc'] def format_selector(ctx): """ Select the best video and the best audio that won't result in an mkv. NOTE: This is just an example and does not handle all cases """ # formats are already sorted worst to best formats = ctx.get('formats')[::-1] # acodec='none' means there is no audio best_video = next(f for f in formats if f['vcodec'] != 'none' and f['acodec'] == 'none') # find compatible audio extension audio_ext = {'mp4': 'm4a', 'webm': 'webm'}[best_video['ext']] # vcodec='none' means there is no video best_audio = next(f for f in formats if ( f['acodec'] != 'none' and f['vcodec'] == 'none' and f['ext'] == audio_ext)) # These are the minimum required fields for a merged format yield { 'format_id': f'{best_video["format_id"]}+{best_audio["format_id"]}', 'ext': best_video['ext'], 'requested_formats': [best_video, best_audio], # Must be + separated list of protocols 'protocol': f'{best_video["protocol"]}+{best_audio["protocol"]}' } ydl_opts = { 'format': format_selector, } with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download(URLS)
                                                                                                      FORMAT SELECTION-Format Selection examples
                                                                                                      Pythondot imgLines of Code : 118dot imgLicense : Permissive (Unlicense)
                                                                                                      copy iconCopy
                                                                                                      
                                                                                                                                          # Download and merge the best video-only format and the best audio-only format, # or download the best combined format if video-only format is not available $ yt-dlp -f "bv+ba/b" # Download best format that contains video, # and if it doesn't already have an audio stream, merge it with best audio-only format $ yt-dlp -f "bv*+ba/b" # Same as above $ yt-dlp # Download the best video-only format and the best audio-only format without merging them # For this case, an output template should be used since # by default, bestvideo and bestaudio will have the same file name. $ yt-dlp -f "bv,ba" -o "%(title)s.f%(format_id)s.%(ext)s" # Download and merge the best format that has a video stream, # and all audio-only formats into one file $ yt-dlp -f "bv*+mergeall[vcodec=none]" --audio-multistreams # Download and merge the best format that has a video stream, # and the best 2 audio-only formats into one file $ yt-dlp -f "bv*+ba+ba.2" --audio-multistreams # The following examples show the old method (without -S) of format selection # and how to use -S to achieve a similar but (generally) better result # Download the worst video available (old method) $ yt-dlp -f "wv*+wa/w" # Download the best video available but with the smallest resolution $ yt-dlp -S "+res" # Download the smallest video available $ yt-dlp -S "+size,+br" # Download the best mp4 video available, or the best video if no mp4 available $ yt-dlp -f "bv*[ext=mp4]+ba[ext=m4a]/b[ext=mp4] / bv*+ba/b" # Download the best video with the best extension # (For video, mp4 > mov > webm > flv. For audio, m4a > aac > mp3 ...) $ yt-dlp -S "ext" # Download the best video available but no better than 480p, # or the worst video if there is no video under 480p $ yt-dlp -f "bv*[height<=480]+ba/b[height<=480] / wv*+ba/w" # Download the best video available with the largest height but no better than 480p, # or the best video with the smallest resolution if there is no video under 480p $ yt-dlp -S "height:480" # Download the best video available with the largest resolution but no better than 480p, # or the best video with the smallest resolution if there is no video under 480p # Resolution is determined by using the smallest dimension. # So this works correctly for vertical videos as well $ yt-dlp -S "res:480" # Download the best video (that also has audio) but no bigger than 50 MB, # or the worst video (that also has audio) if there is no video under 50 MB $ yt-dlp -f "b[filesize<50M] / w" # Download largest video (that also has audio) but no bigger than 50 MB, # or the smallest video (that also has audio) if there is no video under 50 MB $ yt-dlp -f "b" -S "filesize:50M" # Download best video (that also has audio) that is closest in size to 50 MB $ yt-dlp -f "b" -S "filesize~50M" # Download best video available via direct link over HTTP/HTTPS protocol, # or the best video available via any protocol if there is no such video $ yt-dlp -f "(bv*+ba/b)[protocol^=http][protocol!*=dash] / (bv*+ba/b)" # Download best video available via the best protocol # (https/ftps > http/ftp > m3u8_native > m3u8 > http_dash_segments ...) $ yt-dlp -S "proto" # Download the best video with either h264 or h265 codec, # or the best video if there is no such video $ yt-dlp -f "(bv*[vcodec~='^((he|a)vc|h26[45])']+ba) / (bv*+ba/b)" # Download the best video with best codec no better than h264, # or the best video with worst codec if there is no such video $ yt-dlp -S "codec:h264" # Download the best video with worst codec no worse than h264, # or the best video with best codec if there is no such video $ yt-dlp -S "+codec:h264" # More complex examples # Download the best video no better than 720p preferring framerate greater than 30, # or the worst video (still preferring framerate greater than 30) if there is no such video $ yt-dlp -f "((bv*[fps>30]/bv*)[height<=720]/(wv*[fps>30]/wv*)) + ba / (b[fps>30]/b)[height<=720]/(w[fps>30]/w)" # Download the video with the largest resolution no better than 720p, # or the video with the smallest resolution available if there is no such video, # preferring larger framerate for formats with the same resolution $ yt-dlp -S "res:720,fps" # Download the video with smallest resolution no worse than 480p, # or the video with the largest resolution available if there is no such video, # preferring better codec and then larger total bitrate for the same resolution $ yt-dlp -S "+res:480,codec,br"
                                                                                                      grabbing video title from yt-dlp command line output
                                                                                                      Pythondot imgLines of Code : 13dot imgLicense : Strong Copyleft (CC BY-SA 4.0)
                                                                                                      copy iconCopy
                                                                                                      from yt_dlp import YoutubeDL
                                                                                                      
                                                                                                      with YoutubeDL() as ydl: 
                                                                                                        info_dict = ydl.extract_info('https://youtu.be/0KFSuoHEYm0', download=False)
                                                                                                        video_url = info_dict.get("url", None)
                                                                                                        video_id = info_dict.get("id", None)
                                                                                                        video_title = info_dict.get('title', None)
                                                                                                        print("Title: " + video_title) # <= Here, you got the video title
                                                                                                      
                                                                                                      #[youtube] 0KFSuoHEYm0: Downloading webpage
                                                                                                      #[youtube] 0KFSuoHEYm0: Downloading android player API JSON
                                                                                                      #Title: TJ Watt gets his 4th sack of the game vs. Browns
                                                                                                      
                                                                                                      How to hide error message from youtube-dl / yt-dlp?
                                                                                                      Pythondot imgLines of Code : 28dot imgLicense : Strong Copyleft (CC BY-SA 4.0)
                                                                                                      copy iconCopy
                                                                                                      import yt_dlp as youtube_dl
                                                                                                      from yt_dlp.utils import DownloadError
                                                                                                      
                                                                                                      
                                                                                                      url = "https://www.twitch.tv/videos/1410795876"
                                                                                                      
                                                                                                      class loggerOutputs:
                                                                                                          def error(msg):
                                                                                                              print("Captured Error: "+msg)
                                                                                                          def warning(msg):
                                                                                                              print("Captured Warning: "+msg)
                                                                                                          def debug(msg):
                                                                                                              print("Captured Log: "+msg)
                                                                                                      
                                                                                                      
                                                                                                      options = {
                                                                                                          "quiet": True,
                                                                                                          "format": "bestaudio/worst",
                                                                                                          "logger": loggerOutputs,
                                                                                                      }
                                                                                                      
                                                                                                      with youtube_dl.YoutubeDL(options) as ydl:
                                                                                                          try:
                                                                                                              info = ydl.extract_info(url, download=False)
                                                                                                          except DownloadError:
                                                                                                              print("An exception has been caught")
                                                                                                       
                                                                                                      
                                                                                                      Python buffered IO ending early streaming with multiple pipes [BOUNTY]
                                                                                                      Pythondot imgLines of Code : 164dot imgLicense : Strong Copyleft (CC BY-SA 4.0)
                                                                                                      copy iconCopy
                                                                                                      from subprocess import Popen, PIPE, DEVNULL
                                                                                                      import threading
                                                                                                      import time
                                                                                                      
                                                                                                      COPY_BUFSIZE = 65424
                                                                                                      
                                                                                                      playlist = [
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                      ]
                                                                                                      
                                                                                                      
                                                                                                      
                                                                                                      # Writer thread (read from yt-dlp and write to FFmpeg in chunks of COPY_BUFSIZE bytes).
                                                                                                      def writer(yt_dlp_proc, encoder_proc):
                                                                                                          while True:
                                                                                                              yt_dlp_buf = yt_dlp_proc.stdout.read(COPY_BUFSIZE)
                                                                                                              print("READ: yt_dlp")
                                                                                                              if not yt_dlp_buf:
                                                                                                                  print("yt-dlp buffer empty")
                                                                                                                  break
                                                                                                      
                                                                                                              written = encoder_proc.stdin.write(yt_dlp_buf)
                                                                                                              print("WRITE: encoder. Bytes: " + str(written))
                                                                                                          
                                                                                                          encoder_proc.stdin.close()  # Close stdin pipe (closing stdin "pushes" the remaining data to stdout).
                                                                                                          encoder_proc.wait()  # Wait for sub-process finish execution.
                                                                                                      
                                                                                                      
                                                                                                      if __name__ == "__main__":
                                                                                                          rtmp_url = "rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                      
                                                                                                          ffplay_cmd = ['ffplay', '-listen', '1', '-i', rtmp_url] # Start the TCP server first, before the sending client.    
                                                                                                          ffplay_process = Popen(ffplay_cmd, stderr=DEVNULL)  # Use FFplay sub-process for receiving the RTMP video.
                                                                                                      
                                                                                                          stream_cmd = [
                                                                                                              "ffmpeg", "-loglevel", "error",
                                                                                                              "-hide_banner", "-re", "-i", "-",
                                                                                                              "-c:v", "libx264",
                                                                                                              "-f", "flv",
                                                                                                              "-b:v", "3000k", "-minrate", "3000k",
                                                                                                              "-maxrate", "3000k", "-bufsize", "3000k",
                                                                                                              "-r", "25", "-pix_fmt", "yuv420p",
                                                                                                              rtmp_url #"rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                          ]
                                                                                                          print(f'Stream command:\n"{" ".join(stream_cmd)}"')
                                                                                                      
                                                                                                          encoder_cmd = [
                                                                                                              "ffmpeg", "-re", "-i", "-", "-f", "mpegts",
                                                                                                              "-c", "copy", "-"
                                                                                                          ]
                                                                                                          print(f'Encoder command:\n"{" ".join(encoder_cmd)}"')
                                                                                                      
                                                                                                          stream_p = Popen(stream_cmd, stdin=PIPE, stderr=DEVNULL)
                                                                                                      
                                                                                                          for video in playlist:
                                                                                                              yt_dlp_cmd = [
                                                                                                                  "yt-dlp", "-q",
                                                                                                                  video["url"],
                                                                                                                  "-o", "-"
                                                                                                              ]
                                                                                                      
                                                                                                              print("Now playing: " + video["url"])
                                                                                                      
                                                                                                              with Popen(yt_dlp_cmd, stdout=PIPE) as yt_dlp_p:
                                                                                                                  with Popen(encoder_cmd, stdin=PIPE, stdout=PIPE, stderr=DEVNULL) as encoder_p:
                                                                                                      
                                                                                                                      thread = threading.Thread(target=writer, args=(yt_dlp_p, encoder_p))
                                                                                                                      thread.start()  # Start writer thread.
                                                                                                      
                                                                                                                      while True:
                                                                                                                          encoder_buf = encoder_p.stdout.read(COPY_BUFSIZE)
                                                                                                      
                                                                                                                          if not encoder_buf:
                                                                                                                              print("encoder_buf empty")
                                                                                                                              break
                                                                                                      
                                                                                                                          print("READ: encoder")
                                                                                                      
                                                                                                                          stream_bytes_written = stream_p.stdin.write(encoder_buf)
                                                                                                                          print("WRITE: stream, Bytes: " + str(stream_bytes_written))
                                                                                                      
                                                                                                              thread.join()  # Wait for writer thread to end.
                                                                                                              yt_dlp_p.wait()
                                                                                                      
                                                                                                          stream_p.stdin.close()  # Close stdin pipe (closing stdin "pushes" the remaining data to stdout).
                                                                                                          stream_p.wait()  # Wait for sub-process finish execution.
                                                                                                      
                                                                                                      
                                                                                                          time.sleep(3)  # Wait 3 seconds before closing FFplay
                                                                                                          ffplay_process.kill()  # Forcefully close FFplay sub-process
                                                                                                      
                                                                                                      from pytube import YouTube
                                                                                                      from subprocess import Popen, run, PIPE, DEVNULL
                                                                                                      import time
                                                                                                      
                                                                                                      playlist = [
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                      ]
                                                                                                      
                                                                                                      n = len(playlist)
                                                                                                      
                                                                                                      # Build string for concat demuxer https://video.stackexchange.com/a/18256/18277
                                                                                                      filter_complex_str = ''
                                                                                                      for i in range(n):
                                                                                                          filter_complex_str += f'[{i}:v]setpts=PTS-STARTPTS[v{i}];[{i}:a]asetpts=PTS-STARTPTS[a{i}];'   # "[0:v]setpts=PTS-STARTPTS[v0];[0:a]asetpts=PTS-STARTPTS[a0];[1:v]setpts=PTS-STARTPTS[v1];[1:a]asetpts=PTS-STARTPTS[a1];[2:v]setpts=PTS-STARTPTS[v2];[2:a]asetpts=PTS-STARTPTS[a2]"
                                                                                                      for i in range(n):
                                                                                                          filter_complex_str += f'[v{i}][a{i}]'  # ";[v0][a0][v1][a1][v2][a2]"
                                                                                                      filter_complex_str += f'concat=n={n}:v=1:a=1[v][a]'
                                                                                                      
                                                                                                      # Get the video stream URL of every YouTube HTTP URL.
                                                                                                      # Add -i before each URL (to be used as FFmpeg input).
                                                                                                      playlist_url = []
                                                                                                      for video in playlist:
                                                                                                          yt = YouTube(video["url"])
                                                                                                          # https://github.com/pytube/pytube/issues/301
                                                                                                          stream_url = yt.streams[0].url  # Get the URL of the video stream
                                                                                                          playlist_url.append('-i')
                                                                                                          playlist_url.append(stream_url)
                                                                                                      
                                                                                                      
                                                                                                      rtmp_url = "rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                      
                                                                                                      ffplay_cmd = ['ffplay', '-listen', '1', '-i', rtmp_url]  # Start the TCP server first, before the sending client.
                                                                                                      ffplay_process = Popen(ffplay_cmd, stderr=DEVNULL)  # Use FFplay sub-process for receiving the RTMP video.
                                                                                                      
                                                                                                      stream_cmd = [
                                                                                                          "ffmpeg", "-loglevel", "error",
                                                                                                          "-hide_banner", "-re"] + playlist_url + ["-filter_complex",
                                                                                                          filter_complex_str,  # '[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[v][a]'
                                                                                                          "-map", "[v]", "-map", "[a]",
                                                                                                          "-c:v", "libx264",
                                                                                                          "-f", "flv",
                                                                                                          "-b:v", "3000k", "-minrate", "3000k",
                                                                                                          "-maxrate", "3000k", "-bufsize", "3000k",
                                                                                                          "-r", "25", "-pix_fmt", "yuv420p",
                                                                                                          rtmp_url]
                                                                                                      
                                                                                                      run(stream_cmd)
                                                                                                      
                                                                                                      time.sleep(60)  # Wait 60 seconds before closing FFplay
                                                                                                      ffplay_process.kill()  # Forcefully close FFplay sub-process
                                                                                                      
                                                                                                      How to remove "press enter to continue" when running Powershell within Python
                                                                                                      Pythondot imgLines of Code : 2dot imgLicense : Strong Copyleft (CC BY-SA 4.0)
                                                                                                      copy iconCopy
                                                                                                      'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe & {yt-dlp https://www.youtube.com/watch?v=jtjnnykvnh4}'
                                                                                                      
                                                                                                      yt-dlp 'rate-limit' not throttiling speed in Python script
                                                                                                      Pythondot imgLines of Code : 7dot imgLicense : Strong Copyleft (CC BY-SA 4.0)
                                                                                                      copy iconCopy
                                                                                                      ydl_opts = {
                                                                                                              'ratelimit': 500000
                                                                                                          }
                                                                                                      
                                                                                                      with yt_dlp.YoutubeDL(params=ydl_opts) as ydl:
                                                                                                          ydl.download([link]) 
                                                                                                      
                                                                                                      Heroku FFMPEG Postprocessing error with yt-dlp DownloadError
                                                                                                      Pythondot imgLines of Code : 5dot imgLicense : Strong Copyleft (CC BY-SA 4.0)
                                                                                                      copy iconCopy
                                                                                                      'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',
                                                                                                      
                                                                                                      heroku buildpacks:set heroku/python
                                                                                                      heroku buildpacks:add --index 1 https://github.com/FFmpeg/FFmpeg.git
                                                                                                      
                                                                                                      Community Discussions

                                                                                                      Trending Discussions on yt-dlp

                                                                                                      Error adding playlist in yt-dlp discord.py
                                                                                                      chevron right
                                                                                                      How to hide error message from youtube-dl / yt-dlp?
                                                                                                      chevron right
                                                                                                      Porting code from youtube-dl to yt-dlp library for Python Discord Bot
                                                                                                      chevron right
                                                                                                      mpv doesn't recognise ytdl_path as a key
                                                                                                      chevron right
                                                                                                      Heroku FFMPEG Postprocessing error with yt-dlp DownloadError
                                                                                                      chevron right
                                                                                                      grabbing video title from yt-dlp command line output
                                                                                                      chevron right
                                                                                                      How to remove "press enter to continue" when running Powershell within Python
                                                                                                      chevron right
                                                                                                      yt-dlp 'rate-limit' not throttiling speed in Python script
                                                                                                      chevron right
                                                                                                      Abort job on failed fragements yt-dlp
                                                                                                      chevron right
                                                                                                      Python buffered IO ending early streaming with multiple pipes [BOUNTY]
                                                                                                      chevron right

                                                                                                      QUESTION

                                                                                                      Error adding playlist in yt-dlp discord.py
                                                                                                      Asked 2022-Mar-10 at 08:54

                                                                                                      My bot is on Heroku.

                                                                                                      [youtube:tab] PL4fGSI1pDJn5kI81J1fYWK5eZRl1zJ5kM: Downloading webpage
                                                                                                      WARNING: [youtube:tab] unable to extract yt initial data; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using  yt-dlp -U
                                                                                                      WARNING: [youtube:tab] Incomplete yt initial data received. Retrying ...
                                                                                                      [youtube:tab] PL4fGSI1pDJn5kI81J1fYWK5eZRl1zJ5kM: Downloading webpage (retry #1)
                                                                                                      WARNING: [youtube:tab] unable to extract yt initial data; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using  yt-dlp -U
                                                                                                      WARNING: [youtube:tab] Incomplete yt initial data received. Retrying ...
                                                                                                      [youtube:tab] PL4fGSI1pDJn5kI81J1fYWK5eZRl1zJ5kM: Downloading webpage (retry #2)
                                                                                                      WARNING: [youtube:tab] unable to extract yt initial data; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using  yt-dlp -U
                                                                                                      WARNING: [youtube:tab] Incomplete yt initial data received. Retrying ...
                                                                                                      [youtube:tab] PL4fGSI1pDJn5kI81J1fYWK5eZRl1zJ5kM: Downloading webpage (retry #3)
                                                                                                      WARNING: [youtube:tab] unable to extract yt initial data; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using  yt-dlp -U
                                                                                                      WARNING: [youtube:tab] Incomplete yt initial data received
                                                                                                      ERROR: [youtube:tab] PL4fGSI1pDJn5kI81J1fYWK5eZRl1zJ5kM: Playlists that require authentication may not extract correctly without a successful webpage download. If you are not downloading private content, or your cookies are only for the first account and channel, pass "--extractor-args youtubetab:skip=authcheck" to skip this check 
                                                                                                      

                                                                                                      If I write to the heroku console:

                                                                                                      yt-dlp --cookies cookies.txt https://www.youtube.com/playlist?list=PLSdfU8nTff5QcNqq-muG9AZrYiVy4S3zV

                                                                                                      the download of music starts (music is not played), but each time it is not very good to write a command to the console. Thanks in advance for your help

                                                                                                      ANSWER

                                                                                                      Answered 2022-Mar-10 at 08:54

                                                                                                      removed from code: "cookiefile": "/config/cookies/cookies.txt" and everything worked

                                                                                                      Source https://stackoverflow.com/questions/71412022

                                                                                                      QUESTION

                                                                                                      How to hide error message from youtube-dl / yt-dlp?
                                                                                                      Asked 2022-Mar-02 at 20:27

                                                                                                      I'm using yt-dlp (in Python) to extract information from Twitch videos.

                                                                                                      If I try to extract information from a non-existing video or a private one, I get an exception, which is the expected behaviour. But if I set to "quiet" mode and if I catch the potential exception, and I still get the error logged. Here is the code:

                                                                                                      import yt_dlp as youtube_dl
                                                                                                      from yt_dlp.utils import DownloadError
                                                                                                      
                                                                                                      
                                                                                                      url = "https://www.twitch.tv/videos/1410795876"
                                                                                                      
                                                                                                      options = {
                                                                                                          "quiet": True,
                                                                                                          "format": "bestaudio/worst",
                                                                                                      }
                                                                                                      
                                                                                                      with youtube_dl.YoutubeDL(options) as ydl:
                                                                                                          try:
                                                                                                              info = ydl.extract_info(url, download=False)
                                                                                                          except DownloadError:
                                                                                                              print("An exception has been caught")
                                                                                                      

                                                                                                      When using this script, the output is the following:

                                                                                                      ERROR: [twitch:vod] 1410795876: Failed to download m3u8 information: HTTP Error 403: Forbidden (caused by ); please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using -U (caused by ); please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using -U
                                                                                                      An exception has been caught
                                                                                                      

                                                                                                      Is there a way to hide this error log? And if not, is there a way using yt-dlp to check that the video is accessible so that I will not call extract_info if the video is not? Thank you.

                                                                                                      ANSWER

                                                                                                      Answered 2022-Mar-02 at 20:27

                                                                                                      I guess that the easiest way to hide all logging errors is by implementing your own log handler. Consider the following change to your code, I'm sure you'll figure out how to implement what you want from here:

                                                                                                      import yt_dlp as youtube_dl
                                                                                                      from yt_dlp.utils import DownloadError
                                                                                                      
                                                                                                      
                                                                                                      url = "https://www.twitch.tv/videos/1410795876"
                                                                                                      
                                                                                                      class loggerOutputs:
                                                                                                          def error(msg):
                                                                                                              print("Captured Error: "+msg)
                                                                                                          def warning(msg):
                                                                                                              print("Captured Warning: "+msg)
                                                                                                          def debug(msg):
                                                                                                              print("Captured Log: "+msg)
                                                                                                      
                                                                                                      
                                                                                                      options = {
                                                                                                          "quiet": True,
                                                                                                          "format": "bestaudio/worst",
                                                                                                          "logger": loggerOutputs,
                                                                                                      }
                                                                                                      
                                                                                                      with youtube_dl.YoutubeDL(options) as ydl:
                                                                                                          try:
                                                                                                              info = ydl.extract_info(url, download=False)
                                                                                                          except DownloadError:
                                                                                                              print("An exception has been caught")
                                                                                                       
                                                                                                      

                                                                                                      In the following example they disable logging by implementing a "FakeLogger": https://github.com/ytdl-org/youtube-dl/blob/master/test/test_http.py

                                                                                                      Source https://stackoverflow.com/questions/71326109

                                                                                                      QUESTION

                                                                                                      Porting code from youtube-dl to yt-dlp library for Python Discord Bot
                                                                                                      Asked 2022-Feb-27 at 12:23

                                                                                                      This is my first question here therefore I hope this format is fine. I've searched for the issue on internet and checked the documentation of yt-dlp however could not find something useful or maybe I just dont understand what to do.

                                                                                                      In a normal case, I was using youtube-dl to download musics from youtube and play it in my discord bot but its download rate restrictions became problematic (60-80 KiB/s). For this reason I started the use yt-dlp. It works fine if I use url directly. However, when I use a searchword instead of url, seems like code does not extract the info to get url. (Below code was working fine with youtube-dl too) Here is the code:

                                                                                                      @bot.command()
                                                                                                      async def play(ctx, *, searchword):
                                                                                                          ydl_opts = {}
                                                                                                          voice = ctx.voice_client
                                                                                                      
                                                                                                          #get the title and url from video
                                                                                                      

                                                                                                      Below code works fine with direct url but when I write something such as (! is my command prefix by the way) !play By the Sword download does not start but console says:

                                                                                                      Downloading playlist: By the Sword
                                                                                                      
                                                                                                          if searchword[0:4] == "http" or searchword[0:3] == "www":
                                                                                                              with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                                                                                                                  info = ydl.extract_info(searchword, download = False)
                                                                                                                  title = info["title"]
                                                                                                                  url = searchword
                                                                                                       
                                                                                                          if searchword[0:4] != "http" and searchword[0:3] != "www":
                                                                                                              with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                                                                                                                  info = ydl.extract_info(f"ytsearch:{searchword}", download = False)["entries"][0]
                                                                                                                  title = info["title"]
                                                                                                                  url = info["webpage_url"]
                                                                                                       
                                                                                                      
                                                                                                          ydl_opts = {
                                                                                                              'format' : 'bestaudio/best',
                                                                                                              "outtmpl" : f"{title}.mp3",
                                                                                                              "postprocessors": 
                                                                                                              [{"key" : "FFmpegExtractAudio", "preferredcodec" : "mp3", "preferredquality" : "192"}],   
                                                                                                          }
                                                                                                      
                                                                                                      
                                                                                                      
                                                                                                          def download(url):
                                                                                                              with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                                                                                                                  ydl.download([url])
                                                                                                          loop = asyncio.get_event_loop()
                                                                                                          await loop.run_in_executor(None, download, url)
                                                                                                      
                                                                                                      
                                                                                                          #playing and queueing audio
                                                                                                          if voice.is_playing():
                                                                                                              queuelist.append(title)
                                                                                                              await ctx.send(f"Added to queue: {title}")
                                                                                                          else:
                                                                                                              voice.play(discord.FFmpegPCMAudio(f"{title}.mp3"), after = lambda e : check_queue())
                                                                                                              await ctx.send(f"Playing {title} !!!")
                                                                                                              filestodelete.append(title)
                                                                                                      
                                                                                                          def check_queue():
                                                                                                              try:
                                                                                                                  if queuelist[0] != None:
                                                                                                                      voice.play(discord.FFmpegPCMAudio(f"{queuelist[0]}.mp3"), after = lambda e : check_queue())
                                                                                                                      filestodelete.append(queuelist[0])
                                                                                                                      queuelist.pop(0)
                                                                                                              except IndexError:
                                                                                                                  for file in filestodelete:
                                                                                                                      os.remove(f"{file}.mp3")
                                                                                                                  filestodelete.clear() 
                                                                                                      
                                                                                                      

                                                                                                      I am not sure if the problem is about

                                                                                                      info = ydl.extract_info(f"ytsearch:{searchword}", download = False)["entries"][0]
                                                                                                      

                                                                                                      or downloading itself. Documentation of yt-dlp says that,

                                                                                                      Tip: If you are porting your code from youtube-dl to yt-dlp, one important point to look out for is that we do not guarantee the return value of YoutubeDL.extract_info to be json serializable, or even be a dictionary. It will be dictionary-like, but if you want to ensure it is a serializable dictionary, pass it through YoutubeDL.sanitize_info as shown in the example above

                                                                                                      Here is the link: https://github.com/yt-dlp/yt-dlp#embedding-yt-dlp Thanks.

                                                                                                      ANSWER

                                                                                                      Answered 2022-Feb-27 at 12:23

                                                                                                      Apparently, I solved the issue by myself by using a different way. As I mentioned above youtube_dl works fine however yt_dlp .extract_info() is problematic. A simple solution to fix this is extracting info by using youtube_dl module, then download file by using yt_dlp.

                                                                                                      Use this for downlaoding:

                                                                                                      with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                                                                                                                  ydl.download([url])
                                                                                                      

                                                                                                      But this for extracting url and title from a given string which is not URL

                                                                                                      if searchword[0:4] != "http" and searchword[0:3] != "www":
                                                                                                              with youtube_dl.YoutubeDL(ydl_opts) as ydl:
                                                                                                                  info = ydl.extract_info(f"ytsearch:{searchword}", download = False)["entries"][0]
                                                                                                                  title = info["title"]
                                                                                                                  url = info["webpage_url"]
                                                                                                      

                                                                                                      Do not forget to include both modules!

                                                                                                      Source https://stackoverflow.com/questions/70979155

                                                                                                      QUESTION

                                                                                                      mpv doesn't recognise ytdl_path as a key
                                                                                                      Asked 2022-Feb-19 at 18:05

                                                                                                      I'm trying to use yt-dlp rather than youtube-dl due to the bottlenecking on download speeds in youtube-dl but I can't get it to work.

                                                                                                      My mpv.conf file looks like:

                                                                                                      script-opts=ytdl_hook-ytdl_path=/usr/local/bin/yt-dlp

                                                                                                      When trying to get mpv to run I get this warning:

                                                                                                      [ytdl_hook] script-opts: unknown key ytdl_path, ignoring

                                                                                                      Does anyone know what the problem is? I've read through the mpv docs and it says this should work.

                                                                                                      mpv is version 0.27.2

                                                                                                      ANSWER

                                                                                                      Answered 2022-Feb-19 at 18:05

                                                                                                      I had the same problem as you, on mpv version 0.32.0. The problem is that the ytdl-hook settings category is not an option in these older versions. Your solutions are to update your mpv version or to create a link from youtube-dl to yt-dlp. Hope this helps.

                                                                                                      Source https://stackoverflow.com/questions/70748046

                                                                                                      QUESTION

                                                                                                      Heroku FFMPEG Postprocessing error with yt-dlp DownloadError
                                                                                                      Asked 2022-Feb-14 at 00:57

                                                                                                      I am building a discord music bot that uses FFMPEG to download and play the music. yt-dlp seems to not be able to find the ffmpeg file for some reason although I give it the direct path. It works perfectly fine whe I run it on my cpu, but it doesn't work in heroku.

                                                                                                      Here's the error in heroku:

                                                                                                      2022-02-14T00:34:29.047823+00:00 app[worker.1]: During handling of the above exception, another exception occurred:
                                                                                                      2022-02-14T00:34:29.047823+00:00 app[worker.1]: 
                                                                                                      2022-02-14T00:34:29.047825+00:00 app[worker.1]: Traceback (most recent call last):
                                                                                                      2022-02-14T00:34:29.047854+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/discord/client.py", line 343, in _run_event
                                                                                                      2022-02-14T00:34:29.047855+00:00 app[worker.1]:     await coro(*args, **kwargs)
                                                                                                      2022-02-14T00:34:29.047856+00:00 app[worker.1]:   File "/app/engine.py", line 97, in on_reaction_add
                                                                                                      2022-02-14T00:34:29.047856+00:00 app[worker.1]:     ydl.download([f'{result["link"]}'])
                                                                                                      2022-02-14T00:34:29.047863+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3212, in download
                                                                                                      2022-02-14T00:34:29.047863+00:00 app[worker.1]:     self.__download_wrapper(self.extract_info)(
                                                                                                      2022-02-14T00:34:29.047865+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3185, in wrapper
                                                                                                      2022-02-14T00:34:29.047865+00:00 app[worker.1]:     res = func(*args, **kwargs)
                                                                                                      2022-02-14T00:34:29.047875+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1372, in extract_info
                                                                                                      2022-02-14T00:34:29.047876+00:00 app[worker.1]:     return self.__extract_info(url, self.get_info_extractor(ie_key), download, extra_info, process)
                                                                                                      2022-02-14T00:34:29.047877+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1381, in wrapper
                                                                                                      2022-02-14T00:34:29.047877+00:00 app[worker.1]:     return func(self, *args, **kwargs)
                                                                                                      2022-02-14T00:34:29.047891+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1465, in __extract_info
                                                                                                      2022-02-14T00:34:29.047891+00:00 app[worker.1]:     return self.process_ie_result(ie_result, download, extra_info)
                                                                                                      2022-02-14T00:34:29.047893+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 1517, in process_ie_result
                                                                                                      2022-02-14T00:34:29.047894+00:00 app[worker.1]:     ie_result = self.process_video_result(ie_result, download=download)
                                                                                                      2022-02-14T00:34:29.047894+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 2607, in process_video_result
                                                                                                      2022-02-14T00:34:29.047894+00:00 app[worker.1]:     self.process_info(new_info)
                                                                                                      2022-02-14T00:34:29.047896+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 3161, in process_info
                                                                                                      2022-02-14T00:34:29.047896+00:00 app[worker.1]:     self.report_error('Postprocessing: %s' % str(err))
                                                                                                      2022-02-14T00:34:29.047904+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 930, in report_error
                                                                                                      2022-02-14T00:34:29.047904+00:00 app[worker.1]:     self.trouble(f'{self._format_err("ERROR:", self.Styles.ERROR)} {message}', *args, **kwargs)
                                                                                                      2022-02-14T00:34:29.047905+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/yt_dlp/YoutubeDL.py", line 871, in trouble
                                                                                                      2022-02-14T00:34:29.047905+00:00 app[worker.1]:     raise DownloadError(message, exc_info)
                                                                                                      2022-02-14T00:34:29.047921+00:00 app[worker.1]: yt_dlp.utils.DownloadError: ERROR: Postprocessing: ffprobe and ffmpeg not found. Please install or provide the path using --ffmpeg-location
                                                                                                      

                                                                                                      Here's my setup: ![root level directory]: https://i.stack.imgur.com/HKo8L.png

                                                                                                      Here's the code:

                                                                                                      yt_opts = {
                                                                                                              'format': 'bestaudio/best',
                                                                                                              'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',
                                                                                                              'postprocessors': [{
                                                                                                                  'key': 'FFmpegExtractAudio',
                                                                                                                  'preferredcodec': 'mp3',
                                                                                                                  'preferredquality': '192',
                                                                                                              }]
                                                                                                          }
                                                                                                      # Getting Song From Thy YOUTUBE
                                                                                                           await channel.send("> Getting Song From Youtube")
                                                                                                           with yt_dlp.YoutubeDL(yt_opts) as ydl:
                                                                                                                ydl.download([f'{result["link"]}'])
                                                                                                      

                                                                                                      ANSWER

                                                                                                      Answered 2022-Feb-14 at 00:57

                                                                                                      You can't do this:

                                                                                                      'ffmpeg_location': './FFMPEG_CONFIG/ffmpeg.exe',
                                                                                                      

                                                                                                      ffmpeg.exe is a Windows binary. It cannot be used on Heroku (and should not be part of your repository to begin with).

                                                                                                      Most users who want to use ffmpeg on Heroku use the buildpack (see also multiple buildpacks), e.g.:

                                                                                                      heroku buildpacks:set heroku/python
                                                                                                      heroku buildpacks:add --index 1 https://github.com/FFmpeg/FFmpeg.git
                                                                                                      

                                                                                                      Then remove that hard-coded ffmpeg_location, commit, and redeploy. Your app should find ffmpeg.

                                                                                                      For local development you have a couple of of options:

                                                                                                      • Update your PATH to make sure ffmpeg.exe can be found
                                                                                                      • Update your code to set an ffmpeg_location, ideally from an environment variable

                                                                                                      Source https://stackoverflow.com/questions/71106114

                                                                                                      QUESTION

                                                                                                      grabbing video title from yt-dlp command line output
                                                                                                      Asked 2022-Jan-07 at 15:39
                                                                                                      from yt_dlp import YoutubeDL
                                                                                                      
                                                                                                      with YoutubeDL() as ydl:
                                                                                                          ydl.download('https://youtu.be/0KFSuoHEYm0')
                                                                                                      

                                                                                                      this is the relevant bit of code producing the output.

                                                                                                      what I would like to do is grab the 2nd last line from the output below, specifying the video title.

                                                                                                      I have tried a few variations of

                                                                                                      output = subprocess.getoutput(ydl)
                                                                                                      

                                                                                                      as well as

                                                                                                      output = subprocess.Popen( ydl, stdout=subprocess.PIPE ).communicate()[0]
                                                                                                      

                                                                                                      the output I am attempting to capture is the 2nd last line here:

                                                                                                      [youtube] 0KFSuoHEYm0: Downloading webpage
                                                                                                      [youtube] 0KFSuoHEYm0: Downloading android player API JSON
                                                                                                      [info] 0KFSuoHEYm0: Downloading 1 format(s): 22
                                                                                                      [download] Destination: TJ Watt gets his 4th sack of the game vs. Browns [0KFSuoHEYm0].mp4
                                                                                                      [download] 100% of 13.10MiB in 00:01 
                                                                                                      
                                                                                                           
                                                                                                      

                                                                                                      There is also documentation on yt-dlp on how to pull title from metadata or include as something in the brackets behind YoutubeDL(), but I can not quite figure it out.

                                                                                                      This is part of the first project I am making in python. I am missing an understanding of many concepts any help would be much appreciated.

                                                                                                      ANSWER

                                                                                                      Answered 2022-Jan-07 at 15:39

                                                                                                      Credits: answer to question: How to get information from youtube-dl in python ??

                                                                                                      Modify your code as follows:

                                                                                                      from yt_dlp import YoutubeDL
                                                                                                      
                                                                                                      with YoutubeDL() as ydl: 
                                                                                                        info_dict = ydl.extract_info('https://youtu.be/0KFSuoHEYm0', download=False)
                                                                                                        video_url = info_dict.get("url", None)
                                                                                                        video_id = info_dict.get("id", None)
                                                                                                        video_title = info_dict.get('title', None)
                                                                                                        print("Title: " + video_title) # <= Here, you got the video title
                                                                                                      

                                                                                                      This is the output:

                                                                                                      #[youtube] 0KFSuoHEYm0: Downloading webpage
                                                                                                      #[youtube] 0KFSuoHEYm0: Downloading android player API JSON
                                                                                                      #Title: TJ Watt gets his 4th sack of the game vs. Browns
                                                                                                      

                                                                                                      Source https://stackoverflow.com/questions/70583652

                                                                                                      QUESTION

                                                                                                      How to remove "press enter to continue" when running Powershell within Python
                                                                                                      Asked 2022-Jan-07 at 03:42

                                                                                                      Edited* Solution: Remove "pause". I'm running a python script which calls upon powershell to execute a line of code:

                                                                                                      def download():
                                                                                                          subprocess.call('C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe yt-dlp https://www.youtube.com/watch?v=jtjnnykvnh4;pause', shell=True)
                                                                                                      
                                                                                                      download()
                                                                                                      

                                                                                                      The problem was that after executing, it would output "Press Enter to continue..." This interrupts the program.*in my original example I forgot to include the ";pause" which is what turned out to be what was causing the interruption in the program, as kindly pointed out by the marked answer. Below is the fixed line of code which does not prompt "press enter to continue" after running:

                                                                                                      def download():
                                                                                                          subprocess.call('C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe yt-dlp https://www.youtube.com/watch?v=jtjnnykvnh4;kill $pid', shell=True)
                                                                                                      
                                                                                                      download()
                                                                                                      

                                                                                                      Apologies for confusion caused by the original post. Thanks for the help.

                                                                                                      ANSWER

                                                                                                      Answered 2022-Jan-07 at 03:17

                                                                                                      PowerShell normally exits unless you specify -NoExit at the commandline. Even then it will not include the message you are seeing unless you add a pause at the end instead. Even so, I would expect your command to look more like

                                                                                                      'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe & {yt-dlp https://www.youtube.com/watch?v=jtjnnykvnh4}'
                                                                                                      

                                                                                                      My guess this has more to do with Python, though I have not encountered it before...have you tried executing the PowerShell line from another commandline (cmd on Windows or bash on Linux/Mac or another favourite) to verify that you get the same result independently of Python?

                                                                                                      Another possibility is that it is the yt-dlp tool that you are using that has the pause effect (I am not familiar with the tool). Is it a PowerShell module? Or is it something that can be run on the commandline and you don't need PowerShell as a middleman anyway? Would it have a "silent" or "-q" argument, or another more relevant argument?

                                                                                                      Source https://stackoverflow.com/questions/70615340

                                                                                                      QUESTION

                                                                                                      yt-dlp 'rate-limit' not throttiling speed in Python script
                                                                                                      Asked 2021-Nov-16 at 17:18

                                                                                                      I have implemented yt-dlp as part of my Python script, it works well, but I am unable to get the rate-limit feature to work. If you run the same command from the CLI the rate is limited correctly, is anyone able to tell me the correct syntax?

                                                                                                      I have tried several combinations such as rate-limit, limit-rate 0.5m, 500k, 500KiB, 500, and none seem to work

                                                                                                              ydl_opts = {
                                                                                                              'limit-rate': '500k',
                                                                                                      
                                                                                                          }
                                                                                                      
                                                                                                          with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                                                                                                              ydl.download([link]) 
                                                                                                      

                                                                                                      I am using the docs here; https://github.com/yt-dlp/yt-dlp But am confused as the CLI command works but not the embedded script version,

                                                                                                      I also tried replacing - with _ but still to no effect, do you have any ideas? Other options in the ydl_opts work without issue

                                                                                                      Hopefully we can resolve the correct syntax rather than having to implement Trickle or throttling the socket

                                                                                                      Thank you if you can help

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-07 at 17:07

                                                                                                      Looking at the source code you'll find that the option you're looking for is called ratelimit. Its value should be a float:

                                                                                                      ydl_opts = {
                                                                                                              'ratelimit': 500000
                                                                                                          }
                                                                                                      
                                                                                                      with yt_dlp.YoutubeDL(params=ydl_opts) as ydl:
                                                                                                          ydl.download([link]) 
                                                                                                      

                                                                                                      Source https://stackoverflow.com/questions/69871651

                                                                                                      QUESTION

                                                                                                      Abort job on failed fragements yt-dlp
                                                                                                      Asked 2021-Nov-16 at 16:50

                                                                                                      I've written a downloader in python 3.9.1 that utilizes yt-dlp, using this format:

                                                                                                      outTmpl = "{}"
                                                                                                      rows = c.fetchall()
                                                                                                      ydl_opts = dict()
                                                                                                      for row in rows:
                                                                                                          ydl_opts = {
                                                                                                          'verbose': True,
                                                                                                          'outtmpl': outTmpl.format(row[1]),
                                                                                                          'abort-on-unavailable-fragment': True,
                                                                                                          }
                                                                                                          with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                                                                                                              ydl.download([row[0]])
                                                                                                      

                                                                                                      However some downloads skip fragments (due to timeouts or whatever), leaving me with something that is cut short.

                                                                                                      Any idea what i need to put in the ydl_opts? I thought 'abort-on-unavailable-fragment': True would suffice, but the download carries on and processes the file with ffmpeg.

                                                                                                      Any idea how i fix this please and if it starts failing to download segments, just abort the job and remove any files its created? Maybe the option i'm calling is incorrect?

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-16 at 16:50

                                                                                                      The option is named skip_unavailable_fragments. See the docstring of FragmentFD

                                                                                                      if it starts failing to download segments, just abort the job and remove any files its created?

                                                                                                      There is no functionality in yt-dlp to automatically remove the temporary files. You will have to catch the error and do it yourself

                                                                                                      Source https://stackoverflow.com/questions/69947067

                                                                                                      QUESTION

                                                                                                      Python buffered IO ending early streaming with multiple pipes [BOUNTY]
                                                                                                      Asked 2021-Nov-07 at 18:06

                                                                                                      I'm trying to make a continuous livestream of videos downloaded via yt-dlp. I need to port this (working) bash command into Python.

                                                                                                      (
                                                                                                          youtube-dl -v --buffer-size 16k https://youtube.com/watch?v=QiInzFHIDp4 -o - | ffmpeg -i - -f mpegts -c copy - ;
                                                                                                          youtube-dl -v --buffer-size 16k https://youtube.com/watch?v=QiInzFHIDp4 -o - | ffmpeg -i - -f mpegts -c copy - ;
                                                                                                      ) | ffmpeg -re -i - -c:v libx264 -f flv rtmp://127.0.0.1/live/H1P_x5WPF
                                                                                                      

                                                                                                      My Python attempt is cutting off the last ~2 seconds of each video. My suspicion is that although the first pipe, yt-dlp, has an empty stdout, there is still data travelling between the second and third pipe. I haven't been able to figure out a way to properly handle the data between those two pipes at the end of the video.

                                                                                                      from subprocess import Popen, PIPE, DEVNULL
                                                                                                      
                                                                                                      COPY_BUFSIZE = 65424
                                                                                                      
                                                                                                      playlist = [
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                      ]
                                                                                                      
                                                                                                      if __name__ == "__main__":
                                                                                                          stream_cmd = [
                                                                                                              "ffmpeg", "-loglevel", "error",
                                                                                                              "-hide_banner", "-re", "-i", "-",
                                                                                                              "-c:v", "libx264",
                                                                                                              "-f", "flv",
                                                                                                              "-b:v", "3000k", "-minrate", "3000k",
                                                                                                              "-maxrate", "3000k", "-bufsize", "3000k",
                                                                                                              "-r", "25", "-pix_fmt", "yuv420p",
                                                                                                              "rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                          ]
                                                                                                          print(f'Stream command:\n"{" ".join(stream_cmd)}"')
                                                                                                      
                                                                                                          encoder_cmd = [
                                                                                                              "ffmpeg", "-re", "-i", "-", "-f", "mpegts",
                                                                                                              "-c", "copy", "-"
                                                                                                          ]
                                                                                                          print(f'Encoder command:\n"{" ".join(encoder_cmd)}"')
                                                                                                      
                                                                                                          stream_p = Popen(stream_cmd, stdin=PIPE, stderr=DEVNULL)
                                                                                                      
                                                                                                          for video in playlist:
                                                                                                              yt_dlp_cmd = [
                                                                                                                  "yt-dlp", "-q",
                                                                                                                  video["url"],
                                                                                                                  "-o", "-"
                                                                                                              ]
                                                                                                      
                                                                                                              print("Now playing: " + video["url"])
                                                                                                      
                                                                                                              with Popen(yt_dlp_cmd, stdout=PIPE) as yt_dlp_p:
                                                                                                                  with Popen(encoder_cmd, stdin=PIPE, stdout=PIPE, stderr=DEVNULL) as encoder_p:
                                                                                                                      while True:
                                                                                                                          yt_dlp_buf = yt_dlp_p.stdout.read(COPY_BUFSIZE)
                                                                                                                          print("READ: yt_dlp")
                                                                                                                          if not yt_dlp_buf:
                                                                                                                              print("yt-dlp buffer empty")
                                                                                                                              # Handle any data in 2nd/3rd pipes before breaking?
                                                                                                                              break
                                                                                                      
                                                                                                                          written = encoder_p.stdin.write(yt_dlp_buf)
                                                                                                                          print("WRITE: encoder. Bytes: " + str(written))
                                                                                                      
                                                                                                                          encoder_buf = encoder_p.stdout.read(COPY_BUFSIZE)
                                                                                                                          # if not encoder_buf:
                                                                                                                          #     print("encoder_buf empty")
                                                                                                                          #     break
                                                                                                                          print("READ: encoder")
                                                                                                      
                                                                                                                          stream_bytes_written = stream_p.stdin.write(encoder_buf)
                                                                                                                          print("WRITE: stream, Bytes: " + str(stream_bytes_written))
                                                                                                      

                                                                                                      $20 BTC bounty to anyone who can help.

                                                                                                      Running Python 3.6.9 on MacOS.

                                                                                                      ANSWER

                                                                                                      Answered 2021-Nov-07 at 18:06

                                                                                                      Closing the stdin pipe is required for "pushing" the sub-process remaining (buffered) data to stdout pipe.

                                                                                                      For example, add encoder_p.stdin.close() after finish writing all data to encoder_p.stdin.

                                                                                                      I don't understand how your code is working.
                                                                                                      In my machine, it gets stack at encoder_buf = encoder_p.stdout.read(COPY_BUFSIZE).

                                                                                                      I solved the problem using a "writer thread".
                                                                                                      The "writer thread" reads data from yt_dlp_p and write it to encoder_p.stdin.

                                                                                                      Note: In your specific case, it could work without a thread (because the data is just passed through FFmpeg, and not being encoded), but usually, the encoded data is not ready right after writing the input to FFmpeg.

                                                                                                      My code sample uses FFplay sub-process for playing the video (we need the video player because the RTMP streaming requires a "listener" in order to keep streaming).

                                                                                                      Here is a complete code sample:

                                                                                                      from subprocess import Popen, PIPE, DEVNULL
                                                                                                      import threading
                                                                                                      import time
                                                                                                      
                                                                                                      COPY_BUFSIZE = 65424
                                                                                                      
                                                                                                      playlist = [
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                      ]
                                                                                                      
                                                                                                      
                                                                                                      
                                                                                                      # Writer thread (read from yt-dlp and write to FFmpeg in chunks of COPY_BUFSIZE bytes).
                                                                                                      def writer(yt_dlp_proc, encoder_proc):
                                                                                                          while True:
                                                                                                              yt_dlp_buf = yt_dlp_proc.stdout.read(COPY_BUFSIZE)
                                                                                                              print("READ: yt_dlp")
                                                                                                              if not yt_dlp_buf:
                                                                                                                  print("yt-dlp buffer empty")
                                                                                                                  break
                                                                                                      
                                                                                                              written = encoder_proc.stdin.write(yt_dlp_buf)
                                                                                                              print("WRITE: encoder. Bytes: " + str(written))
                                                                                                          
                                                                                                          encoder_proc.stdin.close()  # Close stdin pipe (closing stdin "pushes" the remaining data to stdout).
                                                                                                          encoder_proc.wait()  # Wait for sub-process finish execution.
                                                                                                      
                                                                                                      
                                                                                                      if __name__ == "__main__":
                                                                                                          rtmp_url = "rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                      
                                                                                                          ffplay_cmd = ['ffplay', '-listen', '1', '-i', rtmp_url] # Start the TCP server first, before the sending client.    
                                                                                                          ffplay_process = Popen(ffplay_cmd, stderr=DEVNULL)  # Use FFplay sub-process for receiving the RTMP video.
                                                                                                      
                                                                                                          stream_cmd = [
                                                                                                              "ffmpeg", "-loglevel", "error",
                                                                                                              "-hide_banner", "-re", "-i", "-",
                                                                                                              "-c:v", "libx264",
                                                                                                              "-f", "flv",
                                                                                                              "-b:v", "3000k", "-minrate", "3000k",
                                                                                                              "-maxrate", "3000k", "-bufsize", "3000k",
                                                                                                              "-r", "25", "-pix_fmt", "yuv420p",
                                                                                                              rtmp_url #"rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                          ]
                                                                                                          print(f'Stream command:\n"{" ".join(stream_cmd)}"')
                                                                                                      
                                                                                                          encoder_cmd = [
                                                                                                              "ffmpeg", "-re", "-i", "-", "-f", "mpegts",
                                                                                                              "-c", "copy", "-"
                                                                                                          ]
                                                                                                          print(f'Encoder command:\n"{" ".join(encoder_cmd)}"')
                                                                                                      
                                                                                                          stream_p = Popen(stream_cmd, stdin=PIPE, stderr=DEVNULL)
                                                                                                      
                                                                                                          for video in playlist:
                                                                                                              yt_dlp_cmd = [
                                                                                                                  "yt-dlp", "-q",
                                                                                                                  video["url"],
                                                                                                                  "-o", "-"
                                                                                                              ]
                                                                                                      
                                                                                                              print("Now playing: " + video["url"])
                                                                                                      
                                                                                                              with Popen(yt_dlp_cmd, stdout=PIPE) as yt_dlp_p:
                                                                                                                  with Popen(encoder_cmd, stdin=PIPE, stdout=PIPE, stderr=DEVNULL) as encoder_p:
                                                                                                      
                                                                                                                      thread = threading.Thread(target=writer, args=(yt_dlp_p, encoder_p))
                                                                                                                      thread.start()  # Start writer thread.
                                                                                                      
                                                                                                                      while True:
                                                                                                                          encoder_buf = encoder_p.stdout.read(COPY_BUFSIZE)
                                                                                                      
                                                                                                                          if not encoder_buf:
                                                                                                                              print("encoder_buf empty")
                                                                                                                              break
                                                                                                      
                                                                                                                          print("READ: encoder")
                                                                                                      
                                                                                                                          stream_bytes_written = stream_p.stdin.write(encoder_buf)
                                                                                                                          print("WRITE: stream, Bytes: " + str(stream_bytes_written))
                                                                                                      
                                                                                                              thread.join()  # Wait for writer thread to end.
                                                                                                              yt_dlp_p.wait()
                                                                                                      
                                                                                                          stream_p.stdin.close()  # Close stdin pipe (closing stdin "pushes" the remaining data to stdout).
                                                                                                          stream_p.wait()  # Wait for sub-process finish execution.
                                                                                                      
                                                                                                      
                                                                                                          time.sleep(3)  # Wait 3 seconds before closing FFplay
                                                                                                          ffplay_process.kill()  # Forcefully close FFplay sub-process
                                                                                                      
                                                                                                      Update:

                                                                                                      I found a simpler solution using pytube and concat filter (without pipes).

                                                                                                      I don't know if the solution is relevant for you...

                                                                                                      Code sample:

                                                                                                      from pytube import YouTube
                                                                                                      from subprocess import Popen, run, PIPE, DEVNULL
                                                                                                      import time
                                                                                                      
                                                                                                      playlist = [
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                          {
                                                                                                              # 15 second video
                                                                                                              "url": "https://youtube.com/watch?v=QiInzFHIDp4"
                                                                                                          },
                                                                                                      ]
                                                                                                      
                                                                                                      n = len(playlist)
                                                                                                      
                                                                                                      # Build string for concat demuxer https://video.stackexchange.com/a/18256/18277
                                                                                                      filter_complex_str = ''
                                                                                                      for i in range(n):
                                                                                                          filter_complex_str += f'[{i}:v]setpts=PTS-STARTPTS[v{i}];[{i}:a]asetpts=PTS-STARTPTS[a{i}];'   # "[0:v]setpts=PTS-STARTPTS[v0];[0:a]asetpts=PTS-STARTPTS[a0];[1:v]setpts=PTS-STARTPTS[v1];[1:a]asetpts=PTS-STARTPTS[a1];[2:v]setpts=PTS-STARTPTS[v2];[2:a]asetpts=PTS-STARTPTS[a2]"
                                                                                                      for i in range(n):
                                                                                                          filter_complex_str += f'[v{i}][a{i}]'  # ";[v0][a0][v1][a1][v2][a2]"
                                                                                                      filter_complex_str += f'concat=n={n}:v=1:a=1[v][a]'
                                                                                                      
                                                                                                      # Get the video stream URL of every YouTube HTTP URL.
                                                                                                      # Add -i before each URL (to be used as FFmpeg input).
                                                                                                      playlist_url = []
                                                                                                      for video in playlist:
                                                                                                          yt = YouTube(video["url"])
                                                                                                          # https://github.com/pytube/pytube/issues/301
                                                                                                          stream_url = yt.streams[0].url  # Get the URL of the video stream
                                                                                                          playlist_url.append('-i')
                                                                                                          playlist_url.append(stream_url)
                                                                                                      
                                                                                                      
                                                                                                      rtmp_url = "rtmp://127.0.0.1/live/H1P_x5WPF"
                                                                                                      
                                                                                                      ffplay_cmd = ['ffplay', '-listen', '1', '-i', rtmp_url]  # Start the TCP server first, before the sending client.
                                                                                                      ffplay_process = Popen(ffplay_cmd, stderr=DEVNULL)  # Use FFplay sub-process for receiving the RTMP video.
                                                                                                      
                                                                                                      stream_cmd = [
                                                                                                          "ffmpeg", "-loglevel", "error",
                                                                                                          "-hide_banner", "-re"] + playlist_url + ["-filter_complex",
                                                                                                          filter_complex_str,  # '[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[v][a]'
                                                                                                          "-map", "[v]", "-map", "[a]",
                                                                                                          "-c:v", "libx264",
                                                                                                          "-f", "flv",
                                                                                                          "-b:v", "3000k", "-minrate", "3000k",
                                                                                                          "-maxrate", "3000k", "-bufsize", "3000k",
                                                                                                          "-r", "25", "-pix_fmt", "yuv420p",
                                                                                                          rtmp_url]
                                                                                                      
                                                                                                      run(stream_cmd)
                                                                                                      
                                                                                                      time.sleep(60)  # Wait 60 seconds before closing FFplay
                                                                                                      ffplay_process.kill()  # Forcefully close FFplay sub-process
                                                                                                      

                                                                                                      Source https://stackoverflow.com/questions/69857470

                                                                                                      Community Discussions, Code Snippets contain sources that include Stack Exchange Network

                                                                                                      Vulnerabilities

                                                                                                      No vulnerabilities reported

                                                                                                      Install yt-dlp

                                                                                                      You can install yt-dlp using one of the following methods:.

                                                                                                      Support

                                                                                                      See CONTRIBUTING.md for instructions on Opening an Issue and Contributing code to the project.
                                                                                                      Find more information at:
                                                                                                      Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
                                                                                                      Find more libraries
                                                                                                      Explore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits​
                                                                                                      Save this library and start creating your kit
                                                                                                      Install
                                                                                                    • PyPI

                                                                                                      pip install yt-dlp

                                                                                                    • CLONE
                                                                                                    • HTTPS

                                                                                                      https://github.com/yt-dlp/yt-dlp.git

                                                                                                    • CLI

                                                                                                      gh repo clone yt-dlp/yt-dlp

                                                                                                    • sshUrl

                                                                                                      git@github.com:yt-dlp/yt-dlp.git

                                                                                                    • Share this Page

                                                                                                      share link

                                                                                                      Explore Related Topics

                                                                                                      Consider Popular Video Utils Libraries

                                                                                                      obs-studio

                                                                                                      by obsproject

                                                                                                      video.js

                                                                                                      by videojs

                                                                                                      ijkplayer

                                                                                                      by bilibili

                                                                                                      FFmpeg

                                                                                                      by FFmpeg

                                                                                                      iina

                                                                                                      by iina

                                                                                                      Try Top Libraries by yt-dlp

                                                                                                      FFmpeg-Builds

                                                                                                      by yt-dlpShell

                                                                                                      homebrew-taps

                                                                                                      by yt-dlpRuby

                                                                                                      yt-dlp-sample-plugins

                                                                                                      by yt-dlpPython

                                                                                                      Compare Video Utils Libraries with Highest Support

                                                                                                      obs-studio

                                                                                                      by obsproject

                                                                                                      video.js

                                                                                                      by videojs

                                                                                                      bigbluebutton

                                                                                                      by bigbluebutton

                                                                                                      mpv

                                                                                                      by mpv-player

                                                                                                      jitsi-meet

                                                                                                      by jitsi

                                                                                                      Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
                                                                                                      Find more libraries
                                                                                                      Explore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits​
                                                                                                      Save this library and start creating your kit