【VSML/VSS】動画を編集できる言語を作った話

# はじめに
みなさんは動画編集をやったことはありますか？
私は，頻度は低いものの動画編集をして動画投稿サイトに動画をアップロードした経験があります．

動画編集とは元来めんどくさく手間がかかるものではあるのですが，普段からWebアプリの開発をしている私は，以下のようなことを考えていました．
HTML/CSSのように複数オブジェクトを一つのコンポーネントのように扱えたら，CSSのように統括して装飾を指定できたら，HTMLのレンダラー(ブラウザ)が相対値から計算して幅や高さを指定するように，動画のオブジェクトの時間長も編集アプリが計算して指定してくれたら，もっと楽に動画編集できるのになぁ，と．
そこで私は，HTML/CSSをベースとした，動画の構成を記述する言語を記述することで動画編集を行えるという技術を開発しました．

元々OSSでやるか，未踏のようなイベントに持ち込むか悩んでいたのですが，大学4年の時期，卒業研究に追われながら開発したら飽きてやめる未来が見えたので，卒業研究のテーマとして研究室に持ち込んでみました．卒論発表を終えた所，割と教授たちからも良い反応を得ることができました．
しかし，本大学の学士の論文は学内にしか発表されないので，卒業研究を終えて時間が少しできたこともあり，少しでも世に広まることを祈って本記事を執筆しています．

