完善打包与代理支持文档

main
MAOMOMO 2026-05-23 18:59:00 +08:00
parent adca311c0a
commit 7d58acf0b4
4 changed files with 180 additions and 30 deletions

5
.gitignore vendored
View File

@ -1,6 +1,11 @@
__pycache__
.venv
tinify_keys.json
tinify_usage.json
optimized
source
uv.lock
build/
dist/
*.spec
*.exe

184
README.md
View File

@ -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 额度。

View File

@ -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",
]

View File

@ -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)