youtube-knowledge-mcp 2.2.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +126 -36
- package/dist/brain-schemas.d.ts +10 -0
- package/dist/brain-schemas.d.ts.map +1 -1
- package/dist/harvest-schemas.d.ts +75 -0
- package/dist/harvest-schemas.d.ts.map +1 -0
- package/dist/harvest-schemas.js +111 -0
- package/dist/harvest-schemas.js.map +1 -0
- package/dist/registry/brain-tools.d.ts.map +1 -1
- package/dist/registry/brain-tools.js +16 -0
- package/dist/registry/brain-tools.js.map +1 -1
- package/dist/registry/channel-tools.d.ts.map +1 -1
- package/dist/registry/channel-tools.js +16 -0
- package/dist/registry/channel-tools.js.map +1 -1
- package/dist/registry/harvest-tools.d.ts +10 -0
- package/dist/registry/harvest-tools.d.ts.map +1 -0
- package/dist/registry/harvest-tools.js +109 -0
- package/dist/registry/harvest-tools.js.map +1 -0
- package/dist/registry/health-tools.d.ts.map +1 -1
- package/dist/registry/health-tools.js +18 -0
- package/dist/registry/health-tools.js.map +1 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +6 -0
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/media-tools.d.ts.map +1 -1
- package/dist/registry/media-tools.js +31 -0
- package/dist/registry/media-tools.js.map +1 -1
- package/dist/registry/store-tools.d.ts +9 -0
- package/dist/registry/store-tools.d.ts.map +1 -0
- package/dist/registry/store-tools.js +59 -0
- package/dist/registry/store-tools.js.map +1 -0
- package/dist/registry/transcript-tools.d.ts +4 -1
- package/dist/registry/transcript-tools.d.ts.map +1 -1
- package/dist/registry/transcript-tools.js +20 -1
- package/dist/registry/transcript-tools.js.map +1 -1
- package/dist/registry/video-tools.d.ts.map +1 -1
- package/dist/registry/video-tools.js +49 -1
- package/dist/registry/video-tools.js.map +1 -1
- package/dist/registry/vision-tools.d.ts +7 -0
- package/dist/registry/vision-tools.d.ts.map +1 -0
- package/dist/registry/vision-tools.js +55 -0
- package/dist/registry/vision-tools.js.map +1 -0
- package/dist/schemas.d.ts +245 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +58 -0
- package/dist/schemas.js.map +1 -1
- package/dist/thumbnail-schemas.d.ts +38 -28
- package/dist/thumbnail-schemas.d.ts.map +1 -1
- package/dist/tools/ask-brain.js +1 -1
- package/dist/tools/ask-brain.js.map +1 -1
- package/dist/tools/ask-brains.d.ts +66 -0
- package/dist/tools/ask-brains.d.ts.map +1 -0
- package/dist/tools/ask-brains.js +111 -0
- package/dist/tools/ask-brains.js.map +1 -0
- package/dist/tools/brain-info.js +1 -1
- package/dist/tools/brain-info.js.map +1 -1
- package/dist/tools/check-health.d.ts +75 -6
- package/dist/tools/check-health.d.ts.map +1 -1
- package/dist/tools/check-health.js +114 -6
- package/dist/tools/check-health.js.map +1 -1
- package/dist/tools/check-new-uploads.d.ts +55 -0
- package/dist/tools/check-new-uploads.d.ts.map +1 -0
- package/dist/tools/check-new-uploads.js +74 -0
- package/dist/tools/check-new-uploads.js.map +1 -0
- package/dist/tools/clips.d.ts +15 -0
- package/dist/tools/clips.d.ts.map +1 -1
- package/dist/tools/clips.js +5 -5
- package/dist/tools/clips.js.map +1 -1
- package/dist/tools/detect-scenes.d.ts +38 -0
- package/dist/tools/detect-scenes.d.ts.map +1 -0
- package/dist/tools/detect-scenes.js +66 -0
- package/dist/tools/detect-scenes.js.map +1 -0
- package/dist/tools/export-data.d.ts +85 -0
- package/dist/tools/export-data.d.ts.map +1 -0
- package/dist/tools/export-data.js +99 -0
- package/dist/tools/export-data.js.map +1 -0
- package/dist/tools/fetch-channel-thumbnails.d.ts +8 -8
- package/dist/tools/fetch-videos.d.ts +15 -4
- package/dist/tools/fetch-videos.d.ts.map +1 -1
- package/dist/tools/fetch-videos.js +63 -22
- package/dist/tools/fetch-videos.js.map +1 -1
- package/dist/tools/frames-subtitles.d.ts.map +1 -1
- package/dist/tools/frames-subtitles.js +16 -8
- package/dist/tools/frames-subtitles.js.map +1 -1
- package/dist/tools/frames.d.ts +73 -0
- package/dist/tools/frames.d.ts.map +1 -0
- package/dist/tools/frames.js +136 -0
- package/dist/tools/frames.js.map +1 -0
- package/dist/tools/get-channel-info.d.ts +2 -0
- package/dist/tools/get-channel-info.d.ts.map +1 -1
- package/dist/tools/get-channel-info.js +4 -0
- package/dist/tools/get-channel-info.js.map +1 -1
- package/dist/tools/get-comments.d.ts +238 -6
- package/dist/tools/get-comments.d.ts.map +1 -1
- package/dist/tools/get-comments.js +85 -21
- package/dist/tools/get-comments.js.map +1 -1
- package/dist/tools/get-coverage.d.ts +122 -0
- package/dist/tools/get-coverage.d.ts.map +1 -0
- package/dist/tools/get-coverage.js +105 -0
- package/dist/tools/get-coverage.js.map +1 -0
- package/dist/tools/get-sponsor-segments.d.ts +49 -0
- package/dist/tools/get-sponsor-segments.d.ts.map +1 -0
- package/dist/tools/get-sponsor-segments.js +61 -0
- package/dist/tools/get-sponsor-segments.js.map +1 -0
- package/dist/tools/get-thumbnail.d.ts.map +1 -1
- package/dist/tools/get-thumbnail.js +2 -1
- package/dist/tools/get-thumbnail.js.map +1 -1
- package/dist/tools/get-transcript.d.ts +1 -0
- package/dist/tools/get-transcript.d.ts.map +1 -1
- package/dist/tools/get-transcript.js +11 -4
- package/dist/tools/get-transcript.js.map +1 -1
- package/dist/tools/get-video-details.d.ts +118 -0
- package/dist/tools/get-video-details.d.ts.map +1 -0
- package/dist/tools/get-video-details.js +147 -0
- package/dist/tools/get-video-details.js.map +1 -0
- package/dist/tools/gif-concat.d.ts +49 -0
- package/dist/tools/gif-concat.d.ts.map +1 -0
- package/dist/tools/gif-concat.js +96 -0
- package/dist/tools/gif-concat.js.map +1 -0
- package/dist/tools/harvest-channel.d.ts +92 -0
- package/dist/tools/harvest-channel.d.ts.map +1 -0
- package/dist/tools/harvest-channel.js +62 -0
- package/dist/tools/harvest-channel.js.map +1 -0
- package/dist/tools/harvest-comments.d.ts +81 -0
- package/dist/tools/harvest-comments.d.ts.map +1 -0
- package/dist/tools/harvest-comments.js +115 -0
- package/dist/tools/harvest-comments.js.map +1 -0
- package/dist/tools/harvest-details.d.ts +84 -0
- package/dist/tools/harvest-details.d.ts.map +1 -0
- package/dist/tools/harvest-details.js +71 -0
- package/dist/tools/harvest-details.js.map +1 -0
- package/dist/tools/library.js +1 -1
- package/dist/tools/library.js.map +1 -1
- package/dist/tools/list-captions.d.ts +17 -0
- package/dist/tools/list-captions.d.ts.map +1 -0
- package/dist/tools/list-captions.js +60 -0
- package/dist/tools/list-captions.js.map +1 -0
- package/dist/tools/list-channel-playlists.d.ts +30 -0
- package/dist/tools/list-channel-playlists.d.ts.map +1 -0
- package/dist/tools/list-channel-playlists.js +44 -0
- package/dist/tools/list-channel-playlists.js.map +1 -0
- package/dist/tools/list-channel-thumbnails.d.ts +10 -10
- package/dist/tools/list-channel-thumbnails.js +1 -1
- package/dist/tools/list-channel-thumbnails.js.map +1 -1
- package/dist/tools/list-library.js +1 -1
- package/dist/tools/list-library.js.map +1 -1
- package/dist/tools/prune-harvest.d.ts +59 -0
- package/dist/tools/prune-harvest.d.ts.map +1 -0
- package/dist/tools/prune-harvest.js +108 -0
- package/dist/tools/prune-harvest.js.map +1 -0
- package/dist/tools/query-comments.d.ts +125 -0
- package/dist/tools/query-comments.d.ts.map +1 -0
- package/dist/tools/query-comments.js +106 -0
- package/dist/tools/query-comments.js.map +1 -0
- package/dist/tools/query-videos.d.ts +118 -0
- package/dist/tools/query-videos.d.ts.map +1 -0
- package/dist/tools/query-videos.js +97 -0
- package/dist/tools/query-videos.js.map +1 -0
- package/dist/tools/repair-store.d.ts +34 -0
- package/dist/tools/repair-store.d.ts.map +1 -0
- package/dist/tools/repair-store.js +58 -0
- package/dist/tools/repair-store.js.map +1 -0
- package/dist/tools/search-channels.d.ts +6 -0
- package/dist/tools/search-channels.d.ts.map +1 -1
- package/dist/tools/search-channels.js +5 -1
- package/dist/tools/search-channels.js.map +1 -1
- package/dist/tools/search-videos.js +1 -1
- package/dist/tools/search-videos.js.map +1 -1
- package/dist/tools/transcribe-video.d.ts +28 -0
- package/dist/tools/transcribe-video.d.ts.map +1 -0
- package/dist/tools/transcribe-video.js +52 -0
- package/dist/tools/transcribe-video.js.map +1 -0
- package/dist/utils/brain-fusion.d.ts +24 -0
- package/dist/utils/brain-fusion.d.ts.map +1 -0
- package/dist/utils/brain-fusion.js +18 -0
- package/dist/utils/brain-fusion.js.map +1 -0
- package/dist/utils/channel-playlists.d.ts +21 -0
- package/dist/utils/channel-playlists.d.ts.map +1 -0
- package/dist/utils/channel-playlists.js +56 -0
- package/dist/utils/channel-playlists.js.map +1 -0
- package/dist/utils/clips.d.ts.map +1 -1
- package/dist/utils/clips.js +3 -17
- package/dist/utils/clips.js.map +1 -1
- package/dist/utils/comment-store.d.ts +71 -0
- package/dist/utils/comment-store.d.ts.map +1 -0
- package/dist/utils/comment-store.js +129 -0
- package/dist/utils/comment-store.js.map +1 -0
- package/dist/utils/comment-threads.d.ts +51 -0
- package/dist/utils/comment-threads.d.ts.map +1 -0
- package/dist/utils/comment-threads.js +76 -0
- package/dist/utils/comment-threads.js.map +1 -0
- package/dist/utils/concat.d.ts +19 -0
- package/dist/utils/concat.d.ts.map +1 -0
- package/dist/utils/concat.js +135 -0
- package/dist/utils/concat.js.map +1 -0
- package/dist/utils/contact-sheet.d.ts +28 -0
- package/dist/utils/contact-sheet.d.ts.map +1 -0
- package/dist/utils/contact-sheet.js +65 -0
- package/dist/utils/contact-sheet.js.map +1 -0
- package/dist/utils/coverage-text.d.ts +3 -0
- package/dist/utils/coverage-text.d.ts.map +1 -0
- package/dist/utils/coverage-text.js +62 -0
- package/dist/utils/coverage-text.js.map +1 -0
- package/dist/utils/coverage.d.ts +57 -0
- package/dist/utils/coverage.d.ts.map +1 -0
- package/dist/utils/coverage.js +142 -0
- package/dist/utils/coverage.js.map +1 -0
- package/dist/utils/detail-batch.d.ts +25 -0
- package/dist/utils/detail-batch.d.ts.map +1 -0
- package/dist/utils/detail-batch.js +58 -0
- package/dist/utils/detail-batch.js.map +1 -0
- package/dist/utils/errors.d.ts +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +19 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/export-data.d.ts +41 -0
- package/dist/utils/export-data.d.ts.map +1 -0
- package/dist/utils/export-data.js +114 -0
- package/dist/utils/export-data.js.map +1 -0
- package/dist/utils/export-format.d.ts +23 -0
- package/dist/utils/export-format.d.ts.map +1 -0
- package/dist/utils/export-format.js +59 -0
- package/dist/utils/export-format.js.map +1 -0
- package/dist/utils/export-load.d.ts +28 -0
- package/dist/utils/export-load.d.ts.map +1 -0
- package/dist/utils/export-load.js +70 -0
- package/dist/utils/export-load.js.map +1 -0
- package/dist/utils/export-rows.d.ts +35 -0
- package/dist/utils/export-rows.d.ts.map +1 -0
- package/dist/utils/export-rows.js +69 -0
- package/dist/utils/export-rows.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +26 -0
- package/dist/utils/ffmpeg.d.ts.map +1 -0
- package/dist/utils/ffmpeg.js +28 -0
- package/dist/utils/ffmpeg.js.map +1 -0
- package/dist/utils/format.d.ts +23 -1
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +5 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/frame-plan.d.ts +24 -0
- package/dist/utils/frame-plan.d.ts.map +1 -0
- package/dist/utils/frame-plan.js +58 -0
- package/dist/utils/frame-plan.js.map +1 -0
- package/dist/utils/frames.d.ts +32 -0
- package/dist/utils/frames.d.ts.map +1 -0
- package/dist/utils/frames.js +60 -0
- package/dist/utils/frames.js.map +1 -0
- package/dist/utils/gif.d.ts +31 -0
- package/dist/utils/gif.d.ts.map +1 -0
- package/dist/utils/gif.js +77 -0
- package/dist/utils/gif.js.map +1 -0
- package/dist/utils/harvest-catalog.d.ts +54 -0
- package/dist/utils/harvest-catalog.d.ts.map +1 -0
- package/dist/utils/harvest-catalog.js +173 -0
- package/dist/utils/harvest-catalog.js.map +1 -0
- package/dist/utils/harvest-details.d.ts +30 -0
- package/dist/utils/harvest-details.d.ts.map +1 -0
- package/dist/utils/harvest-details.js +98 -0
- package/dist/utils/harvest-details.js.map +1 -0
- package/dist/utils/harvest-lock.d.ts +3 -0
- package/dist/utils/harvest-lock.d.ts.map +1 -0
- package/dist/utils/harvest-lock.js +26 -0
- package/dist/utils/harvest-lock.js.map +1 -0
- package/dist/utils/harvest-receipts.d.ts +14 -0
- package/dist/utils/harvest-receipts.d.ts.map +1 -0
- package/dist/utils/harvest-receipts.js +110 -0
- package/dist/utils/harvest-receipts.js.map +1 -0
- package/dist/utils/listing-cursor.d.ts +31 -0
- package/dist/utils/listing-cursor.d.ts.map +1 -0
- package/dist/utils/listing-cursor.js +39 -0
- package/dist/utils/listing-cursor.js.map +1 -0
- package/dist/utils/local-transcription.d.ts +14 -0
- package/dist/utils/local-transcription.d.ts.map +1 -0
- package/dist/utils/local-transcription.js +85 -0
- package/dist/utils/local-transcription.js.map +1 -0
- package/dist/utils/moment.d.ts +24 -0
- package/dist/utils/moment.d.ts.map +1 -0
- package/dist/utils/moment.js +22 -0
- package/dist/utils/moment.js.map +1 -0
- package/dist/utils/most-replayed.d.ts +15 -0
- package/dist/utils/most-replayed.d.ts.map +1 -0
- package/dist/utils/most-replayed.js +25 -0
- package/dist/utils/most-replayed.js.map +1 -0
- package/dist/utils/pot-preflight.d.ts +53 -0
- package/dist/utils/pot-preflight.d.ts.map +1 -0
- package/dist/utils/pot-preflight.js +146 -0
- package/dist/utils/pot-preflight.js.map +1 -0
- package/dist/utils/scenes.d.ts +39 -0
- package/dist/utils/scenes.d.ts.map +1 -0
- package/dist/utils/scenes.js +83 -0
- package/dist/utils/scenes.js.map +1 -0
- package/dist/utils/seconds.d.ts +5 -0
- package/dist/utils/seconds.d.ts.map +1 -0
- package/dist/utils/seconds.js +7 -0
- package/dist/utils/seconds.js.map +1 -0
- package/dist/utils/sleep.d.ts +9 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +25 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/sponsorblock.d.ts +24 -0
- package/dist/utils/sponsorblock.d.ts.map +1 -0
- package/dist/utils/sponsorblock.js +153 -0
- package/dist/utils/sponsorblock.js.map +1 -0
- package/dist/utils/store-health.d.ts +37 -0
- package/dist/utils/store-health.d.ts.map +1 -0
- package/dist/utils/store-health.js +92 -0
- package/dist/utils/store-health.js.map +1 -0
- package/dist/utils/store-migrations.d.ts +33 -0
- package/dist/utils/store-migrations.d.ts.map +1 -0
- package/dist/utils/store-migrations.js +41 -0
- package/dist/utils/store-migrations.js.map +1 -0
- package/dist/utils/store-paths.d.ts +33 -0
- package/dist/utils/store-paths.d.ts.map +1 -0
- package/dist/utils/store-paths.js +48 -0
- package/dist/utils/store-paths.js.map +1 -0
- package/dist/utils/store-rows.d.ts +22 -0
- package/dist/utils/store-rows.d.ts.map +1 -0
- package/dist/utils/store-rows.js +62 -0
- package/dist/utils/store-rows.js.map +1 -0
- package/dist/utils/store-schema.d.ts +16 -0
- package/dist/utils/store-schema.d.ts.map +1 -0
- package/dist/utils/store-schema.js +168 -0
- package/dist/utils/store-schema.js.map +1 -0
- package/dist/utils/store.d.ts +34 -0
- package/dist/utils/store.d.ts.map +1 -0
- package/dist/utils/store.js +157 -0
- package/dist/utils/store.js.map +1 -0
- package/dist/utils/transcript-cache.d.ts +5 -1
- package/dist/utils/transcript-cache.d.ts.map +1 -1
- package/dist/utils/transcript-cache.js +31 -50
- package/dist/utils/transcript-cache.js.map +1 -1
- package/dist/utils/transcript-files.d.ts +24 -0
- package/dist/utils/transcript-files.d.ts.map +1 -0
- package/dist/utils/transcript-files.js +61 -0
- package/dist/utils/transcript-files.js.map +1 -0
- package/dist/utils/transcript.d.ts +3 -0
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +2 -0
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/upload-check.d.ts +38 -0
- package/dist/utils/upload-check.d.ts.map +1 -0
- package/dist/utils/upload-check.js +93 -0
- package/dist/utils/upload-check.js.map +1 -0
- package/dist/utils/validate.d.ts +2 -0
- package/dist/utils/validate.d.ts.map +1 -1
- package/dist/utils/validate.js +4 -0
- package/dist/utils/validate.js.map +1 -1
- package/dist/utils/video-detail-store.d.ts +47 -0
- package/dist/utils/video-detail-store.d.ts.map +1 -0
- package/dist/utils/video-detail-store.js +89 -0
- package/dist/utils/video-detail-store.js.map +1 -0
- package/dist/utils/video-stats-cache.d.ts +16 -0
- package/dist/utils/video-stats-cache.d.ts.map +1 -0
- package/dist/utils/video-stats-cache.js +81 -0
- package/dist/utils/video-stats-cache.js.map +1 -0
- package/dist/utils/video-stats-schema.d.ts +187 -0
- package/dist/utils/video-stats-schema.d.ts.map +1 -0
- package/dist/utils/video-stats-schema.js +50 -0
- package/dist/utils/video-stats-schema.js.map +1 -0
- package/dist/utils/video-stats-storage.d.ts +16 -0
- package/dist/utils/video-stats-storage.d.ts.map +1 -0
- package/dist/utils/video-stats-storage.js +37 -0
- package/dist/utils/video-stats-storage.js.map +1 -0
- package/dist/utils/video-stats.d.ts +82 -0
- package/dist/utils/video-stats.d.ts.map +1 -0
- package/dist/utils/video-stats.js +108 -0
- package/dist/utils/video-stats.js.map +1 -0
- package/dist/utils/video-store.d.ts +69 -0
- package/dist/utils/video-store.d.ts.map +1 -0
- package/dist/utils/video-store.js +77 -0
- package/dist/utils/video-store.js.map +1 -0
- package/dist/utils/video-stream.d.ts +21 -0
- package/dist/utils/video-stream.d.ts.map +1 -0
- package/dist/utils/video-stream.js +36 -0
- package/dist/utils/video-stream.js.map +1 -0
- package/dist/utils/whisper.d.ts +39 -0
- package/dist/utils/whisper.d.ts.map +1 -0
- package/dist/utils/whisper.js +137 -0
- package/dist/utils/whisper.js.map +1 -0
- package/dist/utils/youtube-channel.d.ts +13 -2
- package/dist/utils/youtube-channel.d.ts.map +1 -1
- package/dist/utils/youtube-channel.js +39 -3
- package/dist/utils/youtube-channel.js.map +1 -1
- package/dist/utils/youtube-schemas.d.ts +104 -0
- package/dist/utils/youtube-schemas.d.ts.map +1 -1
- package/dist/utils/youtube-schemas.js +32 -0
- package/dist/utils/youtube-schemas.js.map +1 -1
- package/dist/utils/youtube-video.d.ts +22 -1
- package/dist/utils/youtube-video.d.ts.map +1 -1
- package/dist/utils/youtube-video.js +40 -28
- package/dist/utils/youtube-video.js.map +1 -1
- package/dist/utils/ytdlp-limiter.d.ts +3 -0
- package/dist/utils/ytdlp-limiter.d.ts.map +1 -1
- package/dist/utils/ytdlp-limiter.js +19 -3
- package/dist/utils/ytdlp-limiter.js.map +1 -1
- package/dist/utils/ytdlp-pacer.d.ts +64 -0
- package/dist/utils/ytdlp-pacer.d.ts.map +1 -0
- package/dist/utils/ytdlp-pacer.js +165 -0
- package/dist/utils/ytdlp-pacer.js.map +1 -0
- package/dist/utils/ytdlp-stream.d.ts +32 -0
- package/dist/utils/ytdlp-stream.d.ts.map +1 -0
- package/dist/utils/ytdlp-stream.js +61 -0
- package/dist/utils/ytdlp-stream.js.map +1 -0
- package/dist/utils/ytdlp.d.ts +10 -0
- package/dist/utils/ytdlp.d.ts.map +1 -1
- package/dist/utils/ytdlp.js +36 -25
- package/dist/utils/ytdlp.js.map +1 -1
- package/package.json +10 -4
|
@@ -92,9 +92,16 @@ export declare const videoDetailsRowSchema: z.ZodObject<{
|
|
|
92
92
|
}>, "many">>>;
|
|
93
93
|
upload_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
94
94
|
duration: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
95
|
+
/**
|
|
96
|
+
* The video's real comment count — trustworthy ONLY here, because this read
|
|
97
|
+
* does not pass --write-comments. With that flag yt-dlp replaces the value
|
|
98
|
+
* with the number it extracted (measured: 300 against a video with 2.4M).
|
|
99
|
+
*/
|
|
100
|
+
comment_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
95
101
|
}, "strip", z.ZodTypeAny, {
|
|
96
102
|
duration?: number | null | undefined;
|
|
97
103
|
upload_date?: string | null | undefined;
|
|
104
|
+
comment_count?: number | null | undefined;
|
|
98
105
|
chapters?: {
|
|
99
106
|
title: string;
|
|
100
107
|
start_time: number;
|
|
@@ -103,66 +110,157 @@ export declare const videoDetailsRowSchema: z.ZodObject<{
|
|
|
103
110
|
}, {
|
|
104
111
|
duration?: number | null | undefined;
|
|
105
112
|
upload_date?: string | null | undefined;
|
|
113
|
+
comment_count?: number | null | undefined;
|
|
106
114
|
chapters?: {
|
|
107
115
|
title: string;
|
|
108
116
|
start_time: number;
|
|
109
117
|
end_time: number;
|
|
110
118
|
}[] | null | undefined;
|
|
111
119
|
}>;
|
|
120
|
+
/**
|
|
121
|
+
* Every field yt-dlp returns for a comment, verified against 2026.08.19.
|
|
122
|
+
*
|
|
123
|
+
* Nine of these were previously dropped on the floor after being paid for:
|
|
124
|
+
* the extraction fetches them either way, so discarding `id` and `parent`
|
|
125
|
+
* meant a thread could not be rebuilt from what we already had.
|
|
126
|
+
*/
|
|
112
127
|
export declare const commentRowSchema: z.ZodObject<{
|
|
128
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
113
129
|
author: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
130
|
+
author_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
131
|
+
author_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
132
|
+
author_thumbnail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
133
|
+
author_is_uploader: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
134
|
+
author_is_verified: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
114
135
|
text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
115
136
|
like_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
116
137
|
is_pinned: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
138
|
+
is_favorited: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
139
|
+
timestamp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
140
|
+
_time_text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
141
|
+
/** 'root' for a top-level comment; the parent's id for a reply. */
|
|
117
142
|
parent: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
118
143
|
}, "strip", z.ZodTypeAny, {
|
|
144
|
+
id?: string | null | undefined;
|
|
119
145
|
author?: string | null | undefined;
|
|
120
146
|
text?: string | null | undefined;
|
|
147
|
+
timestamp?: number | null | undefined;
|
|
121
148
|
parent?: string | null | undefined;
|
|
122
149
|
like_count?: number | null | undefined;
|
|
150
|
+
author_id?: string | null | undefined;
|
|
151
|
+
author_url?: string | null | undefined;
|
|
152
|
+
author_thumbnail?: string | null | undefined;
|
|
153
|
+
author_is_uploader?: boolean | null | undefined;
|
|
154
|
+
author_is_verified?: boolean | null | undefined;
|
|
123
155
|
is_pinned?: boolean | null | undefined;
|
|
156
|
+
is_favorited?: boolean | null | undefined;
|
|
157
|
+
_time_text?: string | null | undefined;
|
|
124
158
|
}, {
|
|
159
|
+
id?: string | null | undefined;
|
|
125
160
|
author?: string | null | undefined;
|
|
126
161
|
text?: string | null | undefined;
|
|
162
|
+
timestamp?: number | null | undefined;
|
|
127
163
|
parent?: string | null | undefined;
|
|
128
164
|
like_count?: number | null | undefined;
|
|
165
|
+
author_id?: string | null | undefined;
|
|
166
|
+
author_url?: string | null | undefined;
|
|
167
|
+
author_thumbnail?: string | null | undefined;
|
|
168
|
+
author_is_uploader?: boolean | null | undefined;
|
|
169
|
+
author_is_verified?: boolean | null | undefined;
|
|
129
170
|
is_pinned?: boolean | null | undefined;
|
|
171
|
+
is_favorited?: boolean | null | undefined;
|
|
172
|
+
_time_text?: string | null | undefined;
|
|
130
173
|
}>;
|
|
131
174
|
export declare const commentsRowSchema: z.ZodObject<{
|
|
132
175
|
comments: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
176
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
133
177
|
author: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
178
|
+
author_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
179
|
+
author_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
180
|
+
author_thumbnail: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
181
|
+
author_is_uploader: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
182
|
+
author_is_verified: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
134
183
|
text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
135
184
|
like_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
136
185
|
is_pinned: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
186
|
+
is_favorited: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
187
|
+
timestamp: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
188
|
+
_time_text: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
189
|
+
/** 'root' for a top-level comment; the parent's id for a reply. */
|
|
137
190
|
parent: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
138
191
|
}, "strip", z.ZodTypeAny, {
|
|
192
|
+
id?: string | null | undefined;
|
|
139
193
|
author?: string | null | undefined;
|
|
140
194
|
text?: string | null | undefined;
|
|
195
|
+
timestamp?: number | null | undefined;
|
|
141
196
|
parent?: string | null | undefined;
|
|
142
197
|
like_count?: number | null | undefined;
|
|
198
|
+
author_id?: string | null | undefined;
|
|
199
|
+
author_url?: string | null | undefined;
|
|
200
|
+
author_thumbnail?: string | null | undefined;
|
|
201
|
+
author_is_uploader?: boolean | null | undefined;
|
|
202
|
+
author_is_verified?: boolean | null | undefined;
|
|
143
203
|
is_pinned?: boolean | null | undefined;
|
|
204
|
+
is_favorited?: boolean | null | undefined;
|
|
205
|
+
_time_text?: string | null | undefined;
|
|
144
206
|
}, {
|
|
207
|
+
id?: string | null | undefined;
|
|
145
208
|
author?: string | null | undefined;
|
|
146
209
|
text?: string | null | undefined;
|
|
210
|
+
timestamp?: number | null | undefined;
|
|
147
211
|
parent?: string | null | undefined;
|
|
148
212
|
like_count?: number | null | undefined;
|
|
213
|
+
author_id?: string | null | undefined;
|
|
214
|
+
author_url?: string | null | undefined;
|
|
215
|
+
author_thumbnail?: string | null | undefined;
|
|
216
|
+
author_is_uploader?: boolean | null | undefined;
|
|
217
|
+
author_is_verified?: boolean | null | undefined;
|
|
149
218
|
is_pinned?: boolean | null | undefined;
|
|
219
|
+
is_favorited?: boolean | null | undefined;
|
|
220
|
+
_time_text?: string | null | undefined;
|
|
150
221
|
}>, "many">>>;
|
|
222
|
+
/**
|
|
223
|
+
* With --write-comments yt-dlp OVERWRITES this with the number extracted,
|
|
224
|
+
* and sets it to null when the extraction was interrupted. So it is a
|
|
225
|
+
* three-state signal about this run, never the video's real total, which
|
|
226
|
+
* only a separate metadata pass can report.
|
|
227
|
+
*/
|
|
228
|
+
comment_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
151
229
|
}, "strip", z.ZodTypeAny, {
|
|
230
|
+
comment_count?: number | null | undefined;
|
|
152
231
|
comments?: {
|
|
232
|
+
id?: string | null | undefined;
|
|
153
233
|
author?: string | null | undefined;
|
|
154
234
|
text?: string | null | undefined;
|
|
235
|
+
timestamp?: number | null | undefined;
|
|
155
236
|
parent?: string | null | undefined;
|
|
156
237
|
like_count?: number | null | undefined;
|
|
238
|
+
author_id?: string | null | undefined;
|
|
239
|
+
author_url?: string | null | undefined;
|
|
240
|
+
author_thumbnail?: string | null | undefined;
|
|
241
|
+
author_is_uploader?: boolean | null | undefined;
|
|
242
|
+
author_is_verified?: boolean | null | undefined;
|
|
157
243
|
is_pinned?: boolean | null | undefined;
|
|
244
|
+
is_favorited?: boolean | null | undefined;
|
|
245
|
+
_time_text?: string | null | undefined;
|
|
158
246
|
}[] | null | undefined;
|
|
159
247
|
}, {
|
|
248
|
+
comment_count?: number | null | undefined;
|
|
160
249
|
comments?: {
|
|
250
|
+
id?: string | null | undefined;
|
|
161
251
|
author?: string | null | undefined;
|
|
162
252
|
text?: string | null | undefined;
|
|
253
|
+
timestamp?: number | null | undefined;
|
|
163
254
|
parent?: string | null | undefined;
|
|
164
255
|
like_count?: number | null | undefined;
|
|
256
|
+
author_id?: string | null | undefined;
|
|
257
|
+
author_url?: string | null | undefined;
|
|
258
|
+
author_thumbnail?: string | null | undefined;
|
|
259
|
+
author_is_uploader?: boolean | null | undefined;
|
|
260
|
+
author_is_verified?: boolean | null | undefined;
|
|
165
261
|
is_pinned?: boolean | null | undefined;
|
|
262
|
+
is_favorited?: boolean | null | undefined;
|
|
263
|
+
_time_text?: string | null | undefined;
|
|
166
264
|
}[] | null | undefined;
|
|
167
265
|
}>;
|
|
168
266
|
export declare const formatRowSchema: z.ZodObject<{
|
|
@@ -340,24 +438,30 @@ export declare const channelMetaSchema: z.ZodObject<{
|
|
|
340
438
|
channel_url: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
341
439
|
uploader_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
342
440
|
channel_follower_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
441
|
+
channel_is_verified: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
442
|
+
tags: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
343
443
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
344
444
|
/** Checked by `selectChannelImages`, which tolerates any shape. */
|
|
345
445
|
thumbnails: z.ZodUnknown;
|
|
346
446
|
}, "strip", z.ZodTypeAny, {
|
|
347
447
|
channel?: string | null | undefined;
|
|
348
448
|
description?: string | null | undefined;
|
|
449
|
+
tags?: string[] | null | undefined;
|
|
349
450
|
channel_id?: string | null | undefined;
|
|
350
451
|
channel_url?: string | null | undefined;
|
|
351
452
|
uploader_id?: string | null | undefined;
|
|
352
453
|
channel_follower_count?: number | null | undefined;
|
|
454
|
+
channel_is_verified?: boolean | null | undefined;
|
|
353
455
|
thumbnails?: unknown;
|
|
354
456
|
}, {
|
|
355
457
|
channel?: string | null | undefined;
|
|
356
458
|
description?: string | null | undefined;
|
|
459
|
+
tags?: string[] | null | undefined;
|
|
357
460
|
channel_id?: string | null | undefined;
|
|
358
461
|
channel_url?: string | null | undefined;
|
|
359
462
|
uploader_id?: string | null | undefined;
|
|
360
463
|
channel_follower_count?: number | null | undefined;
|
|
464
|
+
channel_is_verified?: boolean | null | undefined;
|
|
361
465
|
thumbnails?: unknown;
|
|
362
466
|
}>;
|
|
363
467
|
export declare const playlistMetaSchema: z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-schemas.d.ts","sourceRoot":"","sources":["../../src/utils/youtube-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AAEH,2FAA2F;AAC3F,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB7B,CAAC;AAEH,wFAAwF;AACxF,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAI3B,CAAC;AAEH,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"youtube-schemas.d.ts","sourceRoot":"","sources":["../../src/utils/youtube-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AAEH,2FAA2F;AAC3F,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB7B,CAAC;AAEH,wFAAwF;AACxF,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;EAI3B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;IAIhC;;;;OAIG;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;IAc3B,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEnE,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;QAJ5B,mEAAmE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMnE;;;;;OAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY1B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE3B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;EAG9B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAO7B,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;EASjC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;IAS5B,mEAAmE;;;;;;;;;;;;;;;;;;;;;;EAEnE,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU7B,CAAC"}
|
|
@@ -40,16 +40,46 @@ export const videoDetailsRowSchema = z.object({
|
|
|
40
40
|
chapters: z.array(chapterRowSchema).nullish(),
|
|
41
41
|
upload_date: z.string().nullish(),
|
|
42
42
|
duration: z.number().nullish(),
|
|
43
|
+
/**
|
|
44
|
+
* The video's real comment count — trustworthy ONLY here, because this read
|
|
45
|
+
* does not pass --write-comments. With that flag yt-dlp replaces the value
|
|
46
|
+
* with the number it extracted (measured: 300 against a video with 2.4M).
|
|
47
|
+
*/
|
|
48
|
+
comment_count: z.number().nullish(),
|
|
43
49
|
});
|
|
50
|
+
/**
|
|
51
|
+
* Every field yt-dlp returns for a comment, verified against 2026.08.19.
|
|
52
|
+
*
|
|
53
|
+
* Nine of these were previously dropped on the floor after being paid for:
|
|
54
|
+
* the extraction fetches them either way, so discarding `id` and `parent`
|
|
55
|
+
* meant a thread could not be rebuilt from what we already had.
|
|
56
|
+
*/
|
|
44
57
|
export const commentRowSchema = z.object({
|
|
58
|
+
id: z.string().nullish(),
|
|
45
59
|
author: z.string().nullish(),
|
|
60
|
+
author_id: z.string().nullish(),
|
|
61
|
+
author_url: z.string().nullish(),
|
|
62
|
+
author_thumbnail: z.string().nullish(),
|
|
63
|
+
author_is_uploader: z.boolean().nullish(),
|
|
64
|
+
author_is_verified: z.boolean().nullish(),
|
|
46
65
|
text: z.string().nullish(),
|
|
47
66
|
like_count: z.number().nullish(),
|
|
48
67
|
is_pinned: z.boolean().nullish(),
|
|
68
|
+
is_favorited: z.boolean().nullish(),
|
|
69
|
+
timestamp: z.number().nullish(),
|
|
70
|
+
_time_text: z.string().nullish(),
|
|
71
|
+
/** 'root' for a top-level comment; the parent's id for a reply. */
|
|
49
72
|
parent: z.string().nullish(),
|
|
50
73
|
});
|
|
51
74
|
export const commentsRowSchema = z.object({
|
|
52
75
|
comments: z.array(commentRowSchema).nullish(),
|
|
76
|
+
/**
|
|
77
|
+
* With --write-comments yt-dlp OVERWRITES this with the number extracted,
|
|
78
|
+
* and sets it to null when the extraction was interrupted. So it is a
|
|
79
|
+
* three-state signal about this run, never the video's real total, which
|
|
80
|
+
* only a separate metadata pass can report.
|
|
81
|
+
*/
|
|
82
|
+
comment_count: z.number().nullish(),
|
|
53
83
|
});
|
|
54
84
|
export const formatRowSchema = z.object({
|
|
55
85
|
format_id: z.string(),
|
|
@@ -100,6 +130,8 @@ export const channelMetaSchema = z.object({
|
|
|
100
130
|
channel_url: z.string().nullish(),
|
|
101
131
|
uploader_id: z.string().nullish(),
|
|
102
132
|
channel_follower_count: z.number().nullish(),
|
|
133
|
+
channel_is_verified: z.boolean().nullish(),
|
|
134
|
+
tags: z.array(z.string()).nullish(),
|
|
103
135
|
description: z.string().nullish(),
|
|
104
136
|
/** Checked by `selectChannelImages`, which tolerates any shape. */
|
|
105
137
|
thumbnails: z.unknown(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-schemas.js","sourceRoot":"","sources":["../../src/utils/youtube-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;GAQG;AAEH,2FAA2F;AAC3F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACxB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC3B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACjC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACjC,4EAA4E;IAC5E,0DAA0D;IAC1D,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE;IACjB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC/B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAChC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACnC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;CAClC,CAAC,CAAC;AAEH,wFAAwF;AACxF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;CAC/B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACjC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;
|
|
1
|
+
{"version":3,"file":"youtube-schemas.js","sourceRoot":"","sources":["../../src/utils/youtube-schemas.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ThreadedComments } from './comment-threads.js';
|
|
1
2
|
/** Everything read about one video: metadata, chapters and comments. */
|
|
2
3
|
export interface VideoInfo {
|
|
3
4
|
id: string;
|
|
@@ -41,7 +42,27 @@ export interface VideoDetails {
|
|
|
41
42
|
uploadDate: string;
|
|
42
43
|
durationSeconds: number;
|
|
43
44
|
chapters: Chapter[];
|
|
45
|
+
/** YouTube's own count, from a read without --write-comments. Approximate and lagging. */
|
|
46
|
+
commentCount?: number;
|
|
44
47
|
}
|
|
45
48
|
export declare function getVideoDetails(urlOrId: string): Promise<VideoDetails>;
|
|
46
|
-
export
|
|
49
|
+
export interface CommentsResult extends ThreadedComments {
|
|
50
|
+
/**
|
|
51
|
+
* Whether yt-dlp's own iteration finished rather than being cut off.
|
|
52
|
+
*
|
|
53
|
+
* From common.py:3882-3908: `comment_count` is overwritten with the number
|
|
54
|
+
* extracted, and set to null when the walk was interrupted. Necessary for
|
|
55
|
+
* completeness but NOT sufficient — `itertools.islice` also ends iteration
|
|
56
|
+
* at a cap, so a capped run reports that it finished too.
|
|
57
|
+
*/
|
|
58
|
+
ranToExhaustion: boolean;
|
|
59
|
+
/** True when the video has comments turned off, where zero is the real total. */
|
|
60
|
+
commentsDisabled: boolean;
|
|
61
|
+
extractedTotal: number;
|
|
62
|
+
}
|
|
63
|
+
export declare function getComments(urlOrId: string, options?: {
|
|
64
|
+
limit?: number;
|
|
65
|
+
sort?: 'top' | 'new';
|
|
66
|
+
maxRepliesPerThread?: number;
|
|
67
|
+
}): Promise<CommentsResult>;
|
|
47
68
|
//# sourceMappingURL=youtube-video.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-video.d.ts","sourceRoot":"","sources":["../../src/utils/youtube-video.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"youtube-video.d.ts","sourceRoot":"","sources":["../../src/utils/youtube-video.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxE,wEAAwE;AAExE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAKD,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAoDtE;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAErE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,0FAA0F;IAC1F,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkB5E;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACtD;;;;;;;OAOG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,iFAAiF;IACjF,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAO,GACnF,OAAO,CAAC,cAAc,CAAC,CAgCzB"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { formatYouTubeDate } from './format.js';
|
|
2
2
|
import { classifyPlayability } from './errors.js';
|
|
3
3
|
import { TIMEOUTS, parseYtDlpJson, runYtDlp } from './ytdlp.js';
|
|
4
|
-
import { commentsRowSchema,
|
|
4
|
+
import { commentsRowSchema, videoInfoRowSchema } from './youtube-schemas.js';
|
|
5
5
|
import { extractVideoId, formatDuration, watchUrl } from './youtube-url.js';
|
|
6
|
+
import { toThreads } from './comment-threads.js';
|
|
7
|
+
import { readVideoStats } from './video-stats-cache.js';
|
|
6
8
|
const VIDEO_INFO_TEMPLATE = '%(.{id,title,channel,duration,upload_date,description,tags,thumbnail,view_count,like_count,comment_count,availability,live_status})j';
|
|
7
9
|
export async function getVideoInfo(urlOrId) {
|
|
8
10
|
const videoId = extractVideoId(urlOrId);
|
|
@@ -54,26 +56,26 @@ export async function getChapters(urlOrId) {
|
|
|
54
56
|
return (await getVideoDetails(urlOrId)).chapters;
|
|
55
57
|
}
|
|
56
58
|
export async function getVideoDetails(urlOrId) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
target: url,
|
|
62
|
-
});
|
|
63
|
-
const data = parseYtDlpJson(stdout, videoDetailsRowSchema, 'video details');
|
|
59
|
+
// A projection of the one full read, not a second spawn. This used to run
|
|
60
|
+
// its own `-j` and discard everything but three fields, so a caller wanting
|
|
61
|
+
// a title and a chapter list paid for two extractions of the same video.
|
|
62
|
+
const { stats } = await readVideoStats(urlOrId);
|
|
64
63
|
return {
|
|
65
|
-
uploadDate:
|
|
66
|
-
durationSeconds:
|
|
67
|
-
chapters:
|
|
68
|
-
title:
|
|
69
|
-
startTime:
|
|
70
|
-
startTimeFormatted: formatDuration(Math.floor(
|
|
71
|
-
endTime:
|
|
72
|
-
endTimeFormatted: formatDuration(Math.floor(
|
|
64
|
+
uploadDate: stats.uploadDate,
|
|
65
|
+
durationSeconds: stats.durationSeconds,
|
|
66
|
+
chapters: stats.chapters.map((chapter) => ({
|
|
67
|
+
title: chapter.title,
|
|
68
|
+
startTime: chapter.startTime,
|
|
69
|
+
startTimeFormatted: formatDuration(Math.floor(chapter.startTime)),
|
|
70
|
+
endTime: chapter.endTime,
|
|
71
|
+
endTimeFormatted: formatDuration(Math.floor(chapter.endTime)),
|
|
73
72
|
})),
|
|
73
|
+
...(stats.commentCount === undefined ? {} : { commentCount: stats.commentCount }),
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
|
-
export async function getComments(urlOrId,
|
|
76
|
+
export async function getComments(urlOrId, options = {}) {
|
|
77
|
+
const limit = options.limit ?? 20;
|
|
78
|
+
const sort = options.sort ?? 'top';
|
|
77
79
|
const videoId = extractVideoId(urlOrId);
|
|
78
80
|
const url = watchUrl(videoId);
|
|
79
81
|
const stdout = await runYtDlp([
|
|
@@ -81,18 +83,28 @@ export async function getComments(urlOrId, limit = 20) {
|
|
|
81
83
|
'--skip-download',
|
|
82
84
|
'--write-comments',
|
|
83
85
|
'--extractor-args',
|
|
84
|
-
|
|
86
|
+
// Five positions, per _video.py:2578: total, parents, replies, per
|
|
87
|
+
// thread, depth. An omitted position means unbounded, not a default, so
|
|
88
|
+
// every one is stated. Depth is 2 because YouTube's tree is two levels
|
|
89
|
+
// and a deeper cap would spend requests on nothing.
|
|
90
|
+
youtubeCommentArgs({ limit, sort, maxRepliesPerThread: options.maxRepliesPerThread ?? 100 }),
|
|
85
91
|
], { label: 'get_comments', timeoutMs: TIMEOUTS.comments, target: url });
|
|
86
92
|
const data = parseYtDlpJson(stdout, commentsRowSchema, 'video comments');
|
|
87
|
-
const
|
|
88
|
-
return
|
|
89
|
-
|
|
90
|
-
.
|
|
91
|
-
.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
const rows = data.comments ?? [];
|
|
94
|
+
return {
|
|
95
|
+
...toThreads(rows),
|
|
96
|
+
ranToExhaustion: data.comment_count !== null && data.comment_count !== undefined,
|
|
97
|
+
commentsDisabled: (data.comments === null || data.comments === undefined) &&
|
|
98
|
+
(data.comment_count === null || data.comment_count === undefined),
|
|
99
|
+
extractedTotal: rows.length,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function youtubeCommentArgs(options) {
|
|
103
|
+
const parents = Math.max(1, Math.ceil(options.limit / 2));
|
|
104
|
+
const replies = Math.max(0, options.limit - parents);
|
|
105
|
+
return [
|
|
106
|
+
`youtube:comment_sort=${options.sort}`,
|
|
107
|
+
`max_comments=${String(options.limit)},${String(parents)},${String(replies)},${String(options.maxRepliesPerThread)},2`,
|
|
108
|
+
].join(';');
|
|
97
109
|
}
|
|
98
110
|
//# sourceMappingURL=youtube-video.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube-video.js","sourceRoot":"","sources":["../../src/utils/youtube-video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"youtube-video.js","sourceRoot":"","sources":["../../src/utils/youtube-video.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,9 @@ export declare function releaseSlot(): void;
|
|
|
19
19
|
export declare function concurrencyState(): {
|
|
20
20
|
active: number;
|
|
21
21
|
queued: number;
|
|
22
|
+
/** The level in force now, which throttling can lower. */
|
|
22
23
|
limit: number;
|
|
24
|
+
/** The configured maximum the level never exceeds. */
|
|
25
|
+
ceiling: number;
|
|
23
26
|
};
|
|
24
27
|
//# sourceMappingURL=ytdlp-limiter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ytdlp-limiter.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp-limiter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ytdlp-limiter.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp-limiter.ts"],"names":[],"mappings":"AAiCA;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BhF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAOlC;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,IAAI;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB,CAOA"}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { envInt } from './env.js';
|
|
2
2
|
import { YouTubeError } from './errors.js';
|
|
3
|
+
import { effectiveConcurrency } from './ytdlp-pacer.js';
|
|
3
4
|
/**
|
|
4
5
|
* The concurrency limiter every yt-dlp spawn passes through.
|
|
5
6
|
*
|
|
6
7
|
* A cap so batch operations do not look like a scraper to YouTube, with a queue
|
|
7
8
|
* that honours cancellation so an abandoned request never holds a place in it.
|
|
8
9
|
*/
|
|
9
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* The ceiling this server will never exceed.
|
|
12
|
+
*
|
|
13
|
+
* A limit of 0 (or NaN) would queue every call forever, so the floor is 1.
|
|
14
|
+
* Under throttling the pacer lowers the level below this; the setting is the
|
|
15
|
+
* maximum, not the level.
|
|
16
|
+
*/
|
|
10
17
|
const MAX_CONCURRENT = envInt('YOUTUBE_MCP_MAX_CONCURRENCY', 3, { min: 1, max: 32 });
|
|
18
|
+
/** The level in force right now: the configured ceiling, or less if throttled. */
|
|
19
|
+
function currentLimit() {
|
|
20
|
+
return Math.max(1, Math.min(MAX_CONCURRENT, effectiveConcurrency()));
|
|
21
|
+
}
|
|
11
22
|
let active = 0;
|
|
12
23
|
const waiting = [];
|
|
13
24
|
/**
|
|
@@ -23,7 +34,7 @@ export async function acquireSlot(signal) {
|
|
|
23
34
|
// No already-aborted check here: `runYtDlp` makes it before every attempt and
|
|
24
35
|
// nothing awaits in between, so a second one could never fire — an
|
|
25
36
|
// unreachable guard that reads like a reachable one.
|
|
26
|
-
if (active <
|
|
37
|
+
if (active < currentLimit()) {
|
|
27
38
|
active++;
|
|
28
39
|
return;
|
|
29
40
|
}
|
|
@@ -64,6 +75,11 @@ export function releaseSlot() {
|
|
|
64
75
|
}
|
|
65
76
|
/** Test seam: lets the suite assert the limiter without spawning processes. */
|
|
66
77
|
export function concurrencyState() {
|
|
67
|
-
return {
|
|
78
|
+
return {
|
|
79
|
+
active,
|
|
80
|
+
queued: waiting.length,
|
|
81
|
+
limit: currentLimit(),
|
|
82
|
+
ceiling: MAX_CONCURRENT,
|
|
83
|
+
};
|
|
68
84
|
}
|
|
69
85
|
//# sourceMappingURL=ytdlp-limiter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ytdlp-limiter.js","sourceRoot":"","sources":["../../src/utils/ytdlp-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ytdlp-limiter.js","sourceRoot":"","sources":["../../src/utils/ytdlp-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD;;;;;GAKG;AAEH;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,MAAM,CAAC,6BAA6B,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;AAErF,kFAAkF;AAClF,SAAS,YAAY;IACnB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC;AAOD,IAAI,MAAM,GAAG,CAAC,CAAC;AACf,MAAM,OAAO,GAAa,EAAE,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAA+B;IAC/D,8EAA8E;IAC9E,mEAAmE;IACnE,qDAAqD;IACrD,IAAI,MAAM,GAAG,YAAY,EAAE,EAAE,CAAC;QAC5B,MAAM,EAAE,CAAC;QACT,OAAO;IACT,CAAC;IAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAW;YACrB,KAAK,EAAE,GAAG,EAAE;gBACV,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC9C,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBAChB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC9C,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;SACF,CAAC;QAEF,SAAS,OAAO;YACd,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,WAAW,EAAE,4BAA4B,CAAC,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC7B,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO;IACT,CAAC;IACD,MAAM,EAAE,CAAC;AACX,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB;IAQ9B,OAAO;QACL,MAAM;QACN,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,YAAY,EAAE;QACrB,OAAO,EAAE,cAAc;KACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { YouTubeErrorCode } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* How this server reacts to being throttled.
|
|
4
|
+
*
|
|
5
|
+
* The old behaviour was three attempts with at most ~1.5 seconds of jitter and
|
|
6
|
+
* no memory between calls, which is fine for a blip and useless for an
|
|
7
|
+
* hour-long harvest: nothing slowed down, nothing waited, and a hard block
|
|
8
|
+
* produced an hour of identical failures.
|
|
9
|
+
*
|
|
10
|
+
* This adds three things that only make sense across calls — a shared
|
|
11
|
+
* cooldown, an adaptive concurrency ceiling, and a circuit breaker — so the
|
|
12
|
+
* state is deliberately process-global, the same scope as the limiter it
|
|
13
|
+
* cooperates with.
|
|
14
|
+
*/
|
|
15
|
+
export declare const RATE_LIMIT_COOLDOWN_BASE_MS = 30000;
|
|
16
|
+
export declare const RATE_LIMIT_COOLDOWN_MAX_MS: number;
|
|
17
|
+
export declare const BOT_CHECK_COOLDOWN_MS: number;
|
|
18
|
+
export declare const MAX_BACKOFF_MS = 120000;
|
|
19
|
+
export declare const BASE_BACKOFF_MS = 750;
|
|
20
|
+
export declare const AIMD_MIN_CONCURRENCY = 1;
|
|
21
|
+
export declare const AIMD_INCREASE_AFTER_SUCCESSES = 20;
|
|
22
|
+
export declare const AIMD_DECREASE_FACTOR = 0.5;
|
|
23
|
+
/** Consecutive throttles before a global cooldown starts. */
|
|
24
|
+
export declare const COOLDOWN_AFTER_STRIKES = 2;
|
|
25
|
+
export declare const CIRCUIT_STRIKES = 5;
|
|
26
|
+
export declare const CIRCUIT_OPEN_MS: number;
|
|
27
|
+
interface RetryPolicy {
|
|
28
|
+
/** Total spawns, including the first. */
|
|
29
|
+
attempts: number;
|
|
30
|
+
backoff: 'none' | 'exponential';
|
|
31
|
+
cooldown: 'none' | 'rate-limit' | 'bot-check';
|
|
32
|
+
concurrency: 'none' | 'decrease' | 'floor';
|
|
33
|
+
}
|
|
34
|
+
export declare function policyFor(code: YouTubeErrorCode): RetryPolicy;
|
|
35
|
+
export declare function backoffDelay(attempt: number, style: RetryPolicy['backoff']): number;
|
|
36
|
+
export interface PacerDecision {
|
|
37
|
+
giveUp: boolean;
|
|
38
|
+
delayMs: number;
|
|
39
|
+
}
|
|
40
|
+
/** Records a failure and says whether to try again, and after how long. */
|
|
41
|
+
export declare function onFailure(code: YouTubeErrorCode, attempt: number, now?: number): PacerDecision;
|
|
42
|
+
/** Records a clean spawn, easing the ceiling back up one step at a time. */
|
|
43
|
+
export declare function onSuccess(): void;
|
|
44
|
+
/** How long a caller should wait before spawning, in milliseconds. */
|
|
45
|
+
export declare function waitMs(now?: number): number;
|
|
46
|
+
export declare function circuitOpen(now?: number): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The ceiling the limiter should honour right now.
|
|
49
|
+
*
|
|
50
|
+
* Infinite until something throttles us, so an untroubled server runs at
|
|
51
|
+
* whatever YOUTUBE_MCP_MAX_CONCURRENCY allows and the limiter stays the only
|
|
52
|
+
* authority on the normal case.
|
|
53
|
+
*/
|
|
54
|
+
export declare function effectiveConcurrency(now?: number): number;
|
|
55
|
+
export declare function pacerState(now?: number): {
|
|
56
|
+
cooldownMs: number;
|
|
57
|
+
circuitOpen: boolean;
|
|
58
|
+
strikes: number;
|
|
59
|
+
concurrency: number;
|
|
60
|
+
};
|
|
61
|
+
/** Test seam; the pacer is process-global in normal use. */
|
|
62
|
+
export declare function resetPacer(): void;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=ytdlp-pacer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ytdlp-pacer.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp-pacer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,0BAA0B,QAAc,CAAC;AACtD,eAAO,MAAM,qBAAqB,QAAc,CAAC;AACjD,eAAO,MAAM,cAAc,SAAU,CAAC;AACtC,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC,6DAA6D;AAC7D,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,eAAe,QAAa,CAAC;AAE1C,UAAU,WAAW;IACnB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC;IAChC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,WAAW,CAAC;IAC9C,WAAW,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;CAC5C;AAkCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,CAE7D;AA+BD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC,GAAG,MAAM,CAMnF;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CACvB,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,EACf,GAAG,SAAa,GACf,aAAa,CAuCf;AAED,4EAA4E;AAC5E,wBAAgB,SAAS,IAAI,IAAI,CAQhC;AAED,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,GAAG,SAAa,GAAG,MAAM,CAG/C;AAED,wBAAgB,WAAW,CAAC,GAAG,SAAa,GAAG,OAAO,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,SAAa,GAAG,MAAM,CAG7D;AAED,wBAAgB,UAAU,CAAC,GAAG,SAAa,GAAG;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAOA;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,IAAI,IAAI,CAQjC"}
|