# 作ったもの
## VSML/VSS
### 概要
「[はじめに](#はじめに)」でも触れたように，テキストを記述することによって動画編集ができる言語，VSML/VSSを開発しました．
名前からわかるように，それぞれHTML/CSSに対応しており，Video Structure Markup Language(VSML)では動画内のオブジェクトとその構造(空間的・時間的位置)を記述し，Video Styling Sheets(VSS)では，動画内のオブジェクトの装飾(色，大きさ，余白など)を記述します．

### 言語仕様

β版未満な仕様となっているため，今後機能追加・修正を行う予定ですが，現段階(2024/03/14時点)での仕様は以下にまとめております．
https://github.com/vsml-org/vsml_converter_old/blob/main/syntax.md

### 実際の例

<details>
<summary>コード(長いので折りたたんでいます)</summary>

```xml
<vsml>
  <meta>
    <style>
      cont {
        order: parallel;
        background-color: rgb(200, 200, 255);
      }
      txt {
        font-family: "Meiryo";
        font-weight: bold;
      }
      .zundamon {
        margin-top: 28rh;
        margin-left: -14rw;
        width: 40rw;
      }
      .metan {
        margin-top: 30rh;
        margin-left: 77rw;
        width: 33rw;
      }
      .bgm {
        duration: fit;
        audio-volume: 10%;
      }
      .serif {
        background-color: rgba(0, 0, 0, 0.7);
        padding: 20px;
        font-size: 70px;
        width: 100rw;
        font-border-width: 7px;
      }
      layer {
        direction: column;
      }
      .serif-audio {
        time-margin-end: 0.1s;
      }
      .illustration {
        height: 70rh;
        width: 60rw;
        margin-top: 5rh;
        margin-left: 20rw;
      }
      .zun-serif {
        font-border-color: rgb(100, 200, 50);
      }
      .metan-serif {
        font-border-color: rgb(230, 100, 200);
      }
    </style>
  </meta>
  <cont resolution="1920x1080" fps="30">
    <aud class="bgm" src="./bgm/なんでしょう？.mp3" />
    <img class="zundamon" src="./character/ずんだもん.png" />
    <img class="metan" src="./character/四国めたん.png" />
    <seq>
      <layer>
        <txt class="serif zun-serif">
          今回は大分県名物、とり天について紹介するのだ。
        </txt>
        <img class="illustration" src="./image/大分県.png" />
        <aud class="serif-audio" src="./voice/001_ずんだもん（ノーマル）_今回は大分県名物、….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          とり天とは、鶏肉に片栗粉をまぶして揚げたもので、<br/>ソースや塩で食べるのだ。
        </txt>
        <img class="illustration" src="./image/とり天1.jpg" />
        <aud class="serif-audio" src="./voice/002_ずんだもん（ノーマル）_とり天とは、鶏肉に….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          とり天、おいしそうね。鶏肉はどんな部位を使うの？
        </txt>
        <img class="illustration" src="./image/鶏はてな.png" />
        <aud class="serif-audio" src="./voice/003_四国めたん（ノーマル）_とり天、おいしそう….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          鶏肉は、もも肉やささみ肉など、<br />好みに合わせて選ぶことができるのだ。
        </txt>
        <img class="illustration" src="./image/ささみ.jpg" />
        <aud class="serif-audio" src="./voice/004_ずんだもん（ノーマル）_鶏肉は、もも肉やさ….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          僕は、もも肉の方がジューシーで好きなのだ。
        </txt>
        <img class="illustration" src="./image/とり天2.jpg" />
        <aud class="serif-audio" src="./voice/005_ずんだもん（ノーマル）_僕は、もも肉の方が….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          もも肉、私も好きよ。
        </txt>
        <img class="illustration" src="./image/とり天3.jpg" />
        <aud class="serif-audio" src="./voice/006_四国めたん（ノーマル）_もも肉、私も好きよ。.wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          お腹空いてきたわ、とり天は、どこで食べられるのかしら？
        </txt>
        <aud class="serif-audio" src="./voice/007_四国めたん（ノーマル）_お腹空いてきたわ、….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          とり天は、大分県の飲食店でよく提供されているのだ。
        </txt>
        <img class="illustration" src="./image/とり天定食1.jpg" />
        <aud class="serif-audio" src="./voice/008_ずんだもん（ノーマル）_とり天は、大分県の….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          特に、別府市にはとり天専門店があるのだ。
        </txt>
        <img class="illustration" src="./image/専門店.jpg" />
        <aud class="serif-audio" src="./voice/009_ずんだもん（ノーマル）_特に、別府市にはと….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          とり天専門店、行ってみたいわね。
        </txt>
        <aud class="serif-audio" src="./voice/010_四国めたん（ノーマル）_とり天専門店、行っ….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          とり天は、どんな料理と合わせて食べるの？
        </txt>
        <aud class="serif-audio" src="./voice/011_四国めたん（ノーマル）_とり天は、どんな料….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          とり天は、ご飯やうどんと一緒に食べるのが一般的なのだ。
        </txt>
        <img class="illustration" src="./image/とり天うどん.jpg" />
        <aud class="serif-audio" src="./voice/012_ずんだもん（ノーマル）_とり天は、ご飯やう….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          また、キャベツや大根おろしと合わせると、<br />さっぱりとした味わいになるのだ。
        </txt>
        <img class="illustration" src="./image/キャベツとり天.jpg" />
        <aud class="serif-audio" src="./voice/013_ずんだもん（ノーマル）_また、キャベツや大….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          ご飯やうどんと一緒に食べると、お腹いっぱいになりそうね。
        </txt>
        <img class="illustration" src="./image/とり天丼.jpg" />
        <aud class="serif-audio" src="./voice/014_四国めたん（ノーマル）_ご飯やうどんと一緒….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          キャベツや大根おろしと一緒に食べると、栄養バランスも<br />良さそうだわ。
        </txt>
        <img class="illustration" src="./image/大根おろしとり天.jpg" />
        <aud class="serif-audio" src="./voice/015_四国めたん（ノーマル）_キャベツや大根おろ….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          そうなのだ。とり天は、大分県の人々に愛されている<br/>料理なのだ。
        </txt>
        <img class="illustration" src="./image/とり天定食2.jpg" />
        <aud class="serif-audio" src="./voice/016_ずんだもん（ノーマル）_そうなのだ。とり天….wav" />
      </layer>
      <layer>
        <txt class="serif zun-serif">
          ぜひ、大分県に来たら、とり天を食べてみてほしいのだ。
        </txt>
        <aud class="serif-audio" src="./voice/017_ずんだもん（ノーマル）_ぜひ、大分県に来た….wav" />
      </layer>
      <layer>
        <txt class="serif metan-serif">
          そうね、大分に行ったらとり天を食べてみたいと思うわ。
        </txt>
        <aud class="serif-audio" src="./voice/018_四国めたん（ノーマル）_そうね、大分に行っ….wav" />
      </layer>
    </seq>
  </cont>
</vsml>
```

</details>

上記のVSML/VSSファイルから以下の動画へ変換できます．
<iframe width="560" height="315" src="https://www.youtube.com/embed/Eij6n29Vj4U?si=PbmM9BfHloXn8rM4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

###### クレジット
VOICEVOX/ずんだもん・四国めたん

### 何が嬉しいのか
#### オブジェクトの整列・整頓の手間が少ない

動画編集ソフトにおけるオブジェクト(画像・音声・字幕・映像etc...)は基本的に他のオブジェクトの位置に依存せず，動画内の絶対的時間位置で配置を保持されています．
そのため，例えばセリフを読み上げる音声ファイルとその字幕を同じ時間だけ表示したいと思ったときに，音声オブジェクトが何秒から何秒まで再生されているか意識して，字幕オブジェクトの開始時間を揃えて，終了時間が揃うようオブジェクトを伸縮させて，といった作業が必要でした．
VSMLでは，例えばprlというタグがあり，このタグは子要素を時間的に並列に配置する(同時再生する)タグとなっています．そのためaudタグ(音声オブジェクト)とtxt(字幕オブジェクト)を子要素に与えると，音声が何秒から始まるかなど意識することなく，音声と字幕が同時に同じ時間だけ再生されるようになります．

```xml
<prl>
  <txt>こんにちは</txt>
  <aud src="こんにちは.wav" />
</prl>
```

#### 装飾を推敲する(修正を繰り返す)際の手間が少ない

一般的なアプリで動画編集を行う際，基本的にオブジェクトのもつパラメータ(大きさ，色，傾きなど)は各オブジェクトが持つものであり，それらを統括的に管理する手法が基本的にありません．(ただしプラグインなどで可能なものもあるらしいです)
そのため，例えば動画内に複数回登場する字幕(キャラクターのセリフの字幕など)の色を推敲したいといった場面を想定すると，各オブジェクト1つ1つを変更する必要があります．複数選択で多少手間は減らせますが，推敲のように何度も変更する場面では，色を推敲する操作の間に複数選択を何度も要求されるため，良い対処法とは言いづらいです．
VSSではCSSのように，VSMLにあてたclassに対して装飾を書けば，その装飾を変更するだけで，そのclassを持っている複数のオブジェクトの見た目を統括的に変更できます．

#### 動画編集データがテキストデータである

バイナリデータでなく人間が読み書きできるテキストデータという形式であることによる恩恵がいくつかあります．
まず，スクリプトや生成系AIなどの機械的に出力するフォーマットとして相性が良い点です．
動画を作成したいデータをCSVなどにまとめておき，VSMLに変換するスクリプトを書くこともできますし，将来的にはGithub Copilotなどを利用して，VSMLの記述を補助してもらいながら動画編集することも可能かと考えています．
また，GUIのない環境でも記述，動画生成ができるため，GPUを乗せたサーバに動画生成のみ任せて動画編集をしたり，軽微な修正ならCLI環境でもターミナルを開いて修正することができます．
さらに，Gitを利用することで動画編集データをバージョン管理することも可能となっています．

#### 動画内オブジェクトの構造の記述とオブジェクトへの装飾の記述が分離している

動画編集を行う際には，動画のコンテンツを作成する作業も，コンテンツのみやすさを整える作業も，同一のタイムライン上で行う必要があり，密接した操作になっています．
ですが，VSML/VSSの二つがそれぞれコンテンツの内容と構造・オブジェクトの装飾，とそれらの役割が分離しているため，一方を記述している際にもう一方を意識することなく記述を進めることができます．
また，別の人が作成・使用した装飾(VSSファイル)を使いまわしたり，参照する装飾(VSSファイル)を差し替えて複数の装飾を一括で変更することもできます．(その際動画変換の作業は必要ですが)

## VSMLコンバータ
前述のVSML/VSSを読み取り動画へと変換するコンバータを，Pythonを使用して実装しました．CLIのコマンドのように使用します．
XML読み込み時，XSDファイル(XMLのタグのスキーマを定義するファイル)を使用してバリデーションを行っています．
バックエンドにはFFmpegを使用しており，一つのVSMLファイルからワンラインのFFmpegのコマンドを出力して動画を書き出している実装になっています．

また，実際に使用する際にプレビューがないと動画編集が難しかったので，プレビュー機能も実装しております．`-f`オプションでフレーム数を指定すると画像が出力されます．

実際のプログラムは以下のリポジトリに載せてあります．

ここまで，コンバータが完成しているような言い振りをしましたが，VSSで設計したプロパティの内，対応できていないものも多く，特殊なパターンで発生するバグも大量に潜伏しており，プレビュー機能は数日で実装したのでほぼ未完成と，出来はボロボロです．ベータ版ができたら記事を書こうかとか呑気なこと考えてましたがアルファ版どころかプロトタイプです．最低限は動くと思うので，実際のVSML/VSSの使用感を試す際にお試しで使う分には役に立つかなと考えています…

https://github.com/vsml-org/vsml_converter_old

# 似たプロダクト
VSMLと似たプロダクトもいくつかありましたので，VSMLと同じ点・似ている点，異なる点，VSMLの有用性(なぜこれらを使わずVSMLを使う意味があるのか)に触れていきます．

## Remotion
- React.jsをベースにした動画編集ライブラリ
- 動画編集をテキストベースでできるメリットなど目的は近い
- 各オブジェクトの時間長を意識する必要がありそう(要調査)なのでちょっと手間
- あくまで動画編集技術ではなくReact.jsのレンダリング技術を使用した動画編集ライブラリなので若干ベクトルが違う
- ブラウザへレンダリングしてキャプチャを行うため，ボトルネックとなり**若干遅い**(現段階のVSMLコンバータに比べれば早いが)
- jsはおおかたライブラリが揃っているので，それらを利用して動画を作る点では**有用**
- 既存のCSSを使用して動画編集が可能であるため，**Webの知識があれば新しい学習が不必要**

### 公式サイト
[Remotion](https://www.remotion.dev)

## Synchronized Multimedia Integration Language(SMIL)
- VSMLと同じくXML記法でマルチメディアを記述する言語
- VSMLのseq, prlのように，seq, parといったタグがある(挙動もおおよそ同じく，時間軸の配置を指定する)
- 最終更新が2008年と**規格が古い**
- 現行のSMILプレイヤーがほとんど見つからず，mp4などの動画ファイルへのコンバータは見つからなかった(ない可能性もある)
- SMILはそれ単体でメディアとなるファイルであるが，VSMLは動画へ変換するための動画の構造を示すファイルである
- SMILではメタ情報で空間的位置を記述し本体部分で時間的位置を記述して，VSMLでは空間的・時間的位置どちらも本体部分で記述する

### Wikipedia
[SMIL](https://ja.wikipedia.org/wiki/Synchronized_Multimedia_Integration_Language)

# 今後の展望

最後に今後の展望と題して，これからやっていく予定のことや，こういう事できたら楽しいなって妄想，こうなってほしいという欲望を書き連ねていきます．

## やっていくこと
### 言語への機能追加

現段階では，まだコンポーネントとして分割し再利用する機能が言語として実装されていません．(実装するのはコンバータなので厳密には記法の規格がない)また，アニメーションを行うための機能もまだ存在していません．  
コンポーネントはVSML，アニメーションはVSSで機能を実現していくかなとは考えつつも，まだまだ詰められてはいません．

### コンバータのブラッシュアップ

現状存在しているコンバータは2023年の夏から冬にかけて半年で作成しました．そのため大急ぎで実装したため，機能不足であったり，言語仕様にあっても実装できていなかったり，仕様通りに動かないバグがあったり，とまだまだ未完成であるため修正していきたいです．
ですが，今後長期開発をしていくことを考えると，言語のリプレイスも行いたいなと考えております．候補は速度を考えてC++かRust，もしくはGoで実装していこうかと考えていますが，試験的に今Rustでリプレイスしようと動き始めています．まだHello,worldに毛が生えた程度ですが．

## 妄想
### GUIアプリ化

ここまで，動画編集言語としてVSMLを紹介してきましたが，実際VSMLにユーザが集まるかと考えると厳しいところがあると思います．プログラミング(厳密にはHTML/CSS)に詳しい人と，動画編集に関心がある人ないし動画編集を行っている人の積集合にしかささらず，本当に私のようなニッチな人しか喜べないのではないかと思います．
そのため，ターゲットを少しでも広げるために，VSMLの技術をバックエンドに，従来の動画編集アプリのようなGUIアプリを作成したいと考えています．

VSMLには従来の動画編集ソフトにはなかったような考え方もあり，VSMLはいくつかの要素を子要素に持つ親要素を操作することで，その子要素を意識せず一括して操作することができる，コンテナのような思考で動画編集ができます．そのため，VSMLをバックエンドにGUIアプリを作成しても，従来のGUIアプリとはまた違った供給になるとかんがえています．

また，Wasmを使用してコンバータを動かせたら，ブラウザさえあれば動画編集ができるSaaSとしての動画編集アプリの需要も狙えます．さらにElectronやTauriなどでデスクトップアプリ化すれば，OS問わず動画編集アプリが作れます(選択肢の少ないLinuxもターゲットにできる)．もしかしたらスマホで動画編集する時代も来るかも？

もっと欲張るなら，GPUサーバをサービスとして用意しておき，コンバートのプロセスのみそのサーバで行わせたら，PCのパワーがなくとも動画編集ができるという喜びがあると考えています．
そのGPUサーバを有料プランにして，GPUサーバ代を回収しつつ小銭稼ぎできたら嬉しいなとか…(小声)
ただこれに関してはサーバ上でコンバータのプロセスが動くため，セキュリティ面について十分に気をつける必要があるので，慎重に動かしたいなと考えています．

## 欲望
### VSML・動画編集言語の発展

言語・コンバータ・GUIアプリに関しては私の関心があるため，OSSで先導して動かしていきたいのですが，他の人がその技術を利用してもっと違うものを作ってくれたら面白いなと考えています．(そもそもOSSに参加してくれる人の方がいてほしいのですが)
メリットの点でも触れましたが，VSMLのデータを大量収集してGithub Copilotみたいな生成系AIを作成するなんかもありかなと思います．他編集ソフトのVSMLプラグインとかも面白いかもですね．

また，言語・コンバータ・GUIアプリは私が開発すると述べましたが，VSMLコンバータを使ったもっとモダンなGUIアプリを作ってやるぜ! いや，VSMLをもっと高速で出力できるVSMLコンバータを作ってやるぜ!! いやいや，VSMLなんて言語は糞だ！VSMLをベースに俺が新しい動画編集言語を作ってやるぜ!!!!なんて人も大歓迎です．
私の考えには賛同するが仕様には賛同できないって方は色々生み出していってほしいです．対立する企業なんて生まれたら面白いかも．いや，企業なら協力してくれる方が嬉しいな…

## 宣伝

散々俺と違うもの作れ！みたいな話をしてきましたが，決して協力してほしくないわけではないです．一日でも早くVSMLが使い物になってほしい，それを使って動画編集したい，あわよくばそれを使ってほしいので，VSMLのv1.0.0へ向けて協力してくれる方を待っています！

まだ気が早いですが，VSMLを開発していくOrganizationも作成しました．
VSMLコンバータの開発が軌道に乗り，アルファ版，ベータ版くらいまで開発が進んだら，関心を抱いていただけた人はぜひ開発にコントリビュートしていただきたいです！

https://github.com/vsml-org

# おわりに
最低限の望みとしては，テキストベースで動画編集をできる技術が発展していくことです．Remotion.jsなどは発達しているものの，まだまだ発展していってほしいなという気持ちです．あとその技術のユーザになりたいです．根源のきっかけはそこなので．
最大限の望みは，動画編集技術の選択肢の一つにVSML(とそれのGUIアプリ)が挙がり，VSMLで動画を作っているという人の動画を動画投稿サイト(Youtubeやニコニコ)で見ることです．動画編集技術であるため，これはVSMLで作られた動画だ！と気づくのは難しいと思うので，概要欄にでも書いていただけると一人ホームパーティ開催して小躍りして喜びます．