顔認識で卒業アルバムの作成を支援するWebサービスを作った
Albumieという卒業アルバムの作成を支援するWebサービスを作りました🚀
このサービスでは、顔認識機能により人物で写真を検索できたり、写真ごとに写っている人物を確認できたり、すべての人物が同じくらい写っているアルバムを簡単に作成できる機能を提供しています。
作り始めたきっかけ
AWS re:Invent 2018でフルスタックのアプリケーションを簡単に構築できるらしいというAWS Amplifyを知り、なにかAmplifyで作ってみたいと思っていたところに友人から卒業アルバムの作成に時間がかかって困っているという話を聞いて作ってみようと始めました。
GitHubのコミット履歴を見ると、最初のコミットは2019年3月17日でした。
気がつくと約3年強にも及ぶ長期プロジェクトで、途中、完全に別のことに興味が持っていかれたときもありましたが、なんとかリリースできました🎉
少しずつですが開発を続けてこれたことがよかったです。
AWS Amplifyを使ってみての感想
サーバレスでコマンドひとつで環境一式を作ることができるので楽です。
開発ではAmplifyが提供しているモック機能でローカルにS3やLambda、DynamoDBなどをモックでき、ローカル環境のみで開発できる点も便利です。
ただし、あくまでもモックなので、細かい機能、例えばS3ではHEADアクションやDeleteObjecsCommandがサポートされていなかったり、ちょくちょく不具合があったりします。
S3のトリガーイベントが動かなくてAmplifyの本体に修正のPRを出したこともありました。
fix: support AWS::S3::Bucket FilterRule properly in the mock mode by laboone · Pull Request #10799 · aws-amplify/amplify-cli · GitHub
自分のコードが誤っているのか、モック側が問題なのか切り分けが難しかったりするので、こういうところはどんどん成熟していくとよいなと思います。
また、DynamoDBの設計も大変だった点です。
DynamoDBはRDB(リレーショナルデータベース)とは大きく設計手法が異なります。
RDBではデータを柔軟にクエリできるので正規化さえしておけば特にデータ構造に悩むところは少ないです。
しかし、DynamoDBではRDBのような柔軟なクエリができないので、アプリケーションでどういうデータ取得が発生するかを洗い出し、それに対してどういうデータ構造が最適化かを考える必要があります。
効率的にデータを取得するためにデータを正規化せずに重複して持ったり、ひとつのカラムに複数の値を格納(Composite Key)したり、クライアント側でデータをキャッシュしたり、いろいろな工夫が必要になります。
Example of modeling relational data in DynamoDB - Amazon DynamoDBにリレーショナルデータをDynamoDBではどのように設計するかを記した例があり、このあたりを見るとDynamoDBでの設計の参考になると思います。
Amplifyでアプリケーションを作成する場合は、まずは作ろうとするアプリケーションがDynamoDBのデータモデルとマッチするかを考えてみるとよさそうです。
ちなみに、DBにはAurora Serverlessも使えますが、モックがサポートされていないようなので今のところDynamoDB一択という気がしています。
今後について
まだまだ実装したい機能がたくさんあるので、これからもどんどん機能を追加して使いやすくしていこうと思っています。
Albumieをよろしくお願いします!
高知でリモートワークをはじめてました
去年の6月から株式会社ハートレイルズにエンジニアとして入社して、高知でリモートワーク(在宅勤務)をはじめてました。
ハートレイルズはWebサービスやアプリの開発をしている会社で、2006年の創業期からリモートワークを実践しています。自社サービスもやってますが、最近は受託開発が多めで新規事業の開発・運用を得意としています。
HeartRails | ハートレイルズ | ザ・ウェブサービス・カンパニー
リモートワークをはじめて1年半弱経つので、これまでをふりかえって、今感じているリモートワークの良い点/悪い点などを書いておこうと思います。
はじまり
最初はオフィスに出社が必要かと思いきや、出社の必要がなく1日目に開発環境構築して、2日目からはアサインされたタスクの実装をやってました。(面接、技術試験もオンラインだったので、じつはまだ1度も会社に物理出社してない。)
既存のとあるWebサービスの機能追加を担当することになって、最初はサービス仕様もよくわからず、いろいろとツマリまくりの毎日でした。
オフィスだと困ってそうな雰囲気をだしていたら声をかけてくれたりとかあるけど、リモートだと雰囲気なんてわからないので、能動的に動いてコミュニケーションをとらないと仕事が進みません。
リモートワークにコミュニケーションスキルはあまり必要ないかと思ってたけど、実際はとても必要で、顔が見えない分、言葉に気を使うし、オフィスワークよりむしろ必要だと感じました。
最初はこのままリモートでやっていけるかななんて思っていましたが、色々とヘルプをしてもらって段々と慣れていきました。
社内でのコミュニケーション
社内でのコミュニケーションツールにはSlackを使っています。
このスクリーンショットにでてくる「koharu」はbotです。
毎日、誰かしらkoharuにニュースを聞いたり、話しかけたりするのが日課になっていて、このスクリーンショットは、僕が初めてkoharuにニュースを聞いたときのものです。
ちなみに、ハートレイルズには他にも「鳥山ちゅんこ」というキャラもいて、LINEスタンプもありますので、是非どうぞ:-)
ゆるふわ JK コハルちゃん - クリエイターズスタンプ
鳥山ちゅんこサン - クリエイターズスタンプ
また、年に2回ほど合宿があって、オフラインで一緒に仕事をする機会があります。
同僚が隣でもくもくと仕事しているのを見るのはとても新鮮で毎回不思議な気持ちになります。
合宿では、夜な夜なカラオケをしたり、ボードゲームやカードゲームをしたりして、交流を深めています:-)
合宿中! pic.twitter.com/pYXSGVvJKj
— あいおー (@ioxx) June 24, 2015
ちなみに、これまでやったカードゲームの中ではLove Letterがおすすめです。ルールが簡単で良いです。
あとは、Google Hangoutを使って週報(KPTでのふりかえりとプロジェクト近況報告)と勉強会を週替わりでしています。
仮想オフィスのようなイメージで毎日開かれるHangout部屋もあって、そこで雑談することもできます。最近はフィリピンに短期留学していた同僚 id:ogin_s57 が雑談部屋で英語の発音講座を開いたりしています。
また、今月末は、リクリエーションとして皆で秋のBBQを計画しています。
普段顔を合わせない分、こういう活動を通して交流を深めています。
良い点と悪い点
リモートワークの一番の良い点は、働き方に柔軟性を持てる点だと感じています。
仕事中、煮詰まったら気分転換にジョギングしてもよいし、ベッドで昼寝をしてもよいし、どこで働いてもよいです。
あとは、昼に自炊できるとか、毎日布団が干せるとか、宅急便をいつでも受け取れるとか、そんな小さなことも地味にQOL(Quality of Life)を上げてくれます。
<冬はほぼ毎日鍋を作った。Slackに作った料理をポストする料理部チャンネルがあって、この写真はそこから。>
メンタル面では、オフィスだと自分だけ早く帰るのは申し訳ないとつい残ったりしちゃいがちだけど、成果がすべてのリモートワークではそのストレスもありません。
ただし、オフィスと違って周囲の目がないため、自分が生産的になれるように自分自身でコントロールする必要があります。
働き方が自由というのは良い面もあるけど、取り扱いも難しくて、ともすればダラけすぎたり(逆に働きすぎたり)という面があるので、時間を決めて集中して働くように気をつけています。
僕は「ポモドーロテクニック」という時間管理術を使っていますが、リモートワークはオフィスと違って割り込みが少ないので、ポモドーロテクニックとの相性がとても良いです。
逆に悪い点としては、一人で仕事をするのでリアルの対人関係が減ります。
僕はどちらかというと人付き合いが好きなので、対人関係を増やそうと以前はコワーキングスペースで仕事をしていました。
ですが、高知ではコワーキングスペースを使う人が少なく、コワーキングスペースでほとんどひとりで仕事をする環境になっていたのでやめてしまいました。
仕事以外の趣味などで社交生活の場を増やす必要があるなと感じています。何かよい場があれば教えてください:-)
最後に
ということで、リモートワークについての諸々を書いてみました。
僕の住んでいる高知などの地方だと都市部に比べて仕事が少なく、地元で働きたいけど都市部にでなきゃいけなかったり、自分のやりたい仕事ができなかったりということがありますが、リモートワークがもっと普及すれば、こういう地方問題の少しは解決できそうです。
リモートワークがあたりまえになって、住みたい場所で暮らせる日本になればいいな。
Flickr Fast DownloaderにCC0やパブリックドメインで検索できる機能をつけました
Windowsストアアプリ初心者が初めてストアプリを作ってみた
ちょっと釣り気味なタイトルですが、Windowsストアプリを作ってみました。
ストアプリを作ってみようと決めて、Surfacep Pro3を発売日当日買い*2して日曜プログラミングで約3ヶ月かかりました。
Windowsは安いタブレットがどんどん出てきているし、これから面白いかもしれません。
ということで、これからWindowsストアアプリを作ってみようと思ってる人に参考になるように開発の記録を。
まずはSurface Pro3を購入
タッチパネルのデバイスがないと始まらないので、Surface Pro3を購入。
私が買ったのは以下のSurface(CPU:Core i5、メモリ:4MB、記憶域:256GB)とTypeCover。
CPUはより上位のi7のモデルもありますが、i5で十分です。
今度Core i3版のSurfaceも販売されますが、ディスクが64GBしかないのはツライ。
ということで、ちょっと値は張りますが、快適に開発したい場合はCore i5の256GBがおすすめです。
Windowsストアプリのユーザインターフェース(UI)に慣れる
WindowsストアプリのUIは、これまでのWindowsアプリとまったく違うUIなので、Windows8にインストールされているメールアプリやIEなんかのWindowsストアアプリを触りまくります。
作ろうと思っているカテゴリのアプリをWindowsストアからダウンロードして触ってみるのもお勧めです。
既存アプリのイイトコドリして自分のアプリのUIを考えると良いです:-)
開発本を読む
Windowsストアアプリに慣れたら、Windowsストアプリの開発本を読みます。
何冊か目を通しましたが、私は以下の本がお勧めです。
この書籍はWindows8対応なのでWindows 8.1になってちょっと変わったところもありますが、とてもまとまっているのでお勧めです。
C#を知らない人は、この本と適当なC#の入門本を読むと良いです。
開発環境の構築
開発本を読みつつ開発環境を構築します。
無償の開発環境のVisual Studio Express 2013 for Windowsをインストールします。
開発、開発、開発
コードを書きます、以上(笑
まったく開発経験がない人は、以下の書籍を読むと良いと思います。
この書籍には、アプリケーションのデザインから実装までのひととおりの手順が載っています。
あとは実際に手を動かして、コードを書いて、書いて、書きまくってると次第に慣れてくるはず!
アイコンの作成
作ったアプリのアイコンを作ります。
アイコンを作るのには、Inkscapeというアプリが便利です。
私はデザインが苦手なので、アイコンは四角形や三角形を組みあわせたシンプルなアイコンを書いてお茶を濁してます(泣
ちゃんとデザインできる人になりたいです。。。
Windowsストアへのアプリの登録
ここからは事務作業です。
Windowsストアへの登録については以下のサイトなどを見ると良いです。
開発したユニバーサルアプリを実際にストアに申請、登録するまで | Think IT(シンクイット)
なお、Windowsストアへの登録には、Windowsストアの開発者になる必要があります。
Windowsストア開発者になるには$19必要です。
以前は、年間$49だったのですが、今では更新費用が無償になっています。
Microsoft、Windows/Windows Phoneストアの開発者アカウントの更新費用を無償化 - 窓の杜
ちなみに米国で販売する場合は、W-8フォーム(税務プロファイル)をださないといけません。
このあたりは、以下を参考に。
W-8 フォーム(税プロファイル)について ( Windows ストア / Windows Phone ストア / Office ストア / pubCenter 共通 )
Flickrの写真を一括でダウンロードできるアプリを作った
Flickr Fast DownloaderというFlickrから写真やビデオをまとめてダウンロードできるツールを作りました。
http://flickrdownloader.laboone.net/
元々は、Flickrにあげている自分の写真のバックアップを取っておきたいという理由から自分用のツールとして作っていましたが、どうせなら公開しようと思いたち、2月ぐらいから今まで約6ヶ月もかかりましたが、なんとか公開することができました。
ここでは、その作業ログを残しておこうと思います。
=== 追記(2014/8/17) ===
窓の杜さんがFlickr Fast Downloaderの記事を書いてくれました。
機能については、窓の杜さんの以下の記事を参照してください。
シンプルな“Flickr”のバックアップ・ダウンロードツール「Flickr Fast Downloader」
==================
使用した技術について
開発に使った言語はC#です。
GUIはWPFを使って作成しました。
mahapps.metroというWPF用のフレームワークがあり、これを使うと良い感じのデザインにできるのでお薦めです。
FlickrのOAuth認証回りとGoolge Walletでのライセンス購入回りはASP.NET MVC、Web APIを使いました。
開発についての諸々
スクロールに応じて画像を遅延ロード
写真は画面のスクロールに応じて遅延ロードするようにしています。
これは、WPF Data Virtualizaitonを参考に実装しました。
このキモになるところは、以下のとおりです。
写真やビデオのダウンロード
写真やビデオのダウンロードにはProducer-Consumerパターンを使ってマルチスレッドでダウンロードしています。
Producer-Consumerパターンを実装するにはBlockingCollectionがとても便利です。
これを知らなくて最初はオレオレ実装していましたが、BlockingCollectionで書き直したらコードがすっきりしました。
FlickrのOAuth認証
デスクトップアプリでFlickrの認証を行う場合、Flickrの認証ページを開く→ユーザがFlickrにログインする→表示されるコードをアプリに貼り付けるという手順が一番実装が簡単ですが、コードを貼り付ける手順が省けるようにコードをWebサイト上で記録して、アプリケーション側からWeb APIを叩いてコードを取得するという実装にしています。
Goolge Walletの決済サービス
今回のアプリケーションでは、オリジナル写真のダウンロードにライセンスの購入が必要としています。
この決済回りにはGoogle Wallet、WebPay、Stripe、FastPay、SPIKE、PayPalなどの決済サービスを調べてみて、国内外ともに使えるGoogle Walletにしました。
色々なサイトでよく見かけるのはPayPalなので、PayPalを使おうかとも思いましたが、最終的にはチュートリアルやマニュアルがわかりやすいGoogle Walletにしました。
Googleはドキュメントがわかりやすくてよいですね。
はじめてのWordpress
アプリを公開しているサイトはWordPressで作りました。
WordPressはさわったことがなく最初は結構とまどいました(汗
WordPressについては、以下の本がとてもわかりやすかったです。
総括
いざ公開するアプリケーションを作るとなると細かい作業が多く、且つ、今回はアプリケーションの言語を英語にしたので地味にそこも大変でした。
おかしな英語もあると思いますので、なにかおかしなところがあれば教えてくださいm(_ _)m
ということで、Flickr Fast Downloaderをぜひ使ってみてください!
clickonceの証明書を作る
clickonceのテスト証明書を作るためのメモです。
期限切れにならないようにendを2100年とかにしておくとよいですね。
makecert -sv ClickOnceTestApp.pvk -n CN=Sample ClickOnceTestApp.cer -b 01/01/2012 -e 12/31/2100 -r pvk2pfx -pvk "ClickOnceTestApp.pvk" -spc "ClickOnceTestApp.cer" -pfx "ClickOnceTestApp.pfx"
DVD・ブルーレイをレビュー数でランキング表示するWebサービスを作った
DVD・ブルーレイをレビュー数でランキング表示するWebサービス「DVDれび」を作りました。
2013-03-05 - 高知で働くひとの日記で「ぶくれび」を作ってから4ヶ月も経ってしまいました(汗
さくっと1、2週間ぐらいで作る予定でしたが、モチベーションの維持は難しい。。。
レビュー数が多い映画は良い映画が多いので、何か映画が見たいなってときにはこのサービスを使って探してもらえれば嬉しいです。
ちょっと技術的なメモ
「ぶくれび」はSQLServerを使ってますが、「DVDれび」はSQLiteを使ってます。*1
速度的には体感でわかるぐらいSQLServerを使っている「ぶくれび」のほうが速いです。*2
一覧出力に使っているSQL文は以下のとおり。*3
ページング用に一発のクエリで検索にヒットした件数の取得も行っています。(@PageNumber:何ページ目かを表す変数。@PageSize:1ページに表示する件数。)
SELECT Top(@PageSize) * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY reviewCount DESC) RowId, B.*, Count(*) OVER() TotalRows FROM Book AS B WHERE B.genreId = @Genre ) A WHERE A.RowId > ((@PageNumber-1)*@PageSize)
SELECT B.*, (SELECT count(*) FROM Book WHERE genreId = @Genre) TotalRows FROM Book AS B WHERE B.genreId = @Genre ORDER BY B.reviewCount DESC LIMIT @PageSize OFFSET ((@PageNumber-1)*@PageSize)