VOICEVOX / voicevox_core

無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXのコア
https://voicevox.hiroshiba.jp/
MIT License
871 stars 117 forks source link

iOS向けXCFrameworkをXcodeに追加する方法がわからない #785

Open AsanoGenki opened 6 months ago

AsanoGenki commented 6 months ago

質問の内容

https://github.com/VOICEVOX/voicevox_core/releases/tag/0.15.0-preview.6 上記のリンクからvoicevox_core-ios-xcframework-cpu-0.15.0-preview.6.zipをダウンロードしたのちに、解凍したvoicevox_core.xcframeworkを下の写真のようにXcodeのプロジェクトに入れたのですが、

スクリーンショット 2024-04-30 午後9 26 34

次のようなエラーが発生し、ビルドできません。

スクリーンショット 2024-04-30 午後9 31 20

xcframeworkの導入方法などを探してみてもよくわかりませんでした。

初心者すぎる質問なのは重々承知なのですが、分かる方がいたら教えていただきたいです🙇‍♂️

また、voicevoxをSwiftを使ってiOSで実装する方法を詳しく記しているところがなかったため、もしサンプルなどがあれば教えていただきたいです。もしなければ、具体的な導入方法を教えていただければ幸いです。

現状、下記のようなサンプルがあるのですが、機能しない、もしくは機能させる方法がわかりません。 https://github.com/fuziki/voicevox_core.swift

よろしくお願いします。

VOICEVOXのバージョン

0.15.0

OSの種類/ディストリ/バージョン

その他

AsanoGenki commented 6 months ago

https://github.com/VOICEVOX/onnxruntime-builder/releases 上記のリンクからダウンロードしたonnxruntime-ios-xcframework-1.14.1.zipを解凍したonnxruntime.xcframeworkをXcodeのプロジェクトのTargetのGeneralのFrameworks, Libraries, and Embedded Contentに追加しても、以下のようなエラーが出ます。

dyld[67762]: Library not loaded: @rpath/libonnxruntime.1.14.0.dylib Referenced from: <AF52887A-5ECC-36FF-AC51-C85D47229254> /private/var/containers/Bundle/Application/1B8C2E9E-1084-45F9-BD65-F31C6DAE6242/VoiceVoxSample2.app/Frameworks/libvoicevox_core.dylib Reason: tried: '/usr/lib/system/introspection/libonnxruntime.1.14.0.dylib' (no such file, not in dyld cache), '/private/var/containers/Bundle/Application/1B8C2E9E-1084-45F9-BD65-F31C6DAE6242/VoiceVoxSample2.app/Frameworks/libonnxruntime.1.14.0.dylib' (no such file), '/private/var/containers/Bundle/Application/1B8C2E9E-1084-45F9-BD65-F31C6DAE6242/VoiceVoxSample2.app/Frameworks/libonnxruntime.1.14.0.dylib' (no such file), '/private/var/containers/Bundle/Application/1B8C2E9E-1084-45F9-BD65-F31C6DAE6242/VoiceVoxSample2.app/Frameworks/libonnxruntime.1.14.0.dylib' (no such file), '/usr/local/lib/libonnxruntime.1.14.0.dylib' (no such file), '/usr/lib/libonnxruntime.1.14.0.dylib' (no such file, not in dyld cache)

スクリーンショット 2024-05-01 午前11 43 14

アプリケーションが必要なライブラリであるlibonnxruntime.1.14.0.dylibが見つからないことを示しているようなのですが、解決方法がわかりません。

参照したページは以下のものです https://github.com/VOICEVOX/voicevox_core/issues/715

onnxruntime.xcframeworkもしくはvoicevox_core.xcframeworkのバージョンが違っていたり、xcframeworkを取り込む際に設定が必要等ありましたら教えていただきたいです。

忙しいところ申し訳ないのですが、よろしくお願いします🙇‍♂️

nekomimimi commented 6 months ago

こんにちは 推測ですがonnxruntimeを1.14.0に変更すればとりあえず起動できる気がします。

