🔌

YMM4の音声合成プラグインのつくりかた

2024/12/01に公開

はじめに

YMM4 VoiSona Talk Plugin」というYMM4向けの音声合成プラグインを作成したので、音声合成プラグインの作り方を解説してみます。

YMM4の音声合成プラグインはYMM4のプラグインの中でもちょっと複雑な方なので、他の種類のプラグインを作る際にも参考になると思います…!

YMM4はプラグインが作れる

YMM4

合成音声ソフトと連動できるフリーの動画編集ソフトとしては「AviUtl」と「ゆっくりムービーメーカー4(YMM4)」の2つがメジャーです。
(この分野は有料のソフトを買っても効率が悪く手間が掛かって大変です)

大量のプラグインでいろいろカスタマイズする「AviUtl」にたいし、
オールインワンですぐ始められる「YMM4」っていう比較があったのですが、
最新のYMM4は実はプラグインを作成できるようになっています

この記事を書いている時点でプラグイン機能の公開から1年以上が経ち、数もそこそこ増えつつあります。

作れるプラグインの中には外部の合成音声エンジンに対応できるものも

YMM4は標準で多くの合成音声エンジンとの連携ができます。
(ゆっくりとCeVIOしか対応していなかった時代が懐かしい…)

これら標準の機能も、内部的にはプラグインで作られており、現在ではこれをユーザーが自作することができるようになっています。

つくりかたの準備

環境

  • .NET SDK (2024年12月現在は 8.0 または 9.0 )

  • IDEは公式の紹介ではVisual Studioが紹介されています

    • VSCodeやRiderでも作れます
  • YMM4アプリ本体

    • Lite版が推奨

必要な知識

  • C#
    • バージョンは12.0以降の記法もそこそこ使われています
    • 非同期処理(async/await)の知識は必須です
  • WPF
    • 設定UIの自作のためにWPFの知識が必要です
      • ※YMM4自体がWPFアプリケーションです
  • 連携する合成音声ソフトの知識
    • 合成音声ソフトによって違います
  • ニコニコのコンテンツツリーの知識
    • ニコニコ動画の文化とコンテンツツリーの仕組みの知識があった方が良いです
    • ぼ民(Voskyユーザー)なら多くの人は知っていると思いますがYouTube中心の人は知らないかも?
音声合成プラグイン以外で必要な知識
  • Vortice.Windows
    • 描画周りはVortice.Windowsの知識が必要です
      • DirectXやMediaFoundationなども必要です
  • 音声加工の知識
    • 音声処理周りは、音声加工の知識や具体的なライブラリではNAudioの知識が要ります
  • LLM AIサービスのAPIの知識
    • AIテキスト補完プラグインで連携する場合は、REST APIなど各サービスの知識が要ります

YMM4のプラグイン開発の知識の入手先

面倒な人向けの開発テンプレ

https://github.com/InuInu2022/ymme-vscode-boilerplate

いぬいぬ自作の github template リポジトリです。ここから作るとサクッと作れます。
VSCode用ですが、VS/Riderでも使えます。

  • 設定済み
    • src/Sample以下に何もしないサンプルプラグインが設定済みです
      • これをもとにしても、公式のサンプルを元にしてもOK
      • ソリューションファイル:Sample.slnも設定済みです
    • dotnet publishコマンドでymmeファイルをpublish以下に作成&YMM4のプラグインフォルダ以下に展開できます
    • Code Analyzerを色々有効にしています
    • ビルド時に LICENSEREADME.md がdllやymmeに含まれるように設定済
    • licensesフォルダ以下のファイルもdllやymmeに含まれるように
    • MinVerライブラリでgitのタグから自動でSemVerが付きます
    • VSCode: VSCodeのpublishタスクでも上記ができるようにしています
    • VSCode: プラグインをYMM4ごとデバッガ接続で起動することができます
    • gitignore, editorconfig設定済み

https://docs.github.com/ja/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template

