ryotayama / hayaemon_ios_issues

4 stars 0 forks source link

spleeterを使用したボーカルキャンセルに対応したい #723

Open ryotayama opened 4 years ago

ryotayama commented 4 years ago

https://twitter.com/ryota_yama/status/1192428113491218432?s=20 さーて、噂の「spleeter」触ってみよーかな!٩( ᐛ )و

MITライセンスらしいので、ハヤえもんに組み込めたらベストだけど、きっとめちゃくちゃハードル高いんだろうなー!

音楽データからボーカル・ドラム・ベースの音を個別に抽出できる「spleeter」

https://twitter.com/origuchi_tou/status/1207065098637807617?s=20

ハヤえもん のボーカルキャンセル機能に #Spleeter を入れて欲しいところ

https://twitter.com/ryota_yama/status/1207447352904019969?s=20 これはかなりやりたい……! まずはiOSアプリでPythonを動かす方法から勉強しなきゃ。 ↓ここらへんが参考になるかも🤔 https://qiita.com/Hiroki_Kawakami/items/830baa5adcce5e483764

https://twitter.com/origuchi_tou/status/1207497939662229504?s=20 この #Spleeter をiOSで初めて実装した「VocalExtractor」というアプリがあるのですが RAM4GBのiPhone11であってもちょくちょくメモリ不足の表示が出たりするので現状のボーカルキャンセル機能と置き換えるのではなくオプションとして実装した方がいいかもしれません

情報ありがとうございます!🙏

ryotayama commented 4 years ago

↓メモ!٩( ᐛ )و

◆deezer/spleeter https://github.com/deezer/spleeter

◆iOSのSwift,Objective-CでPythonを呼び出す https://qiita.com/Hiroki_Kawakami/items/830baa5adcce5e483764

◆pieter/YoutubeDL-iOS(iOSアプリでPythonを動かしている例) https://github.com/pieter/YoutubeDL-iOS

◆Changes To Embedding Python Using Xcode 5.0 https://developer.apple.com/library/archive/technotes/tn2328/_index.html

◆他のアプリケーションへの Python の埋め込み https://docs.python.org/ja/3/extending/embedding.html

ryotayama commented 4 years ago

https://twitter.com/ExtractorVocal/status/1208274533720870912?s=20 VocalExtractorは概ね1GB以下のメモリーで動くようになっています。それでも大きいのですが、これはSpleeterのせいではありません。うまく実装すれば、もっと小さくできます。またPythonをiOSで動かしているのではなく、iOS上のCoreMLに変換して実装しています。横から失礼しました。

https://twitter.com/origuchi_tou/status/1208275775922638849?s=20 Vocal Extractorの作者の方から返信が来たのですが どうやらPythonをCoreMLに変換した上でSpleeterを動作させているようです

おぉ、なるほど…! 有益な情報、ありがとうございます! となると、iOS 11以上が対象になるのかな…。 CoreML自体触った事がないので、引き続き勉強してみます!🙏

ryotayama commented 4 years ago

https://twitter.com/ryota_yama/status/1256173450428739584?s=20 フォローありがとうございます! うぉー、Spleeter対応してるんですね! ぼくもいつかやりたいと思いつつ「CoreML……はにゃ?」というところで止まってますw めちゃくちゃ尊敬します!

フォローありがとうございます Tensorflowもよく分からないまま執念で変換しました口を開けて冷や汗をかいた笑顔 ご興味あれば聞いてください

えぇー、なんて優しいお言葉を……!号泣 もし詰まったら質問しちゃうかもしれません!

ryotayama commented 4 years ago
ryotayama commented 4 years ago

①TensorFlow Liteを使う場合 ・学習モデルを.pb形式にする ・.tflite形式に変換

②CoreMLを使う場合(他アプリでも実績あり) ・学習モデルを.pb形式にする ・.mlmodel形式に変換

ryotayama commented 4 years ago

以下6種類のエフェクトを追加できたら楽しそう。 (ただしリアルタイムでの変換はできず、処理がとても重たそう)

