かるたの試合動画内で上の句が詠まれる時刻を出力するプログラムを作った
はじめに
競技かるたが趣味なのだが、近所に練習環境がないため、1人で札を並べて取るといういわゆる1人取りをたまにしている。普通の対戦と異なり1人取りの悲しいところは、感想戦ができないことである。仕方ないのでスマホで動画を撮影し、1人反省会をしている。
1試合の動画の長さは約1時間となるがその中で見るべきなのは、余韻から上の句の6文字までの間の、札を取る数秒間である。それ以外の上の句後半や、上の句と下の句の間は視聴する必要がない。このため、もし動画内で100首の余韻から上の句前半の時刻を知ることができれば、その時刻にスキップしながら効率よく視聴することができる。
また最近ではYouTubeで名人戦などの動画も上がっているが、これも同様に上の句が詠まれる時刻を知ることができれば効率よく視聴できてハッピーである。シークバーをちょっとずつ動かしたり矢印キーで5秒ずつスキップするあの地道な作業が不要になる。
というわけで、かるたの試合の動画から、上の句が詠まれる時刻をまとめて出力するpythonプログラムを作ってみた。
プログラムの概要
かるたの試合の動画ファイルを入力すると、その動画内で上の句と下の句の境界を検知して、その時刻をテキストとして出力する機能をpythonプログラムとして実装した。
動画ファイルとは言っても、プログラム内では音声のみを抽出している。また出札と空札の識別はしておらず、すべての上の句の開始時刻を出力している。
実際の動画を用いたデモ
下記リンク先の第68期名人戦の動画において19:47から開始される試合に対して適用した結果をデモとして示す。
[SUB]小倉百人一首競技かるた 第68期名人位・第66期クイーン位 決定戦 [ サブチャンネル・解説なし] - YouTube
上の句開始時刻として出力されたのは82件だった。すべて書くと長くなるため最初の20件だけを記載する。1つ1つ確認はしていないが、概ね合っているようだ。
- 00:22:12
- 00:22:58
- 00:24:15
- 00:24:45
- 00:25:16
- 00:26:03
- 00:27:19
- 00:28:34
- 00:29:26
- 00:30:16
- 00:30:45
- 00:31:38
- 00:32:09
- 00:32:46
- 00:33:31
- 00:35:21
- 00:36:03
- 00:36:34
- 00:37:12
- 00:37:44
しくみ
今回実装した動画内の音声から上の句開始を検出するための方法はいたってシンプルである。ざっくり言うと、下の句→余韻→間→上の句 の流れにおける特有の音量変化を捉えるという方針である。つまり「動画を少しずつ見ていき、数秒間音量が高い時間が続いてから一瞬静寂になり、そしてまた数秒間音量が高いというタイミングを探す」という感じ。具体的な処理の流れは次の通り。
動画内の音量の時間変化を数値化する
動画ファイルを読み込み、音量の時間変化を数値化する。librosaというライブラリを使うとそのあたりの処理が簡単にできるのでありがたい。
また移動平均をとって変化をなめらかにしている。上の句と下の句の間に畳を叩く音が入っていても、少々なら移動平均をとるとうまく消えてくれるようだ。
可視化すると下図のようになる。
音量が小さい区間を特定する
下の句と上の句の間を見つけるため、ある閾値よりも音量が小さい区間を探して列挙する。閾値の設定次第で結果が大きく変わるため、気合を入れて調整する必要がある。
音量が小さい各区間について、長さが適切か判定する
前項の方法で見つけた「音量が小さい区間」には、上の句と下の句の間と下の句と上の句の間の両方が含まれてしまう。今回検出したいのは後者なので、列挙された区間の中からその時間が約1秒であるもののみを選び出す。詠み方が4-3-1-5方式としてしっかり定められていて助かった。
厳密には他にもいくつか処理をしているが、大まかにはこのようにして残った区間の終了時刻を、上の句の開始時刻として出力する。
おわりに
今回作ったpythonプログラムはお試し段階であり、まだあまり美しく書けているわけではないので、もう少しイイ感じにブラッシュアップしてから公開したい。
上の句の開始時刻を検出することはできたので、次はその札が出札なのか空札を識別できたらもっと便利になる。おそらく音量だけで識別するのは難しく、札が飛ぶ特有の音で識別する必要がありそうなので、短時間フーリエ変換した値を特徴量とするといいかもしれない。ただし特徴量は高次元になるので、機械学習を活用するのがよさそうだ。
また、pythonで動画を編集可能なライブラリもあるようなので、上の句の開始時刻をもとに動画を切り出してつなぎ合わせることもできる。いわばハイライト動画のようなものが自動的に作れる。1首あたり6秒と仮定すると、1試合では10分くらいの動画にまとまる計算になる。
以上3点、気が向いたらやってみたい。