🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
PyInstaller

PyInstallerは、Pythonのスクリプトを一括でWindowsなどで動く実行可能ファイルに変換できるツールです。このツールを用いることで自作のPythonプログラムを別で使用する場合でもPythonをインストールする必要がありません。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

FFmpeg

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

Q&A

解決済

2回答

3337閲覧

PyIlnstallerによって単一実行ファイル化したアプリケーションでpydubを利用したい

tomtakeru

総合スコア4

PyInstaller

PyInstallerは、Pythonのスクリプトを一括でWindowsなどで動く実行可能ファイルに変換できるツールです。このツールを用いることで自作のPythonプログラムを別で使用する場合でもPythonをインストールする必要がありません。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

FFmpeg

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

0グッド

0クリップ

投稿2020/12/06 06:40

編集2020/12/09 02:21

前提・実現したいこと

TkInterを用いてGUIを表示するPythonファイル(myapp.py)をPyInstallerによって単一実行ファイル(myapp.app)にしました。そのmyapp.pyでPydubを利用しようとしましたが、エラーがログに出力されました。

発生している問題・エラーメッセージ

[Error 2]No such file or directory: 'ffprobe': 'ffprobe'

myapp.py内でのPydubのコード

Python

1segument = pydub.AudioSegment.from_file(file_path)

試したこと①

myapp.py内でffmpegやffprobeをsubprocessモジュールを用いて実行しているので、PyInstallerでこれらのファイルをmyapp.appにバンドルしています。そのためmyapp.app/Contents/MacOS/内にffmpegやffprobeのバイナリファイルがあります。そこでこれらのファイルパスをPydubに教えることで解消できるのではないかと考えました。

PudubのGitHub
pydubをgitで確認すると、以下のような記述がありました。

pydub/audio_segment.py

class AudioSegment(object): # --略-- converter = get_encoder_name() # either ffmpeg or avconv # --略--

pydub/utils.py

# --略-- def get_encoder_name(): """ Return enconder default application for system, either avconv or ffmpeg """ if which("avconv"): return "avconv" elif which("ffmpeg"): return "ffmpeg" else: # should raise exception warn("Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work", RuntimeWarning) return "ffmpeg" # --略--

そこでpydub.AudioSegmentクラスのconverterを設定してあげれば良いと考え、先述したコードの前に次のコードを追加しましたが、同じエラーが表示され解決できませんでした。(APP_PATHはmyapp.appのパスの文字列)

pydub.AudioSegment.converter = APP_PATH + '/Contents/MacOS/ffmpeg' # 追加 segument = pydub.AudioSegment.from_file(file_path)

また、pydub/audio_segment.pyのAudioSegmentクラス内に次のようなメソッドがありましたが、使い方がわかりませんでした。

pydub/audio_segment.py

class AudioSegment(object): #--略-- # TODO: remove in 1.0 release # maintain backwards compatibility for ffmpeg attr (now called converter) @classproperty def ffmpeg(cls): return cls.converter @ffmpeg.setter def ffmpeg(cls, val): cls.converter = val # --略--

試したこと②

sys.path.appendを用いてpydubにffmpegやffprobeのパスを教えようとしましたが、同じエラーが表示され、解決できませんでした。

sys.path.append(APP_PATH + '/Contents/MacOS/ffmpeg') sys.path.append(APP_PATH + '/Contents/MacOS/ffprobe')

環境

MacOS 10.15.7

Python 3.6
PyInstaller 3.6
FFmpeg 4.3.1
Pydub 0.24.1

(追記)回答してくださった方のアドバイスを聞いて試したこと

確認事項

  1. tkinterなしで問題は再現しますか
  2. pyinstallerを使わない場合に問題が再現するのか
  3. converterのファイルパスの確認

1・2の確認事項

  • tkinterなしpyinstallerなし→正常
  • tkinterありpyinstallerなし→正常
  • tkinterなしpyinstallerあり→正常?
  • tkinterありpyinstallerあり→今回のエラー

このようになったのですが、tkinterなしpyinstallerありでの確認に関しては、実際の状況と全く同じ状況を作れませんでした。このエラーが出る前に単一実行ファイルを作る際のエラーが出ていました。その解決に用いた方法がtkinterなしだとエラーが出ます。

そのため次のコマンドのように実行した結果、正常に動きました。

tkinterなしpyinstallerありでのpyinstallerのコマンドとその実行

