From 7d58acf0b4f971601858e148df58d4cafbf7c3c2 Mon Sep 17 00:00:00 2001 From: MAOMOMO Date: Sat, 23 May 2026 18:59:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=89=93=E5=8C=85=E4=B8=8E?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E6=94=AF=E6=8C=81=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 ++ README.md | 184 +++++++++++++++++++++++++++++++++++++++++-------- pyproject.toml | 6 ++ tinypng_gui.py | 15 +++- 4 files changed, 180 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 63d0c48..bf31448 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,11 @@ __pycache__ +.venv tinify_keys.json tinify_usage.json optimized source uv.lock +build/ +dist/ +*.spec +*.exe diff --git a/README.md b/README.md index 67d207f..f5ab591 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,19 @@ # TinyPNG 批量压缩工具 -这是一个基于 Tinify/TinyPNG Python SDK 的批量图片压缩和格式转换工具。支持 GUI 界面、多个 API Key 按顺序接力使用、官方额度同步、批量转换格式,以及递归处理目录。 +这是一个基于 Tinify/TinyPNG Python SDK 的批量图片压缩和格式转换工具。它提供图形界面和命令行两种使用方式,支持多个 API Key 接力使用、官方额度同步、批量格式转换、递归处理目录、HTTP/SOCKS5 代理,以及 Windows 二进制打包分发。 ## 功能 -- 图形界面选择输入目录和输出目录。 -- 支持多个 Tinify API Key,每个 Key 默认每月 500 张额度,处理时会先用完前一个 Key,再切换到下一个。 -- 启动处理前可同步官方本月已用额度。 -- 支持 PNG、JPG/JPEG、WebP、AVIF 图片。 -- 支持转换为 png、jpeg、webp、avif,也支持“全部格式”一次输出四种格式。 +- GUI 图形界面,适合日常批量处理图片。 +- CLI 命令行入口,适合脚本化或自动化处理。 +- 支持多个 Tinify API Key,每个 Key 默认每月 500 张额度。 +- 支持处理前同步官方本月已用额度。 +- 支持 PNG、JPG/JPEG、WebP、AVIF 输入。 +- 支持输出源格式、PNG、JPEG、WebP、AVIF,也可以一次输出全部格式。 - 支持递归扫描目录。 - 支持覆盖已有输出文件或跳过已有文件。 -- 支持试运行,只预览计划,不调用 Tinify API。 +- 支持试运行,只预览处理计划,不调用 Tinify API。 +- 支持 HTTP 代理和 SOCKS5 代理。 ## 目录说明 @@ -22,12 +24,42 @@ C:\dev\py\tinypng ├─ tinypng_gui.py GUI 程序 ├─ tinypng_balancer.py 命令行和核心处理逻辑 ├─ run_gui.bat 双击启动 GUI -├─ tinify_keys.json 实际 API Key 配置文件 -├─ tinify_usage.json 本月额度缓存文件,运行后自动生成 +├─ tinify_keys.sample.json API Key 配置模板 +├─ tinify_keys.json 实际 API Key 配置文件,本地使用,不提交 Git +├─ tinify_usage.json 本月额度缓存文件,本地使用,不提交 Git ├─ pyproject.toml uv 项目依赖配置 └─ uv.lock uv 锁定文件 ``` +打包后使用 `--onedir` 文件夹版时,默认目录会改为可执行文件所在目录: + +```text +dist\tinypng-gui +├─ tinypng-gui.exe +├─ _internal\ +├─ source\ +├─ optimized\ +├─ tinify_keys.json +└─ tinify_usage.json +``` + +`source`、`optimized` 和 JSON 配置文件不会放到 `_internal` 里。 + +## 安装依赖 + +项目使用 `uv` 管理依赖: + +```powershell +cd C:\dev\py\tinypng +uv sync +``` + +主要依赖: + +- `tinify`:TinyPNG 官方 Python SDK。 +- `requests[socks]`:为 HTTP/SOCKS5 代理提供支持。 +- `pyinstaller`:开发依赖,用于打包 Windows 二进制。 + ## 启动 GUI 推荐直接双击: @@ -43,13 +75,11 @@ cd C:\dev\py\tinypng uv run tinypng_gui.py ``` -程序通过 `uv run` 启动,会自动使用 `pyproject.toml` 中声明的 `tinify` SDK 依赖。 - ## 配置 API Key 打开 GUI 后点击 `填写 API Key`。 -支持以下输入方式: +支持一行一个: ```text KEY_1 @@ -81,19 +111,43 @@ KEY_3 不要把真实 API Key 写入 `tinify_keys.sample.json`,它只作为模板示例。 +## 代理格式 + +不需要代理时留空。 + +HTTP 代理: + +```text +http://127.0.0.1:7890 +``` + +SOCKS5 代理: + +```text +socks5://127.0.0.1:1080 +``` + +带账号密码: + +```text +http://username:password@127.0.0.1:7890 +socks5://username:password@127.0.0.1:1080 +``` + +常见代理软件的 HTTP 端口可能是 `7890`、`10809`,SOCKS5 端口可能是 `1080`、`10808`。以代理软件里实际显示的端口为准。 + ## GUI 使用流程 -1. 把图片放入当前目录下的 `source` 文件夹。 -2. 双击 `run_gui.bat` 打开界面。 -3. 点击 `填写 API Key`,粘贴一个或多个 API Key 并保存。 -4. 确认输入目录为 `source`。 -5. 选择输出目录,默认是 `optimized`。 -6. 按需选择转换格式、递归扫描、覆盖输出、同步官方额度等选项。 -7. 点击 `开始处理`。 +1. 把图片放入 `source` 文件夹,或在界面中选择其他输入目录。 +2. 点击 `填写 API Key`,粘贴一个或多个 API Key 并保存。 +3. 如需代理,在代理输入框填写 HTTP 或 SOCKS5 地址。 +4. 确认输出目录,默认是 `optimized`。 +5. 按需选择转换格式、递归扫描、覆盖输出、试运行、同步官方额度等选项。 +6. 点击 `开始处理`。 ## 转换格式 -`转换格式` 默认是 `保持原格式`。 +`转换格式` 默认选择 `源格式` 和 `webp`。 可选值: @@ -102,10 +156,9 @@ KEY_3 - `jpeg` / `jpg`:输出 JPEG。 - `webp`:输出 WebP。 - `avif`:输出 AVIF。 -- 可多选,例如默认会同时选择 `源格式` 和 `webp`,每张图片会输出源格式压缩结果和 WebP 结果。 -- 命令行的 `all` 会输出源格式、`.png`、`.jpg`、`.webp`、`.avif`。 +- `all`:命令行专用,一次输出源格式、PNG、JPEG、WebP、AVIF。 -注意:转换、缩放等 Tinify API 操作可能会消耗压缩额度。“全部格式”会为每张输入图片生成多个输出,因此额度消耗也会更多。 +注意:转换、缩放等 Tinify API 操作可能会消耗压缩额度。一次输出多个格式时,每张输入图片会产生多个输出,额度消耗也会相应增加。 ## 额度同步 @@ -153,6 +206,12 @@ uv run tinypng_balancer.py source -o optimized --convert source --convert webp uv run tinypng_balancer.py source -o optimized --convert all ``` +缩放: + +```powershell +uv run tinypng_balancer.py source -o optimized --resize-method fit --width 1200 --height 1200 +``` + 试运行: ```powershell @@ -165,6 +224,59 @@ uv run tinypng_balancer.py source -o optimized --dry-run uv run tinypng_balancer.py source -o optimized --no-sync-usage ``` +指定配置和用量文件: + +```powershell +uv run tinypng_balancer.py source -o optimized --config tinify_keys.json --state tinify_usage.json +``` + +生成配置模板: + +```powershell +uv run tinypng_balancer.py --init-config tinify_keys.json +``` + +## 打包 Windows 二进制 + +推荐打包为 `onedir` 文件夹版: + +```powershell +uv run pyinstaller --noconfirm --clean --onedir --windowed --name tinypng-gui --add-data "tinify_keys.sample.json;." tinypng_gui.py +``` + +输出目录: + +```text +dist\tinypng-gui\ +``` + +启动文件: + +```text +dist\tinypng-gui\tinypng-gui.exe +``` + +分发时需要把整个 `dist\tinypng-gui\` 文件夹一起发出去,因为 `_internal\` 里包含运行依赖。 + +不推荐日常使用 `--onefile` 单文件版。单文件版启动时会先解压依赖到系统临时目录;文件夹版不会把依赖释放到 Temp,路径也更容易管理。 + +## Git 忽略 + +以下文件通常不需要提交: + +```gitignore +tinify_keys.json +tinify_usage.json +optimized +source +build/ +dist/ +*.spec +*.exe +``` + +是否提交 `pyproject.toml` 中的 `pyinstaller` 开发依赖,取决于是否希望项目自带打包能力。当前项目保留该开发依赖,方便以后重复打包。 + ## 常见问题 ### 提示 No module named 'tinify' @@ -177,15 +289,29 @@ uv run tinypng_gui.py 或者双击 `run_gui.bat`。 -### 没有找到图片 +### 填写 socks5:// 代理后提示缺少 SOCKS 支持 -确认图片放在输入目录中。默认输入目录是: +确认已经安装 SOCKS 依赖: -```text -C:\dev\py\tinypng\source +```powershell +uv sync ``` -支持的扩展名包括: +如果是旧环境,可以重新添加依赖: + +```powershell +uv add requests[socks] +``` + +然后重新打包二进制。 + +### 打包版路径指向 _internal + +请使用新版代码重新打包。GUI 会在打包环境中使用 `tinypng-gui.exe` 所在目录作为默认目录,不会把 `source`、`optimized`、`tinify_keys.json` 放进 `_internal`。 + +### 没有找到图片 + +确认图片放在输入目录中。支持的扩展名包括: ```text .png .jpg .jpeg .webp .avif @@ -197,4 +323,4 @@ C:\dev\py\tinypng\source ### 全部格式输出时额度消耗变多 -这是正常的。因为每张图片会分别转换为 PNG、JPEG、WebP、AVIF 四种格式,每个输出都可能消耗 Tinify 额度。 +这是正常的。因为每张图片会分别转换为多个格式,每个输出都可能消耗 Tinify 额度。 diff --git a/pyproject.toml b/pyproject.toml index b7bcd59..b34d330 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,5 +4,11 @@ version = "0.1.0" description = "TinyPNG GUI batch compressor with multiple Tinify API keys." requires-python = ">=3.9" dependencies = [ + "requests[socks]>=2.32.5", "tinify>=1.6.0", ] + +[dependency-groups] +dev = [ + "pyinstaller>=6.20.0", +] diff --git a/tinypng_gui.py b/tinypng_gui.py index 8b6c3d9..db0d49e 100644 --- a/tinypng_gui.py +++ b/tinypng_gui.py @@ -4,6 +4,7 @@ import os import queue +import sys import threading import tkinter as tk from tkinter import filedialog, messagebox, ttk @@ -11,7 +12,13 @@ from tkinter import filedialog, messagebox, ttk from tinypng_balancer import BatchArgs, CONVERT_SOURCE, CONVERT_TYPES, run_batch, write_json -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +def app_base_dir(): + if getattr(sys, "frozen", False): + return os.path.dirname(os.path.abspath(sys.executable)) + return os.path.dirname(os.path.abspath(__file__)) + + +BASE_DIR = app_base_dir() DEFAULT_INPUT_DIR = os.path.join(BASE_DIR, "source") @@ -50,6 +57,12 @@ class KeyConfigDialog(tk.Toplevel): ttk.Label(top, text="代理").grid(row=2, column=0, sticky="w", pady=4) ttk.Entry(top, textvariable=self.proxy_var).grid(row=2, column=1, columnspan=2, sticky="ew", padx=8, pady=4) + ttk.Label( + top, + text="示例: http://127.0.0.1:7890 或 socks5://127.0.0.1:1080,留空则不使用代理", + foreground="#666666", + ).grid(row=3, column=1, columnspan=2, sticky="w", padx=8, pady=(0, 4)) + body = ttk.Frame(self, padding=(12, 0, 12, 12)) body.grid(row=1, column=0, sticky="nsew") body.rowconfigure(1, weight=1)