📹

【個人開発】新卒エンジニアがアニメ投稿サイトを作った話

2025/01/17に公開

はじめまして。
2年かけてアニメ投稿サイト(動画投稿サイト)を開発したので、なぜ作成したのかや、技術的な部分について話していきたいと思います。

こちらにもリンクです。
https://anishare.net

こちらにも投稿しています。
https://anishare.fanbox.cc/posts/9202817

背景と動機

私は投稿サイトで個人制作のアニメーション(indie_anime)をよく見ます。
気になった作品はいいねを押したり、ブックマークに追加して見返しています。

しかし、そのような投稿サイトでは個人が制作したアニメだけを調べたりするような機能はありません。またアニメには2D,3D,実写系など複数のジャンルに分かれており、これらをフィルタリングして調べることは困難です。

そこで「個人制作したアニメを投稿できるサイト」があれば、個人でアニメを制作する人、検索する人が双方幸せになれるのではないかと思いつくってみました。

つくったもの

あにしぇあ というアニメ投稿サイトを作りました。
メールアドレスで登録できます。

視聴者側向け機能

ジャンルごとに細かくフィルタリングでき、タグをつけて検索ができます

投稿者向け機能

動画からサムネイルを生成できます

動画が変換されている進捗をみることができます

↓数人アップロードしているのでアップロードを待っている様子

動画変換中

動画のアップロードが完了

サイトの特徴

  1. カテゴリを細分化
  2. オリジナル機能
  3. 1分以上の動画はアップロード不可
  4. 規制なし

カテゴリの細分化

ひとえにアニメと言っても2D,3D,実写系があります。

  • 2D

    • 手書き
    • Live2DやAfterEffectを利用した動くイラスト
    • ピクセルアニメーション
    • うごくメモ帳
  • 3D

    • BlenderやMaya
    • MMD
    • CG系
    • コイカツ
  • 実写 コマ撮り

    • クレイアニメ
    • フェルト
    • 可動フィギュア

このように普通の投稿サイトの視聴者側があまり意識していないだけでアニメーションの種類はたくさんあり、このサービスではカテゴリごとに検索をして見ることができます。

オリジナル機能

アニメ制作者が何を頑張って作ったのかオリジナル要素を選択することができます。モーション、モデル、キャラクターなど一目でわかるようになっています。

1分以上の動画はアップロード不可

オリジナリティの高い作品を投稿するハードルを下げるために作成しました。またアニメーションを作成するうえで、1フレーム1フレーム動きにこだわって作ってほしいという意図があります。

規制なし

自由な創作活動の場になってほしいという思いから特に表現の規制は設けていません。ただし、日本国内の法律は準拠する必要はあります。

現状の問題点

  1. マネタイズ
  2. サーバー費用
  3. 音楽が利用できない

マネタイズ

マネタイズは考えていません。ランニングコスト分のサーバー費用を確保できればいいと考えています 。

サーバー費用

サーバー費用は冗長性を考えると5万円/月かかります。正直めちゃくちゃきついですが、出せない金額ではないのでとりあえず問題はないと考えています。

音楽が利用できない

アニメを制作する中で音楽をBGMやダンスなどで利用したいことがあると思います。このサービスではそのような音楽は利用できません。別途個人でJASRACや音楽の権利者と直接契約する必要があります。

ただ、いずれは音楽を利用したアニメーションも投稿できるようにJASRACと契約ができればいいなと思っています。

技術

アーキテクチャの方針
クラウドに依存しない設計
S3は代替の選択肢がいくらでもあるので採用する
認証系自作
キャッシュサーバー自作(kotlin)

  • Nginxが思った以上に使いにくかったため(SSLや、プロキシ用途では利用しています)

使用技術

フロント
TypeScript
React
tailwind
zustand

バックエンド
Kotlin
ktor
exposed → jooq
Quartz Scheduler

ミドルウェア
meilsearch
postgres
fluentd
ansible
nginx
fluentd

フロントの状態管理

useStateを利用してをコンポーネントを作成してしまうと、UIと状態が結合してしまうため意図しないバグが多発しました。またローカルで持っているのでその状態が変化されたタイミングを知るためにuseEfectを利用したコードを書くことになるのですがこれが非常に大変で、変数が変わったとしても再レンダリングが発生してほしくない場合もあり、レンダリングを制御するためのコードを書いたりと...到底人間が制御できるとは思えませんでした。それを解決したのがzustandです。

zustandが最高

このサービスでは複雑な状態をzustandですべて管理しています。検索機能、動画の状態、動画を投稿する際の状態遷移など。zustandがなければこれらの機能はバグだらけで使い物にならなかったのではないかと思っています。zustandを採用して本当に良かったです。唯一の欠点とすれば状態を単一のストアとして管理するためストア自体が非常に大きくなることです。まだ解決を見つけられていませんが、それでも開発体型は本当に素晴らしいです。Reduxと違い簡単にいれて使える点も魅力的です。

なぜKotlinを採用したのか

