【PythonでGUIを作りたい】Tkinterで作る画像編集ソフト#5:動画編集の仕様を考える
こんにちは。すうちです。
早いもので7月に入り今年も半分終わりました。先週もものすごい暑さで私は少しバテ君味でした。バランス良い食事や睡眠多めにしてこれからの季節を乗り切りたいと思います。
皆さんも体調には、くれぐれもお気をつけ下さい。
しばらく間があきましたが、今週からTkinterで作る画像編集ソフトの連載(続き)を再開したいと思います。
前回の記事はこちらです。
今回はTkinterを使った動画編集の仕様検討に関する話です。
◆はじめに
作りたい機能のイメージ
初期検討のメモです。
ちなみに、動画編集は画像のみで音声は対象外です。
できるだけPythonの簡単なプログラムやTkinterの基本機能の範囲で実現することが目標です。
メモを元に、まずはユーザ視点からGUI操作や必要な部品を考えたいと思います。
◆ユーザ操作と動画編集の仕様検討
動画/静止画の編集切替
最初のお題として、動画機能の追加にあたり既にある静止画編集とどう棲み分けるか(GUIの構成をどうするか)があります。
やり方は色々考えられますが、例えば動画と静止画編集の画面は共通にして、各機能毎に有効なボタン表示を切り替える等です。
この場合、静止画の編集は1枚の画像が対象ですが、動画は複数の画像(フレームの集まり)が対象なので、目的とやりたい操作に結構差があります。
また仮に同一画面とした場合、動画または静止画編集に関わる各widget(GUI部品)毎の状態管理や有効無効の条件などが増えて今より実装が複雑になる気がします(ユーザ操作などの外部仕様を検討する時は内部の設計は一旦脇に置くべきと言う意見もありますが)。
現時点では、静止画と動画の編集画面を共通にするよりも、シンプルに完全に分けて考えた方が良い気がするので、動画と静止画の画面は、Tkinterのタブ(notebook)を使ってユーザ操作で切り替えることにします。
ディレクトリ/ファイル選択
ここは静止画と同様の操作(共通化)を考えています。ただし、動画なので選択ファイルはmp4(動画ファイルの拡張子)が対象です。
動画操作(ボタン)
再生/停止
通常のプレイヤ操作を想定し選択した動画を再生/停止するボタンです。
画面キャプチャ
現在表示している動画の画面(フレーム)を保存するボタンです。
コマ送り(1フレームSTEP再生)
動画をコマ送り(1フレームずつ)再生するボタンです。動画編集時に後述の再生位置の移動とあわせて、画像フレームの切り出し位置の微調整に使うことも想定しています。
倍速再生
動画の再生スピードを変更できる様に x0.5、x1.0、x2.0、x4.0倍を切り替えるボタンも配置します。
再生(フレーム切り出し)位置の移動
通常再生や倍速再生に加えて、再生位置を変えられる様にスライダ(TkinterのScale)を配置します。
フレーム(特定位置)切り出しの画面構成
動画の特定位置(ある期間の画像フレーム)を切り出す場合、最低限の情報として切り出したいフレームの開始/終了位置が必要です。
プログラム上は切り出す期間のフレーム番号がわかれば実装できますが、ユーザ操作の視点では切り出す位置の画像表示があることが前提と思います(多分ほとんどの動画編集のUIはそうかと思います)。
そこで切り出すフレームの位置を目視確認できるように、切り出す画像フレームの開始位置と終了位置の表示画面(TkinterのCanvas)を2つ配置したいと思います。
双方のフレーム表示画面(Canvas)は、どちらか片方を有効/無効に切り替えて操作する想定です。
編集機能(回転/反転/クリップ)
回転(Rotate)、反転(Flip)、クリップ(Clip)は、静止画編集と同様の操作を想定してGUIは共通化する前提で考えます。
編集は切り出したフレームを対象に、回転/反転/クリップした結果をファイル保存できる様にしたいと思います。
編集ファイル保存(Save)
編集した動画を保存するボタンです。日時ファイル名で保存します。
◆GUIの画面構成
以下、検討結果を反映した画面構成のレイアウトです。
1点補足します。
以前、回転と反転はラジオボタン(こういう形⦿)で実装していましたが、そもそもラジオボタンの一般的な使い方は、選択した設定を保持して別のボタンで実行する流れと思います。
今の使い方は、ラジオボタン押下時に回転/反転を行ってるので(UIのテスト時に少し違和感もありましたが)ボタンで実装することが自然ではないかと後で気づきました。
本来ならば前回の記事公開前に気づくべき話ですが。。。この場で訂正と仕様見直した結果が上記レイアウトとなります。
◆GUI部品の簡易テスト
以下、新しく追加したTkinterの部品(タブ、スライダ)とGUI操作(簡易テスト)のログです。簡単に補足します。
動画/静止画の切替タブ(notebook)
# Notebook, Tab生成
self.window_sub_frame = tk.Frame(self.window_root, height=590, width=540)
self.notebook = ttk.Notebook(self.window_sub_frame)
self.tab1 = tk.Frame(self.notebook, height=560, width=500)
self.tab2 = tk.Frame(self.notebook, height=560, width=500)
self.notebook.add(self.tab1, text='[Photo]')
self.notebook.add(self.tab2, text='[Video]')
Tkinterでタブを作る場合は、tkinter.ttk.Notebook()を使用します。
Notebook()の引数は、どのウィンドウに属するかの指定です。
今回は一部の領域をタブで切替えたいので、ルートのwindow配下に別のフレームウィンドウ(window_sub_frame)を作って、それをnotebookに紐づけます。
また切替表示する各タブ毎にそれぞれフレーム(tab1、tab2)を用意します。
notebookにtabを登録(追加)しているが最後のnotebook.add()です。
ちなみに、フレームの構成を図示すると以下の感じです。
再生位置のスライダ(Scale)
self.bar_scale = tk.Scale(self.tab2, from_=0, to_=100, orient='horizontal', resolution=1.0,
variable=self.bar_position, length=400, command=self.event_update_bar)
Tkinterでスライダを作る場合は、tkinter.Scale()を使用します。
(tkinter.ttk.Scale()でも作れますが、仕様を見る限りtkinter.Scale()の方が設定が多くできそうだったのでこちらにしました)
最初の引数はどのウィンドウに属するかの設定です。このスライダは動画編集時のタブで表示させたいので引数の指定はtab2です。from_、to_はスライダの範囲指定。その他スライダの幅やイベント実行するコールバック関数も指定します。
orientのhorizontalは水平方向のスライダを意味し、resolutionはスライダの目盛(例は1.0単位)です。
今回ユーザ操作によるスライダの位置を参照して動画の再生位置を決めるため、variableにViewGUIクラスで値を保持する変数を指定しています。
イベントの実行関数(簡易テストログ)
Videoタブ(tab2)のレイアウトに配置した部品操作のログです。タブの切替や再生に関わる操作、スライダの動作イベントは正常に取れています。
◆今後の予定
次回は、動画編集の内部設計やイベントの実装について検討予定です。
最後に
今回はここまでです。
静止画編集の時もそうでしたが、今回の動画編集も現時点で最終形がある訳ではないので、今後検討を進める過程で変わる部分もあると思います。
動画編集の仕様では、画像フレーム切り出しのUIをどうするか一番悩みましたが、当初考えてたよりも簡易的な方法で現状は行ける気がするので引き続き具体的な実装を考えていきたいと思います。
また設計やテスト時に今気づいてない問題も出てくるかもしれませんが、その辺の話も含めて、もしご興味あれば最後までお付き合い頂ければと思います。
GUI構築の流れを大まかに把握したい方、Tkinterを使うことを検討されている方に、何か参考になれば幸いです。
最後まで読んで頂き、ありがとうございました。
ーーー
ソフトウェアを作る過程を体系的に学びたい方向けの本を書きました(連載記事に大幅に加筆・修正)
Kindle Unlimited 会員の方は無料で読めます。
#連載記事の一覧
ーーー
この記事が気に入ったらサポートをしてみませんか?