参考までにうちで動作した設定とバージョンは以下です。

スクリーンショット 2024-05-03 8 14 34

vocevox_core 0.15.0-preview.16 https://github.com/VOICEVOX/voicevox_core/releases/tag/0.15.0-preview.16 (試してないので推測ですが、0.15.0-preview.6のままで通ると思います。)

onnxruntime 1.14.0 https://github.com/VOICEVOX/onnxruntime-builder/releases/tag/1.14.0

なお、App Storeへの提出には https://github.com/VOICEVOX/voicevox_core/issues/715 の反映がvoicevox_coreに必要で、VOICEVOX CORE 0.16(?)のrelease待ちの認識です。 (確認したところonixruntime側は1.16.3 previewから反映済みでした。)

AsanoGenki commented 6 months ago

ご回答ありがとうございます!

onnxruntime-ios-xcframework-1.14.1では機能しないんですね、

onnxruntime 1.14.0を利用する必要があることは分かったのですが、以下の要素を使って、xcframeworkを作成する具体的な方法がわかりません。 https://github.com/VOICEVOX/onnxruntime-builder/releases/tag/1.14.0

下記のやり方をしようと奮闘してみたのですが、xcframeworkの知見が全くなく、どのように進めていけばいいのかがわかりません。 ネットで調べてみても、わかりませんでした。 https://github.com/VOICEVOX/voicevox_core/issues/715#issuecomment-1871324130 https://github.com/VOICEVOX/voicevox_core/issues/477#issue-1686193852

わがままなのは承知なのですが、onnxruntime 1.14.0.xcframeworkを生成する方法を教えていただけないでしょうか?

忙しいところ申し訳ないのですが、よろしくお願いします🙇‍♂️

nekomimimi commented 6 months ago

なるほど。問題は1.14.0のxcframeworkがないことですね。 おすすめとしては対応したリリースを待つこととなります。

それを待てない場合のやり方を簡単に説明すると以下です。

基本的なやり方としては https://github.com/VOICEVOX/voicevox_core/issues/715#issuecomment-1871324130 にまとまってますので参考にはなると思います。

今回は、onnixruntimeのほうは1.14.1をそのままにvoicevox coreの方を整えるのが方針が楽な気がします。

詳細に書くのは時間的に無理なので簡単にヒントを書くと、

otool -L libvoicevox_core.dylib とコマンドを打つと

/yoru_folder/libvoicevox_core.dylib:
    @rpath/libvoicevox_core.dylib (compatibility version 0.0.0, current version 0.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1953.255.0)
    @rpath/libonnxruntime.1.14.0.dylib (compatibility version 1.14.0, current version 1.14.0)
    /System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 60420.60.20)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1300.36.0)
    /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1953.255.0)

などと利用するライブラリの位置が表示されます。 これを変更してパスを見つかるようにすれば動作すると思います。

そこで、install_name_toolのコマンドで@rpath/libonnxruntime.1.14.0.dylibを@rpath/libonnxruntime.1.14.1.dylibに変更して、見つかるようにします。 これをios-arm64とios-arm64_x86_64-simulatorの両方のdylibにします。

上記で動作すると思いますが、ストアーへのリリース時には加えてcoreとonnxの両方がxcframework内のframework以下にdylibを配置され、それにより@rpath/framework/libonnxruntime.1.14.1.dylibなどが見つかることが必要になります。

(修正せずに動作だけはできた朧げな記憶があるのだけど、今、確認したらみつからなかった...)

AsanoGenki commented 6 months ago

お忙しい中、詳細な回答ありがとうございます!

教えていただいた通りに行ったところ、 Library not loaded: @rpath/libonnxruntime.1.14.0.dylibというエラーは解消することができました。 本当にありがとうございます🙇‍♂️🙇‍♂️