理由としては単純で私自身Minecraftのサーバープラグインを作成していた経験があり、Kotlinが好きで、一番使いやすい言語と思っているからです。当初はGoとTypeScriptの採用も検討していましたが、Goはパフォーマンスに特化した言語のため表現力があまり高くない(シンプルすぎる)こと、TypeScriptは外部から値を与えられたケースだと型チェックがすり抜けるので不採用にしました。(今バックエンド開発するならTypeScriptでもいいのかな思っています。ただ、未だにエラーハンドリングなどのベストプラクティスがよくわかっていないので、バックエンドとして採用するのは怖い気持ちがあります。)

Kotlinを採用してどうだったのか

今回Kotlinを採用して正解でした。KotilnはJavaのライブラリも使えるので基本的にないものを心配する必要性がありません。それに加えてORMがSQL Likeのものが多くデータベース関連が扱いやすいです。またジョブスケジューラに関してもRDBをDataSourceとしているため、インフラコストを抑えたい身として非常にありがたいです。(Redisは冗長化するのが大変な印象)

exposed→jooq

exposedでは機能不足になるのではという危機感から途中でjooqにすべて書き換えました。

バックエンドのアーキテクチャ

戦略的DDDを採用しました。まだDDDを完全に理解できているわけではないので技術的に採用できる点を考えて実装をしました。kotlinはDDDの記事が沢山あるので参考にして実装しています。

現在のサーバーの数

DBのプロキシ
APIサーバー
バッチサーバー
キャッシュサーバー
検索サーバー
フロント配信サーバー
ログ集約サーバー
監視サーバー
これを冗長化するので11台ほどのサーバーがあります。ほとんどが1GB、1コアのインスタンスですが、バッチサーバーは動画を変換する関係で3コアのサーバーを利用しています。(まだ監視サーバーは作れていません)

一番大変だったこと

動画のアップロード処理を作るのに5回ほど作り直しました。最初は動画の変換処理を同期的に行えばいいと思い実装しました。投稿される動画を作るには5つ(サムネイル用、自動再生サムネイル用+p1020用、p540用)作成する必要があり2分ほど待たされることがわかりました。また同時に多数のユーザーがアップロードするとその分余計に待つことになります。これはまずいと思い何度もアーキテクチャを作っては壊してを繰り返し、最終的にバッチ処理を利用した非同期システムを作りました。今ではサーバーを追加することで、簡単にスケールすることができます。それに加え、自宅サーバーからも変換処理が行えます。なのでGPUを利用した変換処理も可能になりました。将来的にはav1にも対応したいと考えています。(クラウドを利用していた場合GPUインスタンスはAI用のものがほとんどなので、最低でも数万/月はします。)

そもそも何も知らなかった

1年前まではバッチ処理がどのようなものなのかがわかりませんでした。たまたまLambdaを利用したバッチ処理の実装を見る機会がありました。それからバッチ処理の具体的な動きがどのようなものなのかを理解することができ、ジョブスケジューラを利用すれば同じシステムを作れる事がわかったのでその知識を利用して今のアップロードシステムを作りました。

モノリスが良いという話

最初はAPIサーバー、検索サーバー、アップロードサーバーなどをgradleのサブプロジェクトとして切り出し、大きな機能ごとにプロジェクトごとに分ける方針にしていました。理由としてはそちらのほうがシンプルになると思ったからです。しかし実際は真逆で、共通化しないことによる認知負荷がそれなりに発生するようになり、プロジェクトごとの依存関係が相互依存状態になってしまい大変でした。そこでわざわざ切り出さなくてもいいのではと思い、思い切ってモノリスにしてみたところロジックがシンプルになり、アーキテクチャとしても見通しが良くなりました。

なぜクラウドに依存したくないのか

イラスト依頼サイトが突然サーバーを停止させられたという話をニュースで見たので、クラウドに依存しないように設計しました。
また、コストの削減という面で一部オンプレで動かしたいところもあったため極力依存しないような設計にしました。なのでもしものことがあれば、自宅でも動かすことができます。

そもそも動画投稿サイトってどうなの

動画投稿サイトをつくる人はほんとに少ないと思います。個人で作っている人は自分ぐらいしかいないんじゃないかと思いながら開発してきました。サービスを作ると決めたときは学生だったので「作れないかも」と思っていたのですが、なんとか動く状態にまで持ってこれました。またランニングコストもできる限り減らせるような工夫もしました。なので世界で使われるようなサービスになってほしいと思っています。いずれ、アニメーションを見ると言ったら「あにしぇあ」があるよ!とかアニメ投稿サイトで「あにしぇあ」というサービスがあるらしい。みたいな話をアニメーションを好きな人たちが共有できるぐらいのサービスの大きさになってほしいと思っています。

ぶっちゃけなんでここまでするの(したのか)

大きいサービスを作りたいという気持ちとそれに加えて、幼少期からアニメや動画が好きでずっと見てきたので何かしらの形で関わりたかったというのが原動力です。またアニメ関係のクエリエイターとつながりを持ちたいという気持ちから続けることができました。

これからについて

まだスタート地点に立っただけなのでこれからもサービスとして価値が提供できるように頑張っていきます。自分のサービスをきっかけに個人制作のアニメーションに興味を持って新しいクリエイターが生まれるような環境を作っていけたらいいなと思っています。

↓アンケートも作りました。質問は2つだけなのでぜひ回答してください!
https://forms.gle/VbvXL3SzpCCQZjPY6

Discussion