・ボーカル抽出(2stems) ・伴奏抽出(2stems) ・ドラム抽出(4stems) ・ベース抽出(4stems) ・ピアノ抽出(5stems) ・ボーカル/ドラム/ベース/ピアノ除去(5stems)

ryotayama commented 4 years ago

以下のコードを「Python write_graph.py」として動かすことでgraph.pbファイルが出力されることを確認✍️

graph = tf.get_default_graph()

sess = tf.Session()

saver = tf.train.import_meta_graph('model.meta') saver.restore(sess, 'model')

tf.train.write_graph(sess.graph_def, '.', 'graph.pb', as_text=False)

ryotayama commented 4 years ago

以下のコードを「Python freeze_graph.py」として動かすことでfrozen.pbファイルが出力されることを確認✍️ (ただし、指定した"waveform"、"global_step/initial_value"しか書き出されていないため、全ての要素を指定する方法を要調査)

with tf.Session(graph=tf.Graph()) as sess: with gfile.FastGFile("graph.pb", 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) frozen_graph_def = convert_variables_to_constants(sess, graph_def, ["waveform", "global_step/initial_value"]) with tf.gfile.GFile('./frozen.pb', "wb") as f: f.write(frozen_graph_def.SerializeToString())

ryotayama commented 4 years ago

↓このライブラリを使う事で、.pb形式に変換できるっぽい✍️(作成された.pbファイルを.tflite形式や.mlmodel形式に変換できるか要調査)

KBone12 commented 4 years ago

CoreMLに変換しようと奮闘した結果、CoreMLへの変換はひとまず断念したことを報告します。 以下そのCoreMLへの変換に必要な道筋と断念した理由を書いていきます。なお、自分はTensorflow初心者なので勘違いしていたら申し訳ないです。また、spleeterがTensorflowの1.15.2を要求するので、以下Tensorflow 1.15.2環境下での話です。全体のコードはこのGoogle Colaboratoryに記しました。

まず、CoreMLに変換するには既に書かれてあるとおり、frozen graphに変換する必要が有ります。spleeterでは学習済みモデルとしてcheckpointを配布していますが、得られる情報量が多いためspleeter.utils.estimator.create_estimatorにより得られるEstimatorからSavedModelを経由してfrozen graphを作成しました。 このSavedModelを用いて、saved_model_cli show --dir "path/to/exported" --allから必要な出力テンソルの名前が得られるのでそれを元に、 python -m tensorflow.python.tools.freeze_graph --input_saved_model_dir "/path/to/saved_model/dir" --output_graph "frozen.pb" --output_node_names strided_slice_21,strided_slice_23 --saved_model_tags "serve" を実行してfrozen graphを得ます。 しかし、ここでtf-coremlにこのfrozen graphを渡すと、minimum_ios_deployment_target="12"の場合はRetval[x] does not have valueminimum_ios_deployment_target="13"の場合はkeras_learning_phaseに関するエラーが出てしまいます。これらのエラーは(恐らく)学習時と推論時に処理を切り替える機能がCoreMLで上手く再現できない(あるいはその機能がtf-coremlにない)ために生じると考えられるのでtensorflow.tools.graph_transforms.TransformGraph等を用いて処理します。

こうして得られたfrozen graphをtf-coremlに渡すと処理が始まるのですが、minimum_ios_deployment_target="12"の場合はFusedBatchNormV3に非対応であるという旨のエラーが出てしまい、tf-coremlのこのissueより、minimum_ios_deployment_target="13"にする必要があるそうです。しかし、minimum_ios_deployment_target="13"とすると、RFFTが非対応であるという旨のエラーが出ます。調べてみるとそもそもCoreMLにフーリエ変換の機能がないようでした。これを解決するには、

という案しか浮かばず、どちらも相当に大変そうだったので断念しました。 Tensorflow Liteに関してはこれから調べてみます。

KBone12 commented 4 years ago

Tensorflow Liteに関して調べてみた(および実行してみた)ところ、結局Tensorflow LiteでもSwitchRFFTは実装されておらず、tf-coremlと同様にカスタムレイヤーを自分で実装する必要があるようです。tf-coremlの場合と違ってC++で実装してビルドしなければいけない一方で、感覚的には検索でヒットする(特に日本語記事)数はTensorflow Liteの方が多いのであとは好みといった印象です。

