[ゆる記事] TiDBの（非公式）マスコット ピンちゃんを動かす

この記事は[TiDB Advent Calendar 2023](https://qiita.com/advent-calendar/2023/tidb) の二日目です。
二日目にして早くもTiDBそのものの記事ではないゆるふわ記事です。

## ピンちゃんとは
ピンちゃんとは、TiDBの普及のためにPingCAP日本法人が作ったゆるキャラの名前です。公式ではないので公式サイトには出てこないのですが、プレゼン資料などではたまに使われており(たとえば[ここ](https://speakerdeck.com/pingcap0315/tuo-siyadeingu-newsqlnotidbdeshi-xian?slide=3))その何を考えているのか分からないつぶらな瞳で多くのTiDBユーザーを虜にしています。

![TiDB_koiB.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/b0cb3c6a-8b45-0f2e-83c6-a8be47e0f274.jpeg)

鯛はTiDBのTiからきており、体が赤ではなくグレーなのはTiDBのもともとの由来であるチタニウムを意識していたと聞いています。


数年前にAsakusa Frameworkの[屋形船を動かすコマンドラインツール](https://qiita.com/bohnen/items/b57967a2c427870d669e)を作ったので、その~~二番煎じ~~インスパイアでこのピンちゃんを動かそうというのがこの記事になります。

## Ascii Art化の挫折
早速ピンちゃんの下絵を元にアスキーアートを作ろうと思ったのですが、これがかなり難航しました。。。というか挫折しました。ピンちゃんの扇のあたりを動かそうと思ったのですが、扇を表現するのが難しいのと、そもそも縦に長くてターミナルで表示すると妙に間延びした感じになるのです。別の手を考えます。

```text
                                                           ┌─────────────┐
                                                           │========    =│
                                                           │=====    ====│
                                                           │==     ===  =│
                                                           │       ==   =│
                   **********                              │====   ==   =│
               ***************                             │====   ==   =│
              **************************                   └─────────────┘
              ****************      **********                            
             ***************     ***          *****      *                
              *************     **                 *** ***                
              ***********      **       .─────.      *****  **            
               *********      **       ╱  ***  ╲       ** ***             
               ****************       (  *   *  )     ******              
                ******                 `. *** ,'   (((     *              
    ********     ***             *       `───'   ((        * ****==       
     *      *****                **           (((          ***    =       
     **        *                  *         ((             *   **=        
      *   ******                  **      ((               *  **          
    ***      **    ^^            ******  (('              ******          
    **      **    ^^^^        ***    ****(               **               
     *  *****      ^^       ***   ****   ****            **               
     *     *              **       *    **              **                
    **    *              ******* ***   **              **                 
  **** ****                    *** ** **              **                  
     *    *    ^^              *    ***              **                   
    **    *    ^^          ^       ((              **                     
   **   ***     ^         ^^^^    ((              **                      
*****     *                ^^     (        **    **                       
    ***   *                       (      ***** ***                        
      **  ***      ^              (     **   **                           
       *    *    ^^^^^           ((   ***    *                            
       ***  ***    ^             ((  **   *  *                            
         **** **                  ( **   **  *                            
            *****          ^      ((*   **  **                            
                ***       ^^^     '*    *   ***                           
                  ****             *   *      ******                      
                      ****             *           *****                  
                         **********   ******           **                 
                                   *        ******      **                
                                    ********        *****                 
                                          ***********       
```

# Gifアニメをターミナルで表示する

普通にGifアニメや、最近ならAIで動画を生成すれば、、、とおも思ったのですが、やっぱり普段使っている環境で素早く見れてこそのマスコット（？）なので、ターミナルに表示することにこだわりたいと思います。
ASCIIエスケープコードでカラーも表示できますから、これを使って画像をターミナルに表示するコマンドは世の中に存在するだろうと思って調べると、やはりあります。色々ありましたが、ここではgoで実装された[imgcat](https://github.com/danielgatis/imgcat) を使います。Gifアニメの表示にも対応しています。
MacOSの場合、インストールはbrewで出来ます。

```
brew install danielgatis/imgcat/imgcat
```

何をしているかソースを見てみましょう。実際に画面に出力しているのは [main.goのescape](https://github.com/danielgatis/imgcat/blob/91f282f8938a54c4f766b162ede5355de45553d1/main.go#L192)です。ここでは下記のように元画像をy軸二行ずつ処理して、1行目を背景色、2行目を前景色として表示しています。

```go
		for y := 0; y < maxY; y += 2 {
			go func(y int) {
				var sb strings.Builder

				for x := 0; x < maxX; x++ {
					r, g, b, a := f.At(x, y).RGBA()
					if a>>8 < 128 {
						sb.WriteString(ANSI_BG_TRANSPARENT_COLOR)
					} else {
						sb.WriteString(fmt.Sprintf(ANSI_BG_RGB_COLOR, r>>8, g>>8, b>>8))
					}

					r, g, b, a = f.At(x, y+1).RGBA()
					if a>>8 < 128 {
						sb.WriteString(ANSI_FG_TRANSPARENT_COLOR)
					} else {
						sb.WriteString(fmt.Sprintf(ANSI_FG_RGB_COLOR, r>>8, g>>8, b>>8))
					}
				}

				sb.WriteString(ANSI_RESET)
				sb.WriteString("\n")

				c <- &data{y / 2, sb.String()}
			}(y)
		}
```

ANSI_BG_* や ANSI_FG_* の定義を見てみると、[ASCIIエスケープコード](https://en.wikipedia.org/wiki/ANSI_escape_code)でそれらを指定していることがわかります。さらにFGでは "▄" を前景色で描画しているのがわかります。そのため、余白部分が背景色の色、"▄"が前景色で描画されます。

これで描画の準備は整ったので、あとはアニメGifを用意してコマンドに渡すだけです。アニメGifを作るのが何気に一番手間のかかるところです。

そしてできたのがこちら。ターミナルの録画には、[t-rec](https://github.com/sassman/t-rec-rs)を利用しました。はからずもTiDBのように、go製ツールとrust製ツールを利用しています。
![t-rec_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/af979d63-da66-7b98-570b-341a9d2eeae7.gif)

味があって良いですよね！？

## おまけ

手っ取り早く生成AIで動く動画つくっちゃえば...という気持ちもあったので、[RunWay](https://runwayml.com/) でピンちゃんごと動画を作るのにチャレンジしました。画像そのまま使っちゃうとなんかチートだなという気がしたので、「野球帽をかぶった鯛が扇を持って踊る動画」みたいなプロンプトで生成にチャレンジしたのですが、、、

あーうんそうだよねーという結果
![pingchan1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/83ccce89-226d-72ce-2ac9-90c9498d8afa.gif)

「アニメ調でかわいらしく、扇を振る感じで」を追加したらそっちじゃねーよって感じになりました。
![pingchan2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/9bb9938b-4683-9d0b-8907-918af7e081fa.gif)

改めて「鯛に野球帽をかぶらせて扇をふらせる」という謎の発想に感心しました。