diff --git a/README.md b/README.md index f3209a252..6ba9163bb 100644 --- a/README.md +++ b/README.md @@ -1392,10 +1392,10 @@ The available fields are: - `hasvid`: Gives priority to formats that has a video stream - `hasaud`: Gives priority to formats that has a audio stream - - `ie_pref`: The format preference as given by the extractor - - `lang`: Language preference as given by the extractor - - `quality`: The quality of the format as given by the extractor - - `source`: Preference of the source as given by the extractor + - `ie_pref`: The format preference + - `lang`: The language preference + - `quality`: The quality of the format + - `source`: The preference of the source - `proto`: Protocol used for download (`https`/`ftps` > `http`/`ftp` > `m3u8_native`/`m3u8` > `http_dash_segments`> `websocket_frag` > `mms`/`rtsp` > `f4f`/`f4m`) - `vcodec`: Video Codec (`av01` > `vp9.2` > `vp9` > `h265` > `h264` > `vp8` > `h263` > `theora` > other) - `acodec`: Audio Codec (`flac`/`alac` > `wav`/`aiff` > `opus` > `vorbis` > `aac` > `mp4a` > `mp3` > `eac3` > `ac3` > `dts` > other) @@ -1687,7 +1687,7 @@ with YoutubeDL(ydl_opts) as ydl: ydl.download(['https://www.youtube.com/watch?v=BaW_jenozKc']) ``` -Most likely, you'll want to use various options. For a list of options available, have a look at [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py#L162). +Most likely, you'll want to use various options. For a list of options available, have a look at [`yt_dlp/YoutubeDL.py`](yt_dlp/YoutubeDL.py#L191). Here's a more complete example demonstrating various functionality: diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index aa7905fc7..71369bc44 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -1637,7 +1637,7 @@ class YoutubeDL(object): ie_entries = ie_result['entries'] if isinstance(ie_entries, list): - playlist_count = len(ie_result) + playlist_count = len(ie_entries) msg = f'Collected {playlist_count} videos; downloading %d of them' ie_result['playlist_count'] = ie_result.get('playlist_count') or playlist_count @@ -2392,15 +2392,15 @@ class YoutubeDL(object): if not self.params.get('allow_unplayable_formats'): formats = [f for f in formats if not f.get('has_drm')] + # backward compatibility + info_dict['fulltitle'] = info_dict['title'] + if info_dict.get('is_live'): get_from_start = bool(self.params.get('live_from_start')) formats = [f for f in formats if bool(f.get('is_from_start')) == get_from_start] if not get_from_start: info_dict['title'] += ' ' + datetime.datetime.now().strftime('%Y-%m-%d %H:%M') - # backward compatibility - info_dict['fulltitle'] = info_dict['title'] - if not formats: self.raise_no_formats(info_dict) diff --git a/yt_dlp/extractor/twitcasting.py b/yt_dlp/extractor/twitcasting.py index ef1e871cf..c3e058709 100644 --- a/yt_dlp/extractor/twitcasting.py +++ b/yt_dlp/extractor/twitcasting.py @@ -99,7 +99,7 @@ class TwitCastingIE(InfoExtractor): is_live = 'data-status="online"' in webpage if not traverse_obj(stream_server_data, 'llfmp4') and is_live: - raise ExtractorError('You must be logged in to watch.', expected=True) + self.raise_login_required(method='cookies') formats = [] if is_live and not m3u8_url: diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 4dd7c6dbd..cc0a933be 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -262,7 +262,8 @@ def create_parser(): action='store_true', dest='ignoreconfig', help=( 'Don\'t load any more configuration files except those given by --config-locations. ' - 'For backward compatibility, if this option is found inside the system configuration file, the user configuration is not loaded')) + 'For backward compatibility, if this option is found inside the system configuration file, the user configuration is not loaded. ' + '(Alias: --no-config')) general.add_option( '--no-config-locations', action='store_const', dest='config_locations', const=[], diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py index 7c99fd018..848fd584a 100644 --- a/yt_dlp/postprocessor/ffmpeg.py +++ b/yt_dlp/postprocessor/ffmpeg.py @@ -585,7 +585,7 @@ class FFmpegVideoRemuxerPP(FFmpegVideoConvertorPP): @staticmethod def _options(target_ext): - return self.stream_copy_opts() + return FFmpegPostProcessor.stream_copy_opts() class FFmpegEmbedSubtitlePP(FFmpegPostProcessor): @@ -678,7 +678,7 @@ class FFmpegMetadataPP(FFmpegPostProcessor): @staticmethod def _options(target_ext): audio_only = target_ext == 'm4a' - yield from self.stream_copy_opts(not audio_only) + yield from FFmpegPostProcessor.stream_copy_opts(not audio_only) if audio_only: yield from ('-vn', '-acodec', 'copy') diff --git a/yt_dlp/postprocessor/modify_chapters.py b/yt_dlp/postprocessor/modify_chapters.py index 91433c364..435a144e2 100644 --- a/yt_dlp/postprocessor/modify_chapters.py +++ b/yt_dlp/postprocessor/modify_chapters.py @@ -57,6 +57,7 @@ class ModifyChaptersPP(FFmpegPostProcessor): self.write_debug('Expected and actual durations mismatch') concat_opts = self._make_concat_opts(cuts, real_duration) + self.write_debug('Concat spec = %s' % ', '.join(f'{c.get("inpoint", 0.0)}-{c.get("outpoint", "inf")}' for c in concat_opts)) def remove_chapters(file, is_sub): return file, self.remove_chapters(file, cuts, concat_opts, self._force_keyframes and not is_sub) @@ -332,6 +333,6 @@ class ModifyChaptersPP(FFmpegPostProcessor): continue opts[-1]['outpoint'] = f'{s["start_time"]:.6f}' # Do not create 0 duration chunk at the end. - if s['end_time'] != duration: + if s['end_time'] < duration: opts.append({'inpoint': f'{s["end_time"]:.6f}'}) return opts