どーも、どくぴーです。
2024/9/11〜2024/9/13にDroidKaigi 2024が開催されました。今年もスタッフとしてお手伝いをさせていただきました。
今年も車を運転して物を運んだり、いろんなことをスタッフとしてもやってたなぁと思うんですが、当日会期中はカメラをもって会場内をあっちこっち歩き回っていました。
もっているカメラにやたらとデカいsomethingがひっついていたり、謎の様相を呈していたので見かけて不思議に思った方もいるのかな〜、とか思っていました。
スキマ時間を縫って以前から試していた写真共有フローも新しく開発し直し、「写真爆速上げるくんV3」が完成したのでその本番運用の機会でもありました。
そんなわけでこの記事は参加レポートの体をした下記記事の続編となります。
前提:写真爆速上げるくんV1について
上記記事でも言及しているtry! Swift Tokyo 2024でお手伝いに参加した際に運用した写真を高速にアップロードするシステムのことです。
ビューワとしてPHPを多少書いた程度で、実際はほとんどなにか手を加えることなくソニー製のアプリを使って写真を打ち上げる技術検証的な要素を多分に含んだものでした。
技術検証として運用した結果、やりたいフローを実現できはしたものの以下の問題が残っている状態でした。
- スマホのWi-Fiテザリングで運用している以上、以下の課題がある
- 最大1000枚オーバーの写真から必要な写真を選ぶ運営サイドの負荷がある
- 広報で使う写真を選ぶ、幕間のスライドショーに使うなど
- フロントエンドがページング付きとはいえ単純な写真一覧だと、時系列で並んでいるだけでは満足ではない
というわけでこれらを解決するには…作るしかねえな!ということでDroidKaigi 2024での写真爆速上げるくんV3に繋がります。
余談:V2はどこに行ったのか
V2はKotlin Fest 2024でカメラマンとしてお手伝いしていたときのものです。
システムとしては何も変化していないんですが、アップロード用の機材がPixel 8から Sony PDT-FP1 のレンタル品に切り替わっています。
ありがとうございました!今日はこんな機材でカメラマンを担当しました!PDT-FP1、やはり求めていたものな感じはあるけど自分用にも買おうか迷うなぁ…。
— どくぴー (@e10dokup) 2024年6月22日
すぐに当日の写真が出てくる体験を作るの、慣れてきたのでもっと使いやすくせねばですね #KotlinFest pic.twitter.com/oN2HwHvgHI
これにより、渋谷ならタイミングさえ良ければpovo 2.0との組み合わせで下り1Gbpsオーバーの5G回線と有線LAN接続による端末側への転送が可能になったことでV1での問題点であったWi-Fiテザリングによる課題が解決しました。
ちなみに、このタイミングで一緒にカメラマンをしていた @KeithYokoma さんにCanon EOS 5D Mark IVからSony Transfer & Tagging経由でのアップロードを試してもらったところ、メタデータを見ているのかエラーを出したので現状のシステムはSony専用であることが発覚しています。一応直接JPGファイルをアップロードすれば関係はないんですが、それをするとストレージとビューワへの負荷が大きいのであんまり取りたい策ではないという感じです。
写真爆速上げるくんV3、つくるぞ
機材方面を整える
銀座でスマホ(のようなもの)を買いました pic.twitter.com/RzHcSGNt7u
— どくぴー (@e10dokup) 2024年9月1日
毎年DroidKaigi直前に同じくスタッフの @satsukies と機材を増やす(謎の)文化があるのですが、今年はPDT-FP1になりました。V2での検証の結果、行けると判断したうえでの購入です。これが僕にとってのPixel 9です(?)
べ、別にα9IIIが値上げで更に買いにくくなった腹いせじゃないんだからね!(ちなみに @satsukies もなにか色々と買っていました)
カメラについてもいつもはα9IIとα7RIVを2台持ちし、登壇者のアップや遠景を撮り分けられるようにしていました。しかしPDT-FP1の有線接続が1台にしかできないこと、Sony Transfer & Taggingの転送待ち受けが有線接続 + Wi-Fiテザリングのような併用ができなさそうなことから今年はα9IIのみでの運用に変更し、レンズを付け替えるためにPeak Designのスリングでレンズを詰め込むことにしました。PCとかも持てるじゃんと言いながらあれこれ突っ込んだ結果、ほぼ使わなかったくせに開催2日後も右肩が激痛に苛まれているので反省しています。
ちなみにカメラ自体にはどうやってつけていたのかというと、PDT-FP1には背面に三脚用のネジ穴があるので、同じく三脚用のネジ穴があるSmallRig製のL字プレートを装着し、ネジで結合する形で装着しています。
システム方面を再開発する
設計が完了したタイミングでは8月も半ばに来ており、ここからFTPサーバのアップロードとかを調べる余裕がないし、サービスデプロイも学生の頃試した程度で調べながらになります。フロントエンドも新しく作るとなると2018年頃の知識しかないので調べながらです。ということで一旦FTPアップロードに関してはV1時代のものを流用することを決定しました。それにより、システム全体を眺めると以下のような構成になります。
なお、「写真爆速上げるくん」と英語で名前につけるのはシュールだったので、ここでプロジェクト名を考えました。Photospeedwayって名前をつけたんですが、これはDroidKaigi 2024の2日後に富士スピードウェイへ世界耐久選手権というレースを見に行く予定があったので、それにちなんでつけています。実際スピードがほしいのもあるのでちょうどいいかなと。略称は元ネタにちなんでPSWとかPISCOとかですかね?
バックエンド編
せっかくAndroidアプリ作ってるんだし、Kotlin Multiplatformでサーバサイドを作るかぁと思ったんですが、ドキュメントもある程度は揃っていて、調べながらで進められるだろうとJVMでKtor + Exposedを使い開発することになりました。サーバーサイドKtor、エンドポイント定義のDSLがわかりやすくてだいぶとっつきやすいですね。
バックエンドとしては、とりあえずFTPサーバの情報を登録してイベントアルバムとしてDBに登録する機能、イベントアルバムDBのアクセス情報から写真一覧を返す機能、お気に入りに登録した写真を別のアルバムとして返却する機能を実装しました。お気に入り登録はV1の問題点である写真を選ぶ運営サイドの負荷削減を目的としたもので、イベントアルバムレベルで保持されることでそのアルバムを見ることになる人全員が同じお気に入りを確認することができます。なお、お気に入りから消す機能を作るのを忘れました。
また、Firebase Authenticationによる認証をイベントの登録機能にはかけており、指定された人だけがイベントの登録を行うことができます。時間の都合、新規登録画面などはなく、Firebaseのコンソール上で裏で登録をすることになりますが、今のところ広く公開されるサービスではないので多分大丈夫でしょう。
デプロイ先としてはGCPやAWS…ではなく、依然使ったことのあるさくらのVPSを選択しました。ローカルと同じ感じで環境を立ち上げられたらいいなと思い、KtorのプロジェクトでビルドしたJARファイルやクレデンシャルをSCPなりでアップロードしたあと、Docker Composeを使って立ち上げるという感じです。Gitのプロジェクトクローンからのコマンドによるビルドがいいのかな〜とも思っていたのですが、実際に借りたVPSが2 Core/1GB RAMのものだったのでビルドを始めた瞬間にターミナルがうんともすんとも言わなくなってしまったので諦めました。さくらのVPSの管理画面で確認したらCPU使用率が100%にぺったりと1時間位張り付いていて「ごめんな…」と思わず声が出たのをよく覚えています。
なお、CORSのことを全く認識しておらず、このあとのフロントエンド開発中にひたすらKtorのCORS周りのドキュメントを読み漁ることになります。この辺はネイティブアプリメインだと認識しないので難しいですね。
フロントエンド編
(さっきと同じ書き出し)せっかくAndroidアプリ作ってるんだし、Kotlin Multiplatform(Kotlin/Wasm)でフロントエンドを作るかぁと思ったんですが、調べてみるとKotlin/WasmはSafari上ではまだサポートが怪しい(Wasm GCをサポートしていないみたい?)ので諦めました。いろんなフレームワークを調べてみたところ、Vue.jsがチュートリアルもわかりやすく、とっつきやすかったのでこれを使って先程のバックエンドにaxiosでAPIアクセスをしながら実装することを採用しました。ちょうど知り合いにVue.jsを推している人もいたので、わからなくなったら質問してみようかな〜と考えたのもあります。
最終的にはGitHub Pagesでデプロイすることになるのですが、Vue.jsによる実装は先述のCORSの件に時間を割いた以外は比較的簡単に進められました。あんまりデザインに気を使ってる余裕がないのでVuetifyを使ってMaterial Designな感じで進めることができたのも大きいですね。Androidアプリと違ってViteによるオートリロードなどですぐ実装したものが確認できたりしたのが特に楽ちんでした。
Androidアプリ編
ここまで作ったらもう十分だったんですが、Androidアプリも作ってみようということで急遽クライアントアプリを開発することにしました。会場を歩きながらXアカウントで告知する、みたいなケースを想定すると、アプリから直接写真がダウンロードできるとすごく都合がいいな?と思ったので一旦作ってみた次第です。
設計的にはNavigation Compose、Material 3、ViewModel、Kotlin Flow、Dagger Hiltといった「今から新規にアプリを作るならどういう構成で作る?」みたいな面接っぽい質問に自分で回答するような気持ちで考えました。規模感的にマルチモジュールは採用しなかったんですが、ある程度馴染みのある構成だったこと、バックエンド、フロントエンドで慣れないものを触り続けてきたあとだと異様にスピード感をもって開発できました。やはりひとつある程度技術的に慣れのあるものをもっておくというのは良いですね。
いずれはスライドショー表示にも対応したいなと思い、このタイミングでAPIにもExifを解析して撮影情報を返すエンドポイントを増設し、全画面表示を出来るようにしてみました。意外とそれっぽいものができて嬉しかったです。
実際に動いたものの出来には満足だったんですが、画像の読み込みが少し不安定でリロードとか再起動をひたすらに繰り返していました。多分Coilのキャッシュ設定がミスっていたので、改善するならそこだったり、時間表示をkotlinx-datetimeのInstantで担っているので時間レベルでのフィルタリングを実装して読み込み数を減らす必要がありそうです。
このアプリは別の場所でとある形で再利用されることになったのですが、それについてはまた別のお話ということで。
最後に:DroidKaigi 2024でのV3本番運用を経て
基本的にはシステムは満足に動いてくれていました。幕間のスライドショーにも、Xの投稿にも「え、今の写真じゃんこれ」となる写真が沢山出せたので、カンファレンスカメラマンは良い写真を撮ってくれるけどすぐ出せないのでスマホによる撮影が結局必要、みたいな課題を解決できる良いものができたと僕も満足しています。自分が使って「便利じゃねえの」と思うものを仕事じゃない部分で作れて嬉しかったですね。
実際に起きた不具合や写真絡みのイベントもいくつかあったので、それは箇条書きにしておきます。
- 初日の夜にシステムが最新100枚までしか表示してくれない不具合に気づいた
- 4部屋のセッションを撮って、Xに投稿できる準備をして、会場を撮り歩いて…とやっていると時間がギリギリだった
- とあるタイミングで写真がアップロードされないな?と思ったら、JPG側のSDカードが不調になってJPGが全部こわれていた
- RAWは別のSDカードに保存していたので致命傷ではないが、SDカードのフォーマットを現地ですることになった。SDカードはちまちま買い替えよう!
- 知り合いを含め参加者の方に「その…なんだ?その…、スマホ…?」と不思議な顔をされる。Sony PDT-FP1がXPERIAベースの端末なので、とにかくでかい
また、現状のシステムの改善点もいくつかあり、以下の改善をしてどこかでV4を運用したいですね。
- 1イベントで大量にアップロードするとシステムがうんともすんとも言わなくなる
- FTPアップロード自体をAPIサーバ側に統合する
- スライドショー表示を作る
- お気に入りのカテゴリを分けれるようにする
- 「あのシーンの写真、ある?」という要望が出るとお気に入りに入れたかどうかすら不明でずっと探していたので、ユースケースとして漏れていたっぽい
- というか撮っている側も「あのシーンあったっけ」って大体覚えていないので、チェックリストとして機能しそう
- FTPアップロードアプリを作る
DroidKaigi 2024のスタッフや会社のお仕事も忙しい時期で大変でしたが、余暇(?)に久々に面白い個人開発ができました。とっても楽しかったです。 しばらくは積んでいたゲームなどを消化しながら、ゆっくり過ごそうと思います。ありがとうございました ( ˘ω˘)スヤァ