YMM4 Plugin 制作メモ
ゆっくりムービーメーカー4(YMM4)のプラグイン機能について
- 2023/09/01についにプラグイン機能が公開された
- 公式
- プラグインを使用する | 饅頭遣いのおもちゃ箱
- プラグインを作成する | 饅頭遣いのおもちゃ箱
- repo
- manju-summoner/YukkuriMovieMaker4PluginSamples: YMM4用プラグインのサンプル集です
- manju-summoner/YukkuriMovieMaker.Plugin.Community: YMM4コミュニティで開発するYMM4プラグインです。 プラグインのサンプルも兼ねています。 ここで開発されたプラグインはYMM4にデフォルトで組み込まれます。
- manju-summoner/SampleReversePlaybackAudioEffectPlugin: キャッシュ機構を備えたYMM4音声エフェクトの実装サンプルです。音声の逆再生機能を提供します。ただし、仮実装のため実用には適しません。
- .NET SDK7/8でプラグインを開発できる
有志
自作
VSCode + dotnet cliで開発する
公式には本家VSの開発情報だけだが、csproj
の書き方工夫でVSCode+dotnet cliでもプラグイン作れる。
csprojの書き方
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<!-- YMM4 plugins -->
<Reference Include="path\to\YukkuriMovieMaker4\YukkuriMovieMaker.Plugin.dll" />
<Reference Include="path\to\YukkuriMovieMaker4\YukkuriMovieMaker.Controls.dll" />
<!-- 環境変数を使う場合
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Plugin.dll" />
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll" />
-->
<!-- ビルド時にdllを展開しない -->
<!--
<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>
</Project>
cliコマンドdotnet add reference
でいけるかどうかは不明なので手書き。
パス
YMM4のメニューの「ヘルプ」>「その他」>「アプリケーションフォルダを開く」でYukkuriMovieMaker.Plugin.dll
へのパスを取得。
環境変数などに登録しておくと良い
- 例:
YMM4_PATH
- csproj内では
$(YMM4_PATH)
でパスが参照できる
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Plugin.dll" />
<Reference Include="$(YMM4_PATH)\YukkuriMovieMaker.Controls.dll" />
SampleSAPI5VoicePluginはdotnet cliでビルドできない
manju-summoner/YukkuriMovieMaker4PluginSamples: YMM4用プラグインのサンプル集です
以下にあるように、利用しているmsbuildが.NET Framework版である必要がある。そのままのdotnet build
では.NET Core系のmsbuildが呼ばれるため。
.NET SDK 8.0 移行
YMM v4.23.0.0で.NET7から.NET8に移行したため、プロジェクトの<TargetFramework>をnet7.0-windows10.0.19041.0からnet8.0-windows10.0.19041.0に変更する必要があります。
ゆっくりMovieMaker v4.22.x.x以前に作成されたプロジェクトファイルの移行手順
未検証だけど <TargetFrameworks>で.NET7/8両対応ビルドできるかも?
<TargetFrameworks>net7.0-windows10.0.19041.0;net8.0-windows10.0.19041.0;</TargetFrameworks>
dllの依存関係でダメかな?
参照先を変えれば?
→ だめだった…
dotnet publish で ymme をつくる
やりかた
- MSBuildをつかってpublish -> zip圧縮 -> ymmeリネーム -> プラグインフォルダへ配置まで一括でやる
csproj
-
$(YMM4_PATH)
は環境変数で通しておく -
ビルド前に出力先をクリアしておくTarget
<Target Name="RemovePublishDirBeforeBuild" BeforeTargets="BeforeBuild">
<RemoveDir Directories="$(OutputPath)/publish/" />
<RemoveDir Directories="$(YMM4_PATH)\user\plugin\$(AssemblyName)\"/>
<Message Text="RemovePublishDirBeforeBuild" Importance="high" />
</Target>
- publish後にいろいろするTarget
<Target Name="MakeZipPackage" AfterTargets="Publish">
<!-- 一旦ymmeの出力先 -->
<MakeDir Directories="$(OutputPath)/../../../../../publish/" />
<ItemGroup>
<!-- 不要なファイルをymmeに取り込まない様にここで指定する -->
<FilesToDelete Include="$(OutputPath)\publish\YukkuriMovieMaker.*.dll"/>
</ItemGroup>
<Delete Files="@(FilesToDelete)">
<Output
TaskParameter="DeletedFiles"
ItemName="FilesDeleted"/>
</Delete>
<!-- zip圧縮、ymme拡張子変更 -->
<ZipDirectory
SourceDirectory="$(OutputPath)/publish/"
DestinationFile="$(OutputPath)/../../../../../publish/$(AssemblyName).ymme"
Overwrite="true" />
<Message Text="Actions After Publish" Importance="high" />
<!-- ※ここから下はやらなくてもymmeは既にできてる。そのままテストしたい場合用 -->
<!-- プラグインフォルダ以下にコピー -->
<Copy
SourceFiles="$(OutputPath)/../../../../../publish/$(AssemblyName).ymme"
DestinationFolder="$(YMM4_PATH)\user\plugin\"
/>
<!-- ymmeを展開して使えるようにする -->
<Unzip
SourceFiles="$(OutputPath)/../../../../../publish/$(AssemblyName).ymme" DestinationFolder="$(YMM4_PATH)\user\plugin\$(AssemblyName)\" />
</Target>
素材一覧に製作者・ニコニコIDを表示する
プラグイン本体
[PluginDetails(AuthorName = "YourName", ContentId = "YourNicoNicoID")]
public MyPlugin: IPlugin {}
または
public PluginDetailsAttribute Details => new()
{
//制作者
AuthorName = "InuInu",
//作品ID
ContentId = "",
};
※PluginDetails属性だけだと反映されないバグ? or プラグインの種類がある模様
その場合、面倒なのでリフレクションで取得。
public PluginDetailsAttribute Details
=> GetType().GetCustomAttribute<PluginDetailsAttribute>()
?? new();
ボイス(声質)
//ボイス(声質)の制作者
public string? SpeakerAuthor { get; } = "test";
//ボイス(声質)の作品ID (ニコニコIDとして有効じゃないとダメ)
public string? SpeakerContentId { get; } = "nc9999999";
//合成エンジン(アプリケーション)の制作者
public string? EngineAuthor { get; } = "test3";
//合成エンジン(アプリケーション)の作品ID (ニコニコIDとして有効じゃないとダメ)
public string? EngineContentId { get; } = "nc9999999";
VideoEffect、AudioEffect
PluginDetails属性
YmmeUtil
自作の便利なユーティリティライブラリ。詳しくはReadmeをみて。
デバッグ(YMM4 + VSCode)
以下の設定でデバッガー接続できる。
launch.json
- 環境変数
YMM_PATH
は以下のように${env:YMM4_PATH}
で参照可能。 -
"justMyCode": false
が無いとたぶんダメ。
{
"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
}
}
csproj
- dotnet build時にdllがYMM4のプラグインフォルダ以下にコピーすればデバッグできる
- pdbも必要
- ライブラリが使っているdllなどすべてがbin/Debug以下にあるわけではないのでpublishしたときのものを追加でコピーする
- 例:bin/Release/publish 以下のdllを全部持ってくる
- 注:publishした時pdbを消す処理していると除外されるのでどうにかする
<Target Name="CopyDebugDlls" BeforeTargets="AfterBuild" Condition="'$(Configuration)' == 'Debug'">
<ItemGroup>
<CommonPaths Include="$(OutputPath)../../Release/$(TargetFramework)/publish"/>
<MissingDlls Include="$(CommonPaths)/*.dll" Exclude="$(CommonPaths)/$(AssemblyName).dll"/>
<MissingPdbs Include="$(CommonPaths)/*.pdb" Exclude="$(CommonPaths)/$(AssemblyName).pdb"/>
</ItemGroup>
<Copy SourceFiles="@(MissingDlls)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true"/>
<Copy SourceFiles="@(MissingPdbs)" DestinationFolder="$(OutputPath)" SkipUnchangedFiles="true"/>
<ItemGroup>
<SourceFiles Include="$(OutputPath)**/*.*" />
</ItemGroup>
<Copy SourceFiles="@(SourceFiles)" DestinationFolder="$(YMM4_PATH)\user\plugin\$(AssemblyName)\" />
</Target>
参考
プラグインの動的なUI付きパラメータ
- パラメータをコレクションで持たせてカスタムコントロールを作るケース
- パラメータをコレクションで持たせてカスタム属性で表示するケース
- 入れ子パラメータ内で既存の
TextBoxSlider
とか使いたい場合
がある(後者は饅頭遣いさんから教えていただいた)
- 入れ子パラメータ内で既存の
コレクションパラメータ
[Display(AutoGenerateField = true)]
で入れ子内の表示を自動生成に任せる
[Display(AutoGenerateField = true)]
public ImmutableList<MyChildParameter> ItemsCollection {/*...*/}
カスタム属性
-
CustomDisplayAttributeBase
を継承した属性を作成。- リフレクションでごにょごにょして表示させる
- カスタム表示させたいプロパティに付与
[MyCustomDisplay]
[TextBoxSlider("F2", "", 0, 1, Delay = -1)]
[Range(0, 1)]
[DefaultValue(0.0)]
public double Value { get => _value; set => Set(ref _value, value);}
Windowsタスクバーに進捗表示
var main = Application.Current.MainWindow;
var taskbar = new TaskbarItemInfo
{
ProgressState = TaskbarItemProgressState.Indeterminate,
};
main.TaskbarItemInfo = taskbar;
//do something...
taskbar.ProgressState = TaskbarItemProgressState.None;
-
Application.Current.MainWindow
でYMM4のメインウィンドウを取得 -
TaskbarItemInfo
に割り当てる -
ProgressState
で進捗表示。ProgressValue
で比率も指定できる。 -
注:UIスレッドの処理になるのでワーカースレッドから呼ぶ場合は注意が必要
- Epoxyの
UIThread
クラスなどを使うと楽
- Epoxyの
//EpoxyのUIThreadクラスを使う(この外はワーカースレッドなので呼べない)
await UIThread.InvokeAsync(()=>{
//ここはUIスレッドになってるのでここで呼び出す
TaskbarUtil.StartIndeterminate();
return ValueTask.CompletedTask;
}).ConfigureAwait(false);
-
YmmeUtil.Ymm4.TaskbarUtil
で使えるようにした
YMM4プラグイン用githubのテンプレートリポジトリ
-
src/Sample
以下に何もしないサンプルプラグインが設定済みです- これをもとにしても、公式のサンプルを元にしてもOK
- ソリューションファイル:
Sample.sln
も設定済みです
-
dotnet publish
コマンドでymmeファイルをpublish
以下に作成&YMM4のプラグインフォルダ以下に展開できます - Code Analyzerを色々有効にしています
- ビルド時に
LICENSE
やREADME.md
がdllやymmeに含まれるように設定済 -
licenses
フォルダ以下のファイルもdllやymmeに含まれるように - MinVerライブラリでgitのタグから自動でSemVerが付きます
- VSCode: VSCodeの
publish
タスクでも上記ができるようにしています - VSCode: プラグインをYMM4ごとデバッガ接続で起動することができます
- gitignore, editorconfig設定済み
FocusHelper
-
YukkuriMovieMaker.Commons.FocusHelper
- 外部のアプリ操作のときなどにYMM4にフォーカスを戻すことができる
//現在のフォーカスされたUI部品(WPFの`FrameworkElement`)を取得できる
FocusHelper.DefaultFocus;
//YMM4のウィンドウ内の要素にフォーカスを移す
FocusHelper.FocusWindowContent(DependencyObject dependencyObject);
//外部アプリなどにフォーカスが移ったあとにYMM4にフォーカスを戻す
Window.GetWindow(FocusHelper.DefaultFocus).Activate();
FocusHelper.FocusWindowContent(FocusHelper.DefaultFocus);
IToolPlugin
IToolPlugin
を実装したプラグインを作り、View(UserControl
)とViewModelの型を渡すと、YMM4のツールメニューから呼び出し可能なツールが作れる。
public class MyToolPlugin : IToolPlugin
{
public string Name => "MyToolPlugin";
public Type ViewModelType
=> typeof(MyToolViewModel);
public Type ViewType
=> typeof(MyToolView);
}
ただし、YMM4内部のAPIとかは他の形式のプラグイン以下の事しかできないため、
ある程度独自処理のツールしか作れない。