sugartarou commented 10 months ago

久しぶりに軽く調べてみたらAndroid/iOS用にライブラリ化して公開してくれてる人が居ました。 FaceOnLiveという会社っぽいですが、↓のリポジトリにライセンス書いてなくて使っていいのかちょっと疑問ですが。。 https://github.com/FaceOnLive/Spleeter-Android-iOS → Androidはaar、iOSはframeworkが入ってたんでそれロードすりゃ動くかと思いきや、  Android版をビルドしてx86エミュレータで動かしてみたら、libttvspleeter.soがないよってエラーでアプリが落ちました。  → もう少しだけ調べてみたらlibttvspleeter.soは実機向けのabiであるarm64-v8aとarmeabi-v7a用のみが用意されていたようで、x86用は存在しないだけでした。なので実機でなら実行できちゃいそうです。   → 手元のRakuten miniの実機でAndroid版の動作確認取れました。    wavファイルを渡したら5つのwavファイルを生成してくれました。    はやえもんとしては、wavへの変換機能を作れば十分使えそうです。    まずはミニマムとしてwavファイルだけ対応してますっていう風に搭載するのもありかと。

sugartarou commented 10 months ago

FaceOnLiveのライブラリは$6000とのこと。 ↓を読んでTFLite版を自分でビルドしてみる? https://github.com/deezer/spleeter/issues/518https://github.com/jinay1991/spleeter  なんかここにもうめっちゃ詳しく手順書いてあるからやってみる。  https://github.com/jinay1991/spleeter/releases/tag/2.3.0  → C++版だったのでAndroid Studioでndkビルドすればnativeライブラリ作れそう?   それか↓を使ってtflite用にモデル変換するべきか?   https://github.com/tinoucas/spleeter-tflite-convert

sugartarou commented 8 months ago

tflite形式のモデルはここにアップされてた。 https://github.com/jinay1991/spleeter/releases/tag/v2.3

モデルはabiに依存していないのでandroidでもこれはそのまま使える。 wavファイル渡したらvectorに変換してmodel利用してくれるC++ソースも使いたいのでlibspleeter.aをビルドしたいが、 用意されているbazelのビルドルールだとx86形式のものしか生成されなさそう。

libspleeter.aのためのC++ソースすべてのCmakeLists.txtをbazelのビルドルール見ながら書くのはなかなかに大変そうなので、 既存のbazelのビルドルールを改造してandroidのabi向けのビルドもしてくれるようにして各abi用のlibspleeter.aを生成するところを目標にする。

sugartarou commented 8 months ago

まずは各種thirdpartyのライブラリたちをandroid向けのabiでクロスコンパイルするルールを書くのを第一目標にする。

Bazelを勉強してBazelでやる or Android NDKを直に使う

sugartarou commented 8 months ago

bazel build -c opt --config=android_arm32 \ --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \ --define tflite_with_xnnpack=true \ //tensorflow/lite:libtensorflowlite.so

bazel build -c opt --config=android_x86_64 \ --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \ --define tflite_with_xnnpack=true \ //tensorflow/lite:libtensorflowlite.so

bazel build -c opt --config=android_x86_32 \ --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \ --define tflite_with_xnnpack=true \ //tensorflow/lite:libtensorflowlite.so

sugartarou commented 8 months ago

一応Javaで直にtfliteモデルを使う方法もトライしたけど、kboneくんの言ってた通りRFFTなんてOperationないよってエラーになった。

java.lang.IllegalArgumentException: Internal error: Failed to run on the given Interpreter: Regular TensorFlow ops are not supported by this interpreter. Make sure you apply/link the Flex delegate before inference.
Node number 39 (FlexRFFT) failed to prepare.
sugartarou commented 8 months ago

spleeterのC++ライブラリ部分はビルド通せた。 あとはJNI実装して動かせれば完璧。。

sugartarou commented 8 months ago

JNI実装して動かしたらなんとRFFTのエラー。 やっぱりダメなのは変わらんか。。

