storyforge-studio 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. storyforge_studio-0.1.0/.githooks/pre-commit +40 -0
  2. storyforge_studio-0.1.0/.github/workflows/ci.yml +52 -0
  3. storyforge_studio-0.1.0/.github/workflows/release.yml +61 -0
  4. storyforge_studio-0.1.0/.gitignore +10 -0
  5. storyforge_studio-0.1.0/AGENTS.md +31 -0
  6. storyforge_studio-0.1.0/CONTEXT.md +116 -0
  7. storyforge_studio-0.1.0/CONTRIBUTING.md +125 -0
  8. storyforge_studio-0.1.0/PKG-INFO +150 -0
  9. storyforge_studio-0.1.0/README.md +135 -0
  10. storyforge_studio-0.1.0/core/__init__.py +1 -0
  11. storyforge_studio-0.1.0/core/entities.py +81 -0
  12. storyforge_studio-0.1.0/core/use_cases.py +89 -0
  13. storyforge_studio-0.1.0/core/voice_catalog.py +147 -0
  14. storyforge_studio-0.1.0/docs/adr/0001-scene-based-audio-pipeline.md +62 -0
  15. storyforge_studio-0.1.0/docs/adr/0002-multi-speaker-recording.md +59 -0
  16. storyforge_studio-0.1.0/docs/adr/0003-portable-distribution-and-packaging.md +46 -0
  17. storyforge_studio-0.1.0/docs/adr/0004-automated-quality-gates.md +64 -0
  18. storyforge_studio-0.1.0/docs/adr/0005-voice-catalog-and-smart-casting.md +54 -0
  19. storyforge_studio-0.1.0/docs/adr/0006-migrate-to-interactions-api.md +43 -0
  20. storyforge_studio-0.1.0/docs/adr/0007-unified-dialogue-group-and-batch-recording.md +43 -0
  21. storyforge_studio-0.1.0/docs/adr/0008-bgm-theme-map.md +9 -0
  22. storyforge_studio-0.1.0/docs/agents/domain.md +51 -0
  23. storyforge_studio-0.1.0/docs/agents/issue-tracker.md +45 -0
  24. storyforge_studio-0.1.0/docs/agents/triage-labels.md +15 -0
  25. storyforge_studio-0.1.0/docs/superpowers/plans/2026-09-10-scene-pipeline.md +1068 -0
  26. storyforge_studio-0.1.0/infrastructure/__init__.py +1 -0
  27. storyforge_studio-0.1.0/infrastructure/audio_mixer.py +25 -0
  28. storyforge_studio-0.1.0/infrastructure/bgm_map_storage.py +26 -0
  29. storyforge_studio-0.1.0/infrastructure/file_storage.py +91 -0
  30. storyforge_studio-0.1.0/infrastructure/gemini_director.py +949 -0
  31. storyforge_studio-0.1.0/infrastructure/schemas.py +86 -0
  32. storyforge_studio-0.1.0/infrastructure/story_folder_storage.py +114 -0
  33. storyforge_studio-0.1.0/infrastructure/voice_map_storage.py +49 -0
  34. storyforge_studio-0.1.0/main.py +342 -0
  35. storyforge_studio-0.1.0/pyproject.toml +50 -0
  36. storyforge_studio-0.1.0/tests/conftest.py +4 -0
  37. storyforge_studio-0.1.0/tests/test_audio_mixer.py +29 -0
  38. storyforge_studio-0.1.0/tests/test_core.py +111 -0
  39. storyforge_studio-0.1.0/tests/test_gemini_director_unit.py +700 -0
  40. storyforge_studio-0.1.0/tests/test_infrastructure.py +34 -0
  41. storyforge_studio-0.1.0/tests/test_story_folder_storage.py +30 -0
  42. storyforge_studio-0.1.0/tests/test_story_selector.py +72 -0
  43. storyforge_studio-0.1.0/tests/test_ui_scene_button.py +325 -0
  44. storyforge_studio-0.1.0/tests/test_use_cases.py +104 -0
  45. storyforge_studio-0.1.0/tests/test_voice_catalog.py +113 -0
  46. storyforge_studio-0.1.0/tests/test_voice_map_storage.py +54 -0
  47. storyforge_studio-0.1.0/ui/app.js +1015 -0
  48. storyforge_studio-0.1.0/ui/index.html +187 -0
  49. storyforge_studio-0.1.0/ui/style.css +621 -0
  50. storyforge_studio-0.1.0/uv.lock +1413 -0
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+ # StoryForge 本地端門口哨兵 (Pre-commit Hook)
3
+ # 只檢查本次暫存 (staged) 的 Python 檔案
4
+
5
+ set -e
6
+
7
+ # 取得本次 git add 暫存的新增、複製、修改之 Python 檔案
8
+ STAGED_PY_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$' || true)
9
+
10
+ if [ -z "$STAGED_PY_FILES" ]; then
11
+ exit 0
12
+ fi
13
+
14
+ echo "🔍 [本地哨兵] 正在檢查本次暫存的 Python 檔案..."
15
+
16
+ LINT_ERR=0
17
+ FORMAT_ERR=0
18
+
19
+ # 1. 程式碼品質與錯誤檢查
20
+ if ! uv run ruff check $STAGED_PY_FILES; then
21
+ LINT_ERR=1
22
+ fi
23
+
24
+ # 2. 程式碼排版風格檢查
25
+ if ! uv run ruff format --check $STAGED_PY_FILES; then
26
+ FORMAT_ERR=1
27
+ fi
28
+
29
+ if [ $LINT_ERR -ne 0 ] || [ $FORMAT_ERR -ne 0 ]; then
30
+ echo ""
31
+ echo "❌ [本地哨兵] 發現本次存檔的程式積木有瑕疵或沒排整齊!"
32
+ echo "💡 請執行下列指令快速整理修正,並重新 git add 後再次存檔:"
33
+ echo " uv run ruff check --fix $STAGED_PY_FILES"
34
+ echo " uv run ruff format $STAGED_PY_FILES"
35
+ echo ""
36
+ exit 1
37
+ fi
38
+
39
+ echo "✅ [本地哨兵] 檢查全數通過,放行存檔!"
40
+ exit 0
@@ -0,0 +1,52 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - '**/*.py'
8
+ - 'ui/**'
9
+ - 'pyproject.toml'
10
+ - 'uv.lock'
11
+ - '.github/workflows/ci.yml'
12
+ pull_request:
13
+ branches: [main]
14
+ paths:
15
+ - '**/*.py'
16
+ - 'ui/**'
17
+ - 'pyproject.toml'
18
+ - 'uv.lock'
19
+ - '.github/workflows/ci.yml'
20
+
21
+ jobs:
22
+ test-and-lint:
23
+ name: Lint & Unit Tests
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - name: Checkout code
27
+ uses: actions/checkout@v4
28
+
29
+ - name: Set up Node.js
30
+ uses: actions/setup-node@v4
31
+ with:
32
+ node-version: 20
33
+
34
+ - name: Set up uv
35
+ uses: astral-sh/setup-uv@v5
36
+ with:
37
+ enable-cache: true
38
+
39
+ - name: Set up Python 3.12
40
+ run: uv python install 3.12
41
+
42
+ - name: Install dependencies
43
+ run: uv sync --dev
44
+
45
+ - name: Check code quality (Ruff lint)
46
+ run: uv run ruff check .
47
+
48
+ - name: Check code formatting (Ruff format)
49
+ run: uv run ruff format --check .
50
+
51
+ - name: Run unit tests (pytest)
52
+ run: uv run pytest
@@ -0,0 +1,61 @@
1
+ name: Release & Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ quality-gate:
13
+ name: Lint & Unit Tests
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Set up uv
20
+ uses: astral-sh/setup-uv@v5
21
+ with:
22
+ enable-cache: true
23
+
24
+ - name: Set up Python 3.12
25
+ run: uv python install 3.12
26
+
27
+ - name: Install dependencies
28
+ run: uv sync --dev
29
+
30
+ - name: Check code quality (Ruff lint)
31
+ run: uv run ruff check .
32
+
33
+ - name: Check code formatting (Ruff format)
34
+ run: uv run ruff format --check .
35
+
36
+ - name: Run unit tests (pytest)
37
+ run: uv run pytest
38
+
39
+ build-and-publish:
40
+ name: Build & Publish to PyPI
41
+ needs: quality-gate
42
+ runs-on: ubuntu-latest
43
+ environment:
44
+ name: pypi
45
+ url: https://pypi.org/p/storyforge-studio
46
+ permissions:
47
+ id-token: write
48
+ steps:
49
+ - name: Checkout code
50
+ uses: actions/checkout@v4
51
+
52
+ - name: Set up uv
53
+ uses: astral-sh/setup-uv@v5
54
+ with:
55
+ enable-cache: true
56
+
57
+ - name: Build package distributions
58
+ run: uv build
59
+
60
+ - name: Publish package distributions to PyPI
61
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,10 @@
1
+ storyforge_config.json
2
+
3
+ *.pyc
4
+ __pycache__/
5
+ .pytest_cache/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .venv/
10
+ .DS_Store
@@ -0,0 +1,31 @@
1
+ # 專案說明書
2
+
3
+ ## 專案與角色
4
+ - **目標**:文字交由 AI 導演(情緒、角色、聲音表演)轉為生動有聲書。
5
+ - **用戶**:非工程師。絕不要求用戶改程式碼。需操作時提供步驟化引導。付費服務事先報價確認。
6
+
7
+ ## 溝通原則
8
+ - **語言**:全程繁體中文。
9
+ - **表達**:禁工程術語,技術概念用五歲小孩比喻。
10
+ - **回報**:每步完成以白話說明「做了什麼」與「原因」。
11
+ - **決策**:白話列出選項並附推薦建議。
12
+
13
+ ## 開發規範
14
+ - **架構**:Clean Architecture(核心邏輯、UI、外部服務分層解耦)。
15
+ - **流程**:嚴格 TDD(先寫測試驗收條件,實作後驗證全過)。
16
+
17
+ ## Agent skills
18
+
19
+ ### Issue tracker
20
+
21
+ GitHub Issues via `gh` CLI. See `docs/agents/issue-tracker.md`.
22
+
23
+ ### Triage labels
24
+
25
+ Canonical five-role vocabulary (`needs-triage`, `ready-for-agent`, etc.). See `docs/agents/triage-labels.md`.
26
+
27
+ ### Domain docs
28
+
29
+ Single-context layout (`CONTEXT.md` and `docs/adr/`). See `docs/agents/domain.md`.
30
+
31
+
@@ -0,0 +1,116 @@
1
+ # StoryForge
2
+
3
+ 將文字故事轉換為具備情緒、角色演繹與生動聲音的有聲書電腦軟體。
4
+
5
+ ## Language
6
+
7
+ **StoryForge**:
8
+ 本專案的名稱,一個在電腦上執行的有聲書產生工具。
9
+ _Avoid_: 小工具、App
10
+
11
+ **AI 導演 (AI Director)**:
12
+ 負責理解文字故事中的情緒與角色,並決定如何發聲的核心大腦。目前使用的是 Gemini 3.8 Flash。
13
+ _Avoid_: 語音合成器、文字轉語音、TTS 模型
14
+
15
+ **故事原稿 (Source Text)**:
16
+ 使用者直接貼上的原始文字,這是 AI 導演的輸入。
17
+ _Avoid_: 腳本、輸入檔
18
+
19
+ **劇本拆解 (Script Breakdown)**:
20
+ AI 導演將原稿自動分析並拆解成一段段「旁白」與「不同角色的對話」,並加上情緒標記的過程。
21
+ _Avoid_: 文字分析、前處理
22
+
23
+ **有聲書成品 (Audio Output)**:
24
+ 最後產生出來並存檔的 MP3 聲音檔,可以直接播放或分享。
25
+ _Avoid_: 輸出檔、結果
26
+
27
+ **劇本編輯區 (Script Editor)**:
28
+ 讓你在 AI 拆解完劇本後,可以手動修改角色、情緒或台詞的畫面。
29
+ _Avoid_: 修改介面
30
+
31
+ **API 通行證 (API Key)**:
32
+ 用來證明你有權限使用 Gemini 大腦的專屬密碼,只要設定一次就會自動記住。
33
+ _Avoid_: 金鑰、憑證
34
+
35
+ **場景 (Scene)**:
36
+ AI 導演將劇本自動分割成的段落,每個場景代表一個情節單元(時間地點或情緒基調相對一致)。每個場景有 AI 自動取的標題,包含若干台詞行,並對應一個獨立的音檔。場景是重新生成語音的最小單位。
37
+ _Avoid_: 段落、片段、chunk
38
+
39
+ **聲音導演備註 (Voice Direction Note)**:
40
+ AI 導演在劇本拆解時為每一行台詞附加的聲音指示文字(例如 `[excited, fast-paced]` 或「用顫抖的聲音輕聲說」),直接作為語音生成時的情緒提示。
41
+ _Avoid_: 情緒標記、TTS prompt
42
+
43
+ **角色聲音對應表 (Voice Map)**:
44
+ 記錄每個角色對應哪個語音聲線的設定,由 AI 導演初步建議,使用者可修改。每個故事有自己的對應表,存放於故事資料夾中。
45
+ _Avoid_: 聲音設定、語音配置
46
+
47
+ **聲音演員庫 (Voice Actor Catalog)**:
48
+ 內建 30 位具備不同聲音特質(如活潑、成熟、溫柔、粗獷等)的 AI 配音演員名冊,供 AI 導演依據故事角色個性挑選最合適的聲線。
49
+ _Avoid_: TTS 清單、模型列表、聲線清單
50
+
51
+ **聲音性別 (Voice Gender)**:
52
+ 聲音演員庫中每位演員專屬的性別屬性(分為男性、女性、中性)。中性保留給非人類角色(如怪獸、精靈)或旁白使用,以避免 AI 盲選造成爸爸配女聲等性別錯置。
53
+ _Avoid_: 男女標籤
54
+
55
+ **說書人 (Narrator)**:
56
+ 故事中的旁白角色,擁有專屬且穩定的平穩聲線(預設為 Kore),與一般故事角色分開,不互相共用。
57
+ _Avoid_: 旁白語音、主述者
58
+
59
+
60
+ **故事資料夾 (Story Folder)**:
61
+ 每個故事專屬的存放位置(預設為 `~/Documents/StoryForge/<故事名稱>/`,亦可為使用者自選的電腦資料夾),內含各場景的音檔、角色聲音對應表,以及最終的有聲書成品。
62
+ _Avoid_: 輸出目錄、資料夾
63
+
64
+ **故事選單視窗 (Story Selector)**:
65
+ 點擊載入舊劇本時彈出的視窗,列出所有既有故事名稱、場景數量與修改時間,並提供直接挑選電腦資料夾的按鈕。
66
+ _Avoid_: 檔案總管、dialog、選單彈窗
67
+
68
+
69
+ **聲音拼接 (Audio Mixing)**:
70
+ 將各場景的獨立音檔依序合併成最終有聲書成品的過程。在所有場景都生成完畢後執行。
71
+ _Avoid_: 合併、concatenate
72
+
73
+ **場景背景音樂 (Scene BGM)**:
74
+ 故事共用的配樂主題(如日常、緊張、戰鬥)。AI 導演在劇本拆解前建立「BGM 主題對應表」,拆解場景時僅從表中挑選(存於 `bgm_theme_id`)。聲音拼接時,每主題僅生成一次音檔並跨場景共用。以 -18 dB 恆定墊底混入對白,首尾 2 秒淡入/淡出,超長無縫循環。
75
+ _Avoid_: 獨立配樂、環境音效
76
+
77
+ **BGM 主題對應表 (BGM Theme Map)**:
78
+ 記錄故事所有 BGM 主題設定(ID、中文名稱、英文 prompt)的檔案(`bgm_map.json`),存於故事資料夾。使用者修改主題會連動所有套用該主題之場景。
79
+ _Avoid_: 總表、配樂清單
80
+
81
+ **思考深度 (Thinking Level)**:
82
+ AI 導演在拆解劇本與生成聲音導演備註時的思考深淺程度(分為 MEDIUM 與 LOW)。
83
+ _Avoid_: model parameter, reasoning level
84
+
85
+ **劇本進度檔 (Screenplay Progress)**:
86
+ 記錄了 AI 拆解完並經過使用者修改的場景與台詞資料,自動存檔於故事資料夾中的檔案,可隨時載入恢復進度。
87
+ _Avoid_: cache file, save state
88
+
89
+ **合奏朗讀 (Multi-speaker Recording)**:
90
+ AI 導演在一個場景中,將最多兩位角色(含說書人)的台詞或對白打包在一起同時演繹出聲音的方式,能大幅縮短錄音時間並提升演繹的自然度。
91
+ _Avoid_: 多人語音合成、批次 TTS
92
+
93
+ **朗讀對話組 (Dialogue Group)**:
94
+ 在合奏朗讀時,由相鄰台詞且角色不超過兩位所組合而成的小段落,為單次交由 AI 導演演繹的單位(若只有一人自白或連續旁白,則為單人朗讀組,同樣整組合併錄音)。
95
+ _Avoid_: batch, chunk, 對話批次
96
+
97
+ **故事設定檔 (StoryForge Config)**:
98
+ 記錄 API 通行證與思考深度設定的秘密筆記本,自動儲存於個人的 `~/Documents/StoryForge/storyforge_config.json`,不管在電腦哪個角落開啟都能記住。
99
+ _Avoid_: 設定檔、環境變數、.env
100
+
101
+ **本地哨兵 (Pre-commit Hook)**:
102
+ 在電腦本機每次要把改好的故事程式積木存檔打包前,在門口快檢檔案有沒有排整齊的小幫手。
103
+ _Avoid_: pre-commit script, hook
104
+
105
+ **雲端守門員 (GitHub CI)**:
106
+ 當把寫好的故事程式送到 GitHub 雲端時,自動在雲端乾淨電腦裡替我們把所有積木全部重新檢查與跑測試的自動化機器人。
107
+ _Avoid_: CI/CD, pipeline, Actions runner
108
+
109
+ **官方世界超市 (PyPI)**:
110
+ 全球 Python 軟體的公開大貨架。使用者電腦只要輸入 `uvx storyforge-studio`,跑腿小幫手就會直接到這座超市把軟體拿下來執行。
111
+ _Avoid_: package index, 包倉庫
112
+
113
+ **免密鑰安全授權 (Trusted Publishing)**:
114
+ GitHub 雲端守門員與 PyPI 超市之間彼此相認的免密碼身分證。替故事軟體貼上新版本貼紙時,自動把軟體安全送上超市,不需在電腦留下任何密碼。
115
+ _Avoid_: PyPI token, API key, OIDC
116
+
@@ -0,0 +1,125 @@
1
+ # 開發者與協作者貢獻指南 (Contributing Guide)
2
+
3
+ 感謝你對 StoryForge 的關注!本專案旨在打造將文字故事轉換為生動有聲書的高品質工具。
4
+
5
+ 為了確保軟體核心邏輯清晰、穩定可維護,本專案嚴格遵守 **整潔架構 (Clean Architecture)** 與 **測試驅動開發 (Strict TDD)** 規範。請在參與貢獻前詳閱以下原則。
6
+
7
+ ---
8
+
9
+ ## 🛠️ 開發環境設定
10
+
11
+ 本專案使用現代化 Python 依賴管理工具 [`uv`](https://github.com/astral-sh/uv)。
12
+
13
+ 1. **複製專案**:
14
+ ```bash
15
+ git clone https://github.com/jonascheng/storyforge-studio.git
16
+ cd storyforge-studio
17
+ ```
18
+
19
+
20
+ 2. **同步依賴環境**:
21
+ ```bash
22
+ uv sync
23
+ ```
24
+
25
+ 3. **啟用本機門口哨兵 (Git Hooks)**:
26
+ ```bash
27
+ git config core.hooksPath .githooks
28
+ ```
29
+
30
+ 4. **啟動本機開發介面**:
31
+ ```bash
32
+ uv run storyforge
33
+ # 或
34
+ uv run python main.py
35
+ ```
36
+
37
+ 5. **執行程式碼風格檢查與自動排版**:
38
+ ```bash
39
+ # 檢查品質與瑕疵
40
+ uv run ruff check .
41
+
42
+ # 檢查排版風格
43
+ uv run ruff format --check .
44
+
45
+ # 自動修復可修正之問題
46
+ uv run ruff check --fix .
47
+ uv run ruff format .
48
+ ```
49
+
50
+ 6. **驗證所有自動化測試**:
51
+ ```bash
52
+ uv run pytest
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 🏛️ 架構原則:整潔架構 (Clean Architecture)
58
+
59
+ 專案分層解耦,單向依賴,核心業務邏輯絕不受外部框架或技術細節干擾:
60
+
61
+ ```
62
+ [ UI 介面層 ] (ui/ + pywebview)
63
+ ↓
64
+ [ 核心業務層 ] (core/entities.py & core/use_cases.py)
65
+ ↑
66
+ [ 外部基礎層 ] (infrastructure/ - Gemini API, Storage, AudioMixer)
67
+ ```
68
+
69
+ - **`core/`(核心邏輯層)**:
70
+ - `entities.py`:定義場景(Scene)、劇本台詞(ScriptLine)、劇本(Screenplay)等純資料物件。
71
+ - `use_cases.py`:定義劇本拆解、語音生成工作流,以及 `IDirector`、`IStorage` 抽象介面。
72
+ - ⚠️ **禁令**:本層絕不可直接引用任何外部函式庫(如 `google-genai`、`pydub`、`webview`)。
73
+ - **`infrastructure/`(外部實作層)**:
74
+ - 實作 `core` 所定義的介面,例如 `GeminiDirector` 串接 Google Gemini API、`StoryFolderStorage` 管理硬碟檔案、`AudioMixer` 處理音訊拼接。
75
+ - **`ui/`(使用者介面層)**:
76
+ - HTML5、Vanilla CSS、Vanilla JavaScript 前端,透過 `pywebview` 的 JS API 與後端溝通。
77
+
78
+ ---
79
+
80
+ ## 🧪 開發流程:嚴格測試驅動開發 (Strict TDD)
81
+
82
+ 所有新功能開發或錯誤修復,**必須遵循紅燈-綠燈-重構(Red-Green-Refactor)流程**:
83
+
84
+ 1. **先寫測試(Red)**:在 `tests/` 新增測試案例,描述預期行為與驗收條件,確認測試失敗。
85
+ 2. **編寫實作(Green)**:編寫最少必要程式碼,使測試通過。
86
+ 3. **重構優化(Refactor)**:在測試保護傘下重構程式碼,維持高可讀性與架構純潔性。
87
+ 4. **全測試驗證**:送出前必須確認 `uv run pytest` 全數通過(目前共有 49 項測試)。
88
+
89
+ ---
90
+
91
+ ## 📋 Issue 與 Pull Request 流程
92
+
93
+ 本專案使用 GitHub Issues 與 Pull Requests 管理工作。
94
+
95
+ ### Triage 標籤分類
96
+ 專案遵循 `docs/agents/triage-labels.md` 定義之五大標準標籤:
97
+ - `needs-triage`:新建立的議題,待審查其問題完整性。
98
+ - `ready-for-agent`:需求明確、驗收條件清楚,可立即指派開發。
99
+ - `agent-working`:目前正在進行開發。
100
+ - `needs-human-review`:實作完成,等待人工驗收審查。
101
+ - `done`:已驗收並合併完成。
102
+
103
+ ### 送出 Pull Request (PR) 檢核清單
104
+ 在提交 PR 之前,請確認:
105
+ - [ ] 遵循 Clean Architecture 架構分層。
106
+ - [ ] 執行 `uv run ruff check .` 與 `uv run ruff format --check .` 確認排版與品質檢查全數通過。
107
+ - [ ] 執行 `uv run pytest` 確認所有測試 100% 通過。
108
+ - [ ] 新增或修改的功能具備對應的單元或整合測試。
109
+ - [ ] 若涉及重要決策,已撰寫或更新對應的 [ADR (Architecture Decision Record)](docs/adr/)。
110
+ - [ ] PR 描述清晰說明修改動機與驗證成果。
111
+
112
+ ---
113
+
114
+ ## 📦 發布新版本至 PyPI (Release Process)
115
+
116
+ 本專案透過 GitHub Actions 與 PyPI **免密鑰安全授權 (Trusted Publishing)** 進行自動發布:
117
+
118
+ 1. **更新版本號**:在 `pyproject.toml` 更新 `version = "x.y.z"`。
119
+ 2. **建立 GitHub Release**:
120
+ - 建立並發布新 Release,Tag 名稱標註為 `vx.y.z`(例如 `v0.1.0`)。
121
+ 3. **自動上架**:
122
+ - 雲端工作流(`release.yml`)會自動觸發品質安檢(Ruff + pytest)。
123
+ - 安檢全數通過後自動執行 `uv build` 打包,並透過 OIDC 安全上傳至 PyPI 官方貨架。
124
+ - 使用者即可直接以 `uvx storyforge-studio` 取得最新版本。
125
+
@@ -0,0 +1,150 @@
1
+ Metadata-Version: 2.5
2
+ Name: storyforge-studio
3
+ Version: 0.1.0
4
+ Summary: 將文字故事轉換為具備情緒、角色演繹與生動聲音的有聲書電腦軟體
5
+ Author: Jonas Cheng
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: audioop-lts>=0.2.1; python_version >= '3.13'
8
+ Requires-Dist: google-genai>=0.1.0
9
+ Requires-Dist: pydub>=0.25.1
10
+ Requires-Dist: pyobjc-framework-webkit>=10.0; sys_platform == 'darwin'
11
+ Requires-Dist: pythonnet>=3.0.0; sys_platform == 'win32'
12
+ Requires-Dist: pywebview>=5.0.0
13
+ Requires-Dist: static-ffmpeg>=2.5
14
+ Description-Content-Type: text/markdown
15
+
16
+ # StoryForge 🎙️✨
17
+
18
+ > **將文字故事轉換為具備情緒、角色演繹與生動聲音的有聲書電腦軟體。**
19
+
20
+ StoryForge 就像一位住在你電腦裡的 **AI 總導演**。只要把心中的故事靈感或文字交給他,他就會從劇本編寫、角色設定、情緒指導到配樂聲音演繹一手包辦,為你錄製出一部生動好聽的完整廣播劇/有聲書 MP3!
21
+
22
+ 不需要懂寫程式,不論你是用 **Windows** 還是 **Mac**,只要跟著以下三個簡單步驟,就能一鍵召喚 StoryForge 開始創作!
23
+
24
+ ---
25
+
26
+ ## 🚀 三分鐘快速上手
27
+
28
+ ### 第一步:召喚小助手(安裝 uv 工具)
29
+
30
+ `uv` 就像是電腦裡的超級快遞員,能幫你免安裝、自動把軟體所有零件準備好。
31
+
32
+ - **🪟 Windows 使用者**:
33
+ 1. 在鍵盤上同時按下 `Win + X` 鍵,點選 **「終端機」** 或 **「PowerShell」**。
34
+ 2. 複製以下指令貼進黑視窗中,並按 `Enter` 執行:
35
+ ```powershell
36
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
37
+ ```
38
+
39
+ - **🍎 Mac 使用者**:
40
+ 1. 在鍵盤上同時按下 `Command + 空白鍵`,輸入 `Terminal` 並打開 **「終端機」**。
41
+ 2. 複製以下指令貼進終端機中,並按 `Enter` 執行:
42
+ ```bash
43
+ curl -LsSf https://astral.sh/uv/install.sh | sh
44
+ ```
45
+
46
+ ### 第二步:一鍵啟動 StoryForge(免安裝!)
47
+
48
+ 在剛剛打開的黑色終端機小視窗中,貼上以下這行指令並按 `Enter`:
49
+
50
+ ```bash
51
+ uvx storyforge-studio
52
+ ```
53
+
54
+ > 💡 **小秘訣**:
55
+ > 電腦會自動準備好所有環境與音訊小工具,只要幾秒鐘,美麗的 **StoryForge 操作視窗** 就會自動彈出來囉!
56
+ > *(若欲測試開發中未發布版本,亦可使用 `uvx --from git+https://github.com/jonascheng/storyforge-studio storyforge`)*
57
+
58
+ ---
59
+
60
+ ### 第三步:領取並設定免費通關鑰匙(Gemini API 通行證)
61
+
62
+ 首次啟動或尚未設定通行證時,畫面會自動跳出提醒視窗,指引您前往右上角的 **「⚙️ 設定」** 完成設定:
63
+
64
+ 1. 點擊設定畫面中 `Gemini API Key` 欄位旁的超連結,前往 [Google AI Studio](https://aistudio.google.com/) 網頁並登入您的 Google 帳號。
65
+ 2. 點擊畫面上的 **「Get API key」**,接著 **「Create API key」**,建立並複製那串英文數字密碼。
66
+ 3. 回到 StoryForge 貼上密碼並點擊 **「儲存」**。(只要設定一次,下次打開不用再輸入!)
67
+
68
+ > 💡 **進階設定**:在「⚙️ 設定」視窗中,您也可以依需求自由調整 **「思考深度 (Thinking Level)」**(預設 MEDIUM)與 **「場景間隔停頓 (秒)」**(預設 1 秒)。
69
+
70
+ ---
71
+
72
+ ## 📖 製作第一本有聲書(操作指引)
73
+
74
+ 當 StoryForge 視窗跳出來後,照著以下清晰步驟就能輕鬆完成作品:
75
+
76
+ ```
77
+ [1. 通行證設定] ⚙️
78
+ ↓
79
+ [2. 輸入故事想法] 💡(或 📂 載入舊劇本)
80
+ ↓
81
+ [3. 故事劇本確認與微調] 📝(角色卡片、世界觀、✨ 讓 AI 重寫 / ↩️ 復原)
82
+ ↓
83
+ [4. 廣播劇本拆解與錄音] 🎬(BGM 配樂、台詞情緒、🎙 生成語音 / ▶️ 試聽)
84
+ ↓
85
+ [5. 產出完整有聲書] 🔊
86
+ ```
87
+
88
+ ### 1. ⚙️ 確認通行證設定
89
+ - 確保已依照快速上手第三步,在右上角 **「⚙️ 設定」** 中填寫 Gemini API 通行證。
90
+ - (首次啟動未設定時,系統會自動跳出提醒視窗引導您。)
91
+
92
+ ### 2. 💡 輸入故事想法(或載入舊進度)
93
+ - 在「1. 輸入故事想法」文字框中貼上您的故事點子或大綱(例如:*一個關於會說話的貓和失憶魔法師的冒險故事...*)。
94
+ - 點擊 **「✍️ AI 撰寫劇本」**,AI 編劇會自動生成故事標題、完整情節、角色設定與世界觀規則。
95
+ - *(若是過去製作過的故事,可點擊 **「📂 載入舊劇本」** 從清單中點選,或點擊「📁 從電腦資料夾瀏覽...」直接開啟舊進度)*。
96
+
97
+ ### 3. 📝 故事劇本確認與微調
98
+ - 進入「2. 故事劇本確認」畫面,您可以檢視並自訂所有故事設定:
99
+ - **故事內容**:可直接修改內文,亦可點擊 **「🔍 放大」** 開啟全螢幕專注編輯。
100
+ - **角色設定**:檢視各角色卡片,包含角色名稱、聲音類型(例如:童趣活潑[男])與個性背景;可點擊 **「➕ 新增角色」** 或刪除角色。
101
+ - **世界觀規則**:檢視故事的世界背景,同樣支援 **「🔍 放大」** 編輯。
102
+ - **AI 靈感微調**:想改變劇情走向?在下方輸入修改需求(例如:*「讓結局更感人」、「加入一個反派角色」*),點擊 **「✨ 讓 AI 重寫」**;若不滿意重寫結果,點擊 **「↩️ 復原」** 即可隨時回到上一版。
103
+ - 確認滿意後,點擊下方 **「🎬 確認劇本,產生廣播劇」**。
104
+
105
+ ### 4. 🎬 廣播劇本拆解、配樂與錄音
106
+ - 進入「3. 廣播劇本編輯區」,AI 導演已將故事切分成一個個精彩場景:
107
+ - **🎵 場景背景音樂 BGM 主題**:每個場景可透過下拉選單挑選 AI 規劃的專屬配樂主題(亦可選「無」)。
108
+ - **台詞與情緒**:每一行清楚標註【角色】、【情緒指導】與【台詞內容】,隨時可自由編輯(修改後該場景會貼心標記 `● 內容已修改`)。
109
+ - **🎙 單幕錄製**:點擊場景右上角的 **「🎙 生成語音」**(或 **「🎙 重新生成」**),AI 演員就會為該場景配音演繹。
110
+ - **▶️ 當場試聽**:錄音完成後,點擊 **「▶️」** 按鈕即可立即播放試聽該場景的聲音與配樂!
111
+ - **✨ 安全審查小幫手**:若台詞觸發敏感安全審查,點擊 **「✨ 讓 AI 幫我想安全的台詞」**,AI 會立即提供安全的替代台詞並支援一鍵替換。
112
+
113
+ ### 5. 🔊 產出完整有聲書
114
+ - 所有場景確認完畢後,點擊最下方的 **「🔊 產出完整有聲書」**。
115
+ - 若有尚未生成的場景,系統會貼心詢問是否自動依序補齊錄音。
116
+ - 合併完成後,一部具備情緒演繹與背景音樂的完整有聲書就熱騰騰出爐了!
117
+
118
+ ---
119
+
120
+ ## 📂 我的有聲書存放在哪裡?
121
+
122
+ 你的所有故事、角色設定與錄音成果,都整整齊齊收納在電腦的專屬保險箱中:
123
+
124
+ - **Windows**:`C:\Users\你的使用者名稱\Documents\StoryForge\<故事名稱>\`
125
+ - **Mac**:`~/Documents/StoryForge/<故事名稱>/`
126
+
127
+ 進入該資料夾,你會看到一個名為 **`final_output.mp3`** 的檔案,這就是最終的高音質有聲書成品!你可以直接點開播放、傳到手機或分享給朋友聆聽。
128
+
129
+ ---
130
+
131
+ ## ❓ 常見問題 Q&A
132
+
133
+ **Q1:需要自己安裝 ffmpeg 或其他剪輯工具嗎?**
134
+ 不需要!StoryForge 已經貼心內建了「自動剪刀小幫手」(`static-ffmpeg`),在後台全自動處理音訊拼接,完全不需要手動設定。
135
+
136
+ **Q2:換到不同資料夾打開,設定需要重打嗎?**
137
+ 不需要!通行證與設定統一儲存在電腦的「文件/StoryForge」專屬位置,不管從哪裡啟動都能自動讀取。
138
+
139
+ **Q3:我想修改某個角色的台詞或聲音,需要全部重跑嗎?**
140
+ 不用!StoryForge 是「以場景為單位」錄音的。如果你只想改某一幕的台詞、情緒或配樂,只要單獨重新產生該場景即可,省時又節省額度。
141
+
142
+ **Q4:錄音時如果遇到台詞被安全審查阻擋怎麼辦?**
143
+ 別擔心!遇到阻擋時,該場景會出現「✨ 讓 AI 幫我想安全的台詞」按鈕。點擊後 AI 導演會為您構思既符合劇情的安全替代台詞,點選即可一鍵自動替換!
144
+
145
+ ---
146
+
147
+ ## 🤝 開發與參與貢獻
148
+
149
+ 想了解專案架構、參與程式碼開發、或是送出 PR 協助改進嗎?
150
+ 歡迎閱讀 [開發者與協作者貢獻指南 (CONTRIBUTING.md)](CONTRIBUTING.md)。