読者です 読者をやめる 読者になる 読者になる

社内共用カメラのすゝめ

舘野 (id:secondlife / @hotchpotch) です。

クックパッドでは会社の中心にキッチンがあり、社員同士でランチやお菓子を作ったり、イベントを開いたりと社内のコミュニケーション用途で広く使われています。そんなキッチンで作られている様々な料理や、楽しそうなコミニュケーションをその場に居ない人にも伝えたいなー、どうにか伝える方法は無いのかな〜と思っていました。

そんな中、より良い組織を作るために の中でも触れられているコミニュケーション改善の話をしている最中、社内に共用のカメラが置いてあって、撮った写真が何もせずとも自動で社員が見れる場にアップロードするだけの仕組みを提供するだけでうまく行くかも、と思ったので2014年末に作ってみました。

f:id:secondlife:20160323132837j:plain

サービスのコンセプト

作るときに盛り込んだコンセプトは以下の二点です。

  • 運用コストがゼロ
  • アップロードコストがゼロ

運用コストがゼロ

ここで言う運用コストは、人的な運用コストです。社内の誰かがそれなりに面倒を見て運用することになると「また余計な物作りやがって…*1」ということになりかねないですね。

そのため作った後、人の運用のコストが無いサービスにしようと思いました。

アップロードコストがゼロ

アップロードコストがゼロ、というのは人が意識的にアップロードする行為を入れない、と言うことです。UI で 1 を 0 にすると大きな変化が起こる、と誰かが言ってた*2のですが、「何か行為が必要」な事と「何もしない」ことは大きな隔たりがあります。

能動的なアップロードが必要だと、アップロードすること自体のコストと、どの写真をアップしようかという写真の取捨選択コストがかかってしまいます。

もっと気軽にアップロードされて欲しい、という思いから、意識的にアップロードしなくても良い、アップロードコストがゼロのサービスにしようと思いました。

このコンセプト二つは、人のコストを無くすという点では共通してますね。

プロトタイピング

まずはプロトタイピングを、ということでこの二つのコンセプトを満たしたサービスを作ってみました*3。アップロードコストがゼロという視点では EyeFi (旧バージョンの方で、現行バージョンは異なる仕様です)を使いました。 EyeFi(旧) は写真を撮るとすぐに EyeFi サーバにアップロードされ、そこ経由で様々なフォトストレージにアップロードすることが可能です。

運用コストゼロ、という視点からはアップロード先に Google Photos を選びました。Google Apps を会社で利用している場合、社員のみ閲覧可能にすぐ変更可能なことも便利ですね。

これで問題なければ…と思ったのですが、アルバム機能が新しい日付順でのソートの Permalink が保持できなかったり…等、今回の用途にそぐわなかったため、Google Photos はやめました。

※ありものを使い、最小コストでのプロトタイピング

f:id:secondlife:20160325133616p:plain

プロトタイピング その2 ~ 完成まで

続いては、EyeFi(旧) は自分のサーバのAPIを叩くこともできるので

  • Heroku の API サーバへ Post
  • Heroku 側で ImageMagick 経由でいくつかのサイズへリサイズ
  • ストレージへアップロード

という仕組みでストレージへファイル名を 2016/02/14/142010_{hash}.jpg のようなファイル名でアップロードします。なお裏側のストレージは、 http(s) の permalink にアップロードするだけでアクセスできる*4機能を持ち、またファイルリストがAPIで取れるサービスであればどれでも良かったので AWS S3 を選びました*5

閲覧側は API から画像一覧を取得し、それを元に permalink を組み立てれば完了です。社内に dokku が立っていたので、画像一覧を返す JSON API をたて、html + JavaScript で UI を実装しとりあえずプロトタイピング完了です。

画像 URL が月日ごとの URL となってるので、各種ストレージのファイルリストを取得するオプションに prefix を指定(2016年2月の写真なら 2016/02/ など)することで、特定月や日の写真一覧の取得なども簡単にできますし、日時が permalink に入ってるので画像のメタ情報無く、permalink をソートするだけで写真の日時順に並べ替えが行えます。

と言うのも、何らかしらの情報をRDBやNoSQL等へ記録してしまうと、それを維持する運用コストが発生してしまうため、使わなくても問題ないような仕様にしました。

※軽く実装

f:id:secondlife:20160325133621p:plain

と言うわけで軽く実装してみて、要求は満たせそうなので JS + CSS で体裁を整え完成です。

f:id:secondlife:20160325133625p:plain

なお削除は、閲覧側の UI に削除ボタンを付け、アップロードされたけど消したい場合に誰でも気軽に消せるようになっています。