2024-03-20 17:08:14.237 28656-28656 tflite                  com.example.spleetertest             E  Attempting to use a delegate that only supports static-sized tensors with a graph that has dynamic-sized tensors.
2024-03-20 17:08:14.325 28656-28656 tflite                  com.example.spleetertest             E  Regular TensorFlow ops are not supported by this interpreter. Make sure you apply/link the Flex delegate before inference.
2024-03-20 17:08:14.325 28656-28656 tflite                  com.example.spleetertest             E  Node number 39 (FlexRFFT) failed to prepare.
sugartarou commented 8 months ago

tfliteモデルの可視化は以下が超お手軽だった。 https://netron.app/

sugartarou commented 8 months ago

Flexについて調べたらJava版なら以下で有効化できることが分かってやってみたらFlexRFFTのエラーは無事突破できた!

        Interpreter.Options options = new Interpreter.Options();
        FlexDelegate flexDelegate = new FlexDelegate();
        options.addDelegate(flexDelegate);

というわけで結局頑張ってビルドしたC++版は使っていない…

Flex delegateについてはこの記事のIntroがとっつき易かった https://qiita.com/PINTO/items/b2af9aec3a8915457dd8

C++版でflex delegateを有効化するにはnnapi無効化しつつtflitdの依存にflex追加しつつビルド時のコマンドでdefine2つ追加でいけそう? https://qiita.com/PINTO/items/b2af9aec3a8915457dd8

sugartarou commented 8 months ago

5stemsの入出力情報 コピー元は5stemsのREADME.md

input tensor_names index
waveform waveform 0
stems tensor_names index
vocal strided_slice_18 4
drums strided_slice_38 1
bass strided_slice_48 0
piano strided_slice_28 3
accompaniment strided_slice_58 2

accompaniment・・・伴奏

sugartarou commented 8 months ago

wavのin/out部分の自作が辛かったのでビルドが通ってるC++版を使ってみた。 動きはするが、出力されるファイルはヘッダのみで空だった。

wsl上でC++版は動かせるようにしてあるので、以下を上から確認していく。

案の定デフォルトはBIG_ENDIANだったのでとても怪しい。 ⇒LITTLE_ENDIANにしたが、まだダメ。とりあえずLITTLE_ENDIANが正しいのは確定なので修正はしたままにする。

単純なサイズミスが3か所くらいにあっただけでした!!無事動いた!

sugartarou commented 8 months ago

iOSにも載っけるなら結局C++ライブラリを頑張った方が良い気がする。 ただひとまずは理解のためにもJavaでしっかり音源分離動かすところまではいきたい。

https://zenn.dev/nnabeyang/articles/3c296e3d38b2f016e0f2

クロスPF頑張らないならiOS版でもちゃんとflex delegate有効にする方法はあった https://www.tensorflow.org/lite/guide/ops_select?hl=ja#ios https://qiita.com/mbotsu/items/6096663376c22c23ef37

x86_64シミュレーターでセレクト TF 演算を使用する必要がある場合は、セレクト演算フレームワークを自分で構築できます 詳細については、Bazel を使用する、および、Xcode のセクションを参照してください。

とのことなのでエミュレータは自分でライブラリのビルドから必要

sugartarou commented 6 months ago

Flex delegateを使うのでSelectTfOpsも必要なはず.

Podfile

  pod 'TensorFlowLiteSwift'
  pod 'TensorFlowLiteSelectTfOps'

先に調べた感じだとビルド時に↓でハマりそう https://github.com/tensorflow/tensorflow/issues/56255

sugartarou commented 6 months ago

こんな記事も見つけた 同じくハマる気がするのでメモ https://qiita.com/mbotsu/items/6096663376c22c23ef37

sugartarou commented 3 months ago

知らぬ間にandroidの方はtfliteがGMSサービスとして入ってたらしい。 これ使えばアプリ側でtfliteライブラリを持たなくていいからapkサイズちっさく出来るよって話。ただこれminimumSDKverとか書いてないから使えない端末がどんだけあるのか不明。 https://www.tensorflow.org/lite/android/play_services

https://www.tensorflow.org/lite/android/java#gpu_with_interpreter_apis