完善打包与代理支持文档
parent
adca311c0a
commit
7d58acf0b4
|
|
@ -1,6 +1,11 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
|
.venv
|
||||||
tinify_keys.json
|
tinify_keys.json
|
||||||
tinify_usage.json
|
tinify_usage.json
|
||||||
optimized
|
optimized
|
||||||
source
|
source
|
||||||
uv.lock
|
uv.lock
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.spec
|
||||||
|
*.exe
|
||||||
|
|
|
||||||
184
README.md
184
README.md
|
|
@ -1,17 +1,19 @@
|
||||||
# TinyPNG 批量压缩工具
|
# TinyPNG 批量压缩工具
|
||||||
|
|
||||||
这是一个基于 Tinify/TinyPNG Python SDK 的批量图片压缩和格式转换工具。支持 GUI 界面、多个 API Key 按顺序接力使用、官方额度同步、批量转换格式,以及递归处理目录。
|
这是一个基于 Tinify/TinyPNG Python SDK 的批量图片压缩和格式转换工具。它提供图形界面和命令行两种使用方式,支持多个 API Key 接力使用、官方额度同步、批量格式转换、递归处理目录、HTTP/SOCKS5 代理,以及 Windows 二进制打包分发。
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
- 图形界面选择输入目录和输出目录。
|
- GUI 图形界面,适合日常批量处理图片。
|
||||||
- 支持多个 Tinify API Key,每个 Key 默认每月 500 张额度,处理时会先用完前一个 Key,再切换到下一个。
|
- CLI 命令行入口,适合脚本化或自动化处理。
|
||||||
- 启动处理前可同步官方本月已用额度。
|
- 支持多个 Tinify API Key,每个 Key 默认每月 500 张额度。
|
||||||
- 支持 PNG、JPG/JPEG、WebP、AVIF 图片。
|
- 支持处理前同步官方本月已用额度。
|
||||||
- 支持转换为 png、jpeg、webp、avif,也支持“全部格式”一次输出四种格式。
|
- 支持 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_gui.py GUI 程序
|
||||||
├─ tinypng_balancer.py 命令行和核心处理逻辑
|
├─ tinypng_balancer.py 命令行和核心处理逻辑
|
||||||
├─ run_gui.bat 双击启动 GUI
|
├─ run_gui.bat 双击启动 GUI
|
||||||
├─ tinify_keys.json 实际 API Key 配置文件
|
├─ tinify_keys.sample.json API Key 配置模板
|
||||||
├─ tinify_usage.json 本月额度缓存文件,运行后自动生成
|
├─ tinify_keys.json 实际 API Key 配置文件,本地使用,不提交 Git
|
||||||
|
├─ tinify_usage.json 本月额度缓存文件,本地使用,不提交 Git
|
||||||
├─ pyproject.toml uv 项目依赖配置
|
├─ pyproject.toml uv 项目依赖配置
|
||||||
└─ uv.lock 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
|
## 启动 GUI
|
||||||
|
|
||||||
推荐直接双击:
|
推荐直接双击:
|
||||||
|
|
@ -43,13 +75,11 @@ cd C:\dev\py\tinypng
|
||||||
uv run tinypng_gui.py
|
uv run tinypng_gui.py
|
||||||
```
|
```
|
||||||
|
|
||||||
程序通过 `uv run` 启动,会自动使用 `pyproject.toml` 中声明的 `tinify` SDK 依赖。
|
|
||||||
|
|
||||||
## 配置 API Key
|
## 配置 API Key
|
||||||
|
|
||||||
打开 GUI 后点击 `填写 API Key`。
|
打开 GUI 后点击 `填写 API Key`。
|
||||||
|
|
||||||
支持以下输入方式:
|
支持一行一个:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
KEY_1
|
KEY_1
|
||||||
|
|
@ -81,19 +111,43 @@ KEY_3
|
||||||
|
|
||||||
不要把真实 API Key 写入 `tinify_keys.sample.json`,它只作为模板示例。
|
不要把真实 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 使用流程
|
## GUI 使用流程
|
||||||
|
|
||||||
1. 把图片放入当前目录下的 `source` 文件夹。
|
1. 把图片放入 `source` 文件夹,或在界面中选择其他输入目录。
|
||||||
2. 双击 `run_gui.bat` 打开界面。
|
2. 点击 `填写 API Key`,粘贴一个或多个 API Key 并保存。
|
||||||
3. 点击 `填写 API Key`,粘贴一个或多个 API Key 并保存。
|
3. 如需代理,在代理输入框填写 HTTP 或 SOCKS5 地址。
|
||||||
4. 确认输入目录为 `source`。
|
4. 确认输出目录,默认是 `optimized`。
|
||||||
5. 选择输出目录,默认是 `optimized`。
|
5. 按需选择转换格式、递归扫描、覆盖输出、试运行、同步官方额度等选项。
|
||||||
6. 按需选择转换格式、递归扫描、覆盖输出、同步官方额度等选项。
|
6. 点击 `开始处理`。
|
||||||
7. 点击 `开始处理`。
|
|
||||||
|
|
||||||
## 转换格式
|
## 转换格式
|
||||||
|
|
||||||
`转换格式` 默认是 `保持原格式`。
|
`转换格式` 默认选择 `源格式` 和 `webp`。
|
||||||
|
|
||||||
可选值:
|
可选值:
|
||||||
|
|
||||||
|
|
@ -102,10 +156,9 @@ KEY_3
|
||||||
- `jpeg` / `jpg`:输出 JPEG。
|
- `jpeg` / `jpg`:输出 JPEG。
|
||||||
- `webp`:输出 WebP。
|
- `webp`:输出 WebP。
|
||||||
- `avif`:输出 AVIF。
|
- `avif`:输出 AVIF。
|
||||||
- 可多选,例如默认会同时选择 `源格式` 和 `webp`,每张图片会输出源格式压缩结果和 WebP 结果。
|
- `all`:命令行专用,一次输出源格式、PNG、JPEG、WebP、AVIF。
|
||||||
- 命令行的 `all` 会输出源格式、`.png`、`.jpg`、`.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
|
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
|
```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
|
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'
|
### 提示 No module named 'tinify'
|
||||||
|
|
@ -177,15 +289,29 @@ uv run tinypng_gui.py
|
||||||
|
|
||||||
或者双击 `run_gui.bat`。
|
或者双击 `run_gui.bat`。
|
||||||
|
|
||||||
### 没有找到图片
|
### 填写 socks5:// 代理后提示缺少 SOCKS 支持
|
||||||
|
|
||||||
确认图片放在输入目录中。默认输入目录是:
|
确认已经安装 SOCKS 依赖:
|
||||||
|
|
||||||
```text
|
```powershell
|
||||||
C:\dev\py\tinypng\source
|
uv sync
|
||||||
```
|
```
|
||||||
|
|
||||||
支持的扩展名包括:
|
如果是旧环境,可以重新添加依赖:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
uv add requests[socks]
|
||||||
|
```
|
||||||
|
|
||||||
|
然后重新打包二进制。
|
||||||
|
|
||||||
|
### 打包版路径指向 _internal
|
||||||
|
|
||||||
|
请使用新版代码重新打包。GUI 会在打包环境中使用 `tinypng-gui.exe` 所在目录作为默认目录,不会把 `source`、`optimized`、`tinify_keys.json` 放进 `_internal`。
|
||||||
|
|
||||||
|
### 没有找到图片
|
||||||
|
|
||||||
|
确认图片放在输入目录中。支持的扩展名包括:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.png .jpg .jpeg .webp .avif
|
.png .jpg .jpeg .webp .avif
|
||||||
|
|
@ -197,4 +323,4 @@ C:\dev\py\tinypng\source
|
||||||
|
|
||||||
### 全部格式输出时额度消耗变多
|
### 全部格式输出时额度消耗变多
|
||||||
|
|
||||||
这是正常的。因为每张图片会分别转换为 PNG、JPEG、WebP、AVIF 四种格式,每个输出都可能消耗 Tinify 额度。
|
这是正常的。因为每张图片会分别转换为多个格式,每个输出都可能消耗 Tinify 额度。
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,11 @@ version = "0.1.0"
|
||||||
description = "TinyPNG GUI batch compressor with multiple Tinify API keys."
|
description = "TinyPNG GUI batch compressor with multiple Tinify API keys."
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"requests[socks]>=2.32.5",
|
||||||
"tinify>=1.6.0",
|
"tinify>=1.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = [
|
||||||
|
"pyinstaller>=6.20.0",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import queue
|
import queue
|
||||||
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import filedialog, messagebox, ttk
|
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
|
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")
|
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.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.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 = ttk.Frame(self, padding=(12, 0, 12, 12))
|
||||||
body.grid(row=1, column=0, sticky="nsew")
|
body.grid(row=1, column=0, sticky="nsew")
|
||||||
body.rowconfigure(1, weight=1)
|
body.rowconfigure(1, weight=1)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue