mirror of
https://github.com/Luchexx/claude-video.git
synced 2026-11-02 09:19:48 +00:00
feat: support only the latest yt-dlp and update it on HTTP 403
A 403 now carries an update-and-retry-once hint, the skill contract tells the agent how to update yt-dlp through its owning package manager, and CI installs the latest yt-dlp instead of a pinned baseline. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3216a9c307
commit
fdbffd1c2e
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
|||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
run: choco install ffmpeg --no-progress -y
|
run: choco install ffmpeg --no-progress -y
|
||||||
- name: Install test tools
|
- name: Install test tools
|
||||||
run: python -m pip install pytest "yt-dlp[default]==2026.8.19"
|
run: python -m pip install --upgrade pytest "yt-dlp[default]"
|
||||||
- name: Verify executables
|
- name: Verify executables
|
||||||
run: |
|
run: |
|
||||||
ffmpeg -version
|
ffmpeg -version
|
||||||
|
|||||||
@ -15,7 +15,7 @@ All notable changes to `/watch` are documented here.
|
|||||||
### Fixed
|
### Fixed
|
||||||
- SessionStart hook command now quotes `${CLAUDE_PLUGIN_ROOT}`, so plugin paths containing spaces work.
|
- SessionStart hook command now quotes `${CLAUDE_PLUGIN_ROOT}`, so plugin paths containing spaces work.
|
||||||
- Uniform sampling now spans the actual capped range and labels selected source frames with their real timestamps, including fractional seeks and cue frames.
|
- Uniform sampling now spans the actual capped range and labels selected source frames with their real timestamps, including fractional seeks and cue frames.
|
||||||
- FFmpeg sync-option capability detection, empty keyframe-window fallback, RGB thumbnail deduplication, and actionable probe/launch errors.
|
- FFmpeg sync-option capability detection (including FFmpeg 9's `-fps_mode[:<stream_spec>]` help format; tested on FFmpeg 4.4 through 9.0), empty keyframe-window fallback, RGB thumbnail deduplication, and actionable probe/launch errors.
|
||||||
- UTF-8 output and subprocess decoding, BOM-aware shared config parsing, provider-key pairing, atomic config updates, keyless readiness, and advisory setup hooks.
|
- UTF-8 output and subprocess decoding, BOM-aware shared config parsing, provider-key pairing, atomic config updates, keyless readiness, and advisory setup hooks.
|
||||||
- Bounded caption downloads respect watch-owned output templates while retaining intentional yt-dlp configuration. Fresh run directories and completed final-path validation prevent stale/partial media reuse.
|
- Bounded caption downloads respect watch-owned output templates while retaining intentional yt-dlp configuration. Fresh run directories and completed final-path validation prevent stale/partial media reuse.
|
||||||
- WebVTT optional-hour timestamps, entities, cue/block parsing, and overlap-scoped deduplication preserve independent repeated speech.
|
- WebVTT optional-hour timestamps, entities, cue/block parsing, and overlap-scoped deduplication preserve independent repeated speech.
|
||||||
@ -23,6 +23,7 @@ All notable changes to `/watch` are documented here.
|
|||||||
- Conservative 24,000,000-byte cloud upload budgets, actual chunk/multipart size checks, and explicit partial/no-speech metadata.
|
- Conservative 24,000,000-byte cloud upload budgets, actual chunk/multipart size checks, and explicit partial/no-speech metadata.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Only the latest yt-dlp release is supported. An HTTP 403 now tells the agent to update yt-dlp with its owning package manager and retry once; CI tests against the latest release instead of a pinned one.
|
||||||
- First-success installation documentation separates media tools from optional speech backends and describes host/network limitations.
|
- First-success installation documentation separates media tools from optional speech backends and describes host/network limitations.
|
||||||
- User-provided output directories now contain a disposable run child; cleanup preserves the parent and source files.
|
- User-provided output directories now contain a disposable run child; cleanup preserves the parent and source files.
|
||||||
- The base runtime remains standard-library-only; local model environments and caches live outside the self-contained skill folder.
|
- The base runtime remains standard-library-only; local model environments and caches live outside the self-contained skill folder.
|
||||||
|
|||||||
@ -171,7 +171,7 @@ Tell me which tools are missing and help me install them here.
|
|||||||
| Ubuntu/Debian | `sudo apt install python3 ffmpeg pipx`, then `pipx install "yt-dlp[default,curl-cffi]"` and `pipx ensurepath`. Install [Deno](https://docs.deno.com/runtime/getting_started/installation/) for YouTube. |
|
| Ubuntu/Debian | `sudo apt install python3 ffmpeg pipx`, then `pipx install "yt-dlp[default,curl-cffi]"` and `pipx ensurepath`. Install [Deno](https://docs.deno.com/runtime/getting_started/installation/) for YouTube. |
|
||||||
| Windows | Install [Python 3.10+](https://www.python.org/downloads/windows/), then `winget install --id Gyan.FFmpeg --exact`, `winget install --id yt-dlp.yt-dlp --exact`, and `winget install --id DenoLand.Deno --exact`. |
|
| Windows | Install [Python 3.10+](https://www.python.org/downloads/windows/), then `winget install --id Gyan.FFmpeg --exact`, `winget install --id yt-dlp.yt-dlp --exact`, and `winget install --id DenoLand.Deno --exact`. |
|
||||||
|
|
||||||
Reopen the terminal and agent after installation so they can find the new tools. On Windows, verify Python with `python --version` or `py -3 --version`. The tested yt-dlp baseline is **2026.08.19**; Watch uses the executable available in the active environment.
|
Reopen the terminal and agent after installation so they can find the new tools. On Windows, verify Python with `python --version` or `py -3 --version`. Watch supports the **latest yt-dlp release** only, because sites routinely break older ones; it uses the executable available in the active environment.
|
||||||
|
|
||||||
## Using a web app?
|
## Using a web app?
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ Update Watch using the same method you installed it with, then start a new sessi
|
|||||||
|
|
||||||
Marketplace auto-update behavior depends on the host and your settings. Updating Watch is separate from updating its media tools.
|
Marketplace auto-update behavior depends on the host and your settings. Updating Watch is separate from updating its media tools.
|
||||||
|
|
||||||
Update yt-dlp with its owning installer, then verify the same executable with `yt-dlp --version`:
|
Keep yt-dlp on its latest release. Update it with its owning installer, then verify the same executable with `yt-dlp --version`:
|
||||||
|
|
||||||
- Homebrew: `brew upgrade yt-dlp`
|
- Homebrew: `brew upgrade yt-dlp`
|
||||||
- pipx: `pipx upgrade yt-dlp`
|
- pipx: `pipx upgrade yt-dlp`
|
||||||
@ -331,7 +331,7 @@ Ask the agent to run bundled `setup.py --json` for resolved paths/versions, JS-r
|
|||||||
| Python opens the Store | Use an installed interpreter verified by `python --version` or `py -3 --version`. |
|
| Python opens the Store | Use an installed interpreter verified by `python --version` or `py -3 --version`. |
|
||||||
| FFmpeg option failure | Inspect the actual FFmpeg path; watch probes `-fps_mode` and retains advertised `-vsync` compatibility for older builds. |
|
| FFmpeg option failure | Inspect the actual FFmpeg path; watch probes `-fps_mode` and retains advertised `-vsync` compatibility for older builds. |
|
||||||
| Missing JS runtime/EJS | Update the owning yt-dlp package and follow upstream Deno/EJS setup. |
|
| Missing JS runtime/EJS | Update the owning yt-dlp package and follow upstream Deno/EJS setup. |
|
||||||
| 403 / login challenge | Read the original error; use explicit authentication only if you have access. A 403 has no universal workaround. |
|
| 403 / login challenge | Update yt-dlp to its latest release (see [Updating and troubleshooting](#updating-and-troubleshooting)) and retry once; the agent does this automatically. If the 403 persists, read the original error and use explicit authentication only if you have access. |
|
||||||
| `Gemini auth` / `quota` / `rejected` / `upload` / `service` / `network` / `response` | The Gemini engine failed: bad or missing key, rate limit, a video Google refused (private, unsupported, too long), a failed upload, a Google-side error, no route to `generativelanguage.googleapis.com`, or an unreadable reply. Nothing ran locally; fix the cause or rerun with `--engine local`. |
|
| `Gemini auth` / `quota` / `rejected` / `upload` / `service` / `network` / `response` | The Gemini engine failed: bad or missing key, rate limit, a video Google refused (private, unsupported, too long), a failed upload, a Google-side error, no route to `generativelanguage.googleapis.com`, or an unreadable reply. Nothing ran locally; fix the cause or rerun with `--engine local`. |
|
||||||
| 429 | Wait before retrying; the service is rate limiting requests. |
|
| 429 | Wait before retrying; the service is rate limiting requests. |
|
||||||
| Explicit hosted egress denial | Check the environment's network settings or use an accessible local source. Cloud ASR/cold model setup still need network access. |
|
| Explicit hosted egress denial | Check the environment's network settings or use an accessible local source. Cloud ASR/cold model setup still need network access. |
|
||||||
|
|||||||
@ -150,7 +150,7 @@ If a small-model transcript is nonsense, suggest the actual spoken-language hint
|
|||||||
|
|
||||||
Cloud fallbacks extract mono 16 kHz MP3 and upload within a conservative 24,000,000-byte file budget. Large files are chunked with source-time offsets restored; missing chunks appear in the final report. Provider errors do not justify automatic provider switching.
|
Cloud fallbacks extract mono 16 kHz MP3 and upload within a conservative 24,000,000-byte file budget. Large files are chunked with source-time offsets restored; missing chunks appear in the final report. Provider errors do not justify automatic provider switching.
|
||||||
|
|
||||||
For download failures, use the bounded original error and its diagnostic hint. A generic 403 has no universal fix. Do not hardcode alternate clients, cycle cookies, or disable TLS verification. Preserve available captions when media/probing fails. For hosted environments, local uploads solve downloading only; cloud ASR and cold local-model setup still need permitted network access.
|
For download failures, use the bounded original error and its diagnostic hint. A 403 has no generic fix, but first update yt-dlp with its owning package manager (e.g. `brew upgrade yt-dlp`, `pipx upgrade yt-dlp`) and retry once. Do not hardcode alternate clients, cycle cookies, or disable TLS verification. Preserve available captions when media/probing fails. For hosted environments, local uploads solve downloading only; cloud ASR and cold local-model setup still need permitted network access.
|
||||||
|
|
||||||
For follow-ups, reuse evidence already viewed before rerunning. Remove only the disposable **Work dir** created by this invocation when no longer needed. Never delete the parent supplied with `--out-dir`, a user source file, the local venv, or model caches as routine cleanup.
|
For follow-ups, reuse evidence already viewed before rerunning. Remove only the disposable **Work dir** created by this invocation when no longer needed. Never delete the parent supplied with `--out-dir`, a user source file, the local venv, or model caches as routine cleanup.
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,9 @@ def network_diagnostic(stderr: str) -> str:
|
|||||||
hint = 'This source requires authentication; supply an explicit cookie option if you have access.'
|
hint = 'This source requires authentication; supply an explicit cookie option if you have access.'
|
||||||
elif '429' in lower or 'too many requests' in lower:
|
elif '429' in lower or 'too many requests' in lower:
|
||||||
hint = 'The service is rate limiting requests; wait before trying again.'
|
hint = 'The service is rate limiting requests; wait before trying again.'
|
||||||
|
elif re.search(r'\b403\b', lower) or 'forbidden' in lower:
|
||||||
|
# Only the latest yt-dlp is supported; sites routinely break older releases with 403s.
|
||||||
|
hint = 'No generic fix for a 403; update yt-dlp to its latest release and retry once.'
|
||||||
elif any(s in lower for s in ('egress denied', 'not in the allowlist', 'blocked by network policy')):
|
elif any(s in lower for s in ('egress denied', 'not in the allowlist', 'blocked by network policy')):
|
||||||
hint = 'This environment blocks the destination; check its network settings or use an accessible local file.'
|
hint = 'This environment blocks the destination; check its network settings or use an accessible local file.'
|
||||||
elif any(s in lower for s in ('certificate_verify_failed', 'certificate verify failed', 'unable to get local issuer certificate')):
|
elif any(s in lower for s in ('certificate_verify_failed', 'certificate verify failed', 'unable to get local issuer certificate')):
|
||||||
|
|||||||
@ -100,7 +100,7 @@ def test_rejects_outside_final_path(monkeypatch, tmp_path):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('message,hint', [
|
@pytest.mark.parametrize('message,hint', [
|
||||||
('HTTP 403 forbidden', 'original error'), ('HTTP 429', 'rate limiting'),
|
('HTTP Error 403: Forbidden', 'latest release'), ('unexpected extractor failure', 'original error'), ('HTTP 429', 'rate limiting'),
|
||||||
('Sign in to continue', 'authentication'), ('No JavaScript runtime', 'Deno/EJS'),
|
('Sign in to continue', 'authentication'), ('No JavaScript runtime', 'Deno/EJS'),
|
||||||
('egress denied', 'network settings'), ('certificate verify failed', 'trusted CA'),
|
('egress denied', 'network settings'), ('certificate verify failed', 'trusted CA'),
|
||||||
])
|
])
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user