2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ffmpegの処理をtkinterでGUI化(その1: プログレスバーとリアルタイム出力表示)

Last updated at Posted at 2023-02-05

初投稿です.よろしくお願いします.

*この記事の続きはこちら

概要

  • このようなプログレスバーを作る.
    Animation.gif

やりたいこと

  • pythonからffmpegを使って動画を処理したい.
  • GUI化したい.

GUIの内容

  • ボタンを押すと処理が開始する.
  • 処理中はtkinterのプログレスバー(不確定モード)のウインドウがポップアップされる.
  • 処理が完了するとプログレスバーのウインドウが自動的に閉じる.

コード

NGな例その1

import os, subprocess
import tkinter as tk
from tkinter import ttk, messagebox

command = "ffmpeg hogehoge" # ffmpegの処理コマンド

def start():
    progress = tk.Toplevel()
    bar = ttk.Progressbar(progress,mode='indeterminate')
    bar.pack()
    bar.start()

    subprocess.run(command, shell=True)

    progress.destroy()

root = tk.Tk()
button = tk.Button(root, text = "start", command = start)
button.pack()

root.mainloop()

ffmpegの処理は始まるが,プログレスバーは表示されない.rootウインドウも応答なしになる.

NGな例その2

  • subprocess.runを非同期処理が可能なsubprocess.Popenにするとどうなる?
    →ffmpegの処理開始と同時にprogress.destroy()が実行されるので,プログレスバーは表示されない.そこで,同期待ちが必要.

OKな例

import os, subprocess
import tkinter as tk
from tkinter import ttk
import threading

command = "ffmpeg hogehoge" # ffmpegの処理コマンド

def start():
    progress = tk.Toplevel()
    bar = ttk.Progressbar(progress,mode='indeterminate')
    bar.pack()
    bar.start()

    def process():
        p = subprocess.Popen(command, shell=True)

        try:
            outs, errs = p.communicate()
        except subprocess.TimeoutExpired:
            pass
        else:
            p.terminate()
            progress.destroy()
    
    th1 = threading.Thread(target=process)
    th1.start()

root = tk.Tk()
button = tk.Button(root, text = "start", command = start)
button.pack()

root.mainloop()

ポイント

  • subprocess.runではなくsubprocess.Popenを使う.
  • threadingで別スレッドでffmpegを実行する.
  • outs, errs = p.communicate()でffmpegの処理待ちを行う.

発展

import os, subprocess
import tkinter as tk
from tkinter import ttk, messagebox
import threading

command = "ffmpeg hogehoge" # ffmpegの処理コマンド

def start():
    progress = tk.Toplevel()
    progress.geometry("600x75")
    progress.title("processing...")
    info_text = tk.StringVar()
    info = tk.Label(progress, textvariable = info_text)
    info.pack(side = tk.TOP, anchor = tk.W)
    bar = ttk.Progressbar(progress,mode='indeterminate')
    bar.pack(side = tk.TOP, fill = tk.X)
    bar.start()

    def process():
        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,shell=True,universal_newlines=True)
        
        for line in p.stdout:
            info_text.set(line)

        try:
            outs, errs = p.communicate()
        except subprocess.TimeoutExpired:
            pass
        else:
            p.terminate()
            progress.destroy()
            warnwindow = messagebox.showwarning("Done", "Animation saved!")

    th1 = threading.Thread(target=process)
    th1.start()


root = tk.Tk()
button = tk.Button(root, text = "start", command = start)
button.pack()

root.mainloop()

今後

  • キャンセルボタンがあるとよい.
  • 確定モードのプログレスバーと標準出力の進捗を同期させたい.

最後までお読みいただきありがとうございました.

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?