From e084d68b955e03c781cdfe5137b356357b954b30 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 23 Jan 2026 11:59:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=A2=9E=E5=BC=B7=20headless=20?= =?UTF-8?q?=E7=92=B0=E5=A2=83=E6=94=AF=E6=8F=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 QT_QPA_PLATFORM=offscreen 環境變數 - 添加 DISPLAY=:99 環境變數 - Calibre 轉換器使用 xvfb-run 包裝 - 添加 CALIBRE_USE_SYSTEM_THEME=0 確保 Qt/GTK 應用在無 display 環境下運作 --- Dockerfile | 9 ++++++++- src/converters/calibre.ts | 22 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index c794dbd..6cb7013 100644 --- a/Dockerfile +++ b/Dockerfile @@ -588,8 +588,15 @@ EXPOSE 3000/tcp # ============================================================================== # 環境變數 # ============================================================================== -# Calibre 需要 +# Headless 環境設定(解決 GTK/Qt 在無 DISPLAY 環境的問題) +# ⚠️ 某些 GUI 工具(Inkscape、Calibre、LibreOffice)需要這些設定 +ENV QT_QPA_PLATFORM="offscreen" +ENV DISPLAY=":99" + +# Calibre 需要(禁用 Chromium sandbox,Docker 環境無法使用) ENV QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox" +ENV CALIBRE_USE_SYSTEM_THEME="0" + # Pandoc PDF 引擎(使用 pdflatex 以獲得最佳相容性) ENV PANDOC_PDF_ENGINE=pdflatex # Node 環境 diff --git a/src/converters/calibre.ts b/src/converters/calibre.ts index 1d06695..c69b39f 100644 --- a/src/converters/calibre.ts +++ b/src/converters/calibre.ts @@ -58,6 +58,17 @@ export const properties = { }, }; +/** + * Calibre ebook-convert 轉換器 + * + * ⚠️ Headless 環境注意事項: + * Calibre 是 Qt 應用,某些操作需要 display。 + * 使用 xvfb-run 確保在無 DISPLAY 環境下也能運作。 + * + * 環境變數設定(Dockerfile): + * QT_QPA_PLATFORM=offscreen + * QTWEBENGINE_CHROMIUM_FLAGS="--no-sandbox" + */ export async function convert( filePath: string, fileType: string, @@ -67,7 +78,16 @@ export async function convert( execFile: ExecFileFn = execFileOriginal, // to make it mockable ): Promise { return new Promise((resolve, reject) => { - execFile("ebook-convert", [filePath, targetPath], (error, stdout, stderr) => { + // 使用 xvfb-run 包裝 ebook-convert,確保在無 DISPLAY 環境下也能運作 + const args = [ + "-a", + "--server-args=-screen 0 1024x768x24", + "ebook-convert", + filePath, + targetPath, + ]; + + execFile("xvfb-run", args, (error, stdout, stderr) => { if (error) { reject(`error: ${error}`); }