もしよろしければ、swiftを使ったvoicevoxでテキストを読み上げる処理を簡単に教えていただけないでしょうか? 処理を行うためのサンプルコードのようなものが探しても見つからない状況でして、、 もし面倒でしたら、参考ドキュメントのようなリンクを教えていただけたら幸いです。

以下のリンクを参考に作成しているのですが、 https://github.com/fuziki/voicevox_core.swift

以下のエラーが出ます。 '/private/var/containers/Bundle/Application/406A…840/VoiceVoxSample2.app/modelsが読めませんでした: Not a directory (os error 20)', /Users/runner/work/voicevox_core/voicevox_core/crates/voicevox_core/src/voice_model.rs:100:33 note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

現在はvvmファイルとしてmodelsとopen_jtalk_dic_utf_8-1をプロジェクトに入れている状況です。

ほんとに質問ばかりで申し訳ないです。

よろしくお願いします

nekomimimi commented 6 months ago

'/private/var/containers/Bundle/Application/406A…840/VoiceVoxSample2.app/modelsが読めませんでした: ですね。 Swiftサンプルは持ってないのですが気になる点など。

1.modelありますか? 「現在はvvmファイルとしてmodels」という表現が気になりました。 modelのファイルは拡張子がvvmとなります。

https://github.com/VOICEVOX/voicevox_core のページの(該当のバージョンの?)環境構築とサンプル実行をしてみるとファイルが見つかると思います。 (もし、他の環境で喋らせたことがなければしてみるとswiftで作成する参考になると思います。)

※今回は違いますが自分でdylibをコンパイルした場合は https://github.com/VOICEVOX/voicevox_core/tree/main/model これを使います。

  1. vvmが取得できてる場合、ファイルを読んでいますか?

modelsを読み込もうとしているのが気になりました。 読み込むのは0.vvmなどではないでしょうか?

3.vvmファイルの位置 もし、読み込んでいるのが.vvmの場合、そのファイルの位置はアプリの中のmodelsフォルダーの中なのか、それともルートに置いてあるのか気になりました。 xcodeのプロジェクトのファイルの一覧にある/Productsフォルダーの中にビルドしたiPAファイルがあるので、右クリックで内容を表示するとアプリの中に入っていれば.vvmファイルが見つかると思います。 (iPAファイルはzipなので拡張子をzipに変えて展開すれば中身見れます。)

AsanoGenki commented 6 months ago

詳細な回答ありがとうございます🙇‍♂️🙇‍♂️

modelsは2.vvmをrenameしたものです、わかりづらくてすいません。(以下、modelsを2.vvmに変更します)

