youtube-knowledge-mcp 2.1.0 → 3.0.0
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 +153 -38
- package/dist/brain-schemas.d.ts +10 -10
- package/dist/brain-schemas.d.ts.map +1 -1
- package/dist/brain-schemas.js +0 -4
- package/dist/brain-schemas.js.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 +106 -0
- package/dist/harvest-schemas.js.map +1 -0
- package/dist/http/app.d.ts +16 -0
- package/dist/http/app.d.ts.map +1 -0
- package/dist/http/app.js +176 -0
- package/dist/http/app.js.map +1 -0
- package/dist/http/auth.d.ts +38 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +79 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/config.d.ts +41 -0
- package/dist/http/config.d.ts.map +1 -0
- package/dist/http/config.js +65 -0
- package/dist/http/config.js.map +1 -0
- package/dist/http/rate-limiter.d.ts +24 -0
- package/dist/http/rate-limiter.d.ts.map +1 -0
- package/dist/http/rate-limiter.js +55 -0
- package/dist/http/rate-limiter.js.map +1 -0
- package/dist/http/sessions.d.ts +34 -0
- package/dist/http/sessions.d.ts.map +1 -0
- package/dist/http/sessions.js +62 -0
- package/dist/http/sessions.js.map +1 -0
- package/dist/http.d.ts +6 -48
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +35 -252
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -517
- package/dist/index.js.map +1 -1
- package/dist/prompts-brain.d.ts +4 -0
- package/dist/prompts-brain.d.ts.map +1 -0
- package/dist/prompts-brain.js +48 -0
- package/dist/prompts-brain.js.map +1 -0
- package/dist/prompts-research.d.ts +4 -0
- package/dist/prompts-research.d.ts.map +1 -0
- package/dist/prompts-research.js +74 -0
- package/dist/prompts-research.js.map +1 -0
- package/dist/prompts-shared.d.ts +13 -0
- package/dist/prompts-shared.d.ts.map +1 -0
- package/dist/prompts-shared.js +7 -0
- package/dist/prompts-shared.js.map +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +5 -100
- package/dist/prompts.js.map +1 -1
- package/dist/registry/brain-tools.d.ts +4 -0
- package/dist/registry/brain-tools.d.ts.map +1 -0
- package/dist/registry/brain-tools.js +104 -0
- package/dist/registry/brain-tools.js.map +1 -0
- package/dist/registry/channel-tools.d.ts +4 -0
- package/dist/registry/channel-tools.d.ts.map +1 -0
- package/dist/registry/channel-tools.js +53 -0
- package/dist/registry/channel-tools.js.map +1 -0
- 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 +4 -0
- package/dist/registry/health-tools.d.ts.map +1 -0
- package/dist/registry/health-tools.js +39 -0
- package/dist/registry/health-tools.js.map +1 -0
- package/dist/registry/index.d.ts +8 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +29 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/library-tools.d.ts +4 -0
- package/dist/registry/library-tools.d.ts.map +1 -0
- package/dist/registry/library-tools.js +116 -0
- package/dist/registry/library-tools.js.map +1 -0
- package/dist/registry/media-tools.d.ts +4 -0
- package/dist/registry/media-tools.d.ts.map +1 -0
- package/dist/registry/media-tools.js +100 -0
- package/dist/registry/media-tools.js.map +1 -0
- package/dist/registry/thumbnail-tools.d.ts +7 -0
- package/dist/registry/thumbnail-tools.d.ts.map +1 -0
- package/dist/registry/thumbnail-tools.js +72 -0
- package/dist/registry/thumbnail-tools.js.map +1 -0
- package/dist/registry/transcript-tools.d.ts +4 -0
- package/dist/registry/transcript-tools.d.ts.map +1 -0
- package/dist/registry/transcript-tools.js +68 -0
- package/dist/registry/transcript-tools.js.map +1 -0
- package/dist/registry/types.d.ts +41 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +17 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/registry/video-tools.d.ts +4 -0
- package/dist/registry/video-tools.d.ts.map +1 -0
- package/dist/registry/video-tools.js +101 -0
- package/dist/registry/video-tools.js.map +1 -0
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +13 -10
- package/dist/resources.js.map +1 -1
- package/dist/schemas.d.ts +250 -2
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +61 -0
- package/dist/schemas.js.map +1 -1
- package/dist/thumbnail-resource.d.ts +8 -0
- package/dist/thumbnail-resource.d.ts.map +1 -0
- package/dist/thumbnail-resource.js +38 -0
- package/dist/thumbnail-resource.js.map +1 -0
- package/dist/thumbnail-schemas.d.ts +512 -0
- package/dist/thumbnail-schemas.d.ts.map +1 -0
- package/dist/thumbnail-schemas.js +95 -0
- package/dist/thumbnail-schemas.js.map +1 -0
- package/dist/tools/ask-brain.js +1 -1
- package/dist/tools/ask-brain.js.map +1 -1
- package/dist/tools/batch.js +1 -1
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/brain-info.js +1 -1
- package/dist/tools/brain-info.js.map +1 -1
- package/dist/tools/build-brain.js +1 -1
- package/dist/tools/build-brain.js.map +1 -1
- package/dist/tools/check-health.d.ts +61 -0
- package/dist/tools/check-health.d.ts.map +1 -1
- package/dist/tools/check-health.js +94 -6
- package/dist/tools/check-health.js.map +1 -1
- package/dist/tools/clips.d.ts +9 -41
- package/dist/tools/clips.d.ts.map +1 -1
- package/dist/tools/clips.js +52 -128
- package/dist/tools/clips.js.map +1 -1
- package/dist/tools/fetch-channel-thumbnails.d.ts +179 -0
- package/dist/tools/fetch-channel-thumbnails.d.ts.map +1 -0
- package/dist/tools/fetch-channel-thumbnails.js +123 -0
- package/dist/tools/fetch-channel-thumbnails.js.map +1 -0
- package/dist/tools/fetch-videos.d.ts +18 -4
- package/dist/tools/fetch-videos.d.ts.map +1 -1
- package/dist/tools/fetch-videos.js +64 -20
- package/dist/tools/fetch-videos.js.map +1 -1
- package/dist/tools/frames-subtitles.d.ts +44 -0
- package/dist/tools/frames-subtitles.d.ts.map +1 -0
- package/dist/tools/frames-subtitles.js +104 -0
- package/dist/tools/frames-subtitles.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 +8 -1
- 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-playlist-info.d.ts.map +1 -1
- package/dist/tools/get-playlist-info.js +1 -0
- package/dist/tools/get-playlist-info.js.map +1 -1
- package/dist/tools/get-thumbnail.d.ts +38 -0
- package/dist/tools/get-thumbnail.d.ts.map +1 -0
- package/dist/tools/get-thumbnail.js +152 -0
- package/dist/tools/get-thumbnail.js.map +1 -0
- package/dist/tools/get-transcript.d.ts.map +1 -1
- package/dist/tools/get-transcript.js +2 -14
- package/dist/tools/get-transcript.js.map +1 -1
- 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/library.d.ts.map +1 -1
- package/dist/tools/library.js +14 -4
- package/dist/tools/library.js.map +1 -1
- package/dist/tools/list-channel-thumbnails.d.ts +235 -0
- package/dist/tools/list-channel-thumbnails.d.ts.map +1 -0
- package/dist/tools/list-channel-thumbnails.js +79 -0
- package/dist/tools/list-channel-thumbnails.js.map +1 -0
- 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/save-to-library.d.ts.map +1 -1
- package/dist/tools/save-to-library.js +5 -1
- package/dist/tools/save-to-library.js.map +1 -1
- 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-transcript.d.ts.map +1 -1
- package/dist/tools/search-transcript.js +6 -13
- package/dist/tools/search-transcript.js.map +1 -1
- package/dist/tools/search-videos.d.ts +3 -0
- package/dist/tools/search-videos.d.ts.map +1 -1
- package/dist/tools/search-videos.js +1 -1
- package/dist/tools/search-videos.js.map +1 -1
- package/dist/utils/batches.d.ts +15 -0
- package/dist/utils/batches.d.ts.map +1 -0
- package/dist/utils/batches.js +31 -0
- package/dist/utils/batches.js.map +1 -0
- package/dist/utils/brain-build.d.ts.map +1 -1
- package/dist/utils/brain-build.js +1 -12
- package/dist/utils/brain-build.js.map +1 -1
- package/dist/utils/brain-index.d.ts.map +1 -1
- package/dist/utils/brain-index.js +3 -2
- package/dist/utils/brain-index.js.map +1 -1
- package/dist/utils/brain-lock.d.ts +2 -18
- package/dist/utils/brain-lock.d.ts.map +1 -1
- package/dist/utils/brain-lock.js +4 -80
- package/dist/utils/brain-lock.js.map +1 -1
- package/dist/utils/brain-lookup.d.ts +8 -0
- package/dist/utils/brain-lookup.d.ts.map +1 -1
- package/dist/utils/brain-lookup.js +5 -31
- package/dist/utils/brain-lookup.js.map +1 -1
- package/dist/utils/brain-storage.d.ts.map +1 -1
- package/dist/utils/brain-storage.js +5 -5
- package/dist/utils/brain-storage.js.map +1 -1
- package/dist/utils/caption-probe.d.ts +7 -0
- package/dist/utils/caption-probe.d.ts.map +1 -0
- package/dist/utils/caption-probe.js +36 -0
- package/dist/utils/caption-probe.js.map +1 -0
- package/dist/utils/channel-images.d.ts +16 -0
- package/dist/utils/channel-images.d.ts.map +1 -0
- package/dist/utils/channel-images.js +35 -0
- package/dist/utils/channel-images.js.map +1 -0
- package/dist/utils/channel-lookup.d.ts +5 -0
- package/dist/utils/channel-lookup.d.ts.map +1 -0
- package/dist/utils/channel-lookup.js +37 -0
- package/dist/utils/channel-lookup.js.map +1 -0
- package/dist/utils/chapters.d.ts +11 -0
- package/dist/utils/chapters.d.ts.map +1 -0
- package/dist/utils/chapters.js +24 -0
- package/dist/utils/chapters.js.map +1 -0
- package/dist/utils/clips.d.ts.map +1 -1
- package/dist/utils/clips.js +18 -26
- 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/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/env.d.ts +26 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +72 -0
- package/dist/utils/env.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 +28 -2
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/file-lock.d.ts +34 -0
- package/dist/utils/file-lock.d.ts.map +1 -0
- package/dist/utils/file-lock.js +91 -0
- package/dist/utils/file-lock.js.map +1 -0
- package/dist/utils/flat-listing.d.ts +89 -0
- package/dist/utils/flat-listing.d.ts.map +1 -0
- package/dist/utils/flat-listing.js +68 -0
- package/dist/utils/flat-listing.js.map +1 -0
- package/dist/utils/format.d.ts +18 -4
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +2 -6
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/guard.d.ts +21 -0
- package/dist/utils/guard.d.ts.map +1 -0
- package/dist/utils/guard.js +105 -0
- package/dist/utils/guard.js.map +1 -0
- package/dist/utils/harvest-catalog.d.ts +44 -0
- package/dist/utils/harvest-catalog.d.ts.map +1 -0
- package/dist/utils/harvest-catalog.js +164 -0
- package/dist/utils/harvest-catalog.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/image-dimensions.d.ts +19 -0
- package/dist/utils/image-dimensions.d.ts.map +1 -0
- package/dist/utils/image-dimensions.js +93 -0
- package/dist/utils/image-dimensions.js.map +1 -0
- package/dist/utils/image-fetch.d.ts +31 -0
- package/dist/utils/image-fetch.d.ts.map +1 -0
- package/dist/utils/image-fetch.js +141 -0
- package/dist/utils/image-fetch.js.map +1 -0
- package/dist/utils/json-file.d.ts +14 -5
- package/dist/utils/json-file.d.ts.map +1 -1
- package/dist/utils/json-file.js +24 -9
- package/dist/utils/json-file.js.map +1 -1
- 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/paths.d.ts +10 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +14 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/pattern.d.ts +30 -0
- package/dist/utils/pattern.d.ts.map +1 -0
- package/dist/utils/pattern.js +130 -0
- package/dist/utils/pattern.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/search-index.d.ts.map +1 -1
- package/dist/utils/search-index.js +9 -4
- package/dist/utils/search-index.js.map +1 -1
- 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/storage.d.ts.map +1 -1
- package/dist/utils/storage.js +14 -8
- package/dist/utils/storage.js.map +1 -1
- 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/subtitles.d.ts +7 -0
- package/dist/utils/subtitles.d.ts.map +1 -0
- package/dist/utils/subtitles.js +30 -0
- package/dist/utils/subtitles.js.map +1 -0
- package/dist/utils/thumbnail-entry.d.ts +19 -0
- package/dist/utils/thumbnail-entry.d.ts.map +1 -0
- package/dist/utils/thumbnail-entry.js +119 -0
- package/dist/utils/thumbnail-entry.js.map +1 -0
- package/dist/utils/thumbnail-fetch.d.ts +37 -0
- package/dist/utils/thumbnail-fetch.d.ts.map +1 -0
- package/dist/utils/thumbnail-fetch.js +89 -0
- package/dist/utils/thumbnail-fetch.js.map +1 -0
- package/dist/utils/thumbnail-ladder.d.ts +44 -0
- package/dist/utils/thumbnail-ladder.d.ts.map +1 -0
- package/dist/utils/thumbnail-ladder.js +68 -0
- package/dist/utils/thumbnail-ladder.js.map +1 -0
- package/dist/utils/thumbnail-listing.d.ts +16 -0
- package/dist/utils/thumbnail-listing.d.ts.map +1 -0
- package/dist/utils/thumbnail-listing.js +26 -0
- package/dist/utils/thumbnail-listing.js.map +1 -0
- package/dist/utils/thumbnail-paths.d.ts +20 -0
- package/dist/utils/thumbnail-paths.d.ts.map +1 -0
- package/dist/utils/thumbnail-paths.js +35 -0
- package/dist/utils/thumbnail-paths.js.map +1 -0
- package/dist/utils/thumbnail-store.d.ts +19 -0
- package/dist/utils/thumbnail-store.d.ts.map +1 -0
- package/dist/utils/thumbnail-store.js +125 -0
- package/dist/utils/thumbnail-store.js.map +1 -0
- package/dist/utils/transcript-cache.d.ts +20 -0
- package/dist/utils/transcript-cache.d.ts.map +1 -0
- package/dist/utils/transcript-cache.js +127 -0
- package/dist/utils/transcript-cache.js.map +1 -0
- package/dist/utils/transcript-search.d.ts +20 -0
- package/dist/utils/transcript-search.d.ts.map +1 -0
- package/dist/utils/transcript-search.js +35 -0
- package/dist/utils/transcript-search.js.map +1 -0
- package/dist/utils/transcript.d.ts +10 -31
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +2 -64
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/validate-youtube.d.ts +35 -0
- package/dist/utils/validate-youtube.d.ts.map +1 -0
- package/dist/utils/validate-youtube.js +87 -0
- package/dist/utils/validate-youtube.js.map +1 -0
- package/dist/utils/validate.d.ts +11 -4
- package/dist/utils/validate.d.ts.map +1 -1
- package/dist/utils/validate.js +43 -36
- package/dist/utils/validate.js.map +1 -1
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +19 -0
- package/dist/utils/version.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.d.ts +186 -0
- package/dist/utils/video-stats.d.ts.map +1 -0
- package/dist/utils/video-stats.js +168 -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/youtube-channel.d.ts +51 -0
- package/dist/utils/youtube-channel.d.ts.map +1 -0
- package/dist/utils/youtube-channel.js +91 -0
- package/dist/utils/youtube-channel.js.map +1 -0
- package/dist/utils/youtube-download.d.ts +27 -0
- package/dist/utils/youtube-download.d.ts.map +1 -0
- package/dist/utils/youtube-download.js +118 -0
- package/dist/utils/youtube-download.js.map +1 -0
- package/dist/utils/youtube-schemas.d.ts +492 -0
- package/dist/utils/youtube-schemas.d.ts.map +1 -0
- package/dist/utils/youtube-schemas.js +148 -0
- package/dist/utils/youtube-schemas.js.map +1 -0
- package/dist/utils/youtube-search.d.ts +14 -0
- package/dist/utils/youtube-search.d.ts.map +1 -0
- package/dist/utils/youtube-search.js +39 -0
- package/dist/utils/youtube-search.js.map +1 -0
- package/dist/utils/youtube-url.d.ts +25 -0
- package/dist/utils/youtube-url.d.ts.map +1 -0
- package/dist/utils/youtube-url.js +75 -0
- package/dist/utils/youtube-url.js.map +1 -0
- package/dist/utils/youtube-video.d.ts +68 -0
- package/dist/utils/youtube-video.d.ts.map +1 -0
- package/dist/utils/youtube-video.js +110 -0
- package/dist/utils/youtube-video.js.map +1 -0
- package/dist/utils/youtube.d.ts +10 -122
- package/dist/utils/youtube.d.ts.map +1 -1
- package/dist/utils/youtube.js +11 -486
- package/dist/utils/youtube.js.map +1 -1
- package/dist/utils/ytdlp-env.d.ts +33 -0
- package/dist/utils/ytdlp-env.d.ts.map +1 -0
- package/dist/utils/ytdlp-env.js +121 -0
- package/dist/utils/ytdlp-env.js.map +1 -0
- package/dist/utils/ytdlp-limiter.d.ts +27 -0
- package/dist/utils/ytdlp-limiter.d.ts.map +1 -0
- package/dist/utils/ytdlp-limiter.js +85 -0
- package/dist/utils/ytdlp-limiter.js.map +1 -0
- 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-parse.d.ts +13 -0
- package/dist/utils/ytdlp-parse.d.ts.map +1 -0
- package/dist/utils/ytdlp-parse.js +48 -0
- package/dist/utils/ytdlp-parse.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 +23 -18
- package/dist/utils/ytdlp.d.ts.map +1 -1
- package/dist/utils/ytdlp.js +56 -134
- package/dist/utils/ytdlp.js.map +1 -1
- package/package.json +3 -2
package/dist/utils/youtube.js
CHANGED
|
@@ -1,489 +1,14 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { mkdir, readFile, writeFile, unlink } from 'fs/promises';
|
|
4
|
-
import { existsSync, readdirSync } from 'fs';
|
|
5
|
-
import { formatYouTubeDate } from './format.js';
|
|
6
|
-
import { YouTubeError, classifyPlayability } from './errors.js';
|
|
7
|
-
import { TIMEOUTS, isRecord, parseYtDlpJson, parseYtDlpJsonLines, runYtDlp } from './ytdlp.js';
|
|
8
|
-
import { assertLanguageTag, resolveOutputDir } from './validate.js';
|
|
9
|
-
import { log } from './context.js';
|
|
10
|
-
import { dataDir } from './paths.js';
|
|
11
|
-
import { TRANSCRIPT_CACHE_VERSION, cachedTranscriptSchema, parseVtt, segmentsToText, } from './transcript.js';
|
|
12
|
-
const CACHE_DIR = dataDir('transcripts');
|
|
13
1
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
2
|
+
* Everything the server knows how to ask YouTube.
|
|
3
|
+
*
|
|
4
|
+
* This is a barrel: the implementation lives in one module per concern so each
|
|
5
|
+
* stays small enough to hold in view. Consumers import from here, so a module
|
|
6
|
+
* can move without every tool and test that uses it having to follow.
|
|
17
7
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
url: z.string().optional(),
|
|
25
|
-
});
|
|
26
|
-
function isSearchResult(value) {
|
|
27
|
-
return searchResultSchema.safeParse(value).success;
|
|
28
|
-
}
|
|
29
|
-
export function extractVideoId(urlOrId) {
|
|
30
|
-
// If it's already an ID (11 characters, no special chars except - and _)
|
|
31
|
-
if (/^[a-zA-Z0-9_-]{11}$/.test(urlOrId)) {
|
|
32
|
-
return urlOrId;
|
|
33
|
-
}
|
|
34
|
-
// Try to extract from URL
|
|
35
|
-
const patterns = [
|
|
36
|
-
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/|youtube\.com\/v\/)([a-zA-Z0-9_-]{11})/,
|
|
37
|
-
/(?:youtube\.com\/shorts\/)([a-zA-Z0-9_-]{11})/,
|
|
38
|
-
];
|
|
39
|
-
for (const pattern of patterns) {
|
|
40
|
-
const match = pattern.exec(urlOrId);
|
|
41
|
-
if (match?.[1] !== undefined) {
|
|
42
|
-
return match[1];
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
throw new Error(`Could not extract video ID from: ${urlOrId}`);
|
|
46
|
-
}
|
|
47
|
-
function formatDuration(seconds) {
|
|
48
|
-
const hours = Math.floor(seconds / 3600);
|
|
49
|
-
const minutes = Math.floor((seconds % 3600) / 60);
|
|
50
|
-
const secs = seconds % 60;
|
|
51
|
-
if (hours > 0) {
|
|
52
|
-
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
|
53
|
-
}
|
|
54
|
-
return `${minutes}:${secs.toString().padStart(2, '0')}`;
|
|
55
|
-
}
|
|
56
|
-
export async function getVideoInfo(urlOrId) {
|
|
57
|
-
const videoId = extractVideoId(urlOrId);
|
|
58
|
-
const url = `https://www.youtube.com/watch?v=${videoId}`;
|
|
59
|
-
const stdout = await runYtDlp([
|
|
60
|
-
'--skip-download',
|
|
61
|
-
// Without this, a video YouTube refuses to serve aborts extraction and the
|
|
62
|
-
// only thing left to read is YouTube's localised refusal text. With it,
|
|
63
|
-
// yt-dlp downgrades that abort to a warning and still fills in the
|
|
64
|
-
// structured fields, so the reason can be read from `availability` and
|
|
65
|
-
// `live_status` instead of guessed at from prose.
|
|
66
|
-
'--ignore-no-formats-error',
|
|
67
|
-
'--print',
|
|
68
|
-
'%(id)s|||%(title)s|||%(channel)s|||%(duration)s|||%(upload_date)s|||%(description)s|||%(tags)j|||%(thumbnail)s|||%(view_count)s|||%(like_count)s|||%(comment_count)s|||%(availability)s|||%(live_status)s',
|
|
69
|
-
url,
|
|
70
|
-
], { label: 'get_video_info' });
|
|
71
|
-
// yt-dlp prints "NA" for absent fields and simply omits trailing ones, so
|
|
72
|
-
// index access has to tolerate a short row rather than trust its length.
|
|
73
|
-
const parts = stdout.split('|||');
|
|
74
|
-
const field = (index) => parts[index] ?? '';
|
|
75
|
-
// Refusals reach us as a populated row rather than a failure, so this is the
|
|
76
|
-
// point at which one becomes a typed error.
|
|
77
|
-
const refusal = classifyPlayability({ availability: field(11), liveStatus: field(12) });
|
|
78
|
-
if (refusal)
|
|
79
|
-
throw refusal;
|
|
80
|
-
const [id, title, channel, durationStr, uploadDate, description, tagsJson, thumbnailUrl] = [
|
|
81
|
-
field(0),
|
|
82
|
-
field(1),
|
|
83
|
-
field(2),
|
|
84
|
-
field(3),
|
|
85
|
-
field(4),
|
|
86
|
-
field(5),
|
|
87
|
-
field(6),
|
|
88
|
-
field(7),
|
|
89
|
-
];
|
|
90
|
-
const duration = parseInt(durationStr, 10) || 0;
|
|
91
|
-
let tags = [];
|
|
92
|
-
try {
|
|
93
|
-
const parsedTags = JSON.parse(tagsJson || '[]');
|
|
94
|
-
if (Array.isArray(parsedTags)) {
|
|
95
|
-
tags = parsedTags.filter((t) => typeof t === 'string');
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
tags = [];
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
id,
|
|
103
|
-
title,
|
|
104
|
-
channel,
|
|
105
|
-
duration,
|
|
106
|
-
durationFormatted: formatDuration(duration),
|
|
107
|
-
uploadDate: formatYouTubeDate(uploadDate),
|
|
108
|
-
description: description || '',
|
|
109
|
-
tags,
|
|
110
|
-
url,
|
|
111
|
-
thumbnailUrl: thumbnailUrl || '',
|
|
112
|
-
viewCount: parseInt(field(8), 10) || 0,
|
|
113
|
-
likeCount: parseInt(field(9), 10) || 0,
|
|
114
|
-
commentCount: parseInt(field(10), 10) || 0,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
export async function listVideos(urlOrChannel, limit = 20) {
|
|
118
|
-
const stdout = await runYtDlp([
|
|
119
|
-
'--skip-download',
|
|
120
|
-
'--flat-playlist',
|
|
121
|
-
'--print',
|
|
122
|
-
'%(id)s|||%(title)s|||%(duration)s|||%(upload_date)s',
|
|
123
|
-
'--playlist-end',
|
|
124
|
-
limit.toString(),
|
|
125
|
-
urlOrChannel,
|
|
126
|
-
], { label: 'fetch_videos', timeoutMs: TIMEOUTS.transcript });
|
|
127
|
-
const lines = stdout.trim().split('\n').filter(Boolean);
|
|
128
|
-
return lines.map((line) => {
|
|
129
|
-
const parts = line.split('|||');
|
|
130
|
-
const field = (index) => parts[index] ?? '';
|
|
131
|
-
const id = field(0);
|
|
132
|
-
const duration = parseInt(field(2), 10) || 0;
|
|
133
|
-
return {
|
|
134
|
-
id,
|
|
135
|
-
title: field(1) || 'Unknown title',
|
|
136
|
-
duration,
|
|
137
|
-
durationFormatted: formatDuration(duration),
|
|
138
|
-
uploadDate: formatYouTubeDate(field(3)),
|
|
139
|
-
url: `https://www.youtube.com/watch?v=${id}`,
|
|
140
|
-
};
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
/** Captions rarely change, but a cache with no expiry is a cache that goes wrong. */
|
|
144
|
-
const TRANSCRIPT_TTL_MS = Number(process.env.YOUTUBE_MCP_TRANSCRIPT_TTL_MS ?? 30 * 86_400_000);
|
|
145
|
-
function cachePath(videoId, language) {
|
|
146
|
-
return join(CACHE_DIR, `${videoId}.${language}.json`);
|
|
147
|
-
}
|
|
148
|
-
async function readCachedTranscript(videoId, language) {
|
|
149
|
-
const path = cachePath(videoId, language);
|
|
150
|
-
if (!existsSync(path))
|
|
151
|
-
return undefined;
|
|
152
|
-
try {
|
|
153
|
-
const parsed = cachedTranscriptSchema.safeParse(JSON.parse(await readFile(path, 'utf-8')));
|
|
154
|
-
// Anything unreadable — an older layout, a truncated write, a hand-edit —
|
|
155
|
-
// is treated as absent and refetched, rather than half-trusted.
|
|
156
|
-
if (!parsed.success)
|
|
157
|
-
return undefined;
|
|
158
|
-
const cached = parsed.data;
|
|
159
|
-
// A cache written by an older version holds untimed text; regenerate it
|
|
160
|
-
// rather than reading it back as if it had timings.
|
|
161
|
-
if (cached.version !== TRANSCRIPT_CACHE_VERSION)
|
|
162
|
-
return undefined;
|
|
163
|
-
const fetchedAt = Date.parse(cached.fetchedAt);
|
|
164
|
-
if (Number.isFinite(fetchedAt) && Date.now() - fetchedAt > TRANSCRIPT_TTL_MS)
|
|
165
|
-
return undefined;
|
|
166
|
-
return cached;
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/** True when a usable transcript is already on disk, in any language. */
|
|
173
|
-
export function hasCachedTranscript(videoId) {
|
|
174
|
-
if (!existsSync(CACHE_DIR))
|
|
175
|
-
return false;
|
|
176
|
-
return readdirSync(CACHE_DIR).some((name) => name.startsWith(`${videoId}.`) && name.endsWith('.json'));
|
|
177
|
-
}
|
|
178
|
-
export async function getTranscript(urlOrId, preferredLangOrOptions = 'en') {
|
|
179
|
-
const options = typeof preferredLangOrOptions === 'string'
|
|
180
|
-
? { language: preferredLangOrOptions }
|
|
181
|
-
: preferredLangOrOptions;
|
|
182
|
-
const preferredLang = options.language ?? 'en';
|
|
183
|
-
const videoId = extractVideoId(urlOrId);
|
|
184
|
-
assertLanguageTag(preferredLang);
|
|
185
|
-
const url = `https://www.youtube.com/watch?v=${videoId}`;
|
|
186
|
-
await mkdir(CACHE_DIR, { recursive: true });
|
|
187
|
-
if (!options.refresh) {
|
|
188
|
-
const cached = await readCachedTranscript(videoId, preferredLang);
|
|
189
|
-
if (cached) {
|
|
190
|
-
return {
|
|
191
|
-
transcript: segmentsToText(cached.segments),
|
|
192
|
-
segments: cached.segments,
|
|
193
|
-
language: cached.language,
|
|
194
|
-
videoId,
|
|
195
|
-
cached: true,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const tempDir = join(CACHE_DIR, 'temp');
|
|
200
|
-
await mkdir(tempDir, { recursive: true });
|
|
201
|
-
const outputTemplate = join(tempDir, videoId);
|
|
202
|
-
try {
|
|
203
|
-
await runYtDlp([
|
|
204
|
-
'--skip-download',
|
|
205
|
-
'--write-auto-sub',
|
|
206
|
-
'--write-sub',
|
|
207
|
-
'--sub-lang',
|
|
208
|
-
`${preferredLang},${preferredLang}-orig`,
|
|
209
|
-
'--sub-format',
|
|
210
|
-
'vtt',
|
|
211
|
-
'--convert-subs',
|
|
212
|
-
'vtt',
|
|
213
|
-
'-o',
|
|
214
|
-
outputTemplate,
|
|
215
|
-
url,
|
|
216
|
-
], { label: 'get_transcript', timeoutMs: TIMEOUTS.transcript });
|
|
217
|
-
const candidates = [
|
|
218
|
-
{ file: `${outputTemplate}.${preferredLang}.vtt`, language: preferredLang },
|
|
219
|
-
{
|
|
220
|
-
file: `${outputTemplate}.${preferredLang}-orig.vtt`,
|
|
221
|
-
language: `${preferredLang} (auto-generated)`,
|
|
222
|
-
},
|
|
223
|
-
{ file: `${outputTemplate}.en.vtt`, language: 'en' },
|
|
224
|
-
];
|
|
225
|
-
const found = candidates.find((candidate) => existsSync(candidate.file));
|
|
226
|
-
if (!found)
|
|
227
|
-
throw await noCaptionsError(url, preferredLang);
|
|
228
|
-
const segments = parseVtt(await readFile(found.file, 'utf-8'));
|
|
229
|
-
if (segments.length === 0)
|
|
230
|
-
throw await noCaptionsError(url, preferredLang);
|
|
231
|
-
const entry = {
|
|
232
|
-
version: TRANSCRIPT_CACHE_VERSION,
|
|
233
|
-
videoId,
|
|
234
|
-
language: found.language,
|
|
235
|
-
fetchedAt: new Date().toISOString(),
|
|
236
|
-
segments,
|
|
237
|
-
};
|
|
238
|
-
await writeFile(cachePath(videoId, preferredLang), JSON.stringify(entry), 'utf-8');
|
|
239
|
-
await unlink(found.file).catch(() => undefined);
|
|
240
|
-
return {
|
|
241
|
-
transcript: segmentsToText(segments),
|
|
242
|
-
segments,
|
|
243
|
-
language: found.language,
|
|
244
|
-
videoId,
|
|
245
|
-
cached: false,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
catch (error) {
|
|
249
|
-
// Already typed and actionable — pass it through rather than flattening it
|
|
250
|
-
// into a generic string, which is what the old wrapper did to every failure.
|
|
251
|
-
if (error instanceof YouTubeError)
|
|
252
|
-
throw error;
|
|
253
|
-
throw new YouTubeError('YTDLP_FAILED', `Could not read the transcript for ${videoId}.`, {
|
|
254
|
-
nextStep: 'Verify the video exists and has captions, or call check_health.',
|
|
255
|
-
cause: error,
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Ask yt-dlp which caption tracks the video actually has, so the error can name
|
|
261
|
-
* the languages that would work instead of just saying "not found".
|
|
262
|
-
*/
|
|
263
|
-
async function noCaptionsError(url, requested) {
|
|
264
|
-
let available = [];
|
|
265
|
-
try {
|
|
266
|
-
const stdout = await runYtDlp(['-j', '--skip-download', url], {
|
|
267
|
-
label: 'get_transcript (caption probe)',
|
|
268
|
-
});
|
|
269
|
-
const data = parseYtDlpJson(stdout, isRecord, 'caption tracks');
|
|
270
|
-
available = [
|
|
271
|
-
...Object.keys(data.subtitles ?? {}),
|
|
272
|
-
...Object.keys(data.automatic_captions ?? {}),
|
|
273
|
-
]
|
|
274
|
-
.filter((code) => !code.endsWith('-orig'))
|
|
275
|
-
.filter((code, index, all) => all.indexOf(code) === index)
|
|
276
|
-
.sort();
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
// The probe is a nicety; never let it mask the original problem.
|
|
280
|
-
}
|
|
281
|
-
if (available.length === 0) {
|
|
282
|
-
return new YouTubeError('NO_CAPTIONS', 'This video has no captions in any language.', {
|
|
283
|
-
nextStep: 'Try get_video_info for the description, or get_comments for viewer discussion instead.',
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
const shown = available.slice(0, 25).join(', ');
|
|
287
|
-
const more = available.length > 25 ? `, and ${available.length - 25} more` : '';
|
|
288
|
-
return new YouTubeError('NO_CAPTIONS', `No "${requested}" captions are available for this video.`, { nextStep: `Call get_transcript again with one of: ${shown}${more}.` });
|
|
289
|
-
}
|
|
290
|
-
const DOWNLOADS_DIR = dataDir('downloads');
|
|
291
|
-
export async function listFormats(urlOrId) {
|
|
292
|
-
const videoId = extractVideoId(urlOrId);
|
|
293
|
-
const url = `https://www.youtube.com/watch?v=${videoId}`;
|
|
294
|
-
const stdout = await runYtDlp(['-j', '--skip-download', url], { label: 'list_formats' });
|
|
295
|
-
const data = parseYtDlpJson(stdout, isRecord, 'video formats');
|
|
296
|
-
const formats = data.formats ?? [];
|
|
297
|
-
return formats
|
|
298
|
-
.filter((f) => !f.format_id.startsWith('sb')) // skip storyboards
|
|
299
|
-
.map((f) => {
|
|
300
|
-
const resolution = f.resolution ?? (f.width && f.height ? `${f.width}x${f.height}` : 'audio only');
|
|
301
|
-
return {
|
|
302
|
-
formatId: f.format_id,
|
|
303
|
-
ext: f.ext,
|
|
304
|
-
resolution,
|
|
305
|
-
fps: f.fps,
|
|
306
|
-
vcodec: f.vcodec ?? 'none',
|
|
307
|
-
acodec: f.acodec ?? 'none',
|
|
308
|
-
filesize: f.filesize ?? f.filesize_approx,
|
|
309
|
-
note: f.format_note ?? '',
|
|
310
|
-
};
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
// Smart format selectors that use yt-dlp's fallback syntax
|
|
314
|
-
const QUALITY_FORMAT_SELECTORS = {
|
|
315
|
-
best: 'bestvideo*+bestaudio/best',
|
|
316
|
-
'2160p': 'bestvideo[height<=2160]+bestaudio/bestvideo*[height<=2160]+bestaudio/best[height<=2160]/bestvideo+bestaudio/best',
|
|
317
|
-
'1440p': 'bestvideo[height<=1440]+bestaudio/bestvideo*[height<=1440]+bestaudio/best[height<=1440]/bestvideo+bestaudio/best',
|
|
318
|
-
'1080p': 'bestvideo[height<=1080]+bestaudio/bestvideo*[height<=1080]+bestaudio/best[height<=1080]/bestvideo+bestaudio/best',
|
|
319
|
-
'720p': 'bestvideo[height<=720]+bestaudio/bestvideo*[height<=720]+bestaudio/best[height<=720]/bestvideo+bestaudio/best',
|
|
320
|
-
'480p': 'bestvideo[height<=480]+bestaudio/bestvideo*[height<=480]+bestaudio/best[height<=480]/bestvideo+bestaudio/best',
|
|
321
|
-
'360p': 'bestvideo[height<=360]+bestaudio/bestvideo*[height<=360]+bestaudio/best[height<=360]/bestvideo+bestaudio/best',
|
|
322
|
-
audio: 'bestaudio/best',
|
|
323
|
-
};
|
|
324
|
-
export async function downloadVideo(urlOrId, formatId, outputDir, quality) {
|
|
325
|
-
const videoId = extractVideoId(urlOrId);
|
|
326
|
-
const url = `https://www.youtube.com/watch?v=${videoId}`;
|
|
327
|
-
const targetDir = resolveOutputDir(outputDir, DOWNLOADS_DIR);
|
|
328
|
-
// Ensure download directory exists
|
|
329
|
-
await mkdir(targetDir, { recursive: true });
|
|
330
|
-
// Get video title first for the result
|
|
331
|
-
const titleOutput = await runYtDlp(['--skip-download', '--print', '%(title)s', url], {
|
|
332
|
-
label: 'download_video (title)',
|
|
333
|
-
});
|
|
334
|
-
const title = titleOutput.trim();
|
|
335
|
-
// Download with specified format
|
|
336
|
-
const outputTemplate = join(targetDir, '%(title)s.%(ext)s');
|
|
337
|
-
// A quality preset always wins over formatId; that is what the tool schema
|
|
338
|
-
// promises, and the two are resolved in exactly one place.
|
|
339
|
-
const formatSelector = quality ? QUALITY_FORMAT_SELECTORS[quality] : formatId;
|
|
340
|
-
// -S vcodec:h264,acodec:m4a prefers H.264+AAC, which merge cleanly into MP4.
|
|
341
|
-
const commonArgs = (selector) => [
|
|
342
|
-
'-f',
|
|
343
|
-
selector,
|
|
344
|
-
'-S',
|
|
345
|
-
'vcodec:h264,acodec:m4a',
|
|
346
|
-
'-o',
|
|
347
|
-
outputTemplate,
|
|
348
|
-
'--no-playlist',
|
|
349
|
-
'--merge-output-format',
|
|
350
|
-
'mp4',
|
|
351
|
-
];
|
|
352
|
-
// Transfers are not retried automatically: a partial file on disk plus a
|
|
353
|
-
// silent second attempt is worse than one clear failure.
|
|
354
|
-
const downloadOptions = {
|
|
355
|
-
label: 'download_video',
|
|
356
|
-
timeoutMs: TIMEOUTS.download,
|
|
357
|
-
retry: false,
|
|
358
|
-
};
|
|
359
|
-
let effectiveSelector = formatSelector;
|
|
360
|
-
try {
|
|
361
|
-
await runYtDlp([...commonArgs(formatSelector), url], downloadOptions);
|
|
362
|
-
}
|
|
363
|
-
catch (error) {
|
|
364
|
-
// An explicitly requested format may simply not exist for this video, so
|
|
365
|
-
// falling back to "best" is worth one attempt. A preset failing is not:
|
|
366
|
-
// presets already encode their own fallback chain, and "best" failing
|
|
367
|
-
// leaves nothing to fall back to.
|
|
368
|
-
const alreadyBroadest = quality !== undefined || formatId === 'best';
|
|
369
|
-
if (alreadyBroadest)
|
|
370
|
-
throw error;
|
|
371
|
-
log('warning', `format ${formatId} unavailable, falling back to best`);
|
|
372
|
-
effectiveSelector = QUALITY_FORMAT_SELECTORS.best;
|
|
373
|
-
await runYtDlp([...commonArgs(effectiveSelector), url], downloadOptions);
|
|
374
|
-
}
|
|
375
|
-
// Ask yt-dlp what it actually named the file rather than guessing.
|
|
376
|
-
const filenameOutput = await runYtDlp([...commonArgs(effectiveSelector), '--print', 'filename', '--skip-download', url], { label: 'download_video (filename)' });
|
|
377
|
-
return {
|
|
378
|
-
videoId,
|
|
379
|
-
title,
|
|
380
|
-
filePath: filenameOutput.trim(),
|
|
381
|
-
format: quality ?? formatId,
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
export async function searchVideos(query, limit = 5) {
|
|
385
|
-
const stdout = await runYtDlp([`ytsearch${limit}:${query}`, '--dump-json', '--flat-playlist'], {
|
|
386
|
-
label: 'search_videos',
|
|
387
|
-
});
|
|
388
|
-
return parseYtDlpJsonLines(stdout, isSearchResult).map((data) => {
|
|
389
|
-
return {
|
|
390
|
-
id: data.id,
|
|
391
|
-
title: data.title ?? 'Unknown',
|
|
392
|
-
duration: data.duration ?? 0,
|
|
393
|
-
durationFormatted: formatDuration(data.duration ?? 0),
|
|
394
|
-
channel: data.channel ?? 'Unknown',
|
|
395
|
-
viewCount: data.view_count ?? 0,
|
|
396
|
-
url: data.url ?? `https://www.youtube.com/watch?v=${data.id}`,
|
|
397
|
-
};
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
export async function getChapters(urlOrId) {
|
|
401
|
-
return (await getVideoDetails(urlOrId)).chapters;
|
|
402
|
-
}
|
|
403
|
-
export async function getVideoDetails(urlOrId) {
|
|
404
|
-
const videoId = extractVideoId(urlOrId);
|
|
405
|
-
const url = `https://www.youtube.com/watch?v=${videoId}`;
|
|
406
|
-
const stdout = await runYtDlp(['-j', '--skip-download', url], { label: 'get_video_details' });
|
|
407
|
-
const data = parseYtDlpJson(stdout, isRecord, 'video details');
|
|
408
|
-
return {
|
|
409
|
-
uploadDate: formatYouTubeDate(data.upload_date ?? ''),
|
|
410
|
-
durationSeconds: typeof data.duration === 'number' ? data.duration : 0,
|
|
411
|
-
chapters: (data.chapters ?? []).map((ch) => ({
|
|
412
|
-
title: ch.title,
|
|
413
|
-
startTime: ch.start_time,
|
|
414
|
-
startTimeFormatted: formatDuration(Math.floor(ch.start_time)),
|
|
415
|
-
endTime: ch.end_time,
|
|
416
|
-
endTimeFormatted: formatDuration(Math.floor(ch.end_time)),
|
|
417
|
-
})),
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
export async function getComments(urlOrId, limit = 20) {
|
|
421
|
-
const videoId = extractVideoId(urlOrId);
|
|
422
|
-
const url = `https://www.youtube.com/watch?v=${videoId}`;
|
|
423
|
-
const stdout = await runYtDlp([
|
|
424
|
-
'-j',
|
|
425
|
-
'--skip-download',
|
|
426
|
-
'--write-comments',
|
|
427
|
-
'--extractor-args',
|
|
428
|
-
`youtube:comment_sort=top;max_comments=${limit}`,
|
|
429
|
-
url,
|
|
430
|
-
], { label: 'get_comments', timeoutMs: TIMEOUTS.comments });
|
|
431
|
-
const data = parseYtDlpJson(stdout, isRecord, 'video comments');
|
|
432
|
-
const comments = data.comments ?? [];
|
|
433
|
-
return comments
|
|
434
|
-
.filter((c) => c.parent === 'root')
|
|
435
|
-
.slice(0, limit)
|
|
436
|
-
.map((c) => ({
|
|
437
|
-
author: c.author ?? 'Unknown',
|
|
438
|
-
text: c.text ?? '',
|
|
439
|
-
likeCount: c.like_count ?? 0,
|
|
440
|
-
isPinned: c.is_pinned ?? false,
|
|
441
|
-
}));
|
|
442
|
-
}
|
|
443
|
-
export async function searchChannels(query, limit = 5) {
|
|
444
|
-
// YouTube channel filter: sp=EgIQAg%3D%3D
|
|
445
|
-
const searchUrl = `https://www.youtube.com/results?search_query=${encodeURIComponent(query)}&sp=EgIQAg%3D%3D`;
|
|
446
|
-
const stdout = await runYtDlp([searchUrl, '--dump-json', '--flat-playlist', '--playlist-items', `1-${limit}`], { label: 'search_channels' });
|
|
447
|
-
return parseYtDlpJsonLines(stdout, isRecord).map((data) => {
|
|
448
|
-
return {
|
|
449
|
-
name: data.channel ?? data.title ?? 'Unknown',
|
|
450
|
-
channelId: data.channel_id ?? data.id ?? '',
|
|
451
|
-
handle: data.uploader_id ?? '',
|
|
452
|
-
subscriberCount: data.channel_follower_count ?? 0,
|
|
453
|
-
channelUrl: data.channel_url ?? '',
|
|
454
|
-
description: data.description ?? '',
|
|
455
|
-
};
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
export async function getPlaylistInfo(playlistUrl) {
|
|
459
|
-
const stdout = await runYtDlp(['--dump-single-json', '--flat-playlist', '--playlist-items', '0', playlistUrl], { label: 'get_playlist_info' });
|
|
460
|
-
const data = parseYtDlpJson(stdout, isRecord, 'playlist metadata');
|
|
461
|
-
const modDate = data.modified_date ?? '';
|
|
462
|
-
return {
|
|
463
|
-
id: data.id ?? '',
|
|
464
|
-
title: data.title ?? 'Unknown',
|
|
465
|
-
channel: data.channel ?? '',
|
|
466
|
-
handle: data.uploader_id ?? '',
|
|
467
|
-
channelUrl: data.channel_url ?? '',
|
|
468
|
-
videoCount: data.playlist_count ?? 0,
|
|
469
|
-
lastModified: formatYouTubeDate(modDate),
|
|
470
|
-
url: data.webpage_url ?? playlistUrl,
|
|
471
|
-
description: data.description ?? '',
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
export async function getChannelInfo(channel) {
|
|
475
|
-
const channelUrl = channel.startsWith('http')
|
|
476
|
-
? channel
|
|
477
|
-
: `https://www.youtube.com/${channel.startsWith('@') ? channel : `@${channel}`}`;
|
|
478
|
-
const stdout = await runYtDlp(['--dump-single-json', '--flat-playlist', '--playlist-items', '0', channelUrl], { label: 'get_channel_info' });
|
|
479
|
-
const data = parseYtDlpJson(stdout, isRecord, 'channel metadata');
|
|
480
|
-
return {
|
|
481
|
-
name: data.channel ?? 'Unknown',
|
|
482
|
-
channelId: data.channel_id ?? '',
|
|
483
|
-
handle: data.uploader_id ?? '',
|
|
484
|
-
subscriberCount: data.channel_follower_count ?? 0,
|
|
485
|
-
channelUrl: data.channel_url ?? channelUrl,
|
|
486
|
-
description: data.description ?? '',
|
|
487
|
-
};
|
|
488
|
-
}
|
|
8
|
+
export * from './youtube-url.js';
|
|
9
|
+
export * from './youtube-video.js';
|
|
10
|
+
export * from './youtube-channel.js';
|
|
11
|
+
export * from './youtube-search.js';
|
|
12
|
+
export * from './youtube-download.js';
|
|
13
|
+
export * from './transcript-cache.js';
|
|
489
14
|
//# sourceMappingURL=youtube.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../src/utils/youtube.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../src/utils/youtube.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The session options yt-dlp is started with, read from the environment.
|
|
3
|
+
*
|
|
4
|
+
* Cookies are how yt-dlp reads age-restricted, members-only and sign-in-gated
|
|
5
|
+
* videos, and how it gets past the "confirm you're not a bot" check YouTube
|
|
6
|
+
* sometimes applies to an address. They are also the user's own account, so
|
|
7
|
+
* everything here is careful about two things: the values are validated at
|
|
8
|
+
* boot and never at request time, and neither the cookie path nor its contents
|
|
9
|
+
* ever appear in a log line, a tool result or an error message.
|
|
10
|
+
*/
|
|
11
|
+
export declare const COOKIE_BROWSERS: readonly ["brave", "chrome", "chromium", "edge", "firefox", "opera", "safari", "vivaldi", "whale"];
|
|
12
|
+
export type CookieBrowser = (typeof COOKIE_BROWSERS)[number];
|
|
13
|
+
export interface YtDlpEnv {
|
|
14
|
+
/** The flags to place before the caller's arguments on every spawn. */
|
|
15
|
+
args: string[];
|
|
16
|
+
/** Which kind of cookies are configured; safe to report, unlike the values. */
|
|
17
|
+
cookies: 'file' | 'browser' | 'none';
|
|
18
|
+
browser?: CookieBrowser;
|
|
19
|
+
proxy: boolean;
|
|
20
|
+
/** Seconds yt-dlp sleeps between its own requests, when configured. */
|
|
21
|
+
sleepRequestsSeconds?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validate the session settings and turn them into yt-dlp flags.
|
|
25
|
+
*
|
|
26
|
+
* Throws a plain `Error` naming the variable: this runs at boot, where a bad
|
|
27
|
+
* setting should stop the server before a transport starts, not surface as a
|
|
28
|
+
* puzzling failure on the first tool call.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readYtDlpEnv(env?: NodeJS.ProcessEnv): YtDlpEnv;
|
|
31
|
+
/** One line for the boot log: what is configured, never what it is. */
|
|
32
|
+
export declare function describeYtDlpEnv(settings: YtDlpEnv): string;
|
|
33
|
+
//# sourceMappingURL=ytdlp-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ytdlp-env.d.ts","sourceRoot":"","sources":["../../src/utils/ytdlp-env.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,eAAO,MAAM,eAAe,oGAUlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAI7D,MAAM,WAAW,QAAQ;IACvB,uEAAuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,+EAA+E;IAC/E,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AA4DD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,QAAQ,CAyB3E;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAU3D"}
|