console

1pyinstaller --windowed audio_play_test.py 2open dist/audio_play_test/audio/audio_play_test

audio_play_test.py

python

1import sounddevice 2import pydub 3import time 4import numpy 5 6video_path = "/---/sample.mp4" 7segment = pydub.AudioSegment.from_file(video_path) 8samples = numpy.array(segment.get_array_of_samples().tolist(),dtype="int16").reshape(-1,segment.channels) 9sounddevice.play(samples, segment.frame_rate) 10time.sleep(30)

ここまで試した時点でかなり時間がたってしまい、締め切りも迫っていることから根本的な解決を諦め、違う方法をとることにしました。もともと動画ファイルの音声を再生することが目的であったため、subprocessでffmpegを実行し、waveファイルを作成してsinmpleaudioで再生することで実装しました。解答していただいた方には申し訳ないのですが、また時間のある時にこの問題の解決に取り組みたいと思います。

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

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

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

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

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

guest

回答2

0

ベストアンサー

pyinstaller は使ってませんが、同じ問題を再現出来たので対処法

おそらく PATH 指定の問題なのでロギングを有効にして
subprocess に渡されるコマンドの PATH が何処から渡されるかを追えば解消しそうです。


問題点:

python

1pydub.AudioSegment.converter = APP_PATH + '/Contents/MacOS/ffmpeg'

は ffmpeg のPATH指定ですがエラーは

[Error 2]No such file or directory: 'ffprobe': 'ffprobe'

なので、ffprobe のPATH指定が必用なようでした。
但し、pydub ライブラリ側には設定メソッドは用意されてません。

解決策: (どちらか)

  • 環境変数を設定する
  • コマンドを探索するメソッドに patch を当てる

pydub の import 前に環境変数を設定

python

1import os 2os.environ["PATH"] += r";C:\opt\ffmpeg-3.4.1\bin" 3 4import pydub

コマンドを探索する関数を上書きする
import pydub の前に変更します。

python

1import pydub.utils 2pydub.utils.get_prober_name = lambda: r"C:\opt\ffmpeg-3.4.1\bin\ffprobe.exe" 3pydub.utils.get_encoder_name = lambda: r"C:\opt\ffmpeg-3.4.1\bin\ffmpeg.exe" 4 5import pydub

こちらの方法では、
一応、エラーは解消しましたが、subprocess に渡されるコマンドが若干変わってきそうです。
ロギングを有効にして要確認。

(コンソール出力が有効だと) warning が出るかもしれませんが、実行には支障ないはずです。
警告はpython側で抑制したり、pyinstaller 利用時はコンソール出力無効にできます。


※ pyinstaller や tkinter 利用では試してませんが、同じエラーとその解消は再現出来ました。
※ PATH設定は環境に合わせて変更してください。

投稿2020/12/09 03:12

編集2020/12/09 03:33
teamikl

総合スコア8729

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

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

0

確認項目

  • tkinter なしで問題は再現しますか

 掲載するコードは、問題が発生する&最小限のものをお願いします。

  • pyinstaller を使わない場合に問題が再現するか

 pyinstaller 利用時のみの場合は、pyinstaller の実行オプション情報。

  • converter のファイルPATHの確認

 実際にコードで確認してみてください。

python

1pydub.AudioSegment.converter = APP_PATH + '/Contents/MacOS/ffmpeg' 2 3# 実行ファイルが存在するかどうか確認 4# ※ assert 文はデバッグモード時のみ実行されます 5import os 6assert os.path.isfile(pydub.AudioSegment.converter)

試したことについて

  • sys.path は Python のライブラリのPATHなので、今回のケースでは不要です

 設定するとすれば環境変数の os.environ["PATH"]

  • AudioSegmentの ffmpeg 属性は

TODO: remove in 1.0 release
maintain backwards compatibility for ffmpeg attr (now called converter)

とあるので、後方互換のために残された、廃止される予定の属性です。


他に試せること

ロギングを有効にすることで、subprocess呼び出しのコマンドを確認できます。
(注意: pyinstaller を利用の場合は、コンソール出力を有効にすること)

python

1import logging 2logging.basicConfig(level=logging.DEBUG)

投稿2020/12/07 00:43

teamikl

総合スコア8729

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

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

tomtakeru

2020/12/09 02:22

回答していただき、ありがとうございます。その内容について追記させていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問