2.vvmとをopen_jtalk_dic_utf_8-1.11以下の画像のようにプロジェクトに配置し、 (2.vvmはhttps://github.com/VOICEVOX/voicevox_fat_resource、 open_jtalk_dic_utf_8-1.11はhttps://open-jtalk.sourceforge.net/ からダウンロードしたものになります。)

スクリーンショット 2024-05-03 午後8 42 44

以下のように、上記2つのファイルをプロジェクト内で使用しています。

class VoicevoxCoreService: VoicevoxCoreServiceProtocol {
    let synthesizer: Synthesizer
    init() {
        print("version: \(VoicevoxCoreSwift.version)")

        // OpenJtalkRc
        let dictURL = Bundle.main.resourceURL!
            .appendingPathComponent("open_jtalk_dic_utf_8-1.11")
        let ojrc = OpenJtalkRc(openJtalkDic: dictURL)

        // UserDict
        let dict = UserDict()
        let world = UserDictWord(surface: "hoge", pronunciation: "フガ")
        world.type = .commonNoun
        world.priority = 10
        let uuid = dict.add(word: world)
        print("uuid: \(uuid)")
        ojrc.use(userDict: dict)

        // Set Model Root
        let modelURL = Bundle.main.resourceURL!
            .appendingPathComponent("2.vvm")
        VoicevoxCoreSwift.set(modelsRoot: modelURL)

        // Synthesizer
        var initialize_options: VoicevoxInitializeOptions = voicevox_make_default_initialize_options()
        initialize_options.load_all_models = true
        synthesizer = Synthesizer(openJtalk: ojrc, options: initialize_options)
    }

    func createAudioQuery(text: String) -> AudioQuery {
        synthesizer.audioQuery(text: text, styleId: 1, options: VoicevoxAudioQueryOptions(kana: false))
    }

    func synthesis(audioQuery: AudioQuery) -> Data {
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase
        let wav = synthesizer.synthesis(audioQuery: audioQuery, styleId: 1, options: voicevox_make_default_synthesis_options())
        return wav
    }
}

上記のように設定したのちに、実行するとビルド自体は成功するのですが、アプリ立ち上げ時に以下のようなエラーが出ます。

スクリーンショット 2024-05-03 午後8 46 29

2.vvmのパス(位置)はこのアプリのResourceフォルダー内に指定しています。(画像に写っているものです)

お忙しい中、何度も質問して申し訳ないです、、

よろしくお願いします🙇‍♂️

nekomimimi commented 6 months ago

その環境がないのでわからなく、VoicevoxCoreSwiftが何者か知らないので推測です。

なんちゃら/2.vvmはディレクトリと想定してそうでないからエラーが出ていること(os error 20)、 また、VoicevoxCoreSwift.set(modelsRoot: modelURL) でmodelRootとなっています。

そのため、VoicevoxCoreSwift.set(modelsRoot: modelURL)ではファイル自体でなく、vvmファイルのあるディレクトリーを設定することが想定されてるように見えました。

(vvmを全種類読み込むとiPhone的にメモリ的に問題があるかもなので個々のファイルの指定があったりするのでしょうか。全部読み込むのでしょうか。なにか違和感があるので自分が何か前提を間違えてる可能性があります。)

AsanoGenki commented 6 months ago

回答ありがとうございます🙇‍♂️🙇‍♂️

すいません、VoicevoxCoreSwiftに関するコードをお伝えするのを忘れていました。 以下がVoicevoxCoreSwiftに関するコードです。

import Foundation
import VoicevoxCore

public enum VoicevoxCoreSwift {
    public static var version: String {
        (NSString(utf8String: voicevox_get_version()) as? String) ?? "err"
    }

    public static func set(modelsRoot: URL) {
        setenv("VV_MODELS_ROOT_DIR", modelsRoot.path, 1)
    }
}

おっしゃる通り、おそらくvvmファイルのあるディレクトリーを設定する必要があると思います。

そのため、このリンクからhttps://github.com/VOICEVOX/voicevox_core/releases model-0.15.0-preview.16をダウンロードし、先ほど、2.vvmをおいていた場所に置いたところ、異なるエラーが発生しました。

Error(Display): `/private/var/containers/Bundle/Application/7…2EBC/VoiceVoxSample2.app/model-0.15.0-preview.16/9.vvm`の読み込みに失敗しました: モデルデータを読むことができませんでした: Failed to create session: Error calling ONNX Runtime C function: Failed to load model because protobuf parsing failed.
Error(Debug): RustApi(
    LoadModel(
        LoadModelError {
            path: "/private/var/containers/Bundle/Application/75...BC/VoiceVoxSample2.app/model-0.15.0-preview.16/9.vvm",
            context: InvalidModelData,
            source: Some(
                Session(
                    Msg(
                        "Failed to load model because protobuf parsing failed.",
                    ),
                ),
            ),
        },
    ),
)

voicevox_coreのバージョンは0.15.0-preview.6に対して、model-0.15.0-preview.16をダウンロードしていることが問題なのでしょうか? もしくは、model-0.15.0-preview.16を配置する場所が違うのでしょうか?

現在、バージョンが0.15.0-preview.6で、metas.jsonファイルを含んだmodelのファイルが見当たらなかったため、model-0.15.0-preview.16をダウンロードしている状況です。

わかる範囲で良いので教えていただけたら幸いです。

色々と付き合っていただき、本当にありがとうございます🙇‍♂️