YMM4関連のファイルについて

  • .dll
    • YMM4のプラグイン自体は.NETのバイナリ形式です
    • pluginフォルダに置くとプラグインとして読み込まれます
    • ただし、現在はこれをユーザーが直接やり取りすることは少なくなっています
      • プラグイン開発者はバリバリ使います
  • .ymme
    • YMM4のプラグインのインストーラパッケージです
    • 中身は.dllなどをzipでまとめただけのアーカイブです
    • YMM4はこの形式に関連付けられています
    • ダブルクリックすると公式のプラグインインストーラが起動して自動でpluginフォルダにインストールしてくれます
    • 公式:プラグインの配布用パッケージ化
  • .ymmp
    • YMM4のプロジェクトファイルです
    • これを直接プラグインから触る方法は2024-12月現在ありません
  • .ymmt
    • YMM4の「テンプレート」をやり取りできるファイルです
    • これを直接プラグインから触る方法は2024-12月現在ありません

具体的なつくりかた

基本的な作り方の流れ

  1. 開発環境を整える
  2. テンプレなどを元にプラグインを開発
  3. ビルドしたプラグインをymme形式などで配布

開発環境を整える

環境」にあるC#の開発環境を整えましょう。
Windowsに最初から入ってるヤツはレガシーな「.NET Framework」なので使えません。(プラグイン作れません)
後ろに「Framework」って付かない最新の.NET SDKを使いましょう。

