Last active
October 11, 2024 02:24
-
-
Save akkuman/c157e75c13a2d2281b3ad80a315631eb to your computer and use it in GitHub Desktop.
将思源图片转换成 webp 减少体积,系统上需要有安装 node(使用了squoosh-cli)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! coding: utf-8 | |
import http.client | |
import json | |
import sys | |
import typing | |
import pathlib | |
import subprocess | |
import re | |
img_file_pattern = re.compile(r'.*(\.png|\.jpg|\.bmp|\.jpeg)\!?\S*$') | |
def get_block(text: str) -> typing.Optional[str]: | |
conn = http.client.HTTPConnection("127.0.0.1", 6806) | |
payload = json.dumps({ | |
"stmt": f"select * from blocks where markdown like '%{text}%' and type='p'" | |
}) | |
headers = { | |
'Content-Type': 'application/json' | |
} | |
conn.request("POST", "/api/query/sql", payload, headers) | |
res = conn.getresponse() | |
data = res.read() | |
res_json = json.loads(data) | |
if res_json['code'] != 0: | |
raise ValueError(res_json['msg']) | |
if not res_json['data']: | |
return None | |
return res_json['data'][0]['id'] | |
def update_img(block_id: str, path: str): | |
conn = http.client.HTTPConnection("127.0.0.1", 6806) | |
payload = json.dumps({ | |
"dataType": "markdown", | |
"data": f"", | |
"id": block_id | |
}) | |
headers = { | |
'Content-Type': 'application/json' | |
} | |
conn.request("POST", "/api/block/updateBlock", payload, headers) | |
res = conn.getresponse() | |
data = res.read() | |
res_json = json.loads(data) | |
if res_json['code'] != 0: | |
raise ValueError(res_json['msg']) | |
for file in pathlib.Path('C:\\Users\\Administrator\\SiYuan\\data\\assets').rglob('*'): | |
if file.is_dir(): | |
continue | |
if not img_file_pattern.match(str(file)): | |
continue | |
# 如果文件小于20KB,则不进行转换,这种情况下大多数时候转换引入的噪点体验会差于体积焦虑,不划算 | |
if file.stat().st_size < 20 * 1024: | |
continue | |
block_id = get_block(file.name) | |
if not block_id: | |
print(f'[ERR] 未找到图片对应的 block,跳过: {str(file.absolute())}') | |
continue | |
file_dir = file.parent | |
command = [ | |
'npx', | |
'--yes', | |
'@frostoven/squoosh-cli', | |
'--webp', | |
'{"quality":50,"target_size":0,"target_PSNR":0,"method":4,"sns_strength":50,"filter_strength":60,"filter_sharpness":0,"filter_type":1,"partitions":0,"segments":4,"pass":1,"show_compressed":0,"preprocessing":0,"autofilter":0,"partition_limit":0,"alpha_compression":1,"alpha_filtering":1,"alpha_quality":100,"lossless":1,"exact":0,"image_hint":0,"emulate_jpeg_size":0,"thread_level":0,"low_memory":0,"near_lossless":100,"use_delta_palette":0,"use_sharp_yuv":0}', | |
str(file.absolute()) | |
] | |
with subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, stderr=subprocess.PIPE, text=True, cwd=str(file_dir.absolute()), encoding='utf-8', errors='replace') as process: | |
for line in process.stdout: | |
print(line, end='') # 实时输出标准输出 | |
for line in process.stderr: | |
print(line, end='') # 实时输出标准错误 | |
return_code = process.wait() # 等待命令完成 | |
if return_code != 0: | |
print(f'[ERR] 转换失败: {str(file.absolute())}') | |
sys.exit(1) | |
webp_imgpath = pathlib.Path(f'{str(file_dir.absolute())}/{file.stem}.webp') | |
# 如果转换出来的文件是源文件的 80% 以上,则不进行转换 | |
if webp_imgpath.stat().st_size > file.stat().st_size * 0.8: | |
print(f'[INF] 转换后的图片为原图的{webp_imgpath.stat().st_size/file.stat().st_size:.1%},大于 80%,跳过') | |
webp_imgpath.unlink() | |
continue | |
if not webp_imgpath.exists(): | |
print(f'[ERR] 未找到生成的 webp 图片: {webp_imgpath}') | |
sys.exit(1) | |
webp_imgpath = webp_imgpath.relative_to(pathlib.Path("C:\\Users\\Administrator\\SiYuan\\data\\")).as_posix() | |
update_img(block_id, webp_imgpath) | |
if pathlib.Path(webp_imgpath).name != file.name: | |
file.unlink() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment