質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

FFmpeg

FFmpegは、動画と音声を交換できるフリーソフトウェアです。UNIX系OSから派生した、MS-DOSから操作するコマンドラインツールです。libavcodecやlibavformat、libswscale、libavfilterなどを含みます。ライセンスは、コンパイルの際のオプションによりLGPLもしくはGPLに決定されます。対応コーデックや使用できるオプションが多く、幅広く利用されています。

Q&A

解決済

2回答

4737閲覧

[Python初心者] ffmpegとsubprocessを使って動画ファイルの情報取得アプリを作成したい。

退会済みユーザー

退会済みユーザー

総合スコア0

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

FFmpeg

FFmpegは、動画と音声を交換できるフリーソフトウェアです。UNIX系OSから派生した、MS-DOSから操作するコマンドラインツールです。libavcodecやlibavformat、libswscale、libavfilterなどを含みます。ライセンスは、コンパイルの際のオプションによりLGPLもしくはGPLに決定されます。対応コーデックや使用できるオプションが多く、幅広く利用されています。

0グッド

0クリップ

投稿2020/09/19 09:14

編集2020/09/19 10:57

python

1import tkinter as tk 2import tkinter.filedialog as tkfd 3import subprocess 4 5# グローバル変数 6acv_path = "" 7f_path_list = [] 8 9### この下に関数を書く ### 10 11def select_file(): 12 global f_cont, f_path_list 13 14 f_conf = [('MOV file (*.mov)', '*mov'), ('AVI file (*.avi)', '*.avi'),('MP4 file (*.mp4)', '*.mp4')] 15 paths = tkfd.askopenfiles(filetypes=f_conf) 16 for f in paths: 17 f_path_list.append(f.name) 18 # Insert to Message List 19 msgList.insert(tk.END, f_path_list) 20 # Insert Input Path TextBox 21 inpFld.insert(tk.END, f_path_list) 22 23 24def get_mediainfo(f_path_list): 25 # 変数を定義する 26 targetfile = f_path_list 27 # コマンドを定義して、変数を挿入する 28 cmd = 'ffprobe -i {}'.format(targetfile) 29 # コマンドを実行する 30 result = subprocess.run(cmd, shell=True) 31 msgList.insert(tk.END, result) 32 33 34 35 36 37def close_window(): 38 win.destroy() 39 40 41 42if __name__ == "__main__": 43 # Main Window 44 win = tk.Tk() 45 # Window Title 46 win.title("MediaInfo App") 47 # Window Size 48 win.geometry("500x500") 49 # Window Resizable 50 #win.resizable(0,0) 51 # Window Background 52 win.configure(bg="#52514F") 53 54### この下に描画内容を書く ### 55 #メインフレーム 56 mFrm = tk.Frame(win) 57 mFrm.configure(bg="#52514F") 58 mFrm.pack(padx=3, pady=3, fill="both", expand=1) 59 60 # 通知リスト 61 msgList = tk.Listbox(mFrm) 62 msgList.configure(height=20, width=50) 63 msgList.pack(padx=10, pady=10) 64 65 # ボタン中央揃え用のフレーム 66 InpFrm = tk.LabelFrame(mFrm) 67 InpFrm.configure(text="Input Settings", fg="white", bg="#52514F", padx="20", pady="10") 68 InpFrm.pack(pady=5) 69 70 71 # Input Path ラベル 72 inpTxt = tk.Label(InpFrm) 73 inpTxt.configure(text="Input Path | 入力", fg="white", bg="#52514F", font=('Helvetica', 10)) 74 inpTxt.pack(side="left", padx=5) 75 76 # Input Path 表示 77 inpFld = tk.Entry(InpFrm) 78 inpFld.configure(fg="black", highlightbackground="#52514F") 79 inpFld.pack(side="left", padx=5) 80 81 # ファイル選択ボタン 82 inpBtn = tk.Button(InpFrm) 83 inpBtn.configure(text="Select File", command=select_file) 84 inpBtn.pack(side="right", padx=5) 85 86 # Exitボタン 87 extBtn = tk.Button(mFrm) 88 extBtn.configure(text="Exit", command=close_window) 89 extBtn.pack(side="bottom", padx=5,pady=10) 90 91 #アイコン設定 92 icon_photo = tk.PhotoImage(file = '/Volumes/UnsungHero/Python/IVTC_tool/film.png') # icon file | アイコンファイル 93 win.iconphoto(False, icon_photo) # Sets the icon | アイコン 94 # 描画 95 win.mainloop()

読み込んだ動画ファイルをffprobeを使って、ファイルの情報を取得しMessageListに表示したい。

def get_mediainfo(f_path_list): # 変数を定義する targetfile = f_path_list # コマンドを定義して、変数を挿入する cmd = 'ffprobe -i {}'.format(targetfile) # コマンドを実行する result = subprocess.run(cmd, shell=True) msgList.insert(tk.END, result)

def select_file():内のf_path_list(ファイルパス)をdef get_mediainfoで参照したいと思っていますが、ファイルを読み込んでもffproveが実行されず悩んでいます。

**追記**

import tkinter as tk import tkinter.filedialog as tkfd import subprocess # グローバル変数 acv_path = "" f_path_list = [] ### この下に関数を書く ### def select_file(): global f_cont, f_path_list f_conf = [('MOV file (*.mov)', '*mov'), ('AVI file (*.avi)', '*.avi'),('MP4 file (*.mp4)', '*.mp4')] paths = tkfd.askopenfiles(filetypes=f_conf) for f in paths: f_path_list.append(f.name) # Insert to Message List msgList.insert(tk.END, f_path_list) # Insert Input Path TextBox inpFld.insert(tk.END, f_path_list) def get_mediainfo(): # 変数を定義する targetfile = f_path_list # コマンドを定義して、変数を挿入する cmd = 'ffprobe -i {}'.format(targetfile) # コマンドを実行する result = subprocess.run(cmd, shell=True) msgList.insert(tk.END, result)

