前回アップした音声+SRT 同時再生・テキスト編集アプリ『字幕極楽丸』ですが、NumPy を不使用にすることで macOS アプリとしてビルドできるようになりました。ただ、過去の記事紹介したテンプレートを使ってコピーライト等を追加するビルド方法だとエラーで失敗します。Audio コントロールを使っているとうまくいかない様です。その後試行錯誤の末、成功ビルドパターンがわかったのでご紹介します。
念のため環境はこちら
- Hardware: Mac Studio M2 Max 12-core CPU 30-core GPU 32GB RAM
- OS: macOS Sonoma 14.3.1
- Xcode: 15.3
- Python 3.11.7
- Flet: 0.21.2
- Flutter 3.19.3
- Dart: 3.3.1
- CocoaPods: 1.15.2
まずは NumPy を使わないように変更
以前公開したコードでは、音声の再生位置に応じてスクロールさせるため、該当するテキスト位置を算出する事だけに NumPy を使用していました。具体的には、以下の 520 行目になります。これを 522行目に変更することで、NumPy の import を不要にしました (GitHub 反映済み)。3行目のインポート部分もコメントアウト(# import numpy as np
) もしくは削除します。これでとりあえず flet build macos --include-packages flet_audio
でアプリのビルドが確認できました。
# Called when slider position is changed and scroll to subtitle with the nearest end_time.
async def scroll_to(self, e):
end_time = [item[2] for item in self.subtitles]
# Numpy is only used below:
#index = np.argmin(np.abs(np.array(end_time) - e))
# Below works without using Numpy:
index = min(range(len(end_time)), key=lambda i: abs(end_time[i]-e))
key=str(self.subtitles[index][0])
self.subs_view.scroll_to(key=key, duration =1000)
self.update()
この変更による体感できるような遅延は発生していません。ガッツリ NumPy を使ったアプリをビルドしたい方は、Flet 自体の解決を待つか (Issue 報告済み)、flet pack main.py
を使うかですかね (非推奨っぽいですけど)。
単純なビルドは成功、しかしテンプレートが使えない
次にコピーライト表記などを行った上でビルドしようと、テンプレートのクローンをしてファイルを編集して、でビルドを実施したところ、以下のエラーで失敗となりました。flet_audio
のバージョン?依存関係?か何かの問題のようです。複数のバージョンが入り乱れて非常に難解です。
% flet build macos --build-version "1.0.1" --template flet-build-template --include-packag
es flet_audio
Creating Flutter bootstrap project...OK
Customizing app icons and splash images...OK
Generating app icons...Because flet_audio <0.20.1 depends on flet ^0.20.0 and flet_audio >=0.20.1 <0.20.2 depends on flet ^0.20.1, flet_audio <0.20.2 requires flet ^0.20.0.
And because flet_audio ^0.20.2 depends on flet ^0.20.2 and flet_audio >=0.21.0 <0.21.1 depends on flet ^0.21.0, flet_audio <0.21.1 requires flet ^0.20.0 or
^0.21.0.
And because flet_audio >=0.21.1 <0.21.2 depends on flet ^0.21.1 and flet_audio >=0.21.2 depends on flet ^0.21.2, every version of flet_audio requires flet
^0.20.0 or >=0.21.0 <0.22.0.
So, because fletaudioplayback depends on both flet ^0.19.0 and flet_audio any, version solving failed.
You can try the following suggestion to make the pubspec resolve:
* Try upgrading your constraint on flet: dart pub add flet:^0.21.2
Error building Flet app - see the log of failed command above.
Flet のバージョンを上げたり下げたり、Flutter やその他環境面でのバージョンを最新にしたりなどいろいろと試しましたが、最終的にはテンプレートファイルを --template
で読み込むとエラーになることがわかりました。
【解決方法】テンプレートをやめてオプションを使う
どうやら Audio
コントロールを使う場合はテンプレートを読み込めない?みたいなので、オプションを使用してコピーライト表記等を組み込むことで解決しました。スマートじゃ無いですが、いつかは解決すると思うので仕方なし。実際に使ったコマンドとオプションは以下となります。長いです。
flet build macos --build-version "1.0.1" --copyright "Copyright (c) 2024 Peddals.com" --product "地獄極楽丸" --include-packages flet_audio
軽く説明すると、--product
に文字列を渡すとアプリ名にできます (指定しない場合は、親フォルダ名がアプリ名になります)。--include-packages flet_audio
は Audio コントロールを使用する場合に必須です。あとは見たまんまです。使えるオプションのは確認こちらでどうぞ。
ちなみに、assets フォルダ以外のファイル・フォルダはビルドに関係が無いと思っていましたが、main.py と同じフォルダにあった音声ファイルなども取り込まれたようで、最初にビルドした時は非常に時間がかかり、完成したアプリも 1.7GB ほどありました (削除後は 260MB 程度)。なので、ビルドの際は専用のフォルダを作ってそこに main.py とその他必要なファイルのみ格納した状態にするのが望ましいです。
アプリとして実行した後の動き
build/macos
フォルダ内にビルドされたアプリをダブルクリックで開くと、初めての場合ボクの環境では画面が描画されるまでしばらく待たされました。よく見てみるとアプリ自体の問題というより、アンチウィルスソフトが CPU を 300% ほど使って懸命にスキャンをしていたのがその理由のようです。安全性が確認された後は一瞬で開くようになりました。音声ファイルの再生中 の CPU 使用率は、おおよそ 30~40%というところです (なぜか起動時のスプラッシュが無いので、何か問題があるのかもしれません。影響ないので深追いしてないですけど)。
おまけ (Bing Copilot にコードを直してもらったやり方)
冒頭で書いた NumPy 必須のコードを書き換えた、というところですが、実は自力では無く Bing の Copilot 無料版に手伝ってもらいました。字幕極楽丸を仕上げるまでにも Python のロジック部分に何度も手伝ってもらったのですが、やっとお願いの仕方に慣れてきた感じです。具体的な情報を伝えて、何度かやりとりすることを想定して挑むと、チャット上限の 5回でも望む結果が得られやすいですね。参考まで、実際のやりとりがこちらになります。
自分
python で numpy を使っているコードがあるのですが、numpy を使わないで実装できるよう手伝ってもらえますか?
Copilot
もちろん、お手伝いします。numpyを使っているPythonのコードを教えていただけますか?そのコードを見て、numpyを使わないバージョンを提案します。よろしければ、コードを共有してください。よろしくお願いします。🙂
自分
end_time がリストで、小さい値から大きな値までの整数を持っています。e は整数です。import numpy as np でインポートしています。対象のコードはこちらです: index = np.argmin(np.abs(np.array(end_time) – e))
Copilot
numpyを使わないで同じ処理を行うPythonのコードは以下の通りです:
index = min(range(len(end_time)), key=lambda i: abs(end_time[i]-e))
AI で生成されたコード。ご確認のうえ、慎重にご使用ください。FAQ で詳細を確認。
このコードは、end_timeリストの各要素とeとの絶対値の差が最小となるインデックスを見つけます。これは、元のnumpyのコードと同じ動作をします。ただし、numpyを使わないため、大きなリストに対しては実行速度が遅くなる可能性があります。ご了承ください。🙂
Image by Stable Diffusion
まあいいんですが、当初 gray hair (と glasses もかな?) に引っ張られて、恰幅の良いおじさんばかりが生成されました。jumping も無視されがち。Exclude に不要な要素をいくつか加えたらそれっぽくなりました。人物が遠いと顔面が破綻しがちで、ステップを増やしてもあんまり関係ないですね。
Date:
2024年3月31日 1:55:34
Model:
realisticVision-v20_split-einsum
Size:
512 x 512
Include in Image:
realistic, masterpiece, best quality, retro future, happy young guy partially gray hair with glasses jumping with big simle in front of a beautiful building
Exclude from Image:
frame, old, fat, suit
Seed:
1847693693
Steps:
50
Guidance Scale:
20.0
Scheduler:
DPM-Solver++
ML Compute Unit:
CPU & Neural Engine