イラスト専用のデータベース作成ツールを個人開発しています
Pintelier v0.1.0リリースのお知らせ
- Go
- SvelteKit
投稿日: (最終更新日: )
もくじ
はじめに
Try it out!
本稿で紹介するソフトウェア「Pintelier」は、こちらからダウンロードできます(v0.1.0現在、Windows環境にのみ対応しています)。「技術的な内容はどうでもいいからはやく使わせてくれ」という方はご自由にお持ちください。
問題提起
突然ですが、みなさんは人間にイラストを見たり描いたりする習性があることはご存じでしたか?もしかするとみなさんの中にもイラストを見たり描いたりしたことがある方がいるかもしれません。――情報を絵画にして残すことの歴史は極めて長く、発見されている壁画のなかでも最古のものは6万5000年前に描かれたそうです。そして、それらと同時に人類が向き合ってきた問題がイラストの保存と管理です。情報のデジタル化が進んでもなお、我々はプラットフォームのサービス終了による作品の消失や参考資料の収集と管理について悩んでいます。とくにプラットフォームのサービス終了については2022年ごろのX(当時はTwitter)を巡る騒動で多くの人に現実的な懸念として認識されるようになったのではないでしょうか。
また、イラストの検索性も完璧な状況とは言えません。現在のSNSやイラスト投稿プラットフォームが採用している単純なタグシステムは、タグどうしの親子関係や表記ゆれ、別名などを適切に扱えません。ましてや自身のデバイスにイラストを保存する場合は検索性など夢のまた夢です。
さらに、イラストを描くための参考資料を収集するうえで喉から手が出るほど欲しくなるのがイラストの適切なリスト機能です。参考資料を一か所にまとめるだけならExcelやPureRefといった既存のツールでも可能ですが、毎回画像ファイルを探してコピペしてくるよりもイラストの管理ツール上ですべてが完結したほうが楽なのは明らかです。
Pintelierのご紹介
あのツールもダメ、このサービスもダメ……ならば、自分で最強のツールを作るしかない。そうして生まれたのがイラスト専用のデータベース作成ツール「Pintelier」です。実を言うとPintelierは2022年末に開発が始まったツールだったのですが、途中で投げ出してしまい、1年ほどほかのソフトウェアやWebアプリたちの中に埋もれていました。しかし、最近ふとその存在を思い出して最低限やりたいことが実現できるレベルまで開発を進めたので「とりあえず世の中に出しておこう」という意味も込めてv0.1.0を公開することにしました。
本稿ではPintelierがどのような理念や技術に基づいていて、どこまで開発が進んでいるのかについて説明します。
設計理念と仕様
Pintelierはまず筆者自身が使いたいツールにするということを第一に開発しています。日常的にほかのイラストレーターの作品を見たり作品を作るために参考資料を集めたりしているので、イラストを見る側と描く側両方の気持ちを理解できているつもりですし、そもそも開発者が使わないツールは誰も使ってくれません。そのうえで、以下のような設計理念を掲げています。
- 堅牢なタグシステム
- シリーズもの作品の総称と個別の作品名のような、タグ間の親子関係を表現できる。
- 別名機能によって表記ゆれを吸収できる。
- これにより、同じ主題が描かれたイラストなのにタグがバラバラについてしまうことを防止できる。
- イラストのグループ化機能
- タグとは別に「ブック」という単位でイラストをまとめられる。
- バックアップの容易な設計
- アップロードされた画像は軽量なフォーマットであるWebP形式にロスレス変換される。
- 画像はPintelierの実行可能ファイルと同一階層のフォルダ内に画像ファイルとして保存される。
- ユーザーはこのフォルダをコピーするだけでデータをバックアップできる。
- シングルバイナリ・外部依存ゼロ
- Node.jsやMySQLのような外部のソフトウェアを必要とせず、ダウンロードしたらすぐに使える。
- クロスプラットフォームなWebUI
- UIをWebアプリとして提供する。
- ネットワーク内のあらゆるデバイスからアクセスできるため、自宅サーバーやVPS上でセルフホストできる。
タグシステムの設計
文字だけで「親子関係が~」「別名が~」と書いてもわかりづらいので、図を用意しました。
この例では「アイドルマスター」と「学園アイドルマスター」および「学園アイドルマスター」と「篠澤広」の間に親子関係が定義されています。また「アイドルマスター」と「学園アイドルマスター」にはそれぞれ別名も定義されています。これらの機能はイラストの検索時とタグの検索時に役立ちます。まずは親子関係のほうから見てみましょう。
タグ間に親子関係が定義されていると、関連するタグのつけられたイラストを簡単に見つけられるようになります。例えば、文字列がイラストに紐づいているだけの単純なタグシステムの中では「『学園アイドルマスター』のキャラクターが登場するイラストだけど『アイドルマスター』と検索したときも表示されるようにしたい」という場合に両方のタグをつける必要があります。ところが、そうすると今度は「シリーズではなく単一の作品としての『アイドルマスター』のイラストを見たい」というユーザーが困ることになってしまいます。もちろんNOT検索を活用すればシリーズ内の他作品を除外して検索できますが、アイドルマスターシリーズのすべての作品を検索クエリに列挙するのは現実的ではありません。
一方、親子関係を持つタグシステムであれば「アイドルマスター」というタグで検索するだけで自動的に「学園アイドルマスター」や「アイドルマスター シンデレラガールズ」などのタグがつけられたイラストが表示されますし、反対に子タグを除外する設定にすれば単一の作品としての「アイドルマスター」のイラストのみが表示されるようになります。
続いては別名機能の説明です。例にもある通り、多くの作品はさまざまな略称や別名を持っています。イラストレーターたちも自分のイラストへ好きなようにタグをつけているため、イラストを検索するためには表記ゆれを網羅するか、諦めて特定のタグだけを見るかを選ばなければなりません。既存のプラットフォーム上での投稿についてはともかく、同じ現象が個人用のアーカイブでも発生するのは困ります。この問題を解決するため、Pintelierでは別名機能を実装しています。
別名機能の存在によってタグの作成時に正式名称だけでなく別名も登録できるため、タグ検索時の表記ゆれを吸収できる設計になっています。
データ設計
フロントエンド向けにランダムなIDを用意していることを除けばさほど複雑なことはしていないデータ構造だと思います。FKがUUIDではなくNano IDなのは、クエリ文字列としてURLに含めることを想定しているためです。また、タグの別名が専用のテーブルに格納されているのは「配列型が存在しない」というSQLiteの技術的制約によるものです。
テーブルどうしの関連性を図にするとこのようになります。
技術選定
Pintelierは技術的な知識がない人でも使いやすいソフトウェアであることを設計理念としています。そのため、シングルバイナリにコンパイルできて、外部依存ゼロで動作することを目指して技術選定を行いました。また、UIをWebアプリとして提供することに決めたので、そのためのWebフレームワークもあわせて選定しました。
バックエンド: Go
データベース操作や画像の配信・処理を担当するバックエンドにはGoを使うことにしました。主な選定理由はシングルバイナリにコンパイルできることです(当時の筆者がGoとTypeScriptくらいしか書けなかったという理由もありますが……)。
データベース: SQLite
外部依存ゼロを目標にしているため、必然的にデータベースの選択肢はSQLiteしかありませんでした。SQLiteはデータベースを単一のファイルとして扱えるので、バックアップやデータ移行が簡単に行えるのもうれしいところです。データの読み書きにはentを使用しています。
フロントエンド: SvelteKit
WebUIのフレームワークにはSvelteKitを採用。プロトタイプではNuxtを使っていたのですが、いろいろなフレームワークを試してみたくてSvelteKitに乗り換えました。NoboNobo氏の記事を参考にして、実行可能ファイル内にフロントエンドを埋め込んでいます。
UIフレームワーク: Tailwind CSS + shadcn-svelte
もともとはSCSSでスタイリングをしていたのですが、プロジェクト再始動にあたってすべてをTailwind CSSに置き換えました。カードやモーダルなどのコンポーネントは自力で実装していますが、ドロップダウンメニューやページネーションではshadcn-svelteを利用しています。
現在の進捗
v0.1.0時点で実装できている機能と今後実装予定の機能についてまとめておきます。
実装済みの機能
- タグの登録・編集機能
- イラストの登録・編集機能
- ブックの作成・編集機能
- イラスト登録時の重複検知
- イラストと一緒にSHA-1ハッシュをデータベースに格納しておき、それと比較することで同じ画像ファイルを登録することを防止する機能
- イラストのロスレス圧縮機能
- ファイルサイズ削減のために画像をWebPにロスレス変換してから保存する機能
- メタデータが消えてしまうので、将来的にはオプトアウト可能にする予定です
実装予定の機能
- WebUIのモバイルデバイス対応
- LinuxやmacOSへの対応
- イラストの検索機能
- いまのいままで検索機能がないことを忘れていたので、検索機能についていろいろ書いたわりに何も実装できていません(なんで?)
- WebUIの最適化
- 1年間放置していたこともあり「なんか動いてるからリリースしようぜ」の精神でリリースを決めたので、現状ではフロントエンドでのタグやブックの持ち方がめちゃくちゃなことになってしまっています
- ベンチマークもプロファイリングも実施していないので実際どのくらい問題があるのかは分かりませんが、タグを1000個くらい作ったらタグの管理画面が爆発するかもしれません
- 画像圧縮パフォーマンスの改善
- 「こういうのはバックエンド側の仕事な気がするな」と思ってsharpからchai2010/webpに乗り換えたところどういうわけか圧縮処理が大幅に遅くなってしまったので、ライブラリが悪いのか設計が悪いのかを突き止めて対応する予定です
- ――と思っていたらsharpを意識して開発されたlibvipsのGoバインディングが見つかったので、そのうちこれに置き換えようと思います
おわりに
Pintelierは趣味でプログラミングをしている筆者の経歴上ではかなり巨大なプロジェクトです。さまざまな機能が欠けた状態であるとはいえ、まずはリリースできたことを素直に喜ぼうと思います。
プログラムの設計原則などの知識が薄かった1年前に書いたコードということもありところどころにアレな箇所があるので、今後は機能追加をしつつそういった技術的負債を返済していきたいと考えています。いつになるかはわかりませんが、人に見せられるところまで改善できたらOSS化するつもりです。
おまけ: リリース直前になって「操作が複雑なソフトウェアだし、ユーザーマニュアルを用意しておこう」とマニュアルを作り始めたのですが、これが予想以上に大変でした。数年後の世の中ではLLMとSeleniumとかでマニュアルを自動生成するようになっていたりするんでしょうか。