Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/tauri_app_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ jobs:
script-name: app.py
output-file: iib_api_server
output-dir: out
include-module: imageio.plugins.pyav
include-data-dir: |
vue/dist=vue/dist

Expand Down Expand Up @@ -143,7 +144,7 @@ jobs:
with:
spec: 'app.py'
upload_exe_with_name: 'My executable'
options: --onefile
options: --onefile --additional-hooks-dir=pyinstaller_hooks

- run: mv dist/app.exe vue/src-tauri/iib_api_server-x86_64-pc-windows-msvc.exe

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ launch.sh
conf.json
iib.db-journal
.env
standalone.cmd
standalone*
.vscode
build/**/*
dist/**/*
Expand Down
4 changes: 4 additions & 0 deletions pyinstaller_hooks/hook-av.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from PyInstaller.utils.hooks import collect_all

# Collect package code, data and hidden imports for PyAV
datas, binaries, hiddenimports = collect_all('av')
4 changes: 4 additions & 0 deletions pyinstaller_hooks/hook-imageio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from PyInstaller.utils.hooks import collect_all

# Collect package code, data (including .dist-info) and hidden imports
datas, binaries, hiddenimports = collect_all('imageio')
4 changes: 4 additions & 0 deletions pyinstaller_hooks/hook-imageio_ffmpeg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from PyInstaller.utils.hooks import collect_all

# Collect package code, data and hidden imports for imageio-ffmpeg
datas, binaries, hiddenimports = collect_all('imageio_ffmpeg')
4 changes: 4 additions & 0 deletions pyinstaller_hooks/hook-pillow_avif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from PyInstaller.utils.hooks import collect_all

# Collect package code, data and hidden imports for pillow-avif-plugin
datas, binaries, hiddenimports = collect_all('pillow_avif')
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ python-dotenv
Pillow
pillow-avif-plugin
imageio
av
av>=14,<15
lxml
filetype
74 changes: 63 additions & 11 deletions scripts/iib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,45 @@ async def remove_app_fe_setting(req: AppFeSettingDelReq):

@app.get(f"{api_base}/version", dependencies=[Depends(verify_secret)])
async def get_version():
return {
import sys
import platform

def _get_dist_version(dist_name: str = None, module_name: str = None):
# Try importlib.metadata first (distribution metadata), then fallback to module __version__
try:
if dist_name:
try:
from importlib.metadata import version

return version(dist_name)
except Exception:
pass
if module_name:
mod = __import__(module_name)
return getattr(mod, "__version__", None)
if dist_name:
# try importing by normalized name
mod = __import__(dist_name.replace("-", "_"))
return getattr(mod, "__version__", None)
except Exception as e:
logger.debug("Version probe failed for %s/%s: %s", dist_name, module_name, e)
return None

versions = {
"python_version": sys.version.splitlines()[0],
"platform": platform.platform(),
"hash": get_current_commit_hash(),
"tag": get_current_tag(),
"av": _get_dist_version("av", "av"),
"imageio": _get_dist_version("imageio", "imageio"),
"pillow": _get_dist_version("Pillow", "PIL"),
"imageio_ffmpeg": _get_dist_version("imageio-ffmpeg", "imageio_ffmpeg"),
"pillow_avif_plugin": _get_dist_version("pillow-avif-plugin", "pillow_avif"),
}

logger.info("Version info requested: %s", {k: v for k, v in versions.items() if v})
return versions

class DeleteFilesReq(BaseModel):
file_paths: List[str]

Expand Down Expand Up @@ -649,16 +683,34 @@ async def video_cover(path: str, mt: str):
if not is_media_file(path):
raise HTTPException(status_code=400, detail=f"{path} is not a video file")
# 如果缓存文件不存在,则生成缩略图并保存

import imageio.v3 as iio
frame = iio.imread(
path,
index=16,
plugin="pyav",
)

os.makedirs(cache_dir, exist_ok=True)
iio.imwrite(cache_path,frame, extension=".webp")
try:
import imageio.v3 as iio
logger.info(
"Generating video cover thumbnail: path=%s, mt=%s, cache_path=%s",
path,
mt,
cache_path,
)
frame = iio.imread(
path,
index=16,
plugin="pyav",
)

os.makedirs(cache_dir, exist_ok=True)
iio.imwrite(cache_path, frame, extension=".webp")
logger.info("Saved video cover thumbnail: %s", cache_path)
except Exception as e:
# record full stack trace and contextual info in English
logger.exception(
"Failed to generate video cover for path=%s mt=%s cache_dir=%s: %s",
path,
mt,
cache_dir,
e,
)
# return a clear HTTP error (detail contains exception message)
raise HTTPException(status_code=500, detail=f"Failed to generate video cover: {e}")

# 返回缓存文件
return FileResponse(
Expand Down
2 changes: 1 addition & 1 deletion vue/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "Infinite Image Browsing",
"version": "1.5.0"
"version": "1.5.1"
},
"tauri": {
"allowlist": {
Expand Down
Loading