0.14.0: dl and torrent — the media commands - #27
Merged
Conversation
A thin front for yt-dlp in the same shape `vid` is a thin front for ffmpeg: the handful of things worth not remembering the flags for, out of the way for everything else. Argv construction and output parsing live in src/download.ts so they can be reasoned about without a network; bin/dl.ts spawns, inheriting stdio because yt-dlp's progress line is the whole user interface of a long transfer and a captured one arrives all at once, after the wait it explained. Two defaults are decisions rather than plumbing: `--no-playlist`. A YouTube link copied from the browser while a mix is playing carries `list=`, and yt-dlp reads that as "download all of it" — the difference between one file and two hundred, on a command whose entire input is a pasted URL. The whole list is something you ask for. ffmpeg-awareness in the format selector. Above about 720p the picture and the sound arrive separately and have to be muxed, so on a box without ffmpeg the `bv*+ba` alternatives are not a lower-quality option but a wasted download: yt-dlp fetches both halves and only then finds it cannot merge them. Without ffmpeg `dl` restricts itself to single-stream formats and warns that it did. `dl audio` is `-x`, which *is* ffmpeg, so there it is a hard requirement with nothing to downgrade to. findBinary grew a probe flag. It ran every candidate with `-version`, which ImageMagick and ffmpeg both answer 0 — but yt-dlp's parser reads that single dash as seven combined short options and exits non-zero, so probing it the same way would have reported an installed binary missing. youtube-dl is accepted as a fallback name, second, because it still exists on plenty of boxes and is years behind on everything but a plain YouTube URL. The verb is optional (`dl <url>` is the common case), which is only unambiguous because a URL never collides with `audio`/`info`/`formats`. A first argument that is neither is a typo worth naming rather than a hostname to hand to yt-dlp. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LkEHoAhsoDhqVeJ1MJH9yD
| }); | ||
|
|
||
| it('writes where it was told to', () => { | ||
| expect(downloadArgs({ url: URL, kind: 'video', dir: '/tmp/out' })).toEqual( |
|
|
||
| it('writes where it was told to', () => { | ||
| expect(downloadArgs({ url: URL, kind: 'video', dir: '/tmp/out' })).toEqual( | ||
| expect.arrayContaining(['-P', '/tmp/out']), |
ThreatCrush Security Scan15 finding(s) HIGH/CRITICAL: 5 | MEDIUM: 1 | LOW: 9
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two thin fronts, in the shape
vidis a thin front for ffmpeg. Pairs with moshcoder/moshcode#448, which makes the binaries they need installable.dl— yt-dlp--no-playlistby default. A YouTube link copied while a mix is playing carrieslist=, and yt-dlp reads that as "download all of it" — the difference between one file and two hundred, on a command whose entire input is a pasted URL.ffmpeg-awareness in the format selector. Above ~720p the picture and sound arrive as separate streams needing a mux, so without ffmpeg the
bv*+baalternatives are not a lower-quality option but a wasted download: yt-dlp fetches both halves and only then finds it cannot merge. Without ffmpegdlrestricts itself to single-stream formats and warns.dl audiois-x, which is ffmpeg, so there it is a hard requirement.findBinarygrew a probe flag: it ran candidates with-version, which ImageMagick and ffmpeg answer 0 — but yt-dlp's parser reads that single dash as seven combined short options and exits non-zero, so probing it the same way would report an installed binary missing.torrent— create-torrent + torlnkcreate-torrentwrites a file and never prints a hash; torlnk takes a magnet rather than a file. The two do not meet without something in between.The info hash is computed here, not by adding a dependency: a SHA-1 over the bencoded
infodictionary. The hard requirement is that the bytes be the original ones — decode and re-encode and the hash changes the moment a client wrote a key in an order we did not reproduce. Sosrc/torrent.tsscans bencode for the span and hashes it verbatim, in about forty lines, with a test asserting the result equals the info hash a real client computed for a torrent it made itself.Trackers are the part that looks cosmetic and is not. A browser can only ever be a WebRTC peer, so a torrent with no
wss://tracker is invisible to every web player — on the DHT, found by desktop clients, and showing the browser a torrent with no peers, which reads as dead rather than as a missing tracker. Every entry in the default list was checked rather than copied. Of the list the WebTorrent tooling ships by default:tracker.leechers-paradise.orgtracker.coppersurfer.tktracker.empire-js.ustracker.btorrent.xyzWhat is left is two WSS trackers that complete a WebSocket handshake and four UDP trackers that return a connection id.
--privateis opt-in and named, because a private torrent is excluded from the DHT by every client that honours the flag — the opposite of the reason to make one here. Seed duration is deliberately not a flag: torlnk's--seed-timeis a daemon setting, not per-torrent, and a flag that silently does nothing is worse than none.Testing
pnpm test— 490 pass (35 new),pnpm typecheckclean. Both commands smoke-tested end to end:dlon its help/missing-binary/bad-verb paths, andtorrent createon a real directory producing a torrent whose info hash matchescreate-torrent's own reader.🤖 Generated with Claude Code
https://claude.ai/code/session_01LkEHoAhsoDhqVeJ1MJH9yD