Repository navigation
Releases
v0.1.9
iPhone HDR clips stop looking grey, and an impossible target is refused before the encode instead of after it.
- HDR sources (iPhone HLG, HDR10/PQ) are converted to SDR BT.709 inside the same encode. Before, the output kept HDR tags on 8-bit pixels, so iPhone videos looked washed out after compression
- Quality checks tone-map the reference frame too, so VMAF and SSIM measure compression loss instead of the HDR-to-SDR transfer curve
- A target below the minimum bitrate for the video's duration now fails before encoding and reports the smallest achievable size, instead of spending an encode that cannot fit.
--forcestill runs it - When a two-pass encode lands more than 0.5% over target, halfsize re-encodes once with a corrected bitrate instead of handing back an oversized file
--for emailnow targets 18 MB, because base64 makes a 20 MB attachment a 26.7 MB message that bounces at Gmail's 25 MB limit. New--for outlooktargets 15 MB for the 20 MB message cap, and--for gmailis an explicit alias for the 18 MB one
Install
npx halfsize@0.1.9 video.mp4 --to 20mb
Full changelog: https://github.com/YKLovePython/halfsize/blob/main/CHANGELOG.md
v0.1.8
Failure modes, mostly. The kind that leave you with a file you think is fine.
- A failed, cancelled, or interrupted encode no longer leaves a half-written video at the output path. It writes a hidden
.partfile next to the destination and only renames it once FFmpeg exits cleanly Ctrl+Cstops the running FFmpeg instead of leaving it behind, and printscancelledwith exit code 130- The local web app has a Cancel button, and closing the tab stops the encode after a ten-second grace period instead of letting FFmpeg run to completion
- The web app can switch the player between the original and the compressed file, and warns when the browser cannot decode H.265
- The web app retires the oldest uploads past the tenth, so a tab left open all day does not fill the temp directory
- Replacing an output that another program has open now fails with a clear message and keeps the finished file, instead of deleting it
- The version now comes from
package.jsonalone.scripts/bump-site.mjssyncs the site and READMEs, and a test fails if they drift - The local app refuses a text file, an image, or an empty file with a readable message, instead of accepting it and failing later with a path to ffprobe
- Uploaded file names are reduced to a bare file name, so nothing like
../../evil.mp4can reach the download header - Malformed request bodies return 400 instead of 500, and impossible byte ranges return 416 instead of a broken stream
- Both the CLI and the web app now say when tracks are dropped: extra audio tracks, subtitles, surround audio downmixed to stereo, and frame rates above 60 fps
--outrefuses to overwrite the input file, and--crf,--preset,--codec, and--portare validated before encoding starts- Low-frame-rate sources are left alone. A 5 fps timelapse used to be forced up to 10 fps, which duplicated frames and inflated the bitrate the planner assumed
Install
npx halfsize@0.1.8 video.mp4 --to 20mb
Full changelog: https://github.com/YKLovePython/halfsize/blob/main/CHANGELOG.md
halfsize 0.1.7
0.1.7
Install reliability, based on a failure reproduced on a TLS-inspecting network.
ffmpeg-staticandffprobe-staticare now optional dependencies. If the FFmpeg download is blocked,npm installandnpx halfsizestill succeed and the CLI explains how to fix the binary- The missing-FFmpeg message now covers the npmmirror binary mirror,
NODE_OPTIONS=--use-system-cafor TLS-inspecting proxies and antivirus, a system FFmpeg, and a custom path --doctorstays usable when the bundled binary is absent, so a failed download can be diagnosed before the first compression- README install notes (English and Chinese) document the TLS certificate case
Install
npx halfsize@0.1.7 video.mp4 --for discordOr install it globally:
npm install -g halfsizeMIT.
halfsize 0.1.6
0.1.6
First-run friction, mostly.
- A missing FFmpeg now shows three concrete fixes: reinstall with the bundled binary, use a system FFmpeg, or point at your own build, with the npmmirror binary mirror for slow networks
--doctorreports Node, both binary paths, where FFmpeg came from, and whether libvmaf is available, so a first run can be diagnosed in one command--webchecks FFmpeg before starting instead of failing on the first upload- After a successful compression, the CLI (TTY only) and the local web app show one quiet repository link.
HALFSIZE_NO_PROMO=1hides it - README install notes cover the first
npxwait, global install, and stale cache
Install
npx halfsize@0.1.6 video.mp4 --for discordOr install it globally:
npm install -g halfsizeMIT.
halfsize 0.1.5
0.1.5
Discord and WeChat both moved to 20 MB, so the presets did too.
--for discordnow targets 20 MB (Discord's free cap since August 2026)--for wechatnow targets 20 MB- Web app presets and copy match the current caps
- README ships a measured quality table for 20 / 16 / 10 / 5 MB
- New per-platform guides: https://YKLovePython.github.io/halfsize/
Install
npx halfsize@0.1.5 video.mp4 --for discordOr install it globally:
npm install -g halfsizeMIT.
halfsize 0.1.4
Batch mode, platform presets, and a fix for audio/stream handling.
New
halfsize a.mp4 b.mp4 c.mp4 --to 10mbcompresses several files in one command--for discord|whatsapp|wechat|email|twitteruses the platform's upload cap--no-audiodrops the soundtrack and spends the bits on video
Fixed
- Streams are mapped explicitly, so cover art or extra tracks cannot be picked by mistake
- Mono audio stays mono instead of being silently upmixed to stereo
--outis rejected for batches instead of overwriting the same file
Install
npx halfsize video.mp4 --to 25mb
npx halfsize video.mp4 --for discordhalfsize 0.1.3
Two-pass encoding now reports honest progress, and the local app takes a custom port.
Changes
- The progress bar covers both encoding passes and shows
pass 1/2/第 1/2 遍 - New
--port <n>flag forhalfsize --web(default 4174) - Pass logs are cleaned up even when an encode fails
Install
npx halfsize video.mp4 --to 25mbhalfsize 0.1.2
Fit any video into any size limit, locally, and prove the quality survived.
What it does
- Exact target size via two-pass ABR, with a resolution ladder that protects perceived quality
- Measures SSIM on three samples and VMAF at the midpoint, then prints a plain-language verdict
- Local web app with drag and drop, presets for 25/10/20/5 MB, and a share card
- Zero uploads, zero accounts, zero telemetry
Fixes in this release
- Force CFR so two-pass encodes of Matroska/VFR sources stay on target
--versionno longer falls through to the help screen- Warn when an HDR source would lose its color
- Always emit MP4 from the CLI, even for MKV/AVI sources
Install
npx halfsize video.mp4 --to 25mb