0.8.0 — Tkinter GUI
1. 目的
slidemovie の基本的なワークフロー(Markdown から PPTX を作る、PPTX/PDF と原稿から動画を作る)は CLI で提供されている。一方で、毎回多数のオプションを指定することは、コマンドラインに慣れていない利用者には負担になる。
バージョン 0.8.0 では、既存の Movie API と CLI の機能を利用する ローカル用 Tkinter GUI を追加する。GUI は CLI の代替入口であり、動画生成ロジックを二重実装しない。
2. 対象範囲
2.1 提供する機能
- Markdown/PPTX/PDF のあるフォルダーを選び、プロジェクト名を指定する。
- 「PPTX を生成」と「動画を生成」を個別、または同時に実行する。
- 標準プロジェクトとサブプロジェクトの両方を扱う。
- CLI の主要な一時上書き設定(出力先、出力ファイル名、画像ソース、TTS)を入力できる。
- 実行ログ、進行中状態、成功・失敗を GUI 上で確認できる。
- 長時間の生成中もウィンドウを操作可能な状態に保つ。
2.2 対象外
以下は 0.8.0 では扱わない。
- Markdown、PowerPoint、
config.jsonの編集機能。 - API キーや認証情報を GUI に保存・表示する機能。
- 処理の強制停止、キュー実行、並列実行、進捗率の厳密な算出。
Movieの動画生成アルゴリズム、設定ファイルの優先順位、既存 CLI の挙動変更。- OS 固有のインストーラーやネイティブなファイル関連付け。
3. 起動方法と配布
3.1 エントリーポイント
既存の slidemovie コマンドに -g / --gui を追加する。GUI 起動時はプロジェクト名を省略できるように、CLI の位置引数 project_name は任意にする。ただし、GUI なしの従来実行ではプロジェクト名を必須のままとする。
slidemovie -g
slidemovie my-project -g --video --tts-provider openai
slidemovie parent -g --sub chapter-1 --pptx
-g を指定した場合、-p / --pptx、-v / --video、--pdf、-s / --source-dir、--sub、-o / --output-root、-f / --filename、および全 TTS 関連オプションは実行せずに GUI の初期入力値として渡す。CLI で明示された値は GUI 上でも「上書きあり」として扱う。GUI を閉じた場合はビルドを実行しない。
実装は slidemovie.gui:main(initial_options) を呼び出す。initial_options は CLI と GUI の橋渡し用であり、安定した公開 API ではない。別のコンソールコマンド slidemovie-gui は追加しない。
GUI は標準ライブラリの tkinter / tkinter.ttk のみを使い、新しい必須依存パッケージは追加しない。slidemovie 本体のインポート時に Tkinter を必要としないよう、GUI 関連モジュールは slidemovie.__init__ から import しない。
3.2 表示言語
表示言語は日本語と英語を提供する。初期言語は次の順で決める。
- GUI 起動オプションで将来
--language ja/--language enが明示された場合はその値。 - システムロケール(
locale.getlocale()および必要に応じてlocale.getdefaultlocale())の言語部分がjaなら日本語。 - それ以外は英語。
システムロケールは初期値を決める用途だけであり、環境変数を変更しない。ウィンドウ上部の言語選択(日本語 / English)で待機中にいつでも切り替えられる。切替時はラベル、ボタン、ダイアログ、検証メッセージ、状態文字列を更新するが、利用者が入力済みの値・ログ・選択状態は変更しない。実行中もログ本文は生成時の言語のままとし、画面の操作ラベルだけを切り替える。
3.3 Tk が利用できない環境
main() は Tkinter の import または Tk() の生成に失敗した場合、標準エラーへ「Tkinter を利用できない。OS/Python の Tk パッケージを導入すること」を出力し、終了コード 1 で終了する。ヘッドレスの CI で slidemovie や CLI を import するだけでは失敗しないことを保証する。
4. 画面仕様
メインウィンドウは ttk を使い、OS 標準の見た目に従う。タイトルには、実行中の slidemovie パッケージのバージョンを表示する。固定解像度を前提にせず、横幅を拡張できるレイアウトにする。
4.1 プロジェクト
| 項目 | UI | 初期値 | 内容 |
|---|---|---|---|
| ソースフォルダー | テキスト欄 + 「参照」 | . |
.md、.pptx、.pdf を置くフォルダー。フォルダー選択ダイアログで指定できる。 |
| プロジェクト名 | テキスト欄 | 空 | 標準モードではファイルのベース名。 |
| サブプロジェクトを使用 | チェックボックス | オフ | オンの場合、プロジェクト名を親プロジェクト名、下記のサブプロジェクト名を子フォルダー名として扱う。 |
| サブプロジェクト名 | テキスト欄 | 空(オフ時は無効) | --sub に相当する値。 |
| 出力先ルート | テキスト欄 + 「参照」 | 空 | 空なら CLI と同じ自動出力先を使う。指定時は既存フォルダーでなければならない。 |
| 出力ファイル名 | テキスト欄 | 空 | 拡張子を除く名前。空ならプロジェクト ID を使う。 |
4.2 実行内容
「実行内容」には次のチェックボックスを置く。少なくとも一つを必須とする。
PPTX を生成(Movie.build_slide_pptx())動画を生成(Movie.build_all())
動画を生成する場合のみ、画像ソースを選択できる。
PPTX(既定、use_pdf = False)PDF(use_pdf = True)
PPTX と動画を同時に選択したときは、既存 CLI と同じく PPTX 生成を完了してから動画生成を行う。PDF を選択して PPTX だけを実行する場合は、PDF 選択が動画生成にしか影響しない旨をログに記録する。
4.3 TTS 設定と有効設定の表示
「TTS 設定」には折りたたみ可能な詳細領域を置く。GUI は起動時に Movie() が読み込んだ有効設定(ローカル config.json、ユーザー設定、既定値をマージした結果)を各入力欄に表示する。したがって、通常は設定欄が空欄のままにはならない。
各設定には「上書き」状態を内部に持つ。初期表示した有効値は未上書きであり、実行時に GUI が同じ属性を再設定しない。利用者が値を変更したとき、または slidemovie -g に対応する CLI オプションを与えたときだけ上書き状態にする。これにより、値を見ながら編集でき、未変更の設定は config.json と既定値の通常の読み込み経路を保つ。
設定を既定の読み込み状態へ戻すため、各項目または TTS 設定全体に「設定から戻す」操作を設ける。この操作は現在の Movie が読み込んだ有効値を表示し、上書き状態を解除する。config.json 自体を書き換えない。
| 項目 | 対応する属性 | 入力方法 |
|---|---|---|
| プロバイダー | tts_provider |
テキスト欄(例: google, openai, azure, voicevox) |
| モデル | tts_model |
テキスト欄 |
| 声 / style ID | tts_voice |
テキスト欄 |
| VOICEVOX URL | tts_voicevox_url |
テキスト欄 |
| スタイルプロンプト | prompt |
複数行テキスト欄 |
| プロンプトを使用 | tts_use_prompt |
「設定ファイルに従う」「使用する」「使用しない」の 3 択 |
| プロンプト区切り | prompt_separator |
複数行テキスト欄 |
| チャンクサイズ | chunk_size |
正の整数または空欄 |
| 分割候補文字 | split_chars |
テキスト欄 |
| 分割不可時の動作 | chunk_overflow |
extend / error |
複数行欄は入力内容をそのまま渡すため、改行を \n と書き換えない。prompt の編集は CLI の --prompt と同じく、プロンプト使用を「使用する」にする。明示的に「使用しない」を選んだ場合はその選択を優先する。
status.json に記録された TTS 設定を使用する選択をした場合は、実際にビルドへ適用するだけでなく、TTS 設定タブの入力欄もその値へ更新する。対象はプロバイダー、モデル、声、VOICEVOX URL、プロンプト、プロンプト使用有無、プロンプト区切り、チャンクサイズ、分割候補文字、分割不可時の動作である。更新後の各項目は GUI の明示的な上書き値として保持し、次回の実行にも同じ値を適用する。config.json および status.json 自体はこの表示同期によって変更しない。
4.4 status.json のサマリー
プロジェクト欄の下に、読み取り専用の「プロジェクトの状態」領域と 状態を更新 ボタンを置く。プロジェクト名、ソースフォルダー、サブプロジェクト指定が有効な値になった時点、およびビルド終了時に自動更新する。標準モードでは {source_dir}/status.json、サブプロジェクトでは {source_dir}/{subproject_name}/status.json を読む。
表示するのは利用者が次の実行を判断するための要約に限る。
| 表示項目 | status.json の情報 |
|---|---|
| 状態ファイル | 存在の有無、読み込み失敗時の理由 |
| プロジェクト ID / 最終確認日時 | project_id、last_checked |
| PPTX / 画像 | pptx_task.status、images_task.status と、あれば generated_at |
| スライド | 全件数、音声・動画などの完了数、失敗数(各スライド記録の status 等、存在する値から集計) |
| 音声ファイル | 各 slides.*.audio.status を集計した総数、生成済み数、未生成数、失敗数。audio を持たないスライドは集計対象外。 |
| 記録済み TTS | tts_config の provider、model、voice のみ |
原稿本文、プロンプト、ハッシュ、API キー、未知の JSON キーは表示しない。status.json が無い場合は「まだ作成されていません」と表示する。JSON が壊れている、または旧形式で期待するキーが無い場合も GUI を停止させず、読み取れた範囲だけを表示して警告を出す。サマリーの表示は状態を変更しない。
4.5 操作・ログ
実行ボタン: 入力検証後に処理を開始する。ログを消去ボタン: 表示中のログだけを消去する。生成済みファイルは削除しない。終了ボタン: 実行中は無効、実行していないときに有効にする。- 実行状態:
実行ボタンの右に実行中、成功、失敗を表示する。初期状態では表示しない。ソースフォルダー、プロジェクト名、サブプロジェクト名を変更したら、前のプロジェクトの状態表示を消す。 - ログ欄: 読み取り専用・折り返しなし・縦横スクロール可能とし、末尾へ自動スクロールする。
実行中は入力欄、実行ボタン、ログ消去ボタンを無効化し、二重実行を防ぐ。処理終了後は再び有効にする。ウィンドウの閉じる操作も実行中は拒否し、「処理完了後に終了してください」と表示する。
5. 実行モデル
5.1 CLI と共有する処理
GUI は subprocess で slidemovie コマンドを起動しない。ワーカースレッド内で次の CLI と同等の手順を行う。
Movie()を生成し、既存の設定読み込みと外部コマンド検査を行う。- GUI で明示的に入力された設定だけを
Movieの属性へ反映する。 - サブプロジェクト指定の有無に応じ、
configure_project_paths()またはconfigure_subproject_paths()を呼ぶ。 - 選択順に
build_slide_pptx()、build_all()を呼ぶ。
このため、GUI でも config.json の優先順位、status.json による増分ビルド、TTS 設定の変更確認を既存仕様どおり利用できる。
5.2 スレッドとログ
Tkinter のウィジェット操作はメインスレッドだけで行う。動画生成は 1 本の daemon ではないワーカースレッドで実行し、ログレコードと完了結果を queue.Queue に渡す。メインスレッドは root.after() でキューを定期的に読み、ログ欄と状態表示を更新する。
ワーカーから Tkinter、messagebox、ファイル選択ダイアログを直接呼んではならない。GUI 用の logging.Handler は emit() でログレコードをキューへ積むだけにする。GUI 起動時に root logger の既存ハンドラーを削除せず、このハンドラーだけを追加・終了時に解除する。
5.3 TTS 設定の不一致確認
status.json の tts_config と、GUI の入力値および設定ファイルから得た有効 TTS 設定が異なる場合、GUI は build_slide_pptx() / build_all() の前に不一致確認を行う。GUI 実行中は標準入力に依存してはならない。
- メインスレッドは、ワーカーからキューで渡された要求に対し、次の 3 択を表示する。
status.json の設定を使う: 記録済みの全 TTS 設定をMovieへ反映して継続する。status.jsonは更新しない。入力欄も同じ値へ更新する。現在の設定で上書きする: 現在の有効設定で継続し、既存の処理によりstatus.jsonの TTS 設定を更新する。キャンセル: ビルドを開始しない。
status.jsonの設定を使用する処理は GUI 内で完結させ、CLI の TTS 設定確認と状態ファイルの扱いを変更しない。- 上書きを選んだ場合は、同じ不一致に対する確認ダイアログを重複して表示しない。
GUI の要求待ち中にワーカーから Tkinter、messagebox、標準入力を直接呼んではならない。
6. 入力検証とエラー処理
実行開始前に GUI が次を検証し、問題があればダイアログとログで示して処理を開始しない。
- プロジェクト名が空でないこと。
- サブプロジェクト有効時、サブプロジェクト名が空でないこと。
- PPTX/動画の少なくとも一方が選択されていること。
- 出力先ルートが空でない場合、それが既存ディレクトリーであること。
- チャンクサイズが空欄または 1 以上の整数であること。
chunk_overflowが指定された場合、extendまたはerrorであること。
パス内の入力ファイルの存在確認、Pandoc / FFmpeg / ImageMagick の可用性、TTS API・VOICEVOX の到達性は Movie の既存検証に委ねる。ワーカーで発生した Exception と SystemExit は捕捉し、トレースバックをログへ出したうえで状態を 失敗 にする。GUI プロセス自体を終了してはならない。
成功時はログに最終動画のパス(動画生成を選択した場合)を出し、情報ダイアログで完了を知らせる。失敗時は短いエラー概要をダイアログで出し、詳細はログ欄で確認できるようにする。
7. ファイル構成と公開 API
| ファイル | 変更内容 |
|---|---|
slidemovie/gui.py |
SlideMovieApp、GUI 用ログハンドラー、ワーカー制御、言語リソース、TTS 不一致の 3 択、status.json サマリー(音声ファイル状態を含む)、main() を追加。 |
slidemovie/cli.py |
-g / --gui、GUI 起動時だけ任意となるプロジェクト名、既存 CLI オプションから初期 GUI 値への変換を追加。 |
slidemovie/core.py |
標準入力を使う TTS 設定確認を、任意の確認コールバック経由でも解決できるよう最小限に拡張。既定の CLI 挙動は維持。 |
pyproject.toml |
バージョンを 0.8.0 に更新。 |
tests/test_gui.py |
GUI に依存しない入力変換、有効設定と上書き状態、status.json サマリー、ワーカー呼び出し順、ログキュー、確認コールバックをテスト。 |
README.md / docs/installation.md / docs/ja/installation.md |
GUI の起動方法と Tkinter の前提条件を追記。 |
SlideMovieApp と slidemovie.gui:main はライブラリーとしての安定公開 API ではない。利用者向けの安定した起動入口はコンソールコマンド slidemovie -g のみとする。
8. テスト方針
- GUI 以外の既存テストをすべて維持する。
- Tk のディスプレイを必要としない単体テストで、入力値から
Movie属性へ反映する値を検証する。 - 有効設定が GUI に表示される一方、未編集なら属性上書きが発生しないこと、編集・CLI 指定・「設定から戻す」が上書き状態を正しく変更することを検証する。
-g単独、および既存 CLI オプションを組み合わせた-gが、それぞれ正しい初期 GUI 値を作ることを検証する。- 日本語ロケール・それ以外のロケールでの初期言語選択と、言語切替後に入力値・ログが保持されることを検証する。
- 正常、欠損、破損、旧形式の
status.jsonから、安全な要約が作られ、スライド内のaudio.statusについて生成済み・未生成・失敗を正しく集計することを検証する。 - TTS 設定の不一致時に、現在の設定で上書き、
status.jsonの設定を使用、キャンセルの各選択が正しく処理されることを検証する。記録済み設定を選んだ場合は、全 TTS 入力欄とその上書き状態が記録値へ同期されることを検証する。 Movieをモックし、標準・サブプロジェクトそれぞれでパス設定メソッドとビルドメソッドが正しい順序で呼ばれることを検証する。- 例外、
SystemExit、確認の中止時に、失敗または中止としてワーカー完了イベントが送られることを検証する。 - ログハンドラーが Tkinter を直接操作せずキューへ積むことを検証する。
- Tk がない環境で
slidemovie.gui.main()が分かりやすく終了し、import slidemovieと既存 CLI に影響しないことを確認する。
9. 受け入れ条件
slidemovie -gで GUI を起動でき、標準プロジェクトで PPTX または動画を生成できる。既存オプションを併用した場合、その値が対応する入力欄へ反映される。- GUI からの生成結果は、同じ入力・同じ設定の CLI 実行と同じ
Movie処理経路を使う。 - 実行中にウィンドウがフリーズせず、ログが順次表示され、二重実行できない。
- TTS 設定が
status.jsonと異なる場合、GUI 内で「記録済み設定を使う」「現在の設定で上書き」「キャンセル」を選択でき、端末入力待ちで停止しない。記録済み設定を使うと入力欄も同期する。 - エラーは GUI を落とさず、利用者が内容を確認して再実行できる。
- GUI を使わない既存 CLI・設定ファイル・プロジェクトは後方互換である。
- 起動時にシステムロケールから日英を選び、画面から安全に切り替えられる。
status.jsonがあれば機微情報を露出せずに要約を表示し、各スライドの音声ファイル状態を集計して表示する。無い・壊れている場合でも GUI を利用できる。