Skip to content
Last-OrderPublic

About

A lovely video downloader for HLS videos

Topics

Resources

Stars

648 stars

Watchers

15 watching

Forks

Repository files navigation

Minyami

Build Status

中文说明

Requirements

  • Node.js 24 or newer; an active LTS release is recommended.
  • mkvmerge or ffmpeg is optional. Install either one and add it to PATH if you need to mux separate audio and video tracks.
  • Bento4 mp4decrypt must be available in PATH to decrypt fMP4/CMAF SAMPLE-AES (cbcs) playlists.

Installation

npm install --global minyami

You can also install it with Yarn:

yarn global add minyami

For convenient playlist detection in Chrome, install the Minyami Chrome extension. Its source is available in the extension repository.

Command-line usage

Download a playlist:

minyami "https://example.com/video.m3u8" --output "./video.ts"

Useful examples:

# Use eight concurrent downloads
minyami -d "https://example.com/video.m3u8" --threads 8

# Send multiple request headers
minyami -d "https://example.com/video.m3u8" -H "Cookie: session=..." -H "User-Agent: ..."

# Download a time range
minyami -d "https://example.com/video.m3u8" --slice "45:00-53:00"

# Follow a live playlist until you stop the command
minyami -d "https://example.com/live.m3u8" --live

# Use an HTTP, HTTPS, or SOCKS5 proxy
minyami -d "https://example.com/video.m3u8" --proxy "http://127.0.0.1:1080"

Options

The download command requires a URL or local playlist path; missing input displays an error and help. --output and --slice require string values. Invalid values are reported and omitted while other valid options remain active.

Option Description
--help, -h Show help. Pass a command name to show command-specific help.
--version Show the installed version.
--download <input>, -d <input> Download an m3u8 URL or file.
--threads <number> Set the concurrency limit. The default is 5.
--retries <number> Set the maximum attempts for both source requests and download tasks. The default is 5.
--output <path>, -o <path> Set the output basename. The default is ./output.
--temp-dir <path> Choose the parent directory for temporary files.
--key <key|kid:key> Supply an explicit HLS decryption key. One key applies to every AES-128 key URI; repeated keys map to distinct URIs in first-seen order within each Media Playlist. Multiple fMP4 SAMPLE-AES keys require kid:key.
--cookies <cookies> Send cookies with download requests.
--headers <header>, -H <header> Send a custom HTTP header. Repeat the option to send multiple headers.
--live Follow a live playlist.
--proxy <url> Use an HTTP, HTTPS, or SOCKS5 proxy.
--no-proxy Ignore proxy environment variables and system proxy settings.
--slice <start-end> Download a time range such as 45:00-53:00.
--no-merge Keep downloaded chunks separate.
--keep, -k Keep temporary files.
--keep-encrypted-chunks Keep encrypted chunks after decryption. Use with --keep.
--verbose, --debug Enable debug output.

Configuration file

Place a JSON object in ~/.minyami/.minyamirc, ~/.minyami/.minyamirc.json, or ~/.minyami/minyami.config.json. The first readable JSON object in this order supplies defaults. Use the CLI option names in camelCase, such as noProxy, tempDir, and keepEncryptedChunks:

{
    "threads": 8,
    "noProxy": true,
    "verbose": true
}

Explicit CLI values override file defaults before validation. The merged noProxy and verbose settings also control proxy discovery and debug output. Use JSON booleans for flags, positive integers for threads and retries, strings for other values, and a string or string array for headers and key. Unreadable files, malformed JSON, and non-object roots are silently skipped; if no candidate is usable, the command proceeds without file defaults. Invalid merged option types stop the command with an error and exit code 1.

Use as a library

Minyami is distributed as ESM and must be loaded with import rather than CommonJS require().

Download an archive playlist:

import { createArchiveDownloader } from "minyami";

const downloader = createArchiveDownloader("https://example.com/archive.m3u8", {
    output: "./archive.ts",
    threads: 8,
});

downloader.on("chunk-downloaded", (chunk) => {
    console.log(chunk);
});

await downloader.download();

Library callers pass parsed explicit keys as HLSExplicitKey objects, for example explicitKeys: [{ key }] or explicitKeys: [{ kid, key }]. The CLI accepts the equivalent compact key and kid:key forms. For AES-128, one explicit key applies to every key URI; multiple keys are assigned to distinct key URIs in first-seen order within each Media Playlist and retain those assignments across live refreshes. Multiple fMP4 SAMPLE-AES keys are selected by KID instead.

For a live playlist, create a live downloader and call stop() when you want to finish:

import { createLiveDownloader } from "minyami";

const downloader = createLiveDownloader("https://example.com/live.m3u8", {
    output: "./live.ts",
});

setTimeout(() => downloader.stop(), 60_000);
await downloader.download();

Use streamSelector to choose tracks from a master playlist. Return tracks from one of the provided options, or return undefined to cancel the download:

const downloader = createArchiveDownloader("https://example.com/master.m3u8", {
    streamSelector: (catalog) =>
        catalog.options.find((option) =>
            option.tracks.some((track) => track.type === "video" && track.height === 720)
        )?.tracks,
});

await downloader.download();

When streamSelector is omitted, the library selects all tracks from the highest-bandwidth option.

FAQ

Do I need to keep the browser open while downloading?

No.

How do I configure a proxy?

Pass --proxy, or set HTTP_PROXY, HTTPS_PROXY, or ALL_PROXY. On Windows, Minyami can also use the system proxy settings. Pass --no-proxy to ignore all of these settings.

How do I change the temporary file location?

Pass --temp-dir <path>. By default, Minyami creates a minyami_<timestamp>_<random> directory under the current working directory.

How do I send multiple HTTP headers?

Repeat -H or --headers:

minyami -d "https://example.com/video.m3u8" -H "Cookie: ..." --headers "User-Agent: ..."

License

GPLv3. © 2018-2025 Eridanus Sora, member of MeowSound Idols.

About

A lovely video downloader for HLS videos

Topics

Resources

Stars

648 stars

Watchers

15 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages