VEGASスクリプトを組む際に気づいたこと

# はじめに

こんにちわ。
最近、ボイロ動画を作る際の効率化のために、VEGASのスクリプトを組もうとした際に気づいたことをQiitaに投稿しました。

* [VEGAS Pro 20のスクリプトをVisual Studio 2022で作れるようになるまでの手順](https://qiita.com/cyross4vocaloid/items/7c8ad8247836d34d2c22 "VEGAS Pro 20のスクリプトをVisual Studio 2022で作れるようになるまでの手順")
* [VEGASスクリプトで字幕を操作したくなったら、結局Formを使うことになった件](https://qiita.com/cyross4vocaloid/items/9c3062318af25ea254f5 "VEGASスクリプトで字幕を操作したくなったら、結局Formを使うことになった件")

これまでに作ったスクリプトはGithubで公開しております。
また、VegasScriptHelperリポジトリには、出来上がったDLLファイルをリリースとしてDLできるようになっております。

* [VegasScriptHelper / 各スクリプトで使用しているヘルパライブラリ](https://github.com/cyross/VegasScriptHelper)
* ~~[VegasScriptLauncher / 下記スクリプトを呼び出せるランチャ](https://github.com/cyross/VegasScriptLauncher)~~
  * (2023.2.9)VegasScriptHelperに統合しました
* ~~(他にもリポジトリはありますが、ランチャーを作ったこともあり、一手にまとめたほうが将来的に管理しやすいので省略)~~
  * (2023.2.9)統合しました

本記事では、それに加えて、VEGASスクリプトを組んだときに分かった注意点を書き出したいと思います。

# 1. イベントグループを作成するときの順番

VEGASスクリプトではイベントをグループとしてまとめることができます。
以下の順番が自然な流れと思えますが、これでは例外が発生します。

```IllegalGroupCreate.cs
            // グループ作成
            TrackEventGroup group = new TrackEventGroup(Vegas.Project);

            // グループに対象のイベントを挿入
            foreach (TrackEvent trackEvent in events) { group.Add(trackEvent); } // Addメソッドで例外発生

            // グループにプロジェクトに追加
            Vegas.Project.TrackEventGroups.Add(group);
```

正しくは、以下のように実装します。

```LegalGroupCreate.cs
            TrackEventGroup group = new TrackEventGroup(Vegas.Project);

            // まず、グループにプロジェクトに追加
            Vegas.Project.TrackEventGroups.Add(group);

            // それからイベント挿入
            foreach (TrackEvent trackEvent in events){ group.Add(trackEvent); }
```

# 2. プロジェクトの中身を変更する際の注意点

プロジェクトの中身を変更(追加・更新・削除)しようとすると、タイミングによっては`System.FormatError`や`System.Secury.SecurityException`が発生します。
特に、拡張機能として実行している場合は確実に発生します。

```IncorrectEdit.cs
        SetStringIntoOFXParameter(param, "abc");

        :

        public void SetStringIntoOFXParameter(OFXStringParameter param, string value)
        {
            param.SetValueAtTime(new Timecode(0), value); // ここで例外発生
        }
```

これは、Undo対象と明示しないために発生するようです。

そのため、これらの処理を呼び出すときは、それを`UndoBlock`を作成し、`using`文のブロックで囲む必要があります。

```CorrectEdit.cs
        using(new UndoBlock("テキストメディアに文字列設定"))
        {
            SetStringIntoOFXParameter(param, "abc");
        }

        :

        public void SetStringIntoOFXParameter(OFXStringParameter param, string value)
        {
            param.SetValueAtTime(new Timecode(0), value); // 例外が発生しなくなる
        }
```

# 3. Timecodeクラスインスタンスの出力

`Timecode`クラスはイベントの開始時間や長さを示すために使用しますが、文字列として取得する場合にクセがあります。

`ToString`メソッドの引数は省略可能な`RulerFormat`構造体で、省略時は`RulerFormat.TimeAndFrames`です。
これは、時・分・秒とフレーム数という単位になっており、VEGASでは標準な時間表記です。

しかし、「完全な時間単位で編集とかしたい」という場合もありますので、そういう場合は引数として明示的に`RuleFormat.Time`を渡す必要があります。

余談ですが、VEGASではMV向けにトラックのルーラーを小節・拍単位でも表示できます。その形式で出力したいときには`RulerFormat.MeasuresAndBeats`を渡します。

# 4. エラーログの出力

スクリプトや拡張機能のデバッグをするときは、実際にVEGASを起動して行います。
しかし、例外によっては不親切なエラーメッセージやバグレポートダイアログが瞬時に表示されて、どこでどんな例外が発生しているのかわからなくなります。
そのため、メイン処理内で例外処理を施して、発生したらVisualStudioのログに出力したり、
万が一(例えばVEGAS起動処理中に発生)のためにメッセージボックスに表示させられるようにしたほうが便利です。

```ShowLog.cs
            try
            {
                // メイン処理
            }
            catch(Exception ex)
            {
                string errMessage = "[MESSAGE]" + ex.Message + "\n[SOURCE]" + ex.Source + "\n[STACKTRACE]" + ex.StackTrace;
                Debug.WriteLine("---[Exception Occurred]---"); // ヘッダは適時変更
                Debug.WriteLine(errMessage);
                Debug.WriteLine("--------------------------");
                MessageBox.Show(
                    errMessage,
                    "エラー",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                throw ex;
            }
```

# おわりに

VEGASのスクリプト仕様がめちゃくちゃ不親切なので、試行錯誤したり、VEGASのコミュニティで情報を漁ったりするなどして情報を集めました。疲れた…。

最後に、参考にしたVEGASのコミュニティやブログを紹介して筆を置きたいと思います。

* [Forum for VEGAS Pro (SCRIPTING)](https://www.vegascreativesoftware.info/us/vegas-pro-forum/scripting/)
* [JETDV Scripts (Category: VEGAS)](http://www.jetdv.com/category/scripts/vegas/)