メモ帳とか使うと滅茶苦茶効率わるいのでおすすめしません(C#全般そうですが)。

https://zenn.dev/inuinu/articles/40d3a9825c19de

プラグインなのでYMM4本体も必要です。
普段使い用とプラグイン開発用に分けて、別の場所にYMM4をインストールすることをおすすめします。

また、AquesTalk(ゆっくり)を使わない場合、ゆっくり音声を使わなくともライセンス問題が発生しますので、その場合はLite版をおすすめします。
今回は合成音声プラグインなのでAquesTalk(ゆっくり)を使わない前提なので、Lite版一択です。

テンプレなどを元にプラグインを開発

音声合成プラグインの場合、IVoicePluginを実装したプラグインクラスを実装します。

公式サンプルの「SampleSAPI5VoicePlugin」を参考にしてみて下さい。

ymme-vscode-boilerplate をテンプレとしてリポジトリを作る

SamplePluginプロジェクトを公式サンプルを参考に置き換える

という流れがスムーズだと思います!!

最低限、以下のクラスを作成すると音声合成プラグインができます。

  • **VoicePlugin
  • **VoiceParameter
  • **VoiceSpeaker
  • **VoiceSettings

サンプル内のコメントに説明があるのでよく読んでおきましょう。

細かい具体的な書き方のコツは後ほど。

ビルドしたプラグインをymme形式などで配布

プラグインなのでアプリの実行バイナリ(exe)ではなく、
dllとしてビルドします。

ビルドした後のdllをYMM4のプラグインフォルダに配置するとプラグインとして使えますが、配置を自動でやってくれるのがymme形式です。

https://manjubox.net/ymm4/faq/plugin/how_to_make/#プラグインの配布用パッケージ化

なので開発中はともかく、ユーザーの事を考えて基本的にはymme形式で配布しましょう。
どこで配布するかは自由ですが、マルウェアが組み込まれて流通することがあるため、あちこちで配布するのはオススメしません。プラグイン公式な数か所だけで配布するのをおすすめします。

参考記事↓

https://note.com/inuinu_/n/n667400e57e25

タグを付けてGithub、X、BOOTHに置けば拾ってもらえます。

https://ymme.f5.si/

具体的な書き方のコツ(ビルド設定編)

環境変数

開発用YMM4をインストールし、そこへのパスを環境変数として設定しておくのをおすすめします。
(色々な設定が楽になります)

YMM4のメニューの「ヘルプ」>「その他」>「アプリケーションフォルダを開く」でパスを取得できます。

「ヘルプ」>「その他」>「アプリケーションフォルダを開く」

Windowsの環境変数への設定方法は調べて下さい!

https://so-zou.jp/software/tech/os/windows/system/environment-variable.htm#no2

以降、YMM4_PATHで設定されているものとします。

これをすると

  • csproj 内では $(YMM4_PATH) でパスが参照できる
  • VSCodeのlaunch.json では ${env:YMM4_PATH}でパスが参照できる

ようになってとても便利です。

最低限csproj ★★★

  • dotnet newなどでdotnetテンプレートから作る場合は、「クラスライブラリ」として作る
  • TargetFrameworkはYMM4本体と合わせる
    • 11月末現在はnet8.0-windows10.0.19041.0
    • ※12月以降、.NET 9.0 以降予定
  • プラグインのパラメータ入力でWPFを使うためUseWPFtrue
    • ほとんどのプラグインで必要になります
  • YMM4の機能を使うため、YMM4本体のdllへ参照を通す
    • 次の2つが最低限必要
      • YukkuriMovieMaker.Plugin.dll
      • YukkuriMovieMaker.Controls.dll
    • Privateをfalse、CopyLocalをfalseにするとビルド出力先に上記をコピーしません
最低限のcsproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
  <ItemGroup>
    <!-- YMM4_PATH は環境変数で開発用YMM4本体へのパスを通しておく -->
    <Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Plugin.dll">
      <Private>false</Private>
      <CopyLocal>false</CopyLocal>
    </Reference>
    <Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll">
      <Private>false</Private>
      <CopyLocal>false</CopyLocal>
    </Reference>
  </ItemGroup>

本体dllをビルド先にコピーしないようにする ★★★

dllにそのまま参照すると、ビルド先にもdllがコピーされます。
これを同梱してプラグインを配布した場合、YMM4本体のアプデ側とdllのバージョンが異なるためエラーや傾向など様々な問題がでます。
プラグインのサイズも大きくなるので推奨しません。

以下の設定でコピーされないようにします。

Private=false, CopyLocal=false
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll">
  <Private>false</Private>
  <CopyLocal>false</CopyLocal>
</Reference>

これは「YukkuriMovieMaker.Plugin.dll」や「YukkuriMovieMaker.Controls.dll」以外の本体dllや、
本体で使われているライブラリをプラグイン側でも使う場合も該当します。

Newtonsoft.JsonやNAudioとかの定番ライブラリも、
バージョン違い問題が起きるので、同梱されないようにします。
具体的にはnuget経由で導入するのではなく、YMM4本体の同梱dllへのパスにしておきます。
こうすることで本体とバージョンが合うようになります。

dllやymmeとして配布する際も最小限のdllだけ含まれるようにします。
プラグイン本体のdllとプラグインだけで使っているライブラリのdllだけになるようにします。

ymmeのgithub templateはそのあたりの設定をしてあり、publish時に最小限の配布に設定してあります。

ビルド時にプラグインフォルダに自動でdllファイルをコピーする ★★★

YMM4のプラグインはプラグインフォルダ内にdllを置かないと動きませんが、
毎回動作確認のためにdllを手動コピーするのはめちゃくちゃ面倒です。

公式のサンプルやymme-vscode-boilerplateのgithub templateはビルド時に自動でコピーされる設定になっていますのでコピペするか参考に設定してみて下さい。

デバッガーで追いかけられるようにする ★★★

DebuggerとYMM4本体、そしてプラグインを接続してデバッグできるようにしておきましょう。
開発効率がめっちゃ変わります。

Visual Studioの場合

Riderの場合

「実行/デバッグ設定」からexeパスにYMM4のexeを指定することで設定できます。

VSCodeの場合

  • launch.jsonに以下を追加
    • ※環境変数YMM_PATHが設定済み前提
    • ymme-vscode-boilerplate では設定済み
launch.json
"configurations": [
        {
            "name": "Debug YMM4",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${env:YMM4_PATH}/YukkuriMovieMaker.exe",
            "args": [],
            "cwd": "${workspaceFolder}",
            "stopAtEntry": false,
            "console": "internalConsole",
            "justMyCode": false,
            "logging": {
                "moduleLoad": false
            }
        }
]

上記の方法を設定しておき、ビルド時にプラグインフォルダに自動でdllファイルをコピーするようにしておけば、
F5などでデバッグ起動するとYMM4上で動かしながらデバッグができます。

これで原始的なコンソールデバッグとはオサラバ!です!

他おすすめのビルド設定

  • publish時に自動でymmeにまとめるMSBuild設定
    • License, Readmeも同梱するようにしておく
  • プラグイン自体のアセンブリに色々情報を追加
    • 開発者名、バージョン、githubリポジトリとか
  • MinVerライブラリなどを使って自動SemVer付与
    • 現在YMM4のプラグインはバージョンに関するルール等はありません
    • ただし将来的なことを考えるとバージョンを設定しておくのを推奨します

具体的な書き方のコツ(C#編)

IVoicePluginを実装した**Pluginクラス

プラグインの大本となるクラスです。

ボイスライブラリ音源を表すIVoiceSpeakerを実装した**Speakerクラス、
プラグインの設定を保存するSettingsBase<T>を継承する設定クラス、
が必要です。

Voices プロパティ

  • 合成音声エンジンがサポートする、(使用可能な)ボイスライブラリ音源を登録します
  • ボイスライブラリ音源はIVoiceSpeakerを実装した**Speakerクラスで定義します
  • 基本的に合成音声エンジンには複数のボイスライブラリがあります
    • 固定で割り当てることもできますが、ライセンス購入しているか・インストールしているかなどをある程度動的に確認する必要があります
  • 公式サンプルは設定から使えるボイスライブラリ一覧を読み込むようになっていますので基本そのままでいいと思います
    • SettingsBase<T>を継承する設定クラスが必須です

CanUpdateVoices

  • 使えるボイスライブラリ音源の一覧を更新できるかどうかを指定します
    • 普通はtrueになると思います
    • 固定、もしくは更新をプラグイン自体のアプデでやる場合はfalse
  • trueの場合
    • SettingsBase<T>を継承する設定クラスが必須
    • UpdateVoicesAsync()の実装が必須

IsVoicesCached

  • ボイスライブラリ音源の一覧が固定の時は常にtrue
  • それ以外は公式サンプルのように設定クラスのIsCachedを取得する形で

UpdateVoicesAsync()

  • CanUpdateVoices = trueの時に実装が必須です

Detailsプロパティ

配布前にはIPlugin.Detailsを実装しておきましょう。

public PluginDetailsAttribute Details => new()
{
    //制作者
    AuthorName = "My Name",
    //作品ID
    ContentId = "",
};

YMM4の「使用素材一覧」にリストアップされるときにこの情報も載ります。
プラグインを使った人が投稿する際に便利になります。

使用素材一覧

ニコニ・コモンズなどで作品IDを登録している人は設定しておくと、ユーザーの人がコピペ&登録しやすくなるので是非設定しておきましょう。

https://qa.nicovideo.jp/faq/show/885?site_domain=default

またプラグインのニコニ・コモンズや紹介動画からは、YMM4自体のコンテンツID(nc236011)に子作品登録しておきましょう。親子登録しておくことで、プラグインのコンテンツIDが登録されると自動でYMM4自体にも支援が入ります。

https://commons.nicovideo.jp/works/nc236011


IVoiceSpeakerを実装した**Speakerクラス

音声合成ソフトの、ボイスライブラリ(音源)を定義するクラスです。

1ボイスライブラリ(音源)を表現するには、このクラスの1インスタンスごとで表します。
(音源の数が少なければ個別のボイス音源ごとにクラス定義してもいける…?)

公式サンプルのコメントで丁寧な説明があるので基本はそちらを見てもらうとして!

YMM4SamplePlugin/Voice/SAPI5VoiceSpeaker.cs

以下ポイント。

IsVoiceDataCachingRequired

trueにすることでymmpファイル内にテキストで音声データが保存されます。

EngineAuthor / EngineContentId / SpeakerAuthor / SpeakerContentId / License

SpeakerAuthor / SpeakerContentIdは、IPlugin.Detailsのボイスライブラリ(音源)版、
EngineAuthor / EngineContentIdはの合成音声ソフト版です。

合成音声のボイスライブラリは合成音声ソフトとは別に権利が設定されています。
キャラクターがいるボイスライブラリの場合は、ニコニコのコンテンツIDやコンテンツツリーへの登録を求めている場合もあります。

https://commons.nicovideo.jp/works/sm33517192

https://commons.nicovideo.jp/works/nc309924

https://commons.nicovideo.jp/works/nc309120

https://commons.nicovideo.jp/works/nc310893

ここにプラグイン側で設定しておくことで、自動でYMM4の「使用素材一覧」にリストアップされます。
動画投稿者にとても便利なので、合成音声のボイスライブラリの権利関係は確認して設定しておきましょう。

LicenseにはIVoiceLicenseを実装するクラスを指定します。
ボイスライブラリ音源の権利関係のURLを指定すると良いでしょう。

設定するとYMM4のUI上でリンクを表示できます。

音源の出音の規約と、キャラクターのガイドラインの規約は通常別(2つあるのが普通)なので、どちらを登録すれば良いかも確認しておきましょう(通常は音源の出音側)。

CreateVoiceAsync()

YMM4の音声合成プラグインで一番大事な、キモに当たる処理です…!!!
この中で音声合成ソフトに合成してもらう処理を呼び出します。

YMM4のセリフ入力欄に文字を入れたときや、
セリフの読みを変更したとき、
合成パラメータを変更したとき、
台本ツールで連続生成するとき、
などいろいろなところで呼ばれます。

公式サンプルにあるようにセマフォ(Semaphore)の処理を入れるのも大事ですし、
合成音声ソフトによっては合成時間がかかる場合もあるので、非同期処理を徹底しましょう!

工夫

特にユーザーを待たせる場合は、工夫してあげると良いと思います!
自作のプラグインではYMM4のタスクバーアイコン上でインジケータが動くようにしています。

インジケータ

UIの処理を呼ぶときには、この関数内はワーカースレッドなのでUIスレッドへの切り替えが必要です。

Epoxy + 自作ライブラリのYmmeUtilを使ったインジケータ処理の例
await UIThread.InvokeAsync(()=>{
	TaskbarUtil.StartIndeterminate();
	return ValueTask.CompletedTask;
}).ConfigureAwait(false);
抑揚(アクセント)編集可能にするには

「抑揚」(アクセント)を編集できる合成音声ソフトの場合は、戻り値をnullではなく、
合成音声ソフトからのアクセント情報(ソフトによって名前違うかも)をIVoicePronounceを実装したクラスを返すようにします。

また、引数で受け取ったIVoicePronounceを実装したクラスを合成時に反映するようにします。

MigrateParameter(IVoiceParameter currentParameter)

ボイス音源の違いをインスタンスの違いで表現しているとき、ボイスライブラリ(音源)の切替で音源毎の固有Styleが切り替わらないことがありました。

「キャラクターの声質の変更時に呼ばれる。」と公式サンプル説明にあります。

そこで、自作プラグインではここでボイスライブラリを判定して強制再読み込みを掛ける処理をしています。


VoiceParameterBaseを継承した**Parameterクラス

YMM4上で合成音声の調声ができるようにするためのクラスです。
これを使って調整しないと、声は合成できますが、できるだけ、なのであまり嬉しくないです…!
なので、音声合成プラグイン制作で2番目に大事なクラスです!

SAPI5VoiceParameter.cs
/// <summary>
/// アイテム編集エリアに表示する音声の設定項目。
/// [Display]と[TextBoxSlider]等のアイテム編集コントロール属性の2つを設定する必要があります。
/// [TextBoxSlider]以外のアイテム編集コントロール属性の一覧はSamplePropertyEditorsプロジェクトを参照してください。
/// </summary>
[Display(Name = "話速", Description = "テキストの読み上げ速度")]
[TextBoxSlider("F0", "", -10, 10, Delay = -1)]//Delayを-1にするとスライダーを操作し終えるまで反映しない。これがないとスライダーの操作中に音声の再生成処理が走ってしまう。
[Range(-10, 10)]
[DefaultValue(0)]
public double Speed { get => speed; set => Set(ref speed, value); }

公式サンプルにあるSamplePropertyEditorsの説明の通り、色々な属性をプロパティにつけることで、YMM4上でのUIが自動生成されます!

ボイス音源ごとに違うパラメータを設定するには?

合成音声ソフト全体でパラメータが共通の場合はサンプルのママで問題ないんですが、
ボイス音源ごとによってパラメータが違う場合に問題になります。

たとえば、ボイス音源ごとに「感情」パラメータが異なる、みたいな場合です。

3スタイルのボイス音源の例 8スタイルのボイス音源の例

次の方法はあんまりうまくいかないのでオススメしません。

  • インスタンスごとに動的にパラメータ用プロパティを増やす…?
  • あるいはボイス音源ごとに別クラス化する…?

やり方としては2つあります!

1. パラメータをコレクションで持たせてカスタムコントロールを作るケース

ボイス音源ごとに違うパラメータを小パラメータクラスにします(例:MyChildParameter)。
そしてその子パラメータクラスのコレクションクラスを親のパラメータクラスにプロパティとして定義します。

[Display(AutoGenerateField = true)]属性を追加すると、入れ子の子クラスのパラメータUIを自動生成してくれます。

MyParentParameter.cs
[Display(AutoGenerateField = true)]
public ImmutableList<MyChildParameter> ItemsCollection {/*...*/}

小パラメータクラスは通常のパラメータクラスと同じ作りでOK。

2. パラメータをコレクションで持たせてカスタム属性で表示するケース

小パラメータクラスで既存のTextBoxSliderとか使いたい場合はこちらの方法を使います。

CustomDisplayAttributeBaseを継承した独自属性クラス(例:MyCustomDisplay)を作ってそれ小クラスのパラメータに追加します。

MyChildParameter.cs
[MyCustomDisplay]
[TextBoxSlider("F2", "", 0, 1, Delay = -1)]
[Range(0, 1)]
[DefaultValue(0.0)]
public double Value { get => _value; set => Set(ref _value, value);}

CustomDisplayAttributeBaseを継承して実装するクラスでは、引数にobject型のinstanceが得られますが、これは小パラメータクラス(ここの例ならMyChildParameter)のType型が得られるのでリフレクションでごにょごにょできるようになります。

たとえばTextBoxSliderで表示させたいならGetDescription(), GetName()でちゃんとした戻り値を返すようにしてあげてください。

MyChildParameter.cs
[JsonProperty]
public string DisplayName { get => _displayName; init => Set(ref _displayName, value); }
[JsonProperty]
public string Description { get => _description; init => Set(ref _description, value); }
MyCustomDisplayAttribute
public override string? GetDescription(object instance)
{
	if (instance is not MyChildParameter childParam) return null;
	var temp = childParam
		.GetType()
		.GetProperty( nameof(MyChildParameter.Description) )?
		.GetValue(childParam);
	return temp is string propValue ? propValue : null;
}
入れ子のパラメータも

パラメータクラスのプロパティは setter で Set(ref _value, value) を指定する必要がありますが、入れ子の場合はもう少し工夫が必要です。

MyParentParameter.cs
[Display(AutoGenerateField = true)]
public ImmutableList<MyChildParameter> ItemsCollection
{
	get => _styles;
	set
	{
		UnsubscribeFromItems(_styles);
		try
		{
			Set(ref _styles, value);
		}
		catch (Exception e)
		{
			Debug.WriteLine(e.Message);
		}

		SubscribeToItems(_styles);
	}
}

// 個々のアイテムの PropertyChanged イベントに登録
void SubscribeToItems(ImmutableList<MyChildParameter> newItems)
{
	foreach (var item in newItems)
	{
		item.PropertyChanged += Item_PropertyChanged;
	}
}

// 個々のアイテムの PropertyChanged イベントの登録解除
void UnsubscribeFromItems(ImmutableList<MyChildParameter> oldItems)
{
	foreach (var item in oldItems)
	{
		item.PropertyChanged -= Item_PropertyChanged;
	}
}

void Item_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
	OnPropertyChanged($"{nameof(ItemsCollection)}.{e.PropertyName}");
}

SettingsBase<T>を継承した**Settingsクラス

プラグインの設定を保存するクラスです。
合成音声プラグインでは保存しておくことが結構あるのでかなり大事なクラスです。

他のクラスから呼び出す場合は MySettings.Default からプラグイン内のどこからでもアクセスできます。

HasSettingView / SettingView

  • HasSettingViewtrueにした場合、専用の設定UIを持たせることができます
  • SettingViewにWPFのUserControlを継承したクラスを割り当てて表示します
public override object? SettingView
{
	get
	{
		//UserControlを継承したMyVoiceSettingsViewを返すようにする
		var view = new MyVoiceSettingsView
		{
			//vmわりあて (MVVMでやらないなら不要)
			DataContext = new MyVoiceSettingViewModel()
		};
		return view;
	}
}
  • SettingViewに割り当てるクラスはWPFそのものになるので、WPFの知識で作成します
  • 合成音声ソフトはソフト毎に固有の設定がわりとあるので、独自UIを作って設定できるようにする必要があります
    • 合成音声ソフト自体へのマニュアルや利用規約に飛べるようにするとか
    • 自作プラグインの場合はプラグインの更新通知機能を入れています
    • ボイス音源側で共通に設定できるUIを作ってもいいですが、設定項目が多くなって使い勝手が悪くなります

設定するとYMM4の「設定」にプラグイン専用の設定メニューが表示されます。
中身は全部自作してください。

参考例:
設定

IVoiceLicenseを実装する**Licenseクラス

**SpeakerクラスのLicenseパラメータで使用するクラスです。
繰り返しますが、ボイス音源の利用規約をユーザーにわかるようにしてあげましょう。
無料だから何しても言いわけではありません!!!

SummaryLocation

規約をどこに表示するか、です。

  • None:表示なし
  • ItemEditor: セリフアイテムのパラメータの下に毎回表示
  • CharacterEditor: キャラクター設定の声質設定のところに表示

例:CharacterEditor

Terms / TermsURL

Termsがnullかどうかで、YMM4上の扱いが変わります。

Termsになんらかのstringを指定すると、利用規約の青文字リンクをクリックしたときに
利用規約を確認するダイアログがでるようになります。

これは利用規約を承認する必要があるオンライン合成音声サービスなどのときに利用します。

Termsがnullの時は、TermsURLで指定したURLをブラウザで開きます。

ValidateLicenseAsync() / IsTermsAgreed

ValidateLicenseAsync()で利用規約に同意したかを判定する処理を記入します。
判定はIsTermsAgreedプロパティに記録します。

特に利用規約処理がない場合であっても処理が必要なので、そのときはValueTask<bool>(true)を常に返すようにしておきましょう。

利用規約処理がない場合
public ValueTask<bool> ValidateLicenseAsync()
{
	return new ValueTask<bool>(true);
}

独自のパラメータUIをつくる

IPropertyEditorControlIPropertyEditorControl2を実装したUserControl継承のViewクラスを用意します。
IPropertyEditorControl2の方がより細かいことができます)