※気軽に削除できるUI f:id:secondlife:20160325133630p:plain

社内リリースまで

続いて、社内リリースのための周知です。作ってもそもそも認知されない物になってしまうと悲しいです。そのため、社内ポータルのトップ画面*6から XHR の CORS で 閲覧側の JSON API を叩き、ポータルのトップに最新の写真が出るようにしたり、この共用カメラはなんぞや?という解説ページを作りリンクを張るなど、興味を持ってもらうような導線を入れました。

f:id:secondlife:20160325133632p:plain

結果、当初のコンセプト通り、アップロードコストがゼロのため気軽撮られた写真が集まるようになり、一年間で5,000枚以上の写真がアップロードされ、いろいろ料理の写真や楽しそうな写真、イベントの写真等々が会社全体に伝わるようになりました。

最初の頃はシャッターを押したらどの写真もアップロードされてしまうことに慣れない人も居ましたが、ほとんどの写真はとりわけ削除が必要になるような写真では無いため、今では気軽に撮って、もしどうしても削除したい場合でも簡単に消せることから、慣れていったようです。

またもう一つのコンセプトである、人による運用コストゼロも、S3等のオブジェクトストレージしか使ってないため、クラウドサービス障害時のストレージ障害確認の必要性も無く、手間無く運用できているといえると思ってます。

使われなかった機能

社内向けツールのため、機能を自由に実装できるため、いろいろな機能を追加したくなる欲求に駆られます。そして実装してしまいました。説明した機能以外に

  • 撮った写真を社内チャットに流す
  • 写真を特定メールアドレスに送信するとアップロード
  • 写真をブラウザ上にドラッグするとアップロード

等々の機能を実装したのですが、一つ目は撮られた写真をリアルタイムのフローで見たいという欲求はあまりなく、リリースした当時はそれなりの人が居たのですが、今はそのチャットルームは寂れており、需要が無いことが解りました。Instagram 等の写真もリアルタイムで見たいというよりは、空いてる時間に見たい欲求の方が強いですし、仕事上 PC をいつも開いてる状態では、ブラウザ上の UI で俯瞰して見れた方が便利ですね。

また後者二つは、別のカメラやスマートフォンで撮ったファイルのアップロードにも使えるよね、ということで実装したのですが、アップロードコストがゼロのコンセプトに反していて、能動的なアップロードが必要になってしまい、やはりほぼ使われない結果に終わりました。

Tips・予備バッテリーを用意する

共用で誰でも使えるカメラのため、うっかり充電し忘れてカメラのバッテリーを使い切ってしまった状態になることがあります。カメラを使おうと思ったのに「撮影したいのに充電されてない…」という状況が発生してしまうと悲しいですよね。

共用カメラの置き場所のそばに外部充電器 + 予備バッテリーをおいておくことで、カメラ本体のバッテリーが切れていても即座に交換でき、また交換時についでに充電するので電池が切れるという事は基本ありません。撮りたいときに撮れないガッカリを減らすためにも、充電器 + 予備バッテリーがあると便利です。

まとめ

クックパッドでは共用カメラを用い、撮影後自動でアップロードして社内ポータルから閲覧できる仕組みを運用してます。このカメラがあることで、キッチンの楽しい、美味しい写真が社内で共有され、コミニュケーションの促進にも役立ってると思っています。

社内にこのようなカメラが一つあると何かと便利なので、皆さんの会社も気軽に撮影できてアップロードされる共用カメラを検討してみてはどうでしょうか。本エントリーでも紹介している旧版の Eye-Fi を使うことで、提携しているクラウドサービス等々にも撮影した写真をアップロードでき、便利です。

古いサービスは終了になりがちですが、 Eye-Fi はサービス提供していてありがたい…と思って調べてみたら

この度、生産、販売終了品の旧製品における、Eye-Fi View及び、Eye-Fi Premiumが他社オンラインサービスとの連携につきまして、2015年9月9日をもちまして、終了いたしますことをお知らせいたします。

サービス終了告知が出ていた(終了日時以降も何故か使えてるけど…)、というオチが…。お、おう。

*1:※もし私が運用担当でめんどくさいシステムを押しつけられたらそう思ってしまうかも

*2:※要出典

*3:* Google Photos にアップするだけなので作ってみたとは違いますが…

*4:[permalink が万が一漏れるとアクセスできる可能性はありますが、機密事項を取り扱っていない&キッチンは執務スペース外のため、リスクとして許容してます

*5:なお現在は Azure blob storage をメインのストレージとして使ってます

*6: 自家製の Wiki + Blog システムで、JavaScript も書けます

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/