実行ボタンを作成し、情報取得を実行すると
CompletedProcess(args="ffprobe -i ['/Python/IMG_1138.MOV']", returncode=1)
というエラーが出ました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/09/20 13:48

詳しく説明して頂きありがとうございます。少しずつ一つずつ試させていただきます。
guest

回答2

0

ベストアンサー

CompletedProcess(args="ffprobe -i ['/Python/IMG_1138.MOV']", returncode=1) というエラーが出ました。

ファイルのpathの部分がリストになって、subprocessに渡すとき、
Pythonのリストを文字列として解釈した値として渡されています。
実行されているコマンドは

python

1subprocess.run("ffprobe -i ['/Python/IMG_1138.MOV']", shell=True)

/path/to/file ではなく ['/path/to/file'] の様な文字列になっている為、
コマンド自体が正常に実行されてません。

尚、正常終了した場合は、returncode が 0 になります。


他の問題点(重要

問題点: subprocess.run の扱いにセキュリティ上、重大な問題があります
対策: 引数の実行するコマンドを、ファイル名と引数のリストにすることで
subprocessライブラリ側で適切に対応してくれます。

subprocess.run("ffprobe -i /path/to/file", shell=True)
subprocess.run(["ffprobe", "-i", "/path/to/file"])

"/path/to/file" の部分は実際のファイルのパスを指定します。

subprocessのドキュメントに書かれているのですが、

shell=True を使う前に セキュリティで考慮すべき点 を読んでください。

ファイル名のところに任意のコマンドを実行できる問題があります。
これは意図的に入力しなくても、ファイル名を偽装する事で
意図しないコマンドを実行されてしまうという危険性に繋がります。

  • 必要な理由がない限り shell=True は使わない。
  • shell=True を指定する場合は、必ず shlex.quote を使う。
  • よくわからない場合も、shell=True は使わない。

 自分しか使わないし、その様なことはしない、
というだけでは不十分で、必ず対策は必要です。


修正方法

  • まずは、他のコードを一切取り払い

 subprocess.run のコードが正常に動くことを確認しましょう。

  • GUI とは分離して、引数にファイルのpath 戻り値に必要な情報を返す関数を定義します。
  • 次に、GUIから必要な引数を与えて呼び出し、

 戻り値をGUIの任意の場所へ表示します。

  • 途中でエラーになった場合は、関数の引数や戻り値を表示して見て

 期待している値が渡っているかどうか確認します。

以下は同じエラーを再現できる最少のコードです。
これを元に説明します。

python

1import subprocess 2 3if __name__ == "__main__": 4 targetfile = ['/Python/IMG_1138.MOV'] 5 cmd = "ffprobe -i {}".format(targetfile) 6 proc = subprocess.run(cmd, shell=True) 7 print(proc) 8

修正方法は、リストになってる部分を文字列に変更することでエラーは解消できます。
ファイルのPATHは実際のモノに変更してください。

python

1 targetfile = '/Python/IMG_1138.MOV'

但し、上述したshell=Trueを解決するには以下の様にします

python

1 targetfile = '/Python/IMG_1138.MOV' 2 cmd = ["ffprobe", "-i", targetfile] 3 proc = subprocess.run(cmd)

ファイル選択の部分から複数ファイルを対象としてるようですが、
ffprobe コマンドは、複数ファイルを引き数に取れるのでしょうか?

戻り値の型とGUIへの反映方法が一致しないので、Listboxへの表示は
恐らく意図した表示にはならないと思います。
適切な形式で情報を所得し、加工してGUIへ反映という作業が必要になるので、
この辺りも、一つづつ動作を確認しながらコードを組みましょう。

投稿2020/09/20 12:59

teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずコマンドプロンプトからは正常に動くコマンドとして回答します
ffprobe は標準出力ではなく標準エラー出力に出力されます

Pythonのバージョンが判りませんので
subprocessについてより深く(3系,更新版)
を参考に標準エラー出力を取得するようにしてみて下さい。

投稿2020/09/19 10:41

kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/09/19 10:54

ffprobe -i [file path]で実行するとファイルの情報が出力されております。 標準エラー出力が出力されるということは、ffprobeではなくffmpegで情報を取得したほうがいいのでしょうか?
kuma_kuma_

2020/09/19 11:02

いいえ、ffprobeもffmpegも標準エラー出力に出力されます。
退会済みユーザー

退会済みユーザー

2020/09/19 11:20

ffmpegやffprobeを使用して情報取得をする際は、jsonなどに出力するのが主流なのでしょうか? MessageListに情報を表示したいのですができません。 初心者で申し訳ございません。
kuma_kuma_

2020/09/19 12:46

ごめんPythonのMessageListは知らないな... GUI で Treeview表示したいなら判るけど どっちにしてもJSON形式で出力できるなら後々楽だよ ffprobe -v error -i input -show_streams -of json で出力すればよいだけだだから
teamikl

2020/09/20 13:03

エラー自体は出力の得方以前の、コマンド実行に関わるものの様です。 標準エラーに出力されるのは、オプションに何も指定しなかった時のもので -of json 等で得られる情報は標準入力で得られました。 MessageList は、解らないけど。変数 msgList の事かな・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問