PropertyEditorAttribute2を継承したカスタム属性を作成し、独自のパラメータUIで表示したいパラメータクラスのプロパティに付与します。
SetBindings()の引数itemPropertiesから色々情報がリフレクションで取れるので、
ここでゴニョゴニョすることで色々できます…!

UIを多言語化対応する

YukkuriMovieMaker.Generatorというソースジェネレータを利用した公式のローカライズ対応ライブラリがあるのでこれを使います。CSVで作った翻訳ファイルを変換してくれます。

使い方のサンプルとしては、公式サンプルか、公式コミュニティプラグイン「YukkuriMovieMaker.Plugin.Community」を見るのが良いと思います!

まとめ

  • YMM4は動画編集ソフトとしてプラグイン対応が進化しており、音声や映像エフェクト、AIなど多様なプラグインを作成可能。
  • 開発環境には.NET SDK (8.0または9.0) とVisual Studio (VSCodeやRiderも可) が必要。
  • 必須知識にはC# (非同期処理含む)、WPF、連携する音声合成ソフト、ニコニコのコンテンツツリーが挙げられる。
  • テンプレートやサンプルコードが公式リポジトリや有志のリソースで提供されている。
  • 初心者向けに、VSCode用の開発テンプレート「ymme-vscode-boilerplate」が推奨。
  • 音声合成プラグイン作成の基本は、IVoicePluginを実装すること。
  • 必要なクラス例として **VoicePlugin, **VoiceParameter, **VoiceSpeaker, **VoiceSettings を作成。
  • 開発には、普段使いと開発用に別々のYMM4環境を用意するのが望ましい。
  • プラグイン配布形式はdllまたはymmeが主流で、ユーザー向けにはymme形式が推奨される。
  • プロジェクトファイル(csproj)では、TargetFrameworkやUseWPF設定を適切に構成。
  • YMM4のDLL(YukkuriMovieMaker.Plugin.dllなど)への参照が必要。
  • 開発に役立つ情報は公式サイトやGitHub、Discordサーバーなどで入手可能。
  • パッケージ化や配布には非公式プラグインストア「YMME Hub」なども利用できる。
  • 環境変数を利用すると、開発やデバッグの効率が向上。
  • 作成したプラグインをdotnet publishでビルドし、デバッグ時にはYMM4に自動配置する仕組みを整備可能。
  • マルウェア対策として、プラグイン配布は信頼性の高い場所に限定するべき。
  • 配布プラットフォームとしてGitHubやBOOTHなどが一般的。

明日はかなでさんの「ぼすきーの絵文字検索について」です。

https://adventar.org/